Quick i386 question...
Sergio Andrés Gómez del Real
sergio.g.delreal at gmail.com
Mon Nov 22 21:20:16 UTC 2010
Maybe my issue does not belong here, because it is not
FreeBSD-related, but I can't find any other source for this kind of
technical issue.
My problem is that I am trying to design and now implement a small and
simple operating system. I know that it is very difficult to follow
for someone not familiar to the system design, but I am going to try
to describe my problem:
In the following code the first thing is to zero 5MB of memory from
5MB-10MB. This is in call clear_mem. Then in the call to set_pae the
PDPTE's are copied to PDPTEs, that is, address 0x00500000 (5MB). The
control string is at pae_ctrl_str, and the reserved bits are set to 0.
The call to map_monitor maps the first 256 entries of the first page
table referenced by the page directory from the first PDPTE. The call
to map_kernel does the same with the 257's entry. The mappings are to
identical physical addresses. After that, PDPTE is shifted 5 bits to
the left and loaded to cr3, so the address for the PDPTE's is 0x500000
(5MB). Next PAE is set and then %cr0 is loaded to %eax, bits 30 and 29
(starting from 0) are turned off and bit 31 (for paging) is turned on.
When I copy it to %cr0 I get a General-Protection Exception. The eip
that caused it is from the movl %eax, %cr0 instruction. What I have
read from Intel, the only way to get a GP at this instruction is to
write reserved bits to the PDPTE's or with a bad combination in
setting the bits in %cr0. I can't seem to be able to see any of this
faults. I would appreciate if someone could find the source of the
problem, because setting page-table structures and activating
page-table seems quite simple.
.set PDPTEs, 0x00500000 # PDPTE's address (5MB)
.set PG_ENABLE, 0x80000000 # enable paging
.set PDT_1, 0x00501000 # Page-directory table address
.set PTE_D1_E1, 0x00505000 # Page-table address
.
.
.
cld # up we go for string ops
movl $0x500000, %edi # start of memory block
movl $0x500000, %ecx # number of bytes to zeroe
call clear_mem # clear %ecx bytes from %edi memory address
call set_pae # set PDPT's for PAE
call map_monitor # map the monitor program to identical physical pages
call map_kernel # also the kernel
movl $PDPTEs, %eax # load address for PDPT's
shll $5, %eax # first 5 bits are ignored
movl %eax, %cr3 # save
movl %cr4, %eax # load register
orl $0x20, %eax # set PAE bit
movl %eax, %cr4 # enable PAE addressing
movl %cr0, %eax # load %cr0
orl $0x60000000, %eax # clear CD and NW bits
movl %eax, %cr0 # save
orl $PG_ENABLE, %eax # enable paging
movl %eax, %cr0 # save # HERE I GET THE GP EXCEPTION
.
.
.
/*
* Zero contigious blocks of memory.
*/
clear_mem:
rep # clear
stosb # memory block
ret
/*
* We use the PAE extension service of i386 processor to be able to create
* virtual-memory data structures in addresses above (2^20)-1 bytes.
*/
set_pae:
movl $PDPTEs, %edi # pointer to PDPTE's
movl $pae_ctrl_str, %esi # control string
1:
lodsl # load value
testl %eax, %eax # end of control?
jz 2f # yes
movl %eax, (%edi) # PDPTE1 word 1
lodsl # load value
movl %eax, 4(%edi) # PDPTE1 word 2
addl $8, %edi # next entry
jmp 1b
2:
ret
/*
* The strategy is to map the low-memory addresses to identical physical
* addresses.
* Each entry maps a 4KB page, so we loop 256 times to map the first MB
* to identical physical memory.
*/
map_monitor:
movl $PDT_1, %edi # pointer to first page directory
movl $map_monitor_ctrl_str, %esi # monitor's page table
lodsl
movl %eax, (%edi) # page directory entry 1 word 1
lodsl
movl %eax, 4(%edi) # page directory entry 1 word 2
movl $PTE_D1_E1, %edi # pointer to first page table of first page directory
movl $mon_pag, %esi # pointer to first page entry
movl $256, %ecx # loop (map) number of entries (4096 * 256 == 1MB)
call pages_loop
ret
/*
* Kernel's virtual address starts at 0x00100000. Map kernel size starting
* from that address to physical address to which the kernel was loaded, being
* 0x100000.
*/
map_kernel:
movl kernel_size, %eax # load kernel size in sectors (THIS VALUE IS 1)
shll $9, %eax # to bytes
shrl $13, %eax # to pages
incl %ecx # one more
movl %eax, %ecx # loop times
1:
movl $PTE_D1_E1, %edi # pointer to first page table of first page directory
addl $0x800, %edi # point to kernel's first entry in table
movl $kern_pag, %esi # pointer to first page entry
call pages_loop
ret
/*
* Routine to map a contigious block of virtual-memory to a contigious block
* of physical-memory.
*/
pages_loop:
lodsl # load first word
movl %eax, %ebx # save it
lodsl # load second word
movl %eax, %edx # save it
testl %ecx, %ecx
jz end_pages_loop
1:
movl %ebx, (%edi)
movl %edx, 4(%edi)
addl $8, %edi # next entry in table
shrl $12, %ebx
addl $0x1000, %ebx # add one page (4096 bytes)
shll $12, %ebx
orl $0xb, %ebx
loop 1b
end_pages_loop:
ret
map_monitor_ctrl_str:
mon_pag_tab:
.long 0x0500000b, 0x00000005 # page directory table 1
.long 0x00000000
mon_pag:
.long 0x0000000b, 0x00000000 # first page (0x0)
pae_ctrl_str:
.long 0x01000009, 0x00000005 # PDPTE 1
.long 0x02000009, 0x00000005 # PDPTE 1
.long 0x03000009, 0x00000005 # PDPTE 1
.long 0x04000009, 0x00000005 # PDPTE 1
.long 0x00000000
map_kernel_ctrl_str:
kern_pag:
.long 0x0000000b, 0x00000001 # first page (0x100000)
More information about the freebsd-hackers
mailing list