/** * @brief invalidate all TLB entries, including global entries */ static void x86_tlb_global_invalidate() { /* See Intel 3A section 4.10.4.1 */ ulong cr4 = x86_get_cr4(); if (likely(cr4 & X86_CR4_PGE)) { x86_set_cr4(cr4 & ~X86_CR4_PGE); x86_set_cr4(cr4); } else { x86_set_cr3(x86_get_cr3()); } }
void vm_init_paging(struct multiboot_info *boot_info) { struct x86_cpuid_info cpuid_info; struct frame *pgdir_frame; struct frame *pgtab_frame; pte_t *pgtab; ulong_t paddr, mem_max; /* * Check CPUID instruction to see if large pages (PSE feature) * is supported. */ PANIC_IF(!x86_cpuid(&cpuid_info), "GeekOS requires a Pentium-class CPU"); PANIC_IF(!cpuid_info.feature_info_edx.pse, "Processor does not support PSE"); cons_printf("CPU supports PSE\n"); /* * Enable PSE by setting the PSE bit in CR4. */ x86_set_cr4(x86_get_cr4() | CR4_PSE); /* * Allocate kernel page directory. */ pgdir_frame = mem_alloc_frame(FRAME_KERN, 1); s_kernel_pagedir = mem_frame_to_pa(pgdir_frame); memset(s_kernel_pagedir, '\0', PAGE_SIZE); /* * We will support at most 2G of physical memory. */ mem_max = ((ulong_t) boot_info->mem_upper) * 1024; if (mem_max > (1 << 31)) { mem_max = (ulong_t) (1 << 31); } /* * We need a page table for the low 4M of the kernel address space, * since we want to leave the zero page unmapped (to catch null pointer derefs). */ pgtab_frame = mem_alloc_frame(FRAME_KERN, 1); pgtab = mem_frame_to_pa(pgtab_frame); memset(pgtab, '\0', PAGE_SIZE); /* * Initialize low page table, leaving page 0 unmapped */ for (paddr = PAGE_SIZE; paddr < VM_PT_SPAN; paddr += PAGE_SIZE) { vm_set_pte(pgtab, VM_WRITE|VM_READ|VM_EXEC, paddr, paddr); } /* * Add low page table to the kernel pagedir. */ vm_set_pde(s_kernel_pagedir, VM_WRITE|VM_READ|VM_EXEC, 0UL, (u32_t) pgtab); /* * Use 4M pages to map the rest of the low 2G of memory */ for (paddr = VM_PT_SPAN; paddr < mem_max; paddr += VM_PT_SPAN) { vm_set_pde_4m(s_kernel_pagedir, VM_WRITE|VM_READ|VM_EXEC, paddr, paddr); } /* * Turn on paging! */ x86_set_cr3((u32_t) s_kernel_pagedir); /* set the kernel page directory */ x86_set_cr0(x86_get_cr0() | CR0_PG); /* turn on the paging bit in cr0 */ cons_printf("Paging enabled\n"); }