Skip to contentSkip to conversation

Regarding enable paging code and swapper_pg_dir.

DISCUSSION mindentropy 2 participants 7 messages Apr 1, 2011 – Apr 4, 2011 2 messages not in the archive

lore
Share & tools
lore

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]

#3 lore raw
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#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?

Quoted 4 lines

Thanks.

_______________________________________________
Kernelnewbies mailing list

I'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_dir is defined to be the value that will be used once the CPU has switched to Protected Mode, but this asm code in head.S is 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

#4 lore raw

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

#5 lore raw
In reply to James Light
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?

#6 lore raw
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_OFFSET to the address so that the $swapper_pg_dir - __PAGE_OFFSET justifies?

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

#7 lore raw
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_OFFSET to the address so that the $swapper_pg_dir - __PAGE_OFFSET justifies?

Quoted 7 lines

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.

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 */

-----------------------------------------------------------------------------

#8 lore raw
In reply to James Light
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_OFFSET to the address so that the $swapper_pg_dir - __PAGE_OFFSET justifies?

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.

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 of swapper_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.