Experiment 5: memory paging
Corresponding book P199 page 5.2
1. Summary of relevant basic knowledge
Page directory page directory item page table page table item physical page virtual address physical address
Concept Brief
Page directory entries and page table entries
The lower 3 bytes are attributes. The upper 20 bits are physical addresses.
This experiment
Virtual address: 32 bits = 4GB
Physical address: 32MB (but the real address accessible under the paging mechanism is only 1MB lower). 32MB is the test result of the memory capacity of the last experiment.
Physical page size: 4kB
One page table size: 4kB
One page table item size: 4B
A page table has 1024 page table entries
Therefore, a page table can represent 1024*4kB=4MB of virtual memory
One page directory size: 4kB
One page directory entry size: 4B
A page directory has 1024 page directory entries
Therefore, the page directory can represent 4MB*1024=4GB virtual memory
According to the physical page size, the number of 4B page table items is 2 ^ 10
Number of page directory entries 2 ^ 10,
Virtual addresses can be divided into
10 digits | 10 digits | 12 digits |
---|---|---|
Page directory entry index | Page entry index | Intra block offset |
From the above table, the formula for converting virtual address into physical address is very clear.
The upper 10 bits represent that the virtual address will access the page directory entries of the page directory, so as to obtain the first 20 bits of the page directory entry, that is, the first address of the corresponding page table.
The middle 10 bits represent that the virtual address will access the page table entries of the page table, so as to obtain the first 20 bits of the page table entry, that is, the first address of the corresponding physical page.
The last 12 bits represent the offset of the physical page
The obtained physical header address plus the last 12 bit offset is the physical address corresponding to the virtual address.
2. Experimental records
2.1 experimental purpose
1. Construct page directory and page table, complete the mapping from virtual address 3GB~3GB+1MB to real address 0 ~1MB, and the mapping from virtual address 0 ~1MB to physical address 0 ~1MB.
[note] you are not mistaken, which means that the virtual address 3GB and virtual address 0 will be transformed into the same physical address 0 in this experiment
2. Turn on the protection mode and the paging mechanism of the protection mode
3. Modify the segment base address in the GDTR and the segment base address in the segment descriptor of the video memory to ensure the code
mov byte [gs:160],'V'
[gs:160] in [gs:160] will spell out the virtual address 0xc00b800+160 under the segmentation mechanism and paging mechanism of protection mode. Obviously, this address is between 3GB~3GB+1MB virtual addresses.
4. Execute the above sentence code, which is equivalent to writing the ASCLL code of character 'V' to the virtual address 0xc00b800+160,
In the third step, we set up the paging mechanism of protection mode, and the cpu will automatically convert the virtual address provided into physical address and then access the memory.
Therefore, this experiment can detect whether the virtual address can be automatically converted into 0xb800 in 1MB of the real address (i.e. the first address in video memory text mode) according to the page table and page directory defined by ourselves under the paging mechanism of protected mode
If bochs simulation is used, the character V can be printed on the display screen, indicating that the virtual address is successfully transformed into physical address, and the test is successful.
2.2 precautions for this experiment
In this experiment, 1024 page directory items can be constructed
1024 page table entries can also be constructed for each page table
But it should be noted that
1... When constructing the page directory, our code only constructs the 0th page directory item and the 768th ~ 1023rd page directory item. The 0 and 768th directory items are the first address of the 0 page table. The 1023rd page directory item contains the first address of the page directory. The table of contents items on pages 769 to 1022 contain the first address of the table of pages 1 to 254.
2. When constructing the page table, we only constructed the first 256 page table items in the 0-th page table. Because a physical page is 4KB, the real address that can be accessed under the paging mechanism is only 1MB lower, 256*4KB=1MB.
According to the above two points, we can also get a message that needs attention
One page directory entry represents 4MB of virtual memory,
The 0 and 768th directory items are the first address of the 0 page table,
The directory entry on page 768 represents 4MB768=4MB256*3=3GB
Therefore, this experiment only completed the virtual address 3GB~3GB+1MB
The mapping of real address 0~1MB and the mapping of virtual address 0~1MB to real address 0~1MB.
3. The first address of the page directory of this experiment is 0x100000, i.e. 1MB.
The first address of the table on page 0 is 0x101000, i.e. 1MB+4KB
Reason for this setting: low 1MB is used to install MBR s,loader.s and kernel.
4. In this experiment, 3GB~3GB+1MB virtual addresses are mapped to lower 1MB physical addresses in turn, that is, in 3GB~3GB+1MB virtual addresses, the physical address corresponding to the small virtual address must be small.
2.3 experimental code
boot.inc increase
;------------- Page table configuration ---------------- PAGE_DIR_TABLE_POS equ 0x100000 ;---------------- Page table related properties -------------- PG_P equ 1b PG_RW_R equ 00b PG_RW_W equ 10b PG_US_S equ 000b PG_US_U equ 100b
loader.s
%include "boot.inc" section loader vstart=LOADER_BASE_ADDR LOADER_STACK_TOP equ LOADER_BASE_ADDR ;structure gdt And its internal descriptor GDT_BASE: dd 0x00000000 dd 0x00000000 CODE_DESC: dd 0x0000FFFF dd DESC_CODE_HIGH4 DATA_STACK_DESC: dd 0x0000FFFF dd DESC_DATA_HIGH4 VIDEO_DESC: dd 0x80000007 ; limit=(0xbffff-0xb8000)/4k=0x7 dd DESC_VIDEO_HIGH4 ; here dpl Is 0 GDT_SIZE equ $ - GDT_BASE GDT_LIMIT equ GDT_SIZE - 1 times 60 dq 0 ; 60 descriptor spaces are reserved here(slot) SELECTOR_CODE equ (0x0001<<3) + TI_GDT + RPL0 ; amount to(CODE_DESC - ;GDT_BASE)/8 + TI_GDT + RPL0 SELECTOR_DATA equ (0x0002<<3) + TI_GDT + RPL0 ; ditto SELECTOR_VIDEO equ (0x0003<<3) + TI_GDT + RPL0 ; ditto ; total_mem_bytes Used to save memory capacity,In bytes,This position is easy to remember. ; Current offset loader.bin File header 0 x200 byte,loader.bin The loading address of is 0 x900, ; so total_mem_bytes The address in memory is 0 xb00.We will refer to this address in the kernel in the future total_mem_bytes dd 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;The following is the definition gdt The first two bytes are gdt Boundary, the last 4 bytes are gdt Starting address gdt_ptr dw GDT_LIMIT dd GDT_BASE ;Manual alignment:total_mem_bytes4 byte+gdt_ptr6 byte+ards_buf244 byte+ards_nr2,256 bytes in total ards_buf times 244 db 0 ards_nr dw 0 ;For recording ards Number of structures loader_start: ;------- int 15h eax = 0000E820h ,edx = 534D4150h ('SMAP') Get memory layout ------- xor ebx, ebx ;On the first call, ebx The value should be 0 mov edx, 0x534d4150 ;edx It is only assigned once and will not change in the loop body mov di, ards_buf ;ards Structure buffer .e820_mem_get_loop: ;Loop to get each ARDS Memory range description structure mov eax, 0x0000e820 ;implement int 0x15 after,eax The value becomes 0 x534d4150,So every time int ;It should be updated to sub function number before. mov ecx, 20 ;ARDS The size of address range descriptor structure is 20 bytes int 0x15 jc .e820_failed_so_try_e801 ;if cf If the bit is 1, an error occurs. Try 0 xe801 Subfunction add di, cx ;send di Add 20 bytes to point to the new in the buffer ARDS Structure location inc word [ards_nr] ;record ARDS quantity cmp ebx, 0 ;if ebx 0 and cf Not 1,This shows ards Return all. It is the last one at present jnz .e820_mem_get_loop ;At all ards In the structure, find out(base_add_low + length_low)The maximum value of, that is, the capacity of memory. mov cx, [ards_nr] ;Traverse each ARDS structural morphology,The number of cycles is ARDS Number of mov ebx, ards_buf xor edx, edx ;edx Maximum memory capacity,Clear 0 here first .find_max_mem_area: ;No judgment type Is 1,The largest block of memory must be available mov eax, [ebx] ;base_add_low add eax, [ebx+8] ;length_low add ebx, 20 ;Points to the next in the buffer ARDS structure cmp edx, eax ;Bubble sort to find the largest,edx Registers are always the maximum memory capacity jge .next_ards mov edx, eax ;edx Is the total memory size .next_ards: loop .find_max_mem_area jmp .mem_get_ok ;------ int 15h ax = E801h Get memory size,Maximum support 4 G ------ ; After return, ax cx Same value,with KB Unit,bx dx Same value,With 64 KB Unit ; stay ax and cx Low 16 in register M,stay bx and dx 16 in register MB To 4 G. .e820_failed_so_try_e801: mov ax,0xe801 int 0x15 jc .e801_failed_so_try88 ;If current e801 Method failed,Just try 0 x88 method ;1 First calculate the low 15 M Memory,ax and cx Zhongshiyi KB Amount of memory in,Convert it to byte Unit mov cx,0x400 ;cx and ax Same value,cx Used as a multiplier mul cx shl edx,16 and eax,0x0000FFFF or edx,eax add edx, 0x100000 ;ax Just 15 MB,So add 1 MB mov esi,edx ;Lower it by 15 first MB Memory storage esi Register backup ;2 Add 16 more MB The above memory is converted to byte Unit,register bx and dx The middle is 64 KB Amount of memory in xor eax,eax mov ax,bx mov ecx, 0x10000 ;0x10000 64 decimal KB mul ecx ;32 Bit multiplication,The default multiplier is eax,The product is 64 bits,High 32-bit storage edx,Low 32-bit storage eax. add esi,eax ;Because this method can only measure 4 G Memory within,So 32 bits eax that's enough,edx Must be 0,Only add ;eax Then mov edx,esi ;edx Is the total memory size jmp .mem_get_ok ;----------------- int 15h ah = 0x88 Get memory size,Only 64 can be obtained M within ---------- .e801_failed_so_try88: ;int 15 After, ax Deposited in kb Memory capacity in mov ah, 0x88 int 0x15 jc .error_hlt and eax,0x0000FFFF ;16 Multiplicative, multiplicative ax,The product is 32 bits.The upper 16 bits of the product are dx In, the lower 16 bits of the product are ax in mov cx, 0x400 ;0x400 Equal to 1024,take ax Replace the memory capacity in with byte Unit mul cx shl edx, 16 ;hold dx Move to high 16 bits or edx, eax ;Combine the lower 16 bits of the product into edx,Is the product of 32 bits add edx,0x100000 ;0x88 The subfunction will only return 1 MB More memory,Therefore, the actual memory size should be added with 1 MB .mem_get_ok: mov [total_mem_bytes], edx ;Replace memory with byte Deposit after unit total_mem_bytes Office. ;----------------- Ready to enter protection mode ------------------- ;1 open A20 ;2 load gdt ;3 take cr0 of pe Position 1 ;----------------- open A20 ---------------- in al,0x92 or al,0000_0010B out 0x92,al ;----------------- load GDT ---------------- lgdt [gdt_ptr] ;----------------- cr0 Position 0 1 ---------------- mov eax, cr0 or eax, 0x00000001 mov cr0, eax jmp dword SELECTOR_CODE:p_mode_start ; Refresh the pipeline to avoid the impact of branch prediction,this ;species cpu Optimization strategy, most afraid jmp Jump, ; This will lead to the failure of the previous prediction, which plays the role of refreshing. .error_hlt: ;Suspend on error hlt [bits 32] p_mode_start: mov ax, SELECTOR_DATA mov ds, ax mov es, ax mov ss, ax mov esp,LOADER_STACK_TOP mov ax, SELECTOR_VIDEO mov gs, ax; ; Create page directory and page table and initialize page memory bitmap call setup_page ;To write the descriptor table address and offset to memory gdt_ptr,Reload with new address later sgdt [gdt_ptr] ; Store to original gdt All locations ;take gdt Segment base address in video segment descriptor in descriptor+0xc0000000 mov ebx, [gdt_ptr + 2] or dword [ebx + 0x18 + 4], 0xc0000000 ;The video segment is the third segment descriptor,Each descriptor is 8 words ;section,So 0 x18. ;The highest bit of the upper 4 bytes of the segment descriptor is 31 of the segment base address~24 position ;take gdt Base address plus 0 xc0000000 Make it the high address of the kernel add dword [gdt_ptr + 2], 0xc0000000 add esp, 0xc0000000 ; The stack pointer is also mapped to the kernel address ; Assign the page directory address to cr3 mov eax, PAGE_DIR_TABLE_POS mov cr3, eax ; open cr0 of pg position(31st place) mov eax, cr0 or eax, 0x80000000 mov cr0, eax ;After paging is turned on,use gdt Reload new address lgdt [gdt_ptr] ; Reload mov byte [gs:160], 'V'; jmp $; ;------------- Create page directory and page table --------------- setup_page: ;First clear the space occupied by the page directory by 0 byte mov ecx, 4096 mov esi, 0 .clear_page_dir: mov byte [PAGE_DIR_TABLE_POS + esi], 0 inc esi loop .clear_page_dir ;Start creating page directory entries(PDE) .create_pde: ; establish Page Directory Entry mov eax, PAGE_DIR_TABLE_POS add eax, 0x1000 ; here eax Is the location and properties of the first page table mov ebx, eax ; Here is ebx Assignment, yes.create_pte Prepare, ebx Is the base address. ; The page directory entries 0 and 0 will be displayed below xc00 Are saved as the address of the first page table, ; A page table can represent 4 MB Memory,So 0 xc03fffff The following addresses and 0 x003fffff The following addresses point to the same page table, ; This is in preparation for mapping addresses to kernel addresses or eax, PG_US_U | PG_RW_W | PG_P ; Properties of page directory entries RW and P Bit 1,US Is 1,Represents user attributes,All privilege levels are accessible. mov [PAGE_DIR_TABLE_POS + 0x0], eax ; 1st directory entry,The first directory entry in the page directory table is written to the location of the first page table(0x101000)And properties(3) mov [PAGE_DIR_TABLE_POS + 0xc00], eax ; A page table item occupies 4 bytes,0xc00 Indicates the directory entry occupied by the 768th page table,0xc00 The above directory entries are for kernel space, ; That is, 0 of the page table xc0000000~0xffffffff Total 1 G Belong to kernel,0x0~0xbfffffff Total 3 G Belongs to user process. sub eax, 0x1000 mov [PAGE_DIR_TABLE_POS + 4092], eax ; Make the last directory entry point to the address of the page directory table itself ;Next, create a page table entry(PTE) mov ecx, 256 ; 1M low memory / Page size 4 k = 256 mov esi, 0 mov edx, PG_US_U | PG_RW_W | PG_P ; The attribute is 7,US=1,RW=1,P=1 .create_pte: ; establish Page Table Entry mov [ebx+esi*4],edx ; At this time ebx It has passed above eax Assign value to 0 x101000,That is, the address of the first page table add edx,4096 inc esi loop .create_pte ;Creating tables for other pages of the kernel PDE mov eax, PAGE_DIR_TABLE_POS add eax, 0x2000 ; here eax Is the location of the second page table or eax, PG_US_U | PG_RW_W | PG_P ; Properties of page directory entries RW and P Bit 1,US Is 0 mov ebx, PAGE_DIR_TABLE_POS mov ecx, 254 ; The scope is 769~1022 Number of all catalog items mov esi, 769 .create_kernel_pde: mov [ebx+esi*4], eax inc esi add eax, 0x1000 loop .create_kernel_pde ret
Code function summary:
setup_page function
Constructed the 0th page directory item and the 768th ~ 1023rd page directory item
Constructed the first 256 page table entries in the page 0 table. Among them, the addresses of page table items are the lower 1MB of real address
First open the protection mode, then call setup_. Page establish the page table and page directory.
Modify the segment base address in GDTR and the segment base address in the segment descriptor of video memory,
Then assign the page directory address to cr3 and open the pg bit (bit 31) of cr0
Final execution
mov byte [gs:160], 'V';
To verify the experimental results.
Analyze the code addressing process of this sentence.
It involves two virtual address conversions.
gs is the selector of the video memory segment
After the following code is modified
sgdt [gdt_ptr] ;;;;;Modified the segment base address of video memory segment descriptor;;;; mov ebx, [gdt_ptr + 2] or dword [ebx + 0x18 + 4], 0xc0000000 ;;;;Modified GDT Base address;;;; add dword [gdt_ptr + 2], 0xc0000000 add esp, 0xc0000000 ;;;;Modified GDT Assign starting address to gdtr;;;;;; lgdt [gdt_ptr]
The base address of GDT remains unchanged at 1MB lower than the real address and is still 0x900
The base address of the video memory segment descriptor does not change when the real address is lower than 1MB. 0x900+8*3 bytes = 0x918
The descriptor index value in gs has not changed to 3
It becomes the GDT base address in the GDTR and becomes 0xc0000900, that is, 3GB+0x900. This is obviously a virtual address, and the real address is only 32MB
Therefore, the base address of the video memory segment descriptor obtained is also a virtual address
0xc0000900+3 * 8 bytes = 0xc0000918
Since the paging mechanism has been turned on, the virtual address will be converted to the physical address 0x918,
The conversion process is as follows
0xc0000918
10 digits | 10 digits | 12 digits |
---|---|---|
11_0000_0000 | 00_0000_0000 | 0x918 |
The decimal system is 768 | 0 | 0x918 |
The 768th page directory item is set by us, and the top 20 bits are the first address of the 0 page table
The middle 10 bits are 0, that is, the 0 page table item of the 0 page table, and the first 20 bits are 0.
Therefore, the physical address corresponding to this virtual address is 0x00000918,
This is the base address of the video memory segment descriptor.
The segment base address recorded in the segment descriptor of video memory is also a virtual address, 0xc00b8000
Similarly, it is converted to a physical address, that is, 0x000b8000
This is the first address of video memory text mode.
160 is the offset, which is legal.
So 'V' will appear on the second line of the display.
2.4 experimental results
1. Compile loader s
nasm -o loader.bin loader.s
2. Compile MBR s
nasm -o mbr.bin mbr.s
3. Transfer MBR Bin engraved into sector 0
dd if=/home/Seven/bochs2.68/bin/mbr.bin of=/home/Seven/bochs2.68/bin/Seven.img bs=512 count=1 seek=0 conv=notrunc
4. Load the loader Bin is engraved into sector 2 (note that count=3 plus one)
dd if=/home/Seven/bochs2.68/bin/loader.bin of=/home/Seven/bochs2.68/bin/Seven.img bs=512 count=3 seek=2 conv=notrunc
5. Simulate bochs
./bochs -f bochsrc.disk
design sketch
3. Supplement
When building the page directory item, we also set the top 20 bits of the 1023rd page directory item as the first address of the page directory
The process of converting virtual addresses to physical addresses according to paging mechanism
If the upper 20 bits of the virtual address are 0xfffff, the upper 10 bits are all 1. Find the 1023rd page directory item and obtain the page directory header address, and the middle 10 bits are all 1. The page directory is regarded as the page table, the 1023rd page directory item is regarded as the page table item, and the page directory header address is obtained.
Therefore, as long as the upper 20 bits of the virtual address is 0xfffff, you can get the first address of the page directory
We can get it through a specific virtual address
1. Get the physical address of page directory: virtual address 0xffff000
2. Get the physical address of the directory item on the nth page: virtual address: 0xfffffxxx
xxx is the product of page directory index multiplied by 4
For example, if you get the first page directory entry address (the number starts from 0), the virtual address I give should be 0xfffff004 and the first page directory address + 4
If you get the first address of the directory entry on the nth page, you will get the first address of the table on the nth page.
3. Access the page table entry in the page table, that is, get the first address of the nth page table entry in the M-th page table: the first 10 bits of the virtual address I gave are all 1, that is 0x3ff, the middle 10 bits are equal to M, and the last 12 bits are equal to N*4. In this way, the last converted physical address is the first address of the nth page table entry in the M-th page table