IMPLEMENT void* Vmem_alloc::page_alloc (void *address, Zero_fill zf, unsigned mode) { void *vpage = 0; Address page; vpage = Mapped_allocator::allocator()->alloc(Config::PAGE_SHIFT); if (EXPECT_FALSE(!vpage)) return 0; // insert page into master page table Pdir::Iter e = Kmem::kdir->walk(Virt_addr(address), 100, Mapped_allocator::allocator()); if (EXPECT_FALSE(e.e->valid())) { kdb_ke("page_alloc: address already mapped"); goto error; } if (e.shift() != Config::PAGE_SHIFT) goto error; if (zf == ZERO_FILL) memset(vpage, 0, Config::PAGE_SIZE); page = Mem_layout::pmem_to_phys((Address)vpage); *e.e = page | Pt_entry::Writable | Pt_entry::Dirty | Pt_entry::Valid | Pt_entry::Referenced | Pt_entry::global(); page_map (address, 0, zf, page); if (mode & User) e.e->add_attr(Pt_entry::User); return address; error: Mapped_allocator::allocator()->free(Config::PAGE_SHIFT, vpage); // 2^0 = 1 page return 0; }
// Establish a 4k-mapping PUBLIC static void Kmem::map_phys_page(Address phys, Address virt, bool cached, bool global, Address *offs=0) { Pdir::Iter i = kdir->walk(Virt_addr(virt), 100, pdir_alloc(Kmem_alloc::allocator())); Pte_base *e = i.e; Mword pte = phys & Config::PAGE_MASK; assert(i.shift() == Config::PAGE_SHIFT); *e = pte | Pt_entry::Valid | Pt_entry::Writable | Pt_entry::Referenced | Pt_entry::Dirty | (cached ? 0 : (Pt_entry::Write_through | Pt_entry::Noncacheable)) | (global ? Pt_entry::global() : 0); Mem_unit::tlb_flush(virt); if (offs) *offs = phys - pte; }
/* * PPC page cache */ INTERFACE[ppc32]: EXTENSION class Mem_space { private: Status v_insert_cache(Pte_ptr *e, Address virt, size_t size, unsigned page_attribs, Dir_type *dir = 0); unsigned long v_delete_cache(Pt_entry *e, unsigned page_attribs); }; //------------------------------------------------------------------------------ IMPLEMENTATION[ppc32]: IMPLEMENT Mem_space::Status Mem_space::v_insert_cache(Pte_ptr *e, Address virt, size_t size, unsigned page_attribs, Dir_type *dir = 0) { #ifdef FIX_THIS if(!dir) dir = _dir; Pdir::Iter i = dir->walk(Addr(virt), Pdir::Depth, Kmem_alloc::q_allocator(_quota)); if (EXPECT_FALSE(!i.e->valid() && i.shift() != Config::PAGE_SHIFT)) return Insert_err_nomem; Address i_phys; //get physical addresses Pte_htab::pte_lookup(i.e, &i_phys); if(i.e->valid() && e->addr() == i_phys) { Status state = pte_attrib_upgrade(i.e, size, page_attribs); return state; } *i.e = e->raw() | page_attribs; //if super-page, set Pse_bit in Pdir if(size == Config::SUPERPAGE_SIZE) { i = dir->walk(Addr(virt), Pdir::Super_level); *i.e = i.e->raw() | Pte_ptr::Pse_bit; } return Insert_ok; #else (void)e; (void)virt; (void)size; (void)page_attribs; (void)dir; return Insert_err_nomem; #endif } IMPLEMENT unsigned long Mem_space::v_delete_cache(Pt_entry *e, unsigned page_attribs = Page_all_attribs) { #ifdef FIX_THIS unsigned ret; ret = e->raw() & page_attribs; if (!(page_attribs & Page_user_accessible)) // downgrade PDE (superpage) rights e->del_attr(page_attribs); else // delete PDE (superpage) e = 0; return ret; #else (void)e; (void)page_attribs; return 0; #endif }