efi_status_t efi_thunk_set_virtual_address_map( void *phys_set_virtual_address_map, unsigned long memory_map_size, unsigned long descriptor_size, u32 descriptor_version, efi_memory_desc_t *virtual_map) { efi_status_t status; unsigned long flags; u32 func; efi_sync_low_kernel_mappings(); local_irq_save(flags); efi_scratch.prev_cr3 = read_cr3(); write_cr3((unsigned long)efi_scratch.efi_pgt); __flush_tlb_all(); func = (u32)(unsigned long)phys_set_virtual_address_map; status = efi64_thunk(func, memory_map_size, descriptor_size, descriptor_version, virtual_map); write_cr3(efi_scratch.prev_cr3); __flush_tlb_all(); local_irq_restore(flags); return status; }
void page_arch_init(void) { if (config.cpu_active > 1) { write_cr3((uintptr_t) AS_KERNEL->genarch.page_table); return; } uintptr_t cur; unsigned int identity_flags = PAGE_GLOBAL | PAGE_CACHEABLE | PAGE_EXEC | PAGE_WRITE | PAGE_READ; page_mapping_operations = &pt_mapping_operations; page_table_lock(AS_KERNEL, true); /* * PA2KA(identity) mapping for all low-memory frames. */ for (cur = 0; cur < min(config.identity_size, config.physmem_end); cur += FRAME_SIZE) page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, identity_flags); page_table_unlock(AS_KERNEL, true); exc_register(14, "page_fault", true, (iroutine_t) page_fault); write_cr3((uintptr_t) AS_KERNEL->genarch.page_table); }
void set_pte_v2p(u32int vaddr, u32int pfn) { u32int pd_index, pt_index; u32int pde; u32int pte; u32int *page_table; printf_bochs("create vaddr:%x to pfn: %x\n", vaddr, pfn); pd_index = vaddr / 0x400000; pt_index = vaddr / 0x1000 % 1024; printf_bochs("pd_index:%x pt_index:%x\n", pd_index, pt_index); pde = page_directory[pd_index]; if(!pde) { u32int page_table_pfn; page_table_pfn = alloc_page_pfn();; // ocassionally frame for page table has not been mapped. set_pte_v2p(page_table_pfn<<12, page_table_pfn); pde = page_table_pfn << 12 | 0x23; page_directory[pd_index] = pde; page_table = (u32int*)(page_table_pfn<<12); } else { page_table = (u32int*)(pde & 0xFFFFF000); } pte = pfn << 12 | 0x23; page_table[pt_index] = pte; write_cr3(read_cr3()); }
pgd_t * __init efi_call_phys_prolog(void) { unsigned long vaddress; pgd_t *save_pgd; int pgd; int n_pgds; if (!efi_enabled(EFI_OLD_MEMMAP)) { save_pgd = (pgd_t *)read_cr3(); write_cr3((unsigned long)efi_scratch.efi_pgt); goto out; } early_code_mapping_set_exec(1); n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); save_pgd = kmalloc_array(n_pgds, sizeof(*save_pgd), GFP_KERNEL); for (pgd = 0; pgd < n_pgds; pgd++) { save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE); vaddress = (unsigned long)__va(pgd * PGDIR_SIZE); set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); } out: __flush_tlb_all(); return save_pgd; }
int schedule(long system_timer_ms) { TRACE_MSG(("called system timer: %s", current_process->name)); ///check to see if the process is finished with its timeslice if (current_process->timetorun-- <= 0) { ///reset the current process' time to run count current_process->timetorun = (current_process->priority)*PRIORITY_TO_TIMETORUN; ///look through the process queue until a non-sleeping thread is found processes = processes->next; while (processes->pid->sleep > 0) { processes->pid->sleep--; processes = processes->next; } ///when found, point current_process to the ///non-sleeping thread current_process = processes->pid; TRACE_MSG(("switched process: %s [stack: @0x%x]", current_process->name, current_process->esp)); //change cr3 write_cr3(current_process->cr3); } ///the new esp must be passed back to the scheduler isr! return current_process->esp; }
void PageTable::load() { /* load the current page table */ current_page_table = this; /* write the dir addr to the CR3 register */ write_cr3((unsigned long)page_directory); }
/*------------------------------------------------------------------------- * pfint - paging fault ISR *------------------------------------------------------------------------- */ SYSCALL pfint() { kprintf("---------ISR----------\n"); unsigned int pfaddr = read_cr2();// faulted address //Check that pfaddr is a legal address ???? unsigned int pdbaddr = read_cr3()&(~0xfff); //page directory base address unsigned int p = pfaddr >> 22; // upper ten bits of faulted address unsigned int q = (pfaddr >> 12)&0x3ff; // middle ten bits of faulted address unsigned int offset = pfaddr & 0xfff; // last twelve bits pd_t * pt = (pd_t *)pdbaddr + p ; //pth page table //kprintf("%x\n",*pt); if(pt->pd_pres == 0) // if page table is not present { int frm_num = get_frm(1,FR_TBL,pfaddr>>12); //kprintf("%d\n",frm_num); if(frm_num == SYSERR) return SYSERR; pt->pd_base = (0x00400000 + frm_num*4096) >> 12; pt->pd_pres = 1; write_cr3(pdbaddr); kprintf("faulted addr: %x xth page table: %x, content: %x\n",pfaddr,pt,p); return OK; }
void PageTable::load() { write_cr3((unsigned long)page_directory); //current_page_table = this; Console::putui((unsigned int)read_cr3()); Console::puts("load Hello \n"); }
void pci_enumerate(void) { uint64_t ecam_address = segment_groups[0]; // TODO: factor out temporary mappings extern uint64_t kernel_pml4[], pd_map[]; for (int i = 0; i < 8; i += 2) { pd_map[1 + i / 2] = ecam_address | PAGE_PRESENT | PAGE_WRITE | PAGE_CACHE_UC | PAGE_LARGE | PAGE_GLOBAL; } write_cr3(PHYS_KERNEL(kernel_pml4)); ecam = (volatile void*)0xffffffffc0200000; struct pci_function *root = function_address(0, 0, 0); if ((root->header_type & 0x80) == 0) { enumerate_bus(0); } else { for (uint8_t function_id = 0; function_id < 8; function_id++) { struct pci_function *bus = function_address(0, 0, function_id); if (bus->vendor_id != 0xffff) { break; } enumerate_bus(function_id); } } }
static int __init x86_create_initial_map() { unsigned long phy= 0; unsigned long *p = (unsigned long *)FAK_ARCH_X86_INIT_PGTABLE; //The kernel topmost table int i; for (i = 0; i < 1024; i++) p[i] = 0; /* Kernel part in 4mb page; */ for (i = 0; i < 1024; i++) { if (i == get_loaded_base() / 0x400000) phy = 0; //如果到了内核的地址,还是从0开始映射,因为内核装的物理地址实际是在开头; p[i] = phy | 0x83; //0x183 is the global phy += 0x400000; } write_cr3((unsigned long)p); phy = read_cr4(); phy |= X86_CR4_PSE | X86_CR4_PGE; //允许4MB页 write_cr4(phy); phy = read_cr0(); phy |= X86_CR0_PG; //打开页表; phy &= ~(X86_CR0_CD | X86_CR0_NW); //允许缓存; write_cr0(phy); return 0; }
/* Enable paging on the CPU. Typically, a CPU start with paging disabled, and memory is accessed by addressing physical memory directly. After paging is enabled, memory is addressed logically. */ void PageTable::enable_paging() { //write the page_directory address into CR3 write_cr3((unsigned long)current_page_table->get_page_directory()); //set paging bit in CR0 to 1 write_cr0(read_cr0() | 0x80000000); }
/* * Call this when reinitializing a CPU. It fixes the following potential * problems: * * - The ASID changed from what cpu_tlbstate thinks it is (most likely * because the CPU was taken down and came back up with CR3's PCID * bits clear. CPU hotplug can do this. * * - The TLB contains junk in slots corresponding to inactive ASIDs. * * - The CPU went so far out to lunch that it may have missed a TLB * flush. */ void initialize_tlbstate_and_flush(void) { int i; struct mm_struct *mm = this_cpu_read(cpu_tlbstate.loaded_mm); u64 tlb_gen = atomic64_read(&init_mm.context.tlb_gen); unsigned long cr3 = __read_cr3(); /* Assert that CR3 already references the right mm. */ WARN_ON((cr3 & CR3_ADDR_MASK) != __pa(mm->pgd)); /* * Assert that CR4.PCIDE is set if needed. (CR4.PCIDE initialization * doesn't work like other CR4 bits because it can only be set from * long mode.) */ WARN_ON(boot_cpu_has(X86_FEATURE_PCID) && !(cr4_read_shadow() & X86_CR4_PCIDE)); /* Force ASID 0 and force a TLB flush. */ write_cr3(build_cr3(mm->pgd, 0)); /* Reinitialize tlbstate. */ this_cpu_write(cpu_tlbstate.last_user_mm_ibpb, LAST_USER_MM_IBPB); this_cpu_write(cpu_tlbstate.loaded_mm_asid, 0); this_cpu_write(cpu_tlbstate.next_asid, 1); this_cpu_write(cpu_tlbstate.ctxs[0].ctx_id, mm->context.ctx_id); this_cpu_write(cpu_tlbstate.ctxs[0].tlb_gen, tlb_gen); for (i = 1; i < TLB_NR_DYN_ASIDS; i++) this_cpu_write(cpu_tlbstate.ctxs[i].ctx_id, 0); }
static inline void switch_to_tboot_pt(void) { #ifdef CONFIG_X86_32 load_cr3(initial_page_table); #else write_cr3(real_mode_header->trampoline_pgd); #endif }
void __init paging_init() { init_rootmap(); kprintf("# root pgdir=%x\n", root_map.m_pgdir); kprintf("# root pgtable=%x\n", root_map.m_pgtable); write_cr3((u32)root_map.m_pgdir); write_cr0(read_cr0() | 0x80000000); }
uint32_t loader() { Elf32_Ehdr *elf; Elf32_Phdr *ph = NULL; uint8_t buf[4096]; #ifdef HAS_DEVICE ide_read(buf, ELF_OFFSET_IN_DISK, 4096); #else ramdisk_read(buf, ELF_OFFSET_IN_DISK, 4096); #endif elf = (void*)buf; /* TODO: fix the magic number with the correct one */ const uint32_t elf_magic = 0x7f454c46; uint32_t *p_magic = (void *)buf; nemu_assert(*p_magic == elf_magic); /* Load each program segment */ for(; true; ) { /* Scan the program header table, load each segment into memory */ if(ph->p_type == PT_LOAD) { //PT_LOAT=1, Loadable program segment /* TODO: read the content of the segment from the ELF file * to the memory region [VirtAddr, VirtAddr + FileSiz) */ /* TODO: zero the memory region * [VirtAddr + FileSiz, VirtAddr + MemSiz) */ #ifdef IA32_PAGE /* Record the program break for future use. */ extern uint32_t brk; uint32_t new_brk = ph->p_vaddr + ph->p_memsz - 1; if(brk < new_brk) { brk = new_brk; } #endif } } volatile uint32_t entry = elf->e_entry; #ifdef IA32_PAGE mm_malloc(KOFFSET - STACK_SIZE, STACK_SIZE); #ifdef HAS_DEVICE create_video_mapping(); #endif write_cr3(get_ucr3()); #endif return entry; }
/* set up page tables for kernel */ void init_page(void) { CR0 cr0; CR3 cr3; PDE *pdir = (PDE *)va_to_pa(kpdir); PTE *ptable = (PTE *)va_to_pa(kptable); uint32_t pdir_idx; /* make all PDEs invalid */ memset(pdir, 0, NR_PDE * sizeof(PDE)); /* fill PDEs */ for (pdir_idx = 0; pdir_idx < PHY_MEM / PT_SIZE; pdir_idx ++) { pdir[pdir_idx].val = make_pde(ptable); pdir[pdir_idx + KOFFSET / PT_SIZE].val = make_pde(ptable); ptable += NR_PTE; } /* fill PTEs */ /* We use inline assembly here to fill PTEs for efficiency. * If you do not understand it, refer to the C code below. */ asm volatile ("std;\ 1: stosl;\ subl %0, %%eax;\ jge 1b;\ cld" : : "i"(PAGE_SIZE), "a"((PHY_MEM - PAGE_SIZE) | 0x7), "D"(ptable - 1)); /* ===== referenced code for the inline assembly above ===== uint32_t pframe_addr = PHY_MEM - PAGE_SIZE; ptable --; // fill PTEs reversely for (; pframe_addr >= 0; pframe_addr -= PAGE_SIZE) { ptable->val = make_pte(pframe_addr); ptable --; } */ /* make CR3 to be the entry of page directory */ cr3.val = 0; cr3.page_directory_base = ((uint32_t)pdir) >> 12; write_cr3(cr3.val); /* set PG bit in CR0 to enable paging */ cr0.val = read_cr0(); cr0.paging = 1; write_cr0(cr0.val); }
/* Paging Initialization */ void init_paging() { map_mem(); printf("before: %b,%b ---",read_cr0(),read_cr3()); write_cr3((unsigned long)page_directory); unsigned long cr0 = read_cr0(); cr0 = cr0 | 0x8000000; write_cr0(cr0); printf(" after: %b,%b\n",read_cr0(),read_cr3()); }
/*------------------------------------------------------------------------- * set_PDBR - set the page table base register. *------------------------------------------------------------------------- */ void set_PDBR(int pid){ STATWORD ps; // Disable interrupts disable(ps); unsigned long pdbr = proctab[pid].pdbr; write_cr3(pdbr); if(GDB) kprintf("PDBR %8x set to the base register of proc[%d]: %s\n",pdbr, pid, proctab[pid].pname); restore(ps); }
uint32_t loader() { Elf32_Ehdr *elf; Elf32_Phdr *ph = NULL; uint8_t buf[4096]; #ifdef HAS_DEVICE ide_read(buf, ELF_OFFSET_IN_DISK, 4096); #else ramdisk_read(buf, ELF_OFFSET_IN_DISK, 4096); #endif elf = (void*)buf; /* fix the magic number with the correct one */ const uint32_t elf_magic = 0x464c457f; uint32_t *p_magic = (void *)buf; nemu_assert(*p_magic == elf_magic); /* Load each program segment */ int i; for(i=0;i<elf->e_phnum;i++ ) { /* Scan the program header table, load each segment into memory */ ph=(void *)(elf->e_phoff + i * elf->e_phentsize + buf); if(ph->p_type == PT_LOAD) { //Log("success"); #ifdef IA32_PAGE /* Record the program break for future use. */ extern uint32_t brk; uint32_t new_brk = ph->p_vaddr + ph->p_memsz - 1; if(brk < new_brk) { brk = new_brk; } uint32_t pa=mm_malloc(ph->p_vaddr,ph->p_memsz); #endif #ifndef HAS_DEVICE ramdisk_read((void*)pa, ELF_OFFSET_IN_DISK + ph->p_offset, ph->p_filesz); #else ide_read((void*)pa, ELF_OFFSET_IN_DISK + ph->p_offset, ph->p_filesz); #endif memset((void*)(pa + ph->p_filesz), 0, ph->p_memsz - ph->p_filesz); } } volatile uint32_t entry = elf->e_entry; #ifdef IA32_PAGE mm_malloc(KOFFSET - STACK_SIZE, STACK_SIZE); #ifdef HAS_DEVICE create_video_mapping(); #endif write_cr3(get_ucr3()); #endif return entry; }
/*------------------------------------------------------------------------- * xmunmap - xmunmap *------------------------------------------------------------------------- */ SYSCALL xmunmap(int virtpage ) { STATWORD ps; int getStoreValue, getPageNo; bs_map_t* main_bs; int getReturnValue, bs_no, page_no; unsigned int temp; /* sanity check ! */ if ( (virtpage < 4096) ) { // kprintf("xmummap call error: virtpage (%d) invalid! \n", virtpage); return SYSERR; } disable(ps); //kprintf("\nInside xmunmap().. %d ", virtpage); //getStoreValue = 20; getReturnValue = bsm_lookup(currpid, (virtpage*4096), &getStoreValue, &getPageNo); if (getReturnValue == SYSERR) { // kprintf("xmunmap(): could not find mapping!\n"); restore(ps); return SYSERR; } // kprintf("\nxmunmap(): bs returned %d!\n", getStoreValue); bs_no = getStoreValue; page_no = getPageNo; // For all frames that are mapped decrease their refcnts bstore_dec_fr_refcnt(bs_no, virtpage); getReturnValue = bsm_unmap(currpid, virtpage, bs_no); if( getReturnValue == SYSERR ) { //kprintf("xmummap: bsm_unmap error"); restore(ps); return(SYSERR); } //kprintf("\nxmummap: all OK"); temp = ((proctab[currpid].pdbr)<<12); write_cr3(temp); restore(ps); return(OK); }
/* Wipe all early page tables except for the kernel symbol map */ static void __init reset_early_page_tables(void) { unsigned long i; for (i = 0; i < PTRS_PER_PGD-1; i++) early_level4_pgt[i].pgd = 0; next_early_pgt = 0; write_cr3(__pa(early_level4_pgt)); }
void schedule(void) { if (list_empty(&readyhead)) { current = &idle; return; } current=leaveProcQ(&readyhead, &readylen); enterProcQ(false, current, &readyhead); write_cr3(&(current->cr3)); set_tss_esp0((uint32_t)(current->kstack+4095)); }
void PageTable::load() { /* * Page table loaded into processor context * by loading the page directory address into * the CR3 register */ unsigned long *page_dir_addr = (unsigned long*) page_directory; current_page_table = this; write_cr3((long unsigned int)page_dir_addr); }
/* Enable paging on the CPU. Typically, a CPU start with paging disabled, and memory is accessed by addressing physical memory directly. After paging is enabled, memory is addressed logically. */ void PageTable::enable_paging() { // put the page directory address into CR3. write_cr3((long unsigned int) current_page_table -> addressPageDirectory()); //Set the paging bit in CR0 to 1. write_cr0(read_cr0() | 0x80000000); //Set the paging_enabled bit to 1. paging_enabled = 1; Console::puts("Page Table Enabled\n"); }
void enable_paging (unsigned int pd) { unsigned long cr0; kprintf("load cr3\n"); write_cr3 (pd & ~NBPG); kprintf("enable paging\n"); cr0 = read_cr0 (); cr0 |= CR0_PG; write_cr0 (cr0); cr0 = read_cr0 (); kprintf("cr0: %x, cr3 %x\n", read_cr0(), read_cr3()); }
/** Initialize segmentation - code/data/idt tables * */ void pm_init(void) { descriptor_t *gdt_p = (descriptor_t *) gdtr.base; tss_descriptor_t *tss_desc; /* * Each CPU has its private GDT and TSS. * All CPUs share one IDT. */ if (config.cpu_active == 1) { idt_init(); /* * NOTE: bootstrap CPU has statically allocated TSS, because * the heap hasn't been initialized so far. */ tss_p = &tss; } else { /* We are going to use malloc, which may return * non boot-mapped pointer, initialize the CR3 register * ahead of page_init */ write_cr3((uintptr_t) AS_KERNEL->genarch.page_table); tss_p = (tss_t *) malloc(sizeof(tss_t), FRAME_ATOMIC); if (!tss_p) panic("Cannot allocate TSS."); } tss_initialize(tss_p); tss_desc = (tss_descriptor_t *) (&gdt_p[TSS_DES]); tss_desc->present = 1; tss_desc->type = AR_TSS; tss_desc->dpl = PL_KERNEL; gdt_tss_setbase(&gdt_p[TSS_DES], (uintptr_t) tss_p); gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE - 1); gdtr_load(&gdtr); idtr_load(&idtr); /* * As of this moment, the current CPU has its own GDT pointing * to its own TSS. We just need to load the TR register. */ tr_load(GDT_SELECTOR(TSS_DES)); }
void __init efi_call_phys_epilog(pgd_t *save_pgd) { /* * After the lock is released, the original page table is restored. */ int pgd_idx, i; int nr_pgds; pgd_t *pgd; p4d_t *p4d; pud_t *pud; if (!efi_enabled(EFI_OLD_MEMMAP)) { write_cr3((unsigned long)save_pgd); __flush_tlb_all(); return; } nr_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); for (pgd_idx = 0; pgd_idx < nr_pgds; pgd_idx++) { pgd = pgd_offset_k(pgd_idx * PGDIR_SIZE); set_pgd(pgd_offset_k(pgd_idx * PGDIR_SIZE), save_pgd[pgd_idx]); if (!(pgd_val(*pgd) & _PAGE_PRESENT)) continue; for (i = 0; i < PTRS_PER_P4D; i++) { p4d = p4d_offset(pgd, pgd_idx * PGDIR_SIZE + i * P4D_SIZE); if (!(p4d_val(*p4d) & _PAGE_PRESENT)) continue; pud = (pud_t *)p4d_page_vaddr(*p4d); pud_free(&init_mm, pud); } p4d = (p4d_t *)pgd_page_vaddr(*pgd); p4d_free(&init_mm, p4d); } kfree(save_pgd); __flush_tlb_all(); early_code_mapping_set_exec(0); }
static void load_new_mm_cr3(pgd_t *pgdir, u16 new_asid, bool need_flush) { unsigned long new_mm_cr3; if (need_flush) { invalidate_user_asid(new_asid); new_mm_cr3 = build_cr3(pgdir, new_asid); } else { new_mm_cr3 = build_cr3_noflush(pgdir, new_asid); } /* * Caution: many callers of this function expect * that load_cr3() is serializing and orders TLB * fills with respect to the mm_cpumask writes. */ write_cr3(new_mm_cr3); }
static void __restore_processor_state(struct saved_context *ctxt) { /* * control registers */ /* cr4 was introduced in the Pentium CPU */ if (ctxt->cr4) write_cr4(ctxt->cr4); write_cr3(ctxt->cr3); write_cr2(ctxt->cr2); write_cr0(ctxt->cr0); /* * now restore the descriptor tables to their proper values * ltr is done i fix_processor_context(). */ load_gdt(&ctxt->gdt); load_idt(&ctxt->idt); /* * segment registers */ loadsegment(es, ctxt->es); loadsegment(fs, ctxt->fs); loadsegment(gs, ctxt->gs); loadsegment(ss, ctxt->ss); /* * sysenter MSRs */ if (boot_cpu_has(X86_FEATURE_SEP)) enable_sep_cpu(); /* * restore XCR0 for xsave capable cpu's. */ if (cpu_has_xsave) xsetbv(XCR_XFEATURE_ENABLED_MASK, pcntxt_mask); fix_processor_context(); do_fpu_end(); mtrr_ap_init(); mcheck_init(&boot_cpu_data); }
/** @brief Switch memory context */ void km_arch_ctx_switch(struct km * pre_ctx, struct km * next_ctx) { unsigned long cr3_physical; /* Get physical base of cr3 */ cr3_physical = HAL_GET_BASIC_PHYADDRESS(next_ctx->translation_table); //TODO: not use this macro /* Write to cr3 to switch */ write_cr3(cr3_physical); #if 0 /*load the LDT, if the LDT is different*/ if(unlikely(pre_ctx->ldt!=new_ctx->ldt)) { //printk("\nnew_ctx->ldt :%h,%d.",new_ctx->ldt,new_ctx->ldt_entries); set_ldt(new_ctx->ldt,new_ctx->ldt_entries); } #endif }