void enable_paging() { PAGE *addr; PAGE_DIR[0] = make_pde(((uint32_t)KERNEL_PT) >> 12, 0, 1); for(addr = 0; addr < &_START_OF_TEXT_; ++addr) KERNEL_PT[PT_NUM_ADDR(addr)] = make_pte(PT_NUM_ADDR(addr), 1, 0, 1); for(addr = &_START_OF_TEXT_; addr < &_END_OF_RODATA_; ++addr) KERNEL_PT[PT_NUM_ADDR(addr)] = make_pte(PT_NUM_ADDR(addr), 1, 0, 0); for(addr = &_START_OF_DATA_; addr < &_END_OF_BSS_STACK_; ++addr) KERNEL_PT[PT_NUM_ADDR(addr)] = make_pte(PT_NUM_ADDR(addr), 1, 0, 1); __asm__( ".intel_syntax noprefix;" "mov cr3, %0;" "mov eax, cr0;" "or eax, 0x80010000;" "mov cr0, eax;" ".att_syntax;" : :"r"(PAGE_DIR) :"eax" ); }
void map_page(uint32_t *page_dir, uint32_t virt_page_num, uint32_t phy_page_num, bool global, bool user, bool read_write) { uint16_t pd_idx = PD_IDX(virt_page_num), pt_idx = PT_IDX(virt_page_num); uint32_t *page_table; if(!(page_dir[pd_idx] & 0x1)) { uint32_t pt_page_num = alloc_phy_page(0, 1023); map_kernel_page(pt_page_num, pt_page_num, true, false, true); memset((void *)(pt_page_num << 12), 0, 4096); page_dir[pd_idx] = make_pde(pt_page_num, user, read_write); } page_table = (uint32_t *)(page_dir[pd_idx] & 0xfffff000); page_table[pt_idx] = make_pte(phy_page_num, global, user, read_write); ++phy_mem_rc[phy_page_num]; __asm__ volatile( ".intel_syntax noprefix;" "mov eax, cr3;" "mov cr3, eax;" ".att_syntax;" :::"eax" ); }
static inline void create_pte_mapping(unsigned long start, unsigned long end, unsigned long mode, unsigned long mask, int large) { unsigned long addr; HPTE *htab = (HPTE *)__v2a(htab_data.htab); unsigned int step; if (large) step = 16*MB; else step = 4*KB; for (addr = start; addr < end; addr += step) { unsigned long vsid = get_kernel_vsid(addr); unsigned long va = (vsid << 28) | (addr & 0xfffffff); make_pte(htab, va, (unsigned long)__v2a(addr), mode, mask, large); } }
/* * Bolt the kernel addr space into the HPT */ static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr) { unsigned long pa; unsigned long mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; HPTE hpte; for (pa=saddr; pa < eaddr ;pa+=PAGE_SIZE) { unsigned long ea = (unsigned long)__va(pa); unsigned long vsid = get_kernel_vsid( ea ); unsigned long va = ( vsid << 28 ) | ( pa & 0xfffffff ); unsigned long vpn = va >> PAGE_SHIFT; unsigned long slot = HvCallHpt_findValid( &hpte, vpn ); if (hpte.dw0.dw0.v) { /* HPTE exists, so just bolt it */ HvCallHpt_setSwBits(slot, 0x10, 0); } else { /* No HPTE exists, so create a new bolted one */ make_pte(NULL, va, (unsigned long)__v2a(ea), mode_rw, 0, 0); } } }
/* Build a page table for the 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, ptable_idx, pframe_idx; for (pdir_idx = 0; pdir_idx < NR_PDE; pdir_idx ++) { make_invalid_pde(&pdir[pdir_idx]); } pframe_idx = 0; for (pdir_idx = 0; pdir_idx < PHY_MEM / PD_SIZE; pdir_idx ++) { make_pde(&pdir[pdir_idx], ptable); make_pde(&pdir[pdir_idx + KOFFSET / PD_SIZE], ptable); for (ptable_idx = 0; ptable_idx < NR_PTE; ptable_idx ++) { make_pte(ptable, (void*)(pframe_idx << 12)); pframe_idx ++; ptable ++; } } /* make CR3 to be the entry of page directory */ cr3.val = 0; cr3.page_directory_base = ((uint32_t)pdir) >> 12; write_cr3(&cr3); /* set PG bit in CR0 to enable paging */ cr0.val = read_cr0(); cr0.paging = 1; write_cr0(&cr0); /* Now we can access global variables! * Store CR3 in the global variable for future use. */ kcr3.val = cr3.val; }
void create_video_mapping() { /* TODO: create an identical mapping from virtual memory area * [0xa0000, 0xa0000 + SCR_SIZE) to physical memory area * [0xa0000, 0xa0000 + SCR_SIZE) for user program. You may define * some page tables to create this mapping. */ PDE *pdir = (PDE *)get_updir(); PTE *ptable = (PTE *)va_to_pa(vdtable); // ptable += (SCR_SIZE / PAGE_SIZE + 1) * PAGE_SIZE; pdir->val = make_pde(vdtable); // pdir[0 + KOFFSET / PT_SIZE].val = make_pde(vdtable); // ptable --; uint32_t pframe_addr = VMEM_ADDR; int i=0; for(; i<=0xf; i++) { ptable[i+0xa0].val = make_pte(pframe_addr); pframe_addr += PAGE_SIZE; } // panic("please implement me"); }