OSDev.org https://forum.osdev.org/ |
|
Self-referencing page-directory https://forum.osdev.org/viewtopic.php?f=8&t=29474 |
Page 1 of 1 |
Author: | tkausl [ Fri Jul 24, 2015 5:54 am ] |
Post subject: | Self-referencing page-directory |
Hello, since the usual bitshifting and calculating with magic numbers can get really ugly and confusing like in this example: Code: void * get_physaddr(void * virtualaddr) i've created a little struct, which helps me with those problems:{ unsigned long pdindex = (unsigned long)virtualaddr >> 22; unsigned long ptindex = (unsigned long)virtualaddr >> 12 & 0x03FF; unsigned long * pd = (unsigned long *)0xFFFFF000; // Here you need to check whether the PD entry is present. unsigned long * pt = ((unsigned long *)0xFFC00000) + (0x400 * pdindex); // Here you need to check whether the PT entry is present. return (void *)((pt[ptindex] & ~0xFFF) + ((unsigned long)virtualaddr & 0xFFF)); } Code: typedef struct { union { struct { uint32_t present : 1; // 1 uint32_t write : 1; // 2 uint32_t user : 1; // 3 uint32_t writethrough : 1; // 4 uint32_t cache_disabled : 1; // 5 uint32_t accessed : 1; // 6 uint32_t dirty : 1; // 7 uint32_t ignore0 : 1; // 8 uint32_t global : 1; // 9 uint32_t avail : 3; // 12 uint32_t frame : 20; // 32 }; uint32_t val; }; } page_table_entry_t; typedef struct { union { struct { uint32_t present : 1; // 1 uint32_t write : 1; // 2 uint32_t user : 1; // 3 uint32_t writethrough : 1; // 4 uint32_t cache_disabled : 1; // 5 uint32_t accessed : 1; // 6 uint32_t ignore0 : 1; // 7 uint32_t big_pages : 1; // 8 uint32_t ignore1 : 1; // 9 uint32_t avail : 3; // 12 uint32_t frame : 20; // 32 }; uint32_t val; }; } page_directory_entry_t; typedef struct { page_table_entry_t page[1024]; } page_table_t; typedef struct { union { page_table_t table[1023]; page_table_entry_t page[1024 * 1023]; }; page_directory_entry_t directory[1023]; uint32_t ignore; } page_directory_t; This will only work, if the last entry in the page-directory is mapped to itself! After a single line of initialisation: Code: page_directory_t* CURRENT_DIR = (page_directory_t*)0xFFC00000; It can be used fairly easy: Code: uint32_t virtual = 0xC0000000; //our 'demo' virtual address uint32_t page_id = virtual / 4096; // or rightshift by 12, this is the 'id' of the page uint32_t table_id = page_id / 1024; // Or rightshift by 10, the table in which the page is uint32_t table_offset = page_id%1024; // Or &0x3FF, the offset our page in the table CURRENT_DIR->directory[table_id].present; //Not doing anything, only showing how to access the directory CURRENT_DIR->directory[table_id].frame; //and so on //To access a table: CURRENT_DIR->table[table_id]->page[table_offset].present; //or even easier with the full page id CURRENT_DIR->page[page_id].present; Might be worth to put it in the wiki, might not. |
Author: | Icee [ Tue Jul 28, 2015 4:45 am ] |
Post subject: | Re: Self-referencing page-directory |
Note that bit fields in C are not portable. The standard does not dictate whether they appear in little- or big-endian order. This will probably never be a real issue for this piece of (target-specific) code but still worth mentioning. |
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |