OSDev.org https://forum.osdev.org/ |
|
[SOLVED] How do I construct a pointer to a virtual address? https://forum.osdev.org/viewtopic.php?f=1&t=36414 |
Page 1 of 1 |
Author: | peachsmith [ Sat Jan 04, 2020 10:53 pm ] |
Post subject: | [SOLVED] How do I construct a pointer to a virtual address? |
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? |
Author: | nullplan [ Sun Jan 05, 2020 12:48 am ] |
Post subject: | Re: How do I construct a pointer to a virtual address? |
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. |
Author: | peachsmith [ Sun Jan 05, 2020 11:24 am ] |
Post subject: | Re: How do I construct a pointer to a virtual address? |
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. |
Author: | bzt [ Sun Jan 05, 2020 11:29 am ] |
Post subject: | Re: How do I construct a pointer to a virtual address? |
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; and use it like this to make your code more readable:typedef virt_t uint32_t; Code: ptr = (virt_t)0x00001000; Cheers, bzt |
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |