mmu.c 2.2 KB
Newer Older
P
Parallels 已提交
1 2
#include "nemu.h"
#include "memory/memory.h"
Z
Zihao Yu 已提交
3
#include "csr.h"
P
Parallels 已提交
4 5 6 7 8 9 10 11 12 13 14 15

typedef union PageTableEntry {
  struct {
    uint32_t valid  : 1;
    uint32_t read   : 1;
    uint32_t write  : 1;
    uint32_t exec   : 1;
    uint32_t user   : 1;
    uint32_t global : 1;
    uint32_t access : 1;
    uint32_t dirty  : 1;
    uint32_t rsw    : 2;
Z
Zihao Yu 已提交
16 17
    uint64_t ppn    :44;
    uint32_t pad    :10;
P
Parallels 已提交
18
  };
Z
Zihao Yu 已提交
19
  uint64_t val;
P
Parallels 已提交
20 21 22 23
} PTE;

typedef union {
  struct {
Z
Zihao Yu 已提交
24 25 26 27
    uint64_t pf_off		:12;
    uint64_t vpn0  		: 9;
    uint64_t vpn1  		: 9;
    uint64_t vpn2  		: 9;
P
Parallels 已提交
28
  };
Z
Zihao Yu 已提交
29
  uint64_t addr;
P
Parallels 已提交
30 31
} PageAddr;

Z
Zihao Yu 已提交
32 33
// Sv39 page walk
static word_t page_walk(vaddr_t vaddr, bool is_write) {
P
Parallels 已提交
34
  PageAddr *addr = (void *)&vaddr;
Z
Zihao Yu 已提交
35
  word_t pdir_base = satp->ppn << 12;
P
Parallels 已提交
36

Z
Zihao Yu 已提交
37 38 39 40 41
  PTE pte2;
  pte2.val	= paddr_read(pdir_base + addr->vpn2 * 8, 8);
  if (!pte2.valid) {
    panic("pc = " FMT_WORD ", vaddr = " FMT_WORD ", pdir_base = " FMT_WORD ", pte2 = " FMT_WORD,
        cpu.pc, vaddr, pdir_base, pte2.val);
P
Parallels 已提交
42 43
  }

Z
Zihao Yu 已提交
44 45 46 47 48 49
  word_t pt_base1 = pte2.ppn << 12;
  PTE pte1;
  pte1.val = paddr_read(pt_base1 + addr->vpn1 * 8, 8);
  if (!pte1.valid) {
    panic("pc = " FMT_WORD ", vaddr = " FMT_WORD ", pt_base1 = " FMT_WORD ", pte1 = " FMT_WORD,
      cpu.pc, vaddr, pt_base1, pte1.val);
P
Parallels 已提交
50 51
  }

Z
Zihao Yu 已提交
52 53 54 55 56 57
  word_t pt_base0 = pte1.ppn << 12;
  PTE pte0;
  pte0.val = paddr_read(pt_base0 + addr->vpn0 * 8, 8);
  if (!pte0.valid) {
    panic("pc = " FMT_WORD ", vaddr = " FMT_WORD ", pt_base0 = " FMT_WORD ", pte0 = " FMT_WORD,
      cpu.pc, vaddr, pt_base0, pte0.val);
P
Parallels 已提交
58 59
  }

Z
Zihao Yu 已提交
60 61 62 63 64 65 66
  //if (!pte.access || (pte.dirty == 0 && is_write)) {
  //  pte.access = 1;
  //  pte.dirty |= is_write;
  //  paddr_write(pt_base + addr->pt_idx * 4, pte.val, 4);
  //}

  return pte0.ppn << 12;
P
Parallels 已提交
67 68 69 70 71 72
}

static inline paddr_t page_translate(vaddr_t addr, bool is_write) {
  return page_walk(addr, is_write) | (addr & PAGE_MASK);
}

Z
Zihao Yu 已提交
73
word_t isa_vaddr_read(vaddr_t addr, int len) {
Z
Zihao Yu 已提交
74 75
  assert(satp->mode == 0 || satp->mode == 4);
  paddr_t paddr = (satp->mode == 4 ? page_translate(addr, false) : addr);
P
Parallels 已提交
76 77 78
  return paddr_read(paddr, len);
}

Z
Zihao Yu 已提交
79
void isa_vaddr_write(vaddr_t addr, word_t data, int len) {
Z
Zihao Yu 已提交
80 81
  assert(satp->mode == 0 || satp->mode == 4);
  paddr_t paddr = (satp->mode == 4 ? page_translate(addr, true) : addr);
P
Parallels 已提交
82 83
  paddr_write(paddr, data, len);
}