OSDev.org

The Place to Start for Operating System Developers
It is currently Wed Nov 25, 2020 10:10 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Understanding virtual memory translation in AMD64/UEFI
PostPosted: Fri Oct 23, 2020 7:56 am 
Offline

Joined: Thu Dec 12, 2019 7:07 am
Posts: 8
Hi all,

Trying to see if my understanding of page tables is correct. I am currently using UEFI, so I thought to inspect the page tables set up for it and see if my understanding is correct. From what I understand, all addresses in UEFI are identity mapped. I looped through the memory map descriptors and all virtual addresses are set to 0, so I am thinking this is true.

So want to know how virtual addresses are translated starting from CR3. So as an example I am using the RIP value which in this case is 0x65F_6A39. From reading the AMD64 manual, it looks like this address should be translated into the following offsets:

address -> 0x65F_6A39
PML4T -> bits 39-47 -> entry 0
PDPT -> bits 30 - 38 -> entry 0
PDT -> bits 21 - 29 -> entry 0x32 -> byte offset 0x32*8
PT -> bits 12 - 20 -> entry 0x1F6 -> byte offset 0x1F6*8

Do my offset calculations look correct?

From here, I now chase pointers starting from CR3. I assume all addresses are identity mapped because of what I’ve stated in the first paragraph. If they are not identity mapped, that’s the issue here. Below I have what I see when start pointer chasing.
It seems everything looks reasonable up until I reach the PDE, which is the first time I have a non-zero offset. The entry I am pulling from the PDT looks invalid (especially since the present bit is 0). Am I chasing pointers incorrectly? Am I applying the offset incorrectly?

Thank you!
Code:
CR3 -> 0x7C0_1000

PML4E ->  0x7C0_1000 + 0 -> {is_present = true,
is_writable = true,
is_user_accessible = false,
is_write_through_enabled = false,
is_cache_disabled = false,
was_accessed = true,
ignored = 0,
page_size_control_bit = 0,
must_be_zero = 0,
unused1 = 0,
table_address = 0x7C02,
unused0 = 0,
no_execute = false,
}

PDPE -> 0x7C0_2000 + 0 -> {is_present = true,
is_writable = true,
is_user_accessible = false,
is_write_through_enabled = false,
is_cache_disabled = false,
was_accessed = true,
ignored = 0,
page_size_control_bit = 0,
must_be_zero = 0,
unused1 = 0,
table_address = 0x7C03,
unused0 = 0,
no_execute = false,
}

PDE -> 0x7C0_3000 + 0x32*8 -> {is_present = false,
is_writable = false,
is_user_accessible = false,
is_write_through_enabled = false,
is_cache_disabled = false,
was_accessed = false,
ignored = 0,
page_size_control_bit = 0,
must_be_zero = 0x1,
unused1 = 0x3,
table_address = 0x30_0000_0000,
unused0 = 0xE,
no_execute = false,
}



Last edited by DanB91 on Fri Oct 23, 2020 8:22 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Understanding virtual memory translation in AMD64/UEFI
PostPosted: Fri Oct 23, 2020 8:19 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 3994
Location: Chichester, UK
I think your address calculations are wrong. Shouldn't the PTE offset be 0x1F8?


Top
 Profile  
 
 Post subject: Re: Understanding virtual memory translation in AMD64/UEFI
PostPosted: Fri Oct 23, 2020 8:23 am 
Offline

Joined: Thu Dec 12, 2019 7:07 am
Posts: 8
iansjack wrote:
I think your address calculations are wrong. Shouldn't the PTE offset be 0x1F8?

Apologies, I posted the wrong virtual address. The correct virtual address is 0x65F_6A39, NOT 0x65F_8A39. Regardless, the issue starts with the PDTE, not PTE.


Top
 Profile  
 
 Post subject: Re: Understanding virtual memory translation in AMD64/UEFI
PostPosted: Fri Oct 23, 2020 8:41 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 3994
Location: Chichester, UK
My second thought is that you don't show us the code that you are using to read the tables. How have you declared the variables that you use? Don't forget that pointer arithmetic in C automatically takes care of the size of the variable pointed to. Should you perhaps be looking at

0x7C0_3000 + 0x32

rather than

0x7C0_3000 + 0x32*8 ?

It may be more intuitive to declare the variables for the tables as arrays rather than pointers.


Top
 Profile  
 
 Post subject: Re: Understanding virtual memory translation in AMD64/UEFI
PostPosted: Fri Oct 23, 2020 8:13 pm 
Offline

Joined: Thu Dec 12, 2019 7:07 am
Posts: 8
iansjack wrote:
My second thought is that you don't show us the code that you are using to read the tables. How have you declared the variables that you use? Don't forget that pointer arithmetic in C automatically takes care of the size of the variable pointed to. Should you perhaps be looking at

0x7C0_3000 + 0x32

rather than

0x7C0_3000 + 0x32*8 ?

It may be more intuitive to declare the variables for the tables as arrays rather than pointers.

Thanks a lot for the help. So this kind of got my gears turning. I am actually using Zig instead of C. I declared the the table entry struct as a "packed struct", which I've learned is completely broken in the language now. It was badly calculating the struct to be 9 bytes big instead of 8 bytes, throwing off all pointer arithmetic/scaling. So that was my issue. So once I just used regular u64 integers, I got it working.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot] and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group