understanding kernel page tables

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I'm trying to understand how memory is laid out in the kernel. Specifically, I have a tool that will let me view physical memory on a host and I'm using that to try to view data structures in the kernel, so I'm starting with a virtual address and translating it to a physical address. As I currently understand it, there's three major regions of linux kernel memory for a typical x86 machine:

#1 -- 0xc0000000 - high_memory (linearly mapped to physical memory)
#2 -- high_memory - 0xfe000000 (paged)
#3 -- 0xfe000000 - 0xffffffff (other random mappings)

I can successfully view memory in region #1. So right now I'm interested in memory region #2. My understanding is that the starting place for the kernel page table mapping is the master kernel page global directory (aka swapper_pg_dir). Given that starting point, here's where I'm at right now...

The first entry below is the 769th entry in the kernel master page global
directory, or put another way, it is equal to swapper_pg_dir[768].  This
is the first entry for kernel memory (the first 768 entries map linear
addresses lower than 0xc0000000).

00000c00| 67 d0 a6 17 67 c0 a6 17 67 b0 a6 17 67 70 5a 3a g...g...g...gpZ: 00000c10| 67 50 9b 3b 67 70 11 1b 67 f0 f9 39 67 00 07 1c gP.;gp..g..9g... 00000c20| 67 80 28 3f 67 40 91 3b 67 70 f8 2a 67 20 49 3b g.(? g@.;gp.*g I; 00000c30| 67 e0 0a 02 67 90 3e 12 67 e0 3e 12 67 60 dc 07 g...g.>.g.>.g`.. 00000c40| 67 90 3d 12 67 d0 3a 1b 67 10 64 07 67 b0 e4 0d g.=.g.:.g.d.g... 00000c50| 67 50 ac 02 67 00 fe 06 67 60 87 35 67 20 fb 0b gP..g...g`.5g .. 00000c60| 67 90 35 0f 67 d0 18 0d 67 c0 e9 2a 67 f0 3b 12 g. 5.g...g..*g.;. 00000c70| 67 d0 20 12 67 b0 cc 10 67 d0 35 10 67 c0 39 10 g. .g...g.5.g.9. 00000c80| 67 80 95 10 67 c0 db 10 67 30 e2 10 67 e0 65 11 g...g...g0..g.e. 00000c90| 67 b0 74 11 67 a0 83 11 67 00 90 11 67 b0 e1 11 g.t.g...g...g... 00000ca0| 67 b0 7d 12 67 e0 a4 12 67 10 b0 12 67 30 51 13 g.}.g...g...g0Q. 00000cb0| 67 30 d4 13 67 00 22 14 67 20 36 14 67 f0 35 14 g0..g.".g 6.g.5. 00000cc0| 67 f0 37 14 67 60 4d 14 67 40 fa 14 67 f0 0d 15 g. 7.g`M.g@..g... 00000cd0| 67 60 11 15 67 f0 15 15 67 70 17 15 67 90 72 15 g`..g...gp..g.r. 00000ce0| 67 70 76 15 67 40 7e 15 67 00 7f 15 67 b0 87 15 gpv.g@~.g...g... 00000cf0| 67 a0 8a 15 67 40 d3 15 67 90 d6 15 67 40 44 16 g...g@..g...g@D. 00000d00| 67 80 59 16 67 20 09 17 00 00 00 00 00 00 00 00 g.Y.g .......... 00000d10| 67 f0 91 11 00 00 00 00 00 00 00 00 00 00 00 00 g...............

Note: This system has 256 MB ram; PAE is disabled; and is running 2.6.12.

The bottom 12 bits of each entry are flags as follows:
#define _PAGE_PRESENT   0x001
#define _PAGE_RW        0x002
#define _PAGE_USER      0x004
#define _PAGE_PWT       0x008
#define _PAGE_PCD       0x010
#define _PAGE_ACCESSED  0x020
#define _PAGE_DIRTY     0x040
#define _PAGE_PSE 0x080 /* 4 MB (or 2MB) page, Pentium+, if present.. */
#define _PAGE_GLOBAL    0x100   /* Global TLB entry PPro+ */
#define _PAGE_UNUSED1   0x200   /* available for programmer */
#define _PAGE_UNUSED2   0x400
#define _PAGE_UNUSED3   0x800

The rest *should* be the physical address, but that doesn't really seem to make sense to me. For example, look at the last entry in the table:
0x1191f067

Flags Set:
-- _PAGE_PRESENT
-- _PAGE_RW
-- _PAGE_USER
-- _PAGE_ACCESSED
-- _PAGE_DIRTY

Looking at this without the flags:
0x1191f067 & 0xfffff000 = 0x1191f000

Coverting this to a virtual address:
0x1191f000 + 0xc0000000 = 0xd191f000

But this value is above the high_memory line for this computer:
high_memory = 0xd0800000

So why does an entry in the kernel master global directory point to an address that is not linearly mapped (i.e., not between 0xc0000000 and high_memory)? From this, it looks like I'd have to go back into the page tables to resolve that memory address, but it seems wrong that I'd have to use page tables to complete a page table lookup. Right now, that's the point that I'm stuck on.

So my real question is, where has my reasoning gone astray? Am I interpreting the memory values wrong or is my understanding of the memory regions wrong or ???

Thanks,
bryan



--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux