Regarding enable paging code and swapper_pg_dir.
Hi All,
In the code http://lxr.linux.no/#linux+v2.6.12/arch/i386/kernel/head.S#L186
I am not able to understand what's the reason for subtracting swapper_pg_dir with __PAGE_OFFSET(0xc0000000). i.e. movl $swapper_pg_dir-__PAGE_OFFSET Shouldn't it be movl $swapper_pg_dir, %eax?
Thanks.
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 22 lines · mindentropy
Quoted 21 lines · you
Quoted 10 lines · mindentropy
Hi All,
In the code
http://lxr.linux.no/#linux+v2.6.12/arch/i386/kernel/head.S#L186I am not able to understand what's the reason for subtracting
swapper_pg_dirwith__PAGE_OFFSET(0xc0000000). i.e. movl $swapper_pg_dir-__PAGE_OFFSET Shouldn't it be movl $swapper_pg_dir, %eax?Quoted 4 lines
Thanks.
_______________________________________________
Kernelnewbies mailing listI'm no expert here, but I think the reason that it is coded that way has to do with the fact that the
swapper_pg_diris defined to be the value that will be used once the CPU has switched to Protected Mode, but this asm code inhead.Sis executing while the processes is in Real Mode.
Quoted 6 lines
Quoted 4 lines
The instruction that enables paging and protected mode addressing is on line 190, I believe.
-James
Yes but why the subtraction with
__PAGE_OFFSET?
To put the physical address into cr3 later.
$swapper_pg_dir is not the PHYSICAL address of the PGD.
So they have to subtract 0xc0000000 (kernel code segment base linear address) from that the get the physical address as the logical address can not be used yet because the paging unit isn't enabled yet.
Again, my understanding may be wrong. As I said before, I'm just learning this as well.
-James
If you look at the 2.6.38 code for head.S, you may find the newer way it is written to be a bit easier to read.
------------------------------------------------------------------------------
25 /* Physical address */
26 #define pa(X) ((X) - __PAGE_OFFSET)
...
345 /*
346 * Enable paging
347 */
348 movl $pa(initial_page_table), %eax 349 movl %eax,%cr3 /* set the page table pointer.. */ 350 movl %cr0,%eax 351 orl $X86_CR0_PG,%eax 352 movl %eax,%cr0 /* ..and set paging (PG) bit */ 353 ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */
------------------------------------------------------------------------------
-James
Quoted 3 lines · James Light
To put the physical address into cr3 later. $swapper_pg_dir is not the PHYSICAL address of the PGD.
Correct me if I am wrong but a mov $foo,%eax would move the address of foo variable to eax right? Or is there a macro somewhere where they are adding PAGE_OFFSET to the address so that the $swapper_pg_dir - __PAGE_OFFSET justifies?
Quoted 9 lines · mindentropy
Quoted 3 lines · James Light
To put the physical address into cr3 later. $swapper_pg_dir is not the PHYSICAL address of the PGD.
Correct me if I am wrong but a mov $foo,%eax would move the address of foo variable to eax right? Or is there a macro somewhere where they are adding
PAGE_OFFSETto the address so that the $swapper_pg_dir -__PAGE_OFFSETjustifies?
Right, but it uses the logical address of foo which n the case of swapper_pg_dir must be converted to a
physical address. When paging is not enabled, linear addresses are interpreted as physical addressess. So it has to get this logical address only one step farther into a linear address.
So, this "swapper_pg_dir" is a symbol in a section of code. That section of code has an associated segment and this symbol lives at a particular location in that section and thus in that segment, and that particular location, relative to the beginning of the section is it's offset. Combine those two and
you have the logical address of swapper_pg_dir.
The sigil "$" is the immediate
value sigil and the symbol $swapper_pg_dir thus uses the immediate value of swapper_pg_dir. The immediate value of swapper_pg_dir is the value held at the location that is logically labeled by the symbol swapper_pg_dir.
It may help to remind yourself that symbol names in assembly are very similar to labels in assembly. They mark a location in the program. The program runs and while running it only uses logical addresses. This particular code is loading a linear (and w/out paging therefore physical) address.
This is simply because of the design of the cr3 register and
paging in x86.
Quoted 1 line
From http://www.intel.com/design/processor/manuals/253668.pdf
Chapter 4: Paging (Page 1)
------------------------------------------------------------------------------
Software enables paging by using the MOV to CR0 instruction to set CR0.PG. Before
doing so, software should ensure that control register CR3 contains the physical address of the first paging structure that the processor will use for linear-address
translation (see Section 4.2)
------------------------------------------------------------------------------
In linux2.1.66, the physical address is used directly.
Just for comparison:
------------------------------------------------------------------------------
58/*
59 * Setup paging (the tables are already set up, just switch them on) 60 */
611:
62 movl $0x101000,%eax 63 movl %eax,%cr3 /* set the page table pointer.. */ 64 movl %cr0,%eax 65 orl $0x80000000,%eax 66 movl %eax,%cr0 /* ..and set paging (PG) bit */ 67 jmp 1f /* flush the prefetch-queue */
------------------------------------------------------------------------------
If any of my own reasoning is wrong, I hope someone w/ more clue jumps in. ;)
-James L
Quoted 10 lines · James Light
Quoted 8 lines · mindentropy
Quoted 2 lines · James Light
To put the physical address into cr3 later. $swapper_pg_dir is not the PHYSICAL address of the PGD.
Correct me if I am wrong but a mov $foo,%eax would move the address of foo variable to eax right? Or is there a macro somewhere where they are adding
PAGE_OFFSETto the address so that the $swapper_pg_dir -__PAGE_OFFSETjustifies?
Quoted 7 lines
Right, but it uses the logical address of foo which n the case of
swapper_pg_dirmust be converted to a
physical address. When paging is not enabled, linear addresses are interpreted as physical addressess.
So it has to get this logical address
only one step farther into a linear address.
Can you please elaborate on what one step farther is? So why not use the swapper_pg_dir directly i.e. mov $swapper_pg_dir,cr0? In the absence of paging the segment:offset is the physical address isn't it? i.e. the $swapper_pg_dir should be equal to 0x10100 as per the code fragment below?
I am having difficulty in understanding the addressing calculations here and not the code,
Quoted 14 lines
In linux2.1.66, the physical address is used directly.
Just for comparison:
------------------------------------------------------------------------------
58/*
59 * Setup paging (the tables are already set up, just switch them on) 60 */
611:62 movl $0x101000,%eax 63 movl %eax,%cr3 /* set the page table pointer.. */ 64 movl %cr0,%eax 65 orl $0x80000000,%eax 66 movl %eax,%cr0 /* ..and set paging (PG) bit */ 67 jmp 1f /* flush the prefetch-queue */-----------------------------------------------------------------------------
Quoted 16 lines · James Light
Quoted 8 lines · mindentropy
Quoted 2 lines · James Light
To put the physical address into cr3 later. $swapper_pg_dir is not the PHYSICAL address of the PGD.
Correct me if I am wrong but a mov $foo,%eax would move the address of foo variable to eax right? Or is there a macro somewhere where they are adding
PAGE_OFFSETto the address so that the $swapper_pg_dir -__PAGE_OFFSETjustifies?Right, but it uses the logical address of foo which n the case of
swapper_pg_dirmust be converted to a
physical address. When paging is not enabled, linear addresses are interpreted as physical addressess. So it has to get this logical address only one step farther into a linear address.
Quoted 7 lines
So, this "
swapper_pg_dir" is a symbol in a section of code. That section of code has an associated segment and this symbol lives at a particular location in that section and thus in that segment, and that particular location, relative to the beginning of the section is it's offset. Combine those two and
you have the logical address ofswapper_pg_dir.
Ok I think I got where the addresses are assigned. Its in the linker script vmlinux.lds. I got the precise answer here http://tldp.org/HOWTO/Linux-i386-
Boot-Code-HOWTO/kernel_head.html
I had completely forgotten about linker scripts. I was getting confused as the ENTRY(swapper_pg_dir) has ORG 0x10000 as the offset. Was struggling to find where the .text address was.