2

I'm learning/tinkering with kernel memory management on x86-64 linux. I wanted to look at the beginning of the page directory pointed to by cr3 using the asm code below but dereferencing cr3 causes the kernel to lock-up. What's the proper way to access what cr3 points to? Note I know I need to be in ring 0 hence the code is a small kernel module (kmod.S):

.globl init_module
.globl cleanup_module

.text
init_module:
    nop
    movq    $ENTER_MSG,     %rdi
    movq    %cr3,           %rsi
    movq    (%rsi),         %rdx
    xorq    %rax,           %rax
    callq   printk
    xorq    %rax,           %rax
    retq

cleanup_module:
    nop
    movq    $LEAVE_MSG,     %rdi
    xorq    %rax,           %rax
    callq   printk
    retq

.section .rodata
ENTER_MSG:
    .asciz "\n\nHELLO! CR3: %p, (CR3): %p\n"
LEAVE_MSG:
    .asciz "GOODBYE!\n\n"

And compiled using the folling Makefile:

obj-m += kmodule.o
kmodule-objs := kmod.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
boneheadgeek
  • 765
  • 1
  • 7
  • 9
  • 1
    `%cr3` contains a _physical address_. See http://stackoverflow.com/questions/11621911/mapping-physical-addresses-to-virtual-address-linux for how you can "make this visible". You need to create a temporary mapping. – FrankH. Jul 30 '13 at 22:22
  • Even the kernel is prevented from using a physical address? What if I'm writing my own OS, at some point don't I need a physical address? Thanks FrankF. – boneheadgeek Jul 31 '13 at 01:00
  • Not related your question so I hope this won't be considered spamming, but may I ask how are you compiling this? – Fingolfin Jul 31 '13 at 06:37
  • 1
    Adel Qodmani, I editted the original question to add the makefile I used. – boneheadgeek Jul 31 '13 at 12:59
  • 1
    @boneheadgeek no the kernel is not _prevented_ from using a physical address; merely, the _only way to use a physical address_ is to ... create a virtual address that maps to it. There is no mechanism in x86 CPUs that allows to "directly load/store to/from a physical address". Therefore ... as said, read the other posting about how to access this memory. – FrankH. Jul 31 '13 at 14:25
  • 3
    @boneheadgeek to clarify, there is one way of directly using the physical address, and that is to _disable the MMU_ (clear bit 31 in `%cr0`). Doing so, even temporarily, is _never safe_ in Linux except for very specific codepaths, because any interrupt and/or IPI would crash were it to occur during the window the MMU is off. So, for pedantisms sake ... you can do it, but the right way of doing it is ... to create a temporary mapping. – FrankH. Jul 31 '13 at 14:30

1 Answers1

3

The contents of the CR3 register are for the CPU, not for the kernel.

Software always uses virtual addresses. If you want to access the page tables, you should use the helper macros in <asm/page.h>; for details, see Page Table Management (although it's somewhat outdated).

CL.
  • 173,858
  • 17
  • 217
  • 259
  • Thanks @CL. This along with FrankH response helped me figure out how to get what I wanted. Turns out it is sufficient (in kernel mode) to add PAGE_OFFSET to CR3's physical address in order to get to the associated page table. I'd upvote but not enough points yet. Thanks! – boneheadgeek Aug 01 '13 at 16:15
  • @CL. I believe the contents of CR3 being "meant for the CPU" implies it is for use by the hardware page table walker (the MMU) to traverse this multi-level page table right? So as I see it, there must be some other mechanism to ensure that the physical page which contains the page directory (PGD) is not swapped out to disk. How does that work? If the kernel simply chose to lock all pages containing the PGD for all processes in the run queue, it would consume a lot of RAM. So how is it done? Could you please give me an example of some commodity OS like Linux/Windows/*BSD? – AjB Aug 17 '15 at 08:55
  • Swapping and scheduling are done by the OS, not by the CPU. And to ask a question, use the "Ask Question" button. – CL. Aug 17 '15 at 10:47