Windows system PTE

> The 4MB range starting at C0300000 up to C0400000 (i.e the one described by page directory’s 768th entry) is unusable because this entry is reserved for accessing page directory itself

It is not so clear to me why this 768th entry “is reserved for accessing page directory itself”…What do you mean ?

> It is not so clear to me why this 768th entry “is reserved for accessing page directory itself”…

What do you mean ?

Duh…

I thought you had finally made it. However, now, again, it looks you are still at the Stage 0…

Anton Bassov

xxxxx@alice.it wrote:

> The 4MB range starting at C0300000 up to C0400000 (i.e the one described by page directory’s 768th entry) is unusable because this entry is reserved for accessing page directory itself
It is not so clear to me why this 768th entry “is reserved for accessing page directory itself”…What do you mean ?

The page directory is at C0300000. The 768th entry would be at offset
0xC00. The entry at that offset in the page directory (at address
C0300C00) would be the page table entry for the page at 0xC0300000,
which is the page directory itself. It’s self-referential.

This is really more of a mind puzzle than a useful piece of Windows trivia.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Maybe there is something not clear to me…

in my understanding range starting at C0000000 up to C0400000 (4MB) is described by 768’th page directory entry (1024 entries in page directory table interpreted as PTE’s describe the 1024 pages 4KB each in this range). Now of these 1024 page tables the first 512 page tables describe 2GB user space while last 512 should describe 2GB kernel space…

…Maybe the clue is this

page tables in 4MB range C0000000 - C03FFFFF (including process page directory) are per-process page tables; the subset of these page tables that describe system address range (80000000 - FFFFFFFF) in turn should be significant only for the process itself…

Thanks for your help…

If you think about it a bit you will realize that this explanation just defeats the common sense as long as there are only 3 levels of translation - if it worked this way every app would have its own view of kernel. Things could work this way with translation levels >=4, but still it would be a waste of memory on topmost page tables…

Anton Bassov

> Therefore, if you take a 2MB physical range (i.e 512 physical pages), fill its 384th page with the physical addresses of all pages in this range (i.e 0th goes to 0th entry, 1st to 1st…, 384thh to 384th,…511th to 511th), and write the address of this page into page directory’s 900th entry, you will be able to access the system PTE’s as the virtual addresses…

So, IIUC, in the 2MB range E1000000 - E11FFFFF (with 4KB hole for the map itself at E1180000) we have system PTE’s (i.e. 512 physical pages Anton was talking about…)

Now these system PTE’s are used as “dynamic entries” in which insert (when needed) physical addresses af MDL, I/O memory range ecc ?

Thanks…

> Now these system PTE’s are used as “dynamic entries” in which insert (when needed) physical

addresses af MDL, I/O memory range ecc ?

They are updated to point at proper physical addresses.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Well…now what is not so clear to me :slight_smile:

Consider for instance a system PTE entry filled with the physical address of a buffer (described by an MDL).

My question is…Which virtual addresses code running in the system (e.g. driver code) has to use to access this buffer ?

> My question is…Which virtual addresses code running in the system (e.g. driver code) has

to use to access this buffer ?

Well, if we assume the mapping I have suggested earlier is correct ( I have no info about it), then the virtual
kernel address can be calculated, given the PTE virtual address, as
0x80000000 + ((PTE_address - 0xE1000000)<<10). If we don’t make assumptions like that and stick with.
0xC0000000-0xC0400000 range, it can be calculated as ((PTE_address - C0000000)<<10)

Anton Bassov

> 0xC0000000-0xC0400000 range, it can be calculated as ((PTE_address - C0000000)<<10)

This assumes no PAE. (Not a criticism, just a comment.)

> This assumes no PAE.

Sure - we are speaking about the system with just 3-level translation on this thread…

Anton Bassov

> 0xC0000000-0xC0400000 range, it can be calculated as ((PTE_address - C0000000)<<10)

if pte_address is in the range E1000000 - E11FFFFF I think the calculated range should be 0xC0200000-0xC0400000 (2MB range)

xxxxx@alice.it wrote:

Well…now what is not so clear to me :slight_smile:

Consider for instance a system PTE entry filled with the physical address of a buffer (described by an MDL).

My question is…Which virtual addresses code running in the system (e.g. driver code) has to use to access this buffer ?

You’re thinking about this backwards. You don’t start with a PTE
entry. Instead, a driver decides it needs some memory. It calls a
kernel API, which returns a pointer or an MDL. In between, the
operating system has created whatever PTE entries might have been
required to satisfy that request.

The driver uses the pointer or the MDL that it was given to access that
memory.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I think you’re getting confused by the “system PTEs” name. There are no actual PTEs in the “system PTEs” range (or ranges, since there may be more than one). Let me quote an earlier reply from Ken:

“System PTEs” are used to satisfy various kernel allocations
that are broken up into multiples of page-size chunks (i.e.
which have a whole number of PTEs assigned to map them).
It’s best to think of them as used to back a general
allocator for PAGE_SIZE regions.

That’s all there really is to it. When you call MmGetSystemAddressForMdlSafe (or MmMapIoSpace, or MmAllocateContiguousMemory etc) you get back a virtual address from a “system PTEs” VA range. The PTEs mapping that range will be in the same PTE region as everything else (e.g. somewhere in the 0xc0000000 - 0xc03fffff range on x86 non-PAE).

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@alice.it
Sent: Friday, April 27, 2012 1:42 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Windows system PTE

So, IIUC, in the 2MB range E1000000 - E11FFFFF (with 4KB hole for the map itself at E1180000) we have system PTE’s (i.e. 512 physical pages Anton was talking about…)

Now these system PTE’s are used as “dynamic entries” in which insert (when needed) physical addresses af MDL, I/O memory range ecc ?

> This assumes no PAE.

Sure - we are speaking about the system with just 3-level translation on this thread…

Does Win7 even support non-PAE mode anymore?

By the way, x64 does a great trick on system mapping for MDL: any buffer not crossing a page boundary (or contiguous by chance) can use an address from the whole RAM premapped in some region. So no page table modification is necessary then.

> My question is…Which virtual addresses code running in the system (e.g. driver code) has to use to

access this buffer ?

By default, MDLs do NOT provide the way to access the data by pointer.

If the driver needs this - then it maps the MDL to kernel space (system PTEs).

After this, the mapped address returned by MmGetSystemAddressForMdlSafe will be usable by the driver as a data pointer.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

> Sure - we are speaking about the system with just 3-level translation on this thread…

PAE on 32bit is 3-level, with upper level having only 4 entries - 8byte PTEs, upper level describes 4 PDs with 512 PDEs each, of a total of 2K PDEs. Each PDE describes a PT with 512 PTEs, so, 1M PTEs == 4G of address space.

Non-PAE on 32bit is 2-level - 4byte PTEs, 1024 PDEs per a single PD describing 1024 PTs, 1024 PTEs per each PT, so, 1M PTEs == 4G of address space.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

> By the way, x64 does a great trick on system mapping for MDL: any buffer not crossing a page

boundary (or contiguous by chance) can use an address from the whole RAM premapped in some
region.

More so: NT4 and IIRC pre-Vista x86 OSes premap the 512M of RAM as identity mapping from 0xc0000000 up, doing the same trick.

The kernel variable which is the boundary of this premapped memory was called like MmKSeg0Frame or MmKSeg2Frame, forgotten this.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

> PAE on 32bit is 3-level

Non-PAE on 32bit is 2-level

You seem to discard the final part of the translation, i.e. adding the actual offset into the page. Although
this stage already does not involve page tables, it is still a part of the translation…

Anton Bassov