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;
}
Example #3
0
/*
 * 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
}