Re: Why is a PA converted to a VA in pmd_page?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hopefully somebody will correct me if I'm wrong.

"Kirk True" <ktrue@movaris.com> writes:

> Hi Ed,
>
>> > Why does it convert the physical address provided by pmd_val to a
>> > virtual one? The addresses returned from pgd_offset and pmd_offset
>> > represent a physical address, correct?
>>
>> I don't think so.
>
> But the whole traversing starts with pgd_offset:
>
>     #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
>
> Isn't mm_struct's pgd a pointer to a *physical* address? Since pgd's value
> is used in the cr3 register I thought you had to be a *physical* address...

Again, I only know about lowmem x86, but for that to happen you'd have
to leave protected mode when entering the kernel and enter it again
when entering user space.  That isn't what happens, though.  The
kernel uses the MMU just like code running in userspace.

For example, if the kernel tries to write through an invalid pointer,
you get something predictable like an oops.  That's because the MMU
catches the invalid address, even though the CPU is in superuser mode.
Then do_page_fault runs and handles the kernel bug.  

The kernel's page tables are set up in pagetable_init in
arch/i386/mm/init.c.  The kernel's "pgd" is swapper_pg_dir.

>> In memory.c:free_one_pmd there's an example of how pmd_page is used.
>> It yields a pointer to the struct page in the mem_map that corresponds
>> to the page frame where the pmd is stored.  That pointer is a virtual
>> address.
>>
>> On lowmem x86, for kernel data, the relationship between a virtual
>> address and a physical address is just the addition or subtraction of
>> 0xC0000000.  The __va macro just adds 0xC0000000 to the physical
>> address.
>
> One of the big issues I'm having is knowing when the code is using physical,
> virtual, or linear address spaces.

It's pretty simple but very confusing.  I may still be confused, but
hopefully someone will speak up if so.

> Question: When in kernel mode, can you refer to a value/address by a
> physical address *or* a virtual address and have it magically
> work???? 

No, the MMU is going to try to translate the address if you say:

  int a;
  int *p = &a;
  
  *p = 100;

I don't think you can do this:

  *(__pa(p)) = 100;

... because (in lowmem x86), that __pa macro is going to subtract
0xc0000000 from the (virtual) address, meaning that it's now a
userland address!

> If
> you're running kernel code and you try to access a virtual address n, does
> the MMU magically know to subtract PAGE_OFFSET from n? 

It's not magic.  The translations for addresses greater than
0xC0000000 are in the TLB and the page tables just like the others. 

> Otherwise, trying to
> access virtual address n would result in a memory addressing error if you
> had < 3 GB of physical RAM?
>
> Please forgive my complete ignorance ;) Hopefully I'm just missing something
> obvious.

I don't think it's obvious at all.  

-- 
--Ed L Cashin            |   PGP public key:
  ecashin@uga.edu        |   http://noserose.net/e/pgp/

--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/



[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux