📄 mmu.c
字号:
/*
* mmu.c
* Copyright (c) Inst. of Machine Intelligence at Nankai University
*/
#include "types.h"
#include "mmu.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char memory[MEMSIZE] = {0};
void my_pgfault_handler(){
extern phyaddr_t cpu_cr2 ;
struct Page* get_mempage;
get_mempage=page_alloc(); //分配一个空闲页给临时变量
page_insert(cpu_cr2,get_mempage);
};
void (*pgfault_handler)() = my_pgfault_handler;
struct Page* pages;
struct Page* free_list;
int mem_end = 0; // memory 中最后一个被使用的字节
int write_memory(viraddr_t va, char* buf, int size)
{
extern phyaddr_t cpu_cr3;
extern phyaddr_t cpu_cr2;
extern phyaddr_t cpu_cr0;
extern uint32 cpu_errcode;
int i = 0;
pde_t* pgdir;
pte_t* pgtable = 0;
pde_t pde = 0;
pte_t pte = 0;
int start = 0;
if (!buf){
printf("\nError: Buffer is NULL.\n");
exit(1);
}
if ((cpu_cr0 & PAGING) != PAGING)
{
//未开启分页的话,虚拟地址直接是物理内存的地址
for (i = 0; i < size; i++)
memory[va + i] = buf[i];
return 0;
} else
{
pgdir = (pde_t*)(memory + cpu_cr3);//得到顶级页表的首地址:模拟内存地址+进程的顶级页表的地址
for (i = 0; i < size; i++)
{
pde = pgdir[PDX(va + i)];//虚拟地址的前十位为在顶级页表中查找的偏移量,pde取得顶级页表项来分析
if ((pde & PTE_P) != PTE_P || (pde & PTE_W) != PTE_W)//所需的二级页表不在内存中或不可写,缺页中断
{
if (pgfault_handler)
{
cpu_cr2 = va + i;
cpu_errcode = 0x02;
(*pgfault_handler)();
i--;//当前还没有结束,不能i++
continue;
}
printf("Error: Page Directory is invalid.\n");
exit(1);
}
pgtable = (pde_t*)(memory + PTE_ADDR(pde));//pgtable是二级页表的首地址:模拟内存地址+顶级页表项的前20位
pte = pgtable[PTX(va + i)];//虚拟地址的中间十位是二级页表的索引
if (pte & PTE_P != PTE_P || (pde & PTE_W) != PTE_W)
{
if (pgfault_handler)
{
cpu_cr2 = va + i;
cpu_errcode = 0x02;
(*pgfault_handler)();
i--;
continue;
}
printf("Error: Page Table is invalid.\n");
exit(1);
}
memory[PTE_ADDR(pte) + PGOFF(va + i)] = buf[i];
}
return 0;
}
}
int read_memory(viraddr_t va, char* buf, int size)
{
extern char memory[];
extern phyaddr_t cpu_cr3;
extern phyaddr_t cpu_cr2;
extern phyaddr_t cpu_cr0;
extern uint32 cpu_errcode;
int i = 0;
pde_t* pgdir;
pte_t* pgtable = 0;
pde_t pde = 0;
pte_t pte = 0;
int start = 0;
if (!buf){
printf("\nError: Buffer is NULL.\n");
exit(1);
}
if ((cpu_cr0 & PAGING) != PAGING)
{
//未分页
for (i = 0; i < size; i++)
buf[i] = memory[va + i];
return 0;
} else
{
pgdir = (pde_t*)(memory + cpu_cr3);
for (i = 0; i < size; i++)
{
pde = pgdir[PDX(va + i)];
if ((pde & PTE_P) != PTE_P)
{
if (pgfault_handler)
{
cpu_cr2 = va + i;
cpu_errcode = 0x00;
(*pgfault_handler)();
i--;
continue;
}
printf("Error: Page Directory is invalid.\n");
exit(1);
}
pgtable = (pde_t*)(memory + PTE_ADDR(pde));
pte = pgtable[PTX(va + i)];
if ((pte & PTE_P) != PTE_P)
{
if (pgfault_handler)
{
cpu_cr2 = va + i;
cpu_errcode = 0x00;
(*pgfault_handler)();
i--;
continue;
}
printf("Error: Page Table is invalid.\n");
exit(1);
}
buf[i] = memory[PTE_ADDR(pte) + PGOFF(va + i)];
}
return 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -