OSDev.org

The Place to Start for Operating System Developers
It is currently Sun Sep 20, 2020 3:38 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: How do I construct a pointer to a virtual address?
PostPosted: Sat Jan 04, 2020 10:53 pm 
Offline

Joined: Tue Aug 26, 2014 5:07 pm
Posts: 14
My current goal is to create a pointer to a contiguous sequence of bytes.
I've enabled paging and have identity mapped the first page table.
As far as I can tell, it looks like I can build a pointer to a single char, but not an array of char.

Here is my attempt at enabling paging, based on the wiki article:
Code:
uint32_t page_directory[1024] __attribute__((aligned(4096)));
uint32_t first_page_table[1024] __attribute__((aligned(4096)));

extern void load_page_directory(uint32_t*);
extern void enable_paging();

void init_paging()
{
   uint32_t i;

   for (i = 0; i < 1024; i++)
   {
      page_directory[i] = 0x00000002;
   }

   // Identity map the first page table
   for (i = 0; i < 1024; i++)
   {
      first_page_table[i] = (i * 0x1000) | 3;
   }

   page_directory[0] = ((uint32_t)first_page_table) | 3;

   load_page_directory(page_directory);
   enable_paging();
}


It was my understanding that on x86 in 32-bit protected mode without PAE enabled, a virtual address is basically a 32-bit number where the 10 most significant bits are the index within a page directory, the next 10 most significant bits are the index within a page table, and the 12 least significant bits are the offset within a physical frame.
If that's the case, then as long as the page table and directory are present, shouldn't the construction of a pointer just be a matter of combining the page directory index, page table index, and frame offset like so?
Code:
uint32_t dir_i = 0;   // directory index [0, 1023]
uint32_t tab_i = 255; // table index     [0, 1023]
uint32_t offset = 0;  // frame offset    [0, 4095]

/**
* The goal of this function is to construct a valid pointer to virtual memory.
* There is currently only one page table with all of its 1024 entries
* populated with identity mapping.
* So the physical addresses 0x00 - 0x3FFFFF are mapped to the virtual
* addresses 0x00 - 0x3FFFFF.
*/
void* build_pointer(size_t n)
{   
   uint32_t v_addr; // a virtual address

   // shift the 10 bit directory index to the left by 22   
   v_addr = dir_i << 22;
   
   // OR the address with the 10-bit table index shifted to the left by 12
   v_addr |= (tab_i << 12);
   
   // for now, we're only allowing allocation within one frame
   // and not worrying about freeing memory
   if (offset + n < 0xFFF)
   {
      v_addr |= offset;
      offset += n;
      return (void*)v_addr;
   }
   
   return NULL;
}


So basically, when I build a pointer to a char near the beginning of a frame, I can set the value pointed to by that pointer to be a single character, but I can't treat the pointer as an array.
Code:
   char* my_char = (char*)build_pointer(3);
   
   my_char[0] = 'A';
   my_char[1] = 'B';
   my_char[2] = 'C';
   
   vga_putchar(my_char[0]); // This prints 'A'
   vga_putchar('\n');
   
   vga_putchar(my_char[1]); // This prints a garbage character
   vga_putchar('\n');
   
   vga_putchar(my_char[2]); // This prints a garbage character
   vga_putchar('\n');


What am I doing wrong?
Is it my alignment?


Top
 Profile  
 
 Post subject: Re: How do I construct a pointer to a virtual address?
PostPosted: Sun Jan 05, 2020 12:48 am 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 619
No, as far as I can see, you've done most of it right. Your problem is the underlying physical memory. In your case, you are identity mapping everything, and the first pointer returned from build_pointer() is 0x000ff000. That is smack in the middle of BIOS ROM, so you cannot write there, or else you destroy the BIOS ROM copy. Use a different page for your experiments, like 0x00001000, which is past the IVT and the BDA and way below the EBDA.

_________________
Life is beautiful. Nobody said easy.


Top
 Profile  
 
 Post subject: Re: How do I construct a pointer to a virtual address?
PostPosted: Sun Jan 05, 2020 11:24 am 
Offline

Joined: Tue Aug 26, 2014 5:07 pm
Posts: 14
Thanks! That was the problem.
Looks like I have some reading to do on the x86 physical memory map and detecting memory before I can reliably map frames on the fly.


Top
 Profile  
 
 Post subject: Re: How do I construct a pointer to a virtual address?
PostPosted: Sun Jan 05, 2020 11:29 am 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 863
Hi,

@nullplan is right. I'd just like to add that you don't need to construct a pointer. All the translations are done for you by the MMU. See the memory as a contiguous big array of bytes, and don't care which physical page it's mapped to (as long as there's a mapping, present bit set you won't get an exception).

So to "build" a pointer, just simply use
Code:
ptr = 0x00001000;

Because at the early stage it can be very confusing when you're using a physical address or a virtual address, I'd recommend to create two typedefs:
Code:
typedef phys_t uint32_t;
typedef virt_t uint32_t;
and use it like this to make your code more readable:
Code:
ptr = (virt_t)0x00001000;

Cheers,
bzt


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

All times are UTC - 6 hours


Who is online

Users browsing this forum: bloodline, mrjbom, Octocontrabass and 10 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