2015-12-07 1 views
1

Я работаю с упрощенной сборкой Linux 3.18.20, и мне нужно создать два новых системных вызова: один, который читает запись в таблице страниц для данного виртуального адреса, и тот, который записывает запись в таблицу страниц, соответствующую данному виртуальному адресу. Я использую Справочное руководство по архитектуре Intel, том. 3, глава 4, раздел 5, чтобы понять, как виртуальные адреса преобразуются в физические адреса, и для реализации моих системных вызовов я создал вспомогательную функцию, которая возвращает виртуальный адрес запрашиваемой записи таблицы страниц (или NULL, если эта запись в таблице страниц не существует).Bit-Shifting для поиска записи таблицы страниц для данного виртуального адреса в Linux

Я создал тестовую программу, которая создает локальную переменную (предположительно сохраненную в стеке, правильно?) И передает свой виртуальный адрес моему системному вызову, чтобы убедиться, что мой перевод выполнен правильно. Затем я делаю все, что нужно сделать, чтобы убедиться, что мой код делает то, что я думаю; и это кажется правильным, поэтому единственный вывод, который я могу прийти к этому вопросу, заключается в том, что я не знаю, чего я не знаю; Мне нужна важная информация, которую я даже не понимал, что мне нужно.

Можете ли вы посмотреть на мой код и рассказать мне, есть ли что-то очевидное, что я делаю неправильно?

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; 

ответ

1

Ничего. В моем коде нет ничего плохого (кроме пропуска одной строки, что было ошибкой при копировании кода из моего файла в Stack Overflow). Мой тест неправильно маркировал его как сломанный.

Смежные вопросы