【问题标题】:Bit-Shifting to find the Page Table Entry for a given Virtual Address in Linux在 Linux 中为给定虚拟地址查找页表条目的位移
【发布时间】:2015-12-07 20:12:07
【问题描述】:

我正在使用 Linux 3.18.20 的简化版本,我需要创建两个新的系统调用:一个读取给定虚拟地址的页表条目,另一个写入对应的页表条目给定的虚拟地址。我一直在使用英特尔架构参考手册,卷。 3,第4章,第5节,为了了解虚拟地址如何转换为物理地址,并且为了实现我的系统调用,我创建了一个帮助函数,它返回所请求页表条目的虚拟地址(或NULL,如果该页表条目不存在)。

我创建了一个测试程序,它创建了一个局部变量(大概存储在堆栈上,对吗?)并将其虚拟地址传递给我的系统调用,以确保我的翻译正确完成。然后我手动完成所有位移,以确保我的代码执行我认为的操作;而且似乎是正确的,所以在这一点上我唯一能得出的结论就是我不知道我不知道什么;我需要一条我什至没有意识到自己需要的重要信息。

你能看看我的代码并告诉我是否有明显的错误吗?

unsigned long *find_pte(unsigned long vaddr) {
    unsigned long cr3, pml4_addr, pml4e, pml4e_addr;
    unsigned long pdpt_addr, pdpte_addr, pdpte;
    unsigned long pd_addr, pde_addr, pde;
    unsigned long pt_addr, pte_addr;
    unsigned long vaddr30thru38, vaddr39thru47, vaddr21thru29, vaddr12thru20;

    cr3 = (unsigned long) get_pagetable();
    /* get_pageable() is a helper function, provided by my professor,
    that supposedly returns the contents of the CR3 register, with the most
    significant and least significant 12 bits replaced with 0.*/
    printk("in syscall: vaddr=%lx, cr3=%lx\n", vaddr, cr3);//DEBUG
    pml4_addr = cr3;
    vaddr39thru47 = (vaddr >> 36) & 0xff8;
    printk("in syscall: vaddr39thru47=%lx\n", vaddr39thru47);//DEBUG
    pml4e_addr = pml4_addr | vaddr39thru47;
    printk("in syscall: physical pml4e_addr=%lx\n", pml4e_addr);//DEBUG
    pml4e_addr = (unsigned long) __va(pml4e_addr);
    printk("in syscall: virtual pml4e_addr=%lx\n", pml4e_addr);//DEBUG
    pml4e = *((unsigned long*) pml4e_addr);
    printk("in syscall: pml4e=%lx\n", pml4e);//DEBUG
    if ((pml4e & 1) == 0) {
            printk("in syscall: pml4e's valid bit is not set\n");//DEBUG
            return NULL;
    }
    printk("in syscall: pml4e's valid bit is set\n");//DEBUG

    vaddr30thru38 = (vaddr >> 27) & 0xff8;
    printk("in syscall: vaddr30thru38=%lx\n", vaddr30thru38);
    pdpte_addr = (pdpt_addr | vaddr30thru38);
    printk("in syscall: physical pdpte_addr=%lx\n", pdpte_addr);//DEBUG
    pdpte_addr = (unsigned long) __va(pdpte_addr);
    printk("in syscall: virtual pdpte_addr=%lx\n", pdpte_addr);//DEBUG
    pdpte = *((unsigned long*) pdpte_addr);
    printk("in syscall: pdpte=%lx\n", pdpte);//DEBUG
    if (((pdpte >> 7) & 1) == 1) {
            printk("in syscall: pdpte's ps flag is 1\n");//DEBUG
            return (unsigned long*) pdpte_addr;
    }
    printk("in syscall: pdpte's ps flag is 0\n");//DEBUG
    if ((pdpte & 1) == 0) {
            printk("in syscall: pdpte's valid bit is not set\n");//DEBUG
            return NULL;
    }
    printk("in syscall: pdpte's valid bit is set\n");//DEBUG
    pd_addr = pdpte & 0x000ffffffffff000;
    printk("in syscall: pd_addr=%lx\n", pd_addr);//DEBUG
    vaddr21thru29 = (vaddr >> 18) & 0xff8;
    printk("in syscall: vaddr21thru29=%lx\n", vaddr21thru29);//DEBUG
    pde_addr = pd_addr | vaddr21thru29;
    printk("in syscall: physical pde_addr=%lx\n", pde_addr);//DEBUG
    pde_addr = (unsigned long) __va(pde_addr);
    printk("in syscall: virtual pde_addr=%lx\n", pde_addr);//DEBUG
    pde = *((unsigned long*) pde_addr);
    printk("in syscall: pde=%lx\n", pde);//DEBUG
    if (((pde >> 7) & 1) == 1) {
            printk("in syscall: pde's ps flag is 1\n");//DEBUG
            return (unsigned long*) pde_addr;
    }
    printk("in syscall: pde's ps flag is 0\n");//DEBUG
    if ((pde & 1) == 0) {
            printk("in syscall: pde's valid bit is not set\n");//DEBUG
            return NULL;
    }
    printk("in syscall: pde's valid bit is set\n");//DEBUG
    pt_addr = pde & 0x000ffffffffff000;
    printk("in syscall: pt_addr=%lx\n", pt_addr);//DEBUG
    vaddr12thru20 = (vaddr >> 9) & 0xff8;
    printk("in syscall: vaddr12thru20=%lx\n", vaddr12thru20);//DEBUG
    pte_addr = pt_addr | vaddr12thru20;
    printk("in syscall: physical pte_addr=%lx\n", pte_addr);//DEBUG
    pte_addr = (unsigned long) __va(pte_addr);
    return (unsigned long*) pte_addr;

【问题讨论】:

    标签: linux kernel paging


    【解决方案1】:

    没关系。我的代码没有任何问题(除了遗漏了一行,这是将代码从我的文件复制到 Stack Overflow 时的错误)。我的测试错误地将其标记为损坏。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-23
      • 2012-09-05
      • 2021-07-25
      • 2015-06-18
      • 2015-07-09
      • 2018-01-29
      • 2012-01-18
      • 2014-05-18
      相关资源
      最近更新 更多