// // Created by rick on 21-02-21. // #include #include #include #include #include #include #define TABLE_ADDR_MASK 0xFFFFF000 #define TABLE_ADDR_IMASK ~TABLE_ADDR_MASK #define DIRECTORY_SIZE 1024 const uint32_t x = TABLE_ADDR_MASK; typedef struct { union { struct { bool present: 1; bool read_write: 1; bool user_mode: 1; bool write_through: 1; bool cache_disabled: 1; bool accessed: 1; char: 1; bool page_size: 1; bool global: 1; // ignored uint8_t avail: 3; } att_packed; uint32_t addr; }; } att_packed page_directory_entry; typedef struct { union { struct { bool present: 1; bool read_write: 1; bool user_supervisor: 1; bool write_through: 1; bool cache_disabled: 1; bool accessed: 1; bool dirty: 1; char: 1; bool global: 1; uint8_t available: 3; } att_packed; uint32_t addr; }; } att_packed page_table_entry; //#define in_dir(dir, vaddr) ((page_table_entry*)(((page_directory_entry*)((dir)[(vaddr)/4096/1024].addr & TABLE_ADDR_MASK))[(vaddr)/4096%1024])) #define dir_index(vaddr) (((uint32_t)(vaddr)) / PAGE_SIZE / DIRECTORY_SIZE) #define page_index(vaddr) (((uint32_t)(vaddr)) / PAGE_SIZE % DIRECTORY_SIZE) page_directory_entry boot_paging_directory[DIRECTORY_SIZE] att_aligned(4096); page_table_entry boot_primary_table[DIRECTORY_SIZE] att_aligned(4096); extern page_directory_entry *vmm_get_current_page_directory(); void vmm_assign_page_one(uint32_t paddr, uint32_t vaddr) { page_directory_entry *curr = vmm_get_current_page_directory(); page_directory_entry *dentry = &curr[dir_index(vaddr)]; if (!dentry->present || (dentry->addr & TABLE_ADDR_MASK) == 0) { // todo allocate table k_panics("need to allocate new table"); } page_table_entry *first_entry = (page_table_entry *) (dentry->addr & TABLE_ADDR_MASK); page_table_entry *pentry = &first_entry[page_index(vaddr)]; if (pentry->present) { // todo already present k_panics("virtual address already in use"); } pentry->addr = (pentry->addr & TABLE_ADDR_IMASK) | paddr; pentry->present = true; pentry->read_write = true; } void vmm_unassign_page_one(uint32_t vaddr) { page_directory_entry *curr = vmm_get_current_page_directory(); page_directory_entry *dentry = &curr[dir_index(vaddr)]; if (!dentry->present || (dentry->addr & TABLE_ADDR_MASK) == 0) { // todo allocate table k_panics("need to allocate new table"); } page_table_entry *first_entry = (page_table_entry *) (dentry->addr & TABLE_ADDR_MASK); page_table_entry *pentry = &first_entry[page_index(vaddr)]; if (!pentry->present) { // todo already present k_panics("virtual address not in use"); } pentry->present = false; pentry->read_write = false; pentry->addr = pentry->addr & TABLE_ADDR_IMASK; } void vmm_assign_page(void *paddr, void *vaddr, size_t number_of_pages) { for (size_t i = 0; i < number_of_pages; ++i) { vmm_assign_page_one(((uint32_t) paddr) + PAGE_SIZE * i, ((uint32_t) vaddr) + PAGE_SIZE * i); } } void vmm_unassign_page(void *vaddr, size_t number_of_pages) { for (size_t i = 0; i < number_of_pages; ++i) { vmm_unassign_page_one(((uint32_t) vaddr) + PAGE_SIZE * i); } }