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>