📄 mmu.c
字号:
/*
* mmu.c
* Copyright (c) Inst. of Machine Intelligence at Nankai University
*/
#include "types.h"
#include "mmu.h"
#include "page.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
extern phyaddr_t cpu_cr3;
extern phyaddr_t cpu_cr2;
extern phyaddr_t cpu_cr0;
extern uint32 cpu_errcode;
extern char memory[];
void handler()
{
struct Page* new_page;
new_page=page_alloc(); //分配一个空闲页给临时变量
page_insert(cpu_cr2,new_page); //将虚拟地址映射到新分配的页中
}
char memory[MEMSIZE] = {0};
void (*pgfault_handler)() = handler;
struct Page* pages;
struct Page* free_list;
int mem_end = 0; // memory 中最后一个被使用的字节
int write_memory(viraddr_t va, char* buf, int size)
{
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]; //取buf的前size个字节的数据分别存入以va为起点的内存地址
return 0;
}
else
{
pgdir = (pde_t*)(memory + cpu_cr3);//cpu_cr3代表进程要访问页的顶级页表的首位置
for (i = 0; i < size; i++)
{
pde = pgdir[PDX(va + i)]; //pgdir代表顶级页表,PDX(va + i)取虚拟地址的前十位(标识了
//其顶级页表的位置)作为顶级页表的下标,则可以找到顶级页表第
//PDX(va + i)个页表项,每个页表项指向1024个二级页表项
if ((pde & PTE_P) != PTE_P || (pde & PTE_W) != PTE_W)
{ //如果顶级页表指向的页表项不在内存中,则产生缺页中断,重新调页
if (pgfault_handler) //(*pgfault_handler)()可以指向一个中断响应函数
{
cpu_cr2 = va + i;
cpu_errcode = 0x02;
(*pgfault_handler)();
i--;
continue;
}
printf("Error: Page Directory is invalid.\n");//如果缺页中断找不到需要的页,则输出
//提示该页无效
exit(1);
}
pgtable = (pde_t*)(memory + PTE_ADDR(pde));//找到二级页表的首地址:取pde表项的前20位,
//pde的后12位是各种状态标志位
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]; //二级页表表项指向的内存页框号
//+ 虚拟地址的后12位页内偏移量
}
return 0;
}
}
int read_memory(viraddr_t va, char* buf, int size)
{
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];//如果未分页,则物理页和逻辑页一一对应,va为
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 + -