IA32 Paging Scheme Introduction to the Pentium’s support for “virtual” memory

advertisement
IA32 Paging Scheme
Introduction to the Pentium’s
support for “virtual” memory
A quick review
•
•
•
•
•
We’ve learned how to create ‘/proc’ files
We wrote a simple device-driver: ‘dram.c’
We displayed a task’s page-directory
We looked at Linux’s ‘mem_map[]’ array
Now we want to understand the ‘kmap()’
function, used by modules to get a virtual
address for any physical page-frame
‘Traditional’ Linux
0x38000000
(896MB)
0x00000000
HIGH MEMORY
NORMAL
MEMORY
Kernel
space
1G
User
space
3G
Physical addresses
Most of the kernel’s 1GB address-space is
directly mapped to physical RAM at all times
But mappings to the ‘high memory’ page-frames
are, by definition, only temporarily available and
are not mapped according to a predictable rule
Virtual addresses
How ‘mappings’ work
• There are two aspects to consider:
– the Pentium’s address-translation mechanism
– the policies Linux applies to CPU capabilities
• Example of this distinction:
– The ‘page-directory’ array is a Pentium object
– The ‘mem_map’ array is a Linux data-object
Control Register 4
This register consists of bits that enable various architectural
extensions to the standard features of the Pentium processor,
including two that affect virtual-to-physical memory mapping.
31
5 4
0
P P
A S
E E
Legend:
PSE = Page-Size Extensions (1=enabled, 0=disabled)
PAE = Page-Address Extensions (1=enabled, 0=disabled)
Recall that we saw our classroom workstations had CR4 = 000006D0
Two-Level Translation Scheme
PAGE
DIRECTORY
CR3
PAGE
TABLES
PAGE
FRAMES
Control Register 3
31
12
Page-directory base-address
4 3
P P
C W
D T
The ‘page-directory base-address’ field holds the upper 20 address-bits of a
physical page-frame that contains the current task’s page-directory entries;
the lower 12 address-bits of any page-frame are zeros, of course, so can be
used by the processor for other purposes (i.e., PCD [bit 4] and PWT [bit 3]:
PWT = Page Write-Through (1=yes, 0 = no)
PCD = Page Cache-Disable (1 = yes, 0 = no)
Your ‘/proc/cr3’ pseudo-file
• Recall that you created a kernel module
(named ‘cr3.c’) which allows applications
to obtain the current value in register CR3
• This CR3 value gives the physical address
for the current task’s page-directory, if the
‘traditional’ 3G/1G user-kernel mapping is
employed (but not with the 4G/4G “patch”)
• Using ‘fileview’ you saw a page-directory!
Format of a Page-Directory entry
31
PAGE-TABLE BASE ADDRESS
12 11 10 9 8 7 6 5 4 3 2 1 0
P P
P
AVAIL G
0 A C W U W P
S
D T
LEGEND
P = Present (1=yes, 0=no)
W = Writable (1 = yes, 0 = no)
U = User (1 = yes, 0 = no)
A = Accessed (1 = yes, 0 = no)
G = Global (1 = yes, 0 = no)
PS = Page-Size (0=4KB, 1 = 4MB)
PWT = Page Write-Through (1=yes, 0 = no)
PCD = Page Cache-Disable (1 = yes, 0 = no)
Format of a Page-Table entry
31
PAGE-FRAME BASE ADDRESS
12 11 10 9 8 7 6 5 4
P
AVAIL G 0 D A C
D
LEGEND
P = Present (1=yes, 0=no)
W = Writable (1 = yes, 0 = no)
U = User (1 = yes, 0 = no)
A = Accessed (1 = yes, 0 = no)
D = Dirty (1 = yes, 0 = no)
G = Global (1 = yes, 0 = no)
PWT = Page Write-Through (1=yes, 0 = no)
PCD = Page Cache-Disable (1 = yes, 0 = no)
3 2 1 0
P
W U W P
T
kernel mappings
• The ‘kmap()’ function is used by modules
to obtain the virtual address for a physical
page-frame:
void * kmap( struct page * page );
• On systems with 1GB of installed memory,
the majority of physical page-frames are
permanently mapped to kernel addresses,
but page-frames in ‘high’ memory can only
be ‘temporarily’ mapped into kernel space
Normal page-mapping
• For a virtual address in kernel space that
is below the high-memory start-address,
the corresponding physical address can
be gotten by a simple subtraction:
phys_addr = virt_addr – PAGE_OFFSET
• Recall: PAGE_OFFSET = 0xC0000000
Mapping ‘high’ memory
• For addresses in kernel space in the range
from 0xF8000000 to 0xFFFFFFFF
there might be no current mapping to ram
• So the action of the ‘kmap()’ function must
be more complex in these cases (i.e., it’s
necessary to create a temporary mapping
if it happens one does not already exist)
A limited number of kmaps
• In kernel 2.6 there is only one page-table
that is reserved for ‘kmap()’ to use when
temporary mappings into high-memory
need to be created
• This is called the ‘kmap_page_table’
• Its page-table entries are forever changing
as kernel code calls the functions ‘kmap()’
and ‘kunmap()’
PKMAP_BASE
• We can watch the ‘kmap_page_table’ as it
undergoes these dynamic changes – if we
know where to find it in physical memory
• We can do a ‘page-table walk’ to locate it
• There are 1024 virtual page-frames used
for temporary ‘kmap()’ addresses, starting
with the virtual address PKMAP_BASE
In-class exercise #1
• Use the ‘init_mm.c’ module to locate the
page-directory belonging to the ‘init’ task
• Use ‘fileview’ to see these directory entries
• Determine the value of PKMAP_BASE
• Which directory-entry contains the address
of the ‘pkmap_page_table’? (It’s the entry
that ‘maps’ virtual-address PKMAP_BASE
to a page-frame in physical memory)
In-class exercise #2
• Use the result from your ‘page-table walk’
to assign the correct value to ‘zone_base’
in our ‘kmapsnow.cpp’ demo-program
• Run the ‘kmapsnow’ in one window while
you execute some other commands from
inside a different window, to view changes
in the set of currently active kmaps
• Log in remotely from an adjacent station
Download