我正在努力编写一个将虚拟内存地址转换为物理地址的函数我希望函数返回虚拟16位地址的物理内存地址。
我只是使用了16位的虚拟地址,忽略了权限位(读、写等)页表中有256页,所以基表寄存器(BTR)只指向表。
我希望函数返回:

    Success: the physical address (a void*)
    Page Fault: the virtual page number (an integer)
    Protection Fault: a copy of the PTE

以下是页表条目:
    31    30..28 27..............................................4 3 2 1 0
   +-----+------+-------------------------------------------------+-+-+-+-+
   |Valid|unused| 24-bit Physical Page Number                     |P|R|W|X|
   +-----+------+-------------------------------------------------+-+-+-+-+

我正在努力学习虚拟内存是如何工作的我很困惑如何获取16位虚拟地址并将其映射到32位页表条目,然后如何从中获取物理地址我已经定义了result_t和下面的页表条目的联合,但是我不确定如何使用它们我从网上得到了很多帮助,但一切都变得一团糟,我只想知道一切都是如何直接工作的。
以下是一些必要的定义:
  extern void* BTR;

  typedef struct result_st {
     enum {SUCCESS, PAGEFAULT,
                PROTFAULT, NOTIMPLEMENTED} status;
     union {
         void* pa;
         unsigned vpn;
         unsigned pte;
     } value;

    } result_t;
  static result_t success(void* pa) {

      result_t res;
      res.status=SUCCESS;
      res.value.pa = pa;
      return res;
    }

  typedef union {
      unsigned All;
      struct {
        unsigned Valid               :1;
        unsigned Unused              :3;
        unsigned PhysicalPageNumber  :24;
        unsigned SupervisoryMode     :1;
        unsigned Read                :1;
        unsigned Execute             :1;
        unsigned Write               :1;

      };
    } PageTableEntry;

  static int is_valid (unsigned pte) {

        return 1 & (pte >> 31);
      }

以下是我正在编写的函数:
result_t legacy(unsigned short va)
{
  result_t result;
  unsigned pte = va << 8;
  result.value.pte = pte;
  // This is my attempt so far.
  // I want to use is_Valid() somewhere

  void* pa = pte >> 8 | (va & 255);
    return success(pa);
}

谢谢你的建议!

最佳答案

您缺少实际页表的定义我假设是这样(假设我正确理解了你的问题):

#define PAGE_TABLE_SIZE 256
PageTable page_table[PAGE_TABLE_SIZE];

那么你的代码应该是这样的:
#define VIRT_PAGE_SIZE_BITS 8

/* Get virtual page number by dividing by the virt page size */
unsigned int virt_page_num = va >> VIRT_PAGE_SIZE_BITS;

assert(virt_page_num < PAGE_TABLE_SIZE); // Or do proper error handling

/* Use virtual page number to index into page table */
PageTableEntry pte = page_table[virt_page_num];
if (is_valid(pte)) {
    if (is_access_ok(pte)) {
        unsigned int phys_page_num = pte.PhysicalPageNumber;
        return success(phys_page_num);
    } else {
        /* Protection fault code goes here */
    }
} else {
    /* Page fault code goes here */
}

10-04 22:01