Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Nov 2010 16:20:11 -0500
From:      =?ISO-8859-1?Q?Sergio_Andr=E9s_G=F3mez_del_Real?= <sergio.g.delreal@gmail.com>
To:        John Baldwin <jhb@freebsd.org>, freebsd-hackers@freebsd.org
Subject:   Re: Quick i386 question...
Message-ID:  <AANLkTikzB56SB-ghEgncadtd6JPkzgsQnj5iXmwvD2GF@mail.gmail.com>
In-Reply-To: <201011220920.15431.jhb@freebsd.org>
References:  <AANLkTikjX28eu3_Zv0XFcE1LG-7UNVv9DupHCZ9T0qiv@mail.gmail.com> <201011220920.15431.jhb@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
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)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?AANLkTikzB56SB-ghEgncadtd6JPkzgsQnj5iXmwvD2GF>