unsigned long
Generic_obj_space<SPACE>::v_delete(Page_number virt, Size size,
                                   unsigned long page_attribs = L4_fpage::CRWSD)
{
  (void)size;
  assert (size.value() == 1);

  Entry *c;
  if (Optimize_local
      && mem_space() == Mem_space::current_mem_space(current_cpu()))
    {
      c = cap_virt(virt.value());
      if (!c)
	return 0;

      Capability cap = Mem_layout::read_special_safe((Capability*)c);
      if (!cap.valid())
	return 0;
    }
  else
    c = get_cap(virt.value());

  if (c && c->valid())
    {
      if (page_attribs & L4_fpage::R)
        c->invalidate();
      else
        c->del_rights(page_attribs & L4_fpage::CWSD);
    }

  return 0;
}
Obj_space_virt<SPACE>::v_delete(V_pfn virt, Order size,
                                   L4_fpage::Rights page_attribs)
{
  (void)size;
  assert (size == Order(0));

  Entry *c;
  if (Optimize_local
      && SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
    {
      c = cap_virt(virt);
      if (!c)
	return L4_fpage::Rights(0);

      Capability cap = Mem_layout::read_special_safe((Capability*)c);
      if (!cap.valid())
	return L4_fpage::Rights(0);
    }
  else
    c = get_cap(virt);

  if (c && c->valid())
    {
      if (page_attribs & L4_fpage::Rights::R())
        c->invalidate();
      else
        c->del_rights(page_attribs & L4_fpage::Rights::CWSD());
    }

  return L4_fpage::Rights(0);
}
bool
Generic_obj_space<SPACE>::v_lookup(Addr const &virt, Phys_addr *phys = 0,
                                   Size *size = 0, unsigned *attribs = 0)
{
  if (size) size->set_value(1);
  Entry *cap;

  if (Optimize_local
      && mem_space() == Mem_space::current_mem_space(current_cpu()))
    cap = cap_virt(virt.value());
  else
    cap = get_cap(virt.value());

  if (EXPECT_FALSE(!cap))
    {
      if (size) size->set_value(Caps_per_page);
      return false;
    }

  if (Optimize_local)
    {
      Capability c = Mem_layout::read_special_safe((Capability*)cap);

      if (phys) *phys = c.obj();
      if (c.valid() && attribs) *attribs = c.rights();
      return c.valid();
    }
  else
    {
      Obj::set_entry(virt, cap);
      if (phys) *phys = cap->obj();
      if (cap->valid() && attribs) *attribs = cap->rights();
      return cap->valid();
    }
}
Kobject_iface *
Obj_space_virt<SPACE>::lookup_local(Cap_index virt, L4_fpage::Rights *rights)
{
  virt &= Cap_index(~(~0UL << Whole_space));
  Capability *c = reinterpret_cast<Capability*>(cap_virt(virt));
  Capability cap = Mem_layout::read_special_safe(c);
  if (rights) *rights = L4_fpage::Rights(cap.rights());
  return cap.obj();
}
Kobject_iface *
Generic_obj_space<SPACE>::lookup_local(Address virt, unsigned char *rights = 0)
{
  virt &= ~(~0UL << Whole_space);
  Capability *c = reinterpret_cast<Capability*>(cap_virt(virt));
  Capability cap = Mem_layout::read_special_safe(c);
  if (rights) *rights = cap.rights();
  return cap.obj();
}
typename Obj_space_virt<SPACE>::Entry *
Obj_space_virt<SPACE>::get_cap(Cap_index index)
{
  Mem_space *ms = SPACE::mem_space(this);

  Address phys = Address(ms->virt_to_phys((Address)cap_virt(index)));
  if (EXPECT_FALSE(phys == ~0UL))
    return 0;

  return reinterpret_cast<Entry*>(Mem_layout::phys_to_pmem(phys));
}
typename Generic_obj_space<SPACE>::Entry *
Generic_obj_space<SPACE>::alien_lookup(Address index)
{
  Mem_space *ms = mem_space();

  Address phys = Address(ms->virt_to_phys((Address)cap_virt(index)));
  if (EXPECT_FALSE(phys == ~0UL))
    return 0;

  return reinterpret_cast<Entry*>(Mem_layout::phys_to_pmem(phys));
}
typename Obj_space_virt<SPACE>::Capability __attribute__((__flatten__))
Obj_space_virt<SPACE>::lookup(Cap_index virt)
{
  Capability *c;
  virt &= Cap_index(~(~0UL << Whole_space));

  if (SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
    c = reinterpret_cast<Capability*>(cap_virt(virt));
  else
    c = get_cap(virt);

  if (EXPECT_FALSE(!c))
    return Capability(0); // void

  return Mem_layout::read_special_safe(c);
}
typename Generic_obj_space<SPACE>::Capability
Generic_obj_space<SPACE>::lookup(Address virt)
{
  Capability *c;
  virt &= ~(~0UL << Whole_space);

  if (mem_space() == Mem_space::current_mem_space(current_cpu()))
    c = reinterpret_cast<Capability*>(cap_virt(virt));
  else
    c = get_cap(virt);

  if (EXPECT_FALSE(!c))
    return Capability(0); // void

  return Mem_layout::read_special_safe(c);
}
typename Generic_obj_space<SPACE>::Status
Generic_obj_space<SPACE>::v_insert(Phys_addr phys, Addr const &virt, Size size,
                                   unsigned char page_attribs)
{
  (void)size;
  assert (size.value() == 1);

  Entry *c;

  if (Optimize_local
      && mem_space() == Mem_space::current_mem_space(current_cpu()))
    {
      c = cap_virt(virt.value());
      if (!c)
	return Insert_err_nomem;

      Capability cap;
      if (!Mem_layout::read_special_safe((Capability*)c, cap)
	  && !caps_alloc(virt.value()))
	return Insert_err_nomem;
    }
  else
    {
      c = alien_lookup(virt.value());
      if (!c && !(c = caps_alloc(virt.value())))
	return Insert_err_nomem;
      Obj::set_entry(virt, c);
    }

  if (c->valid())
    {
      if (c->obj() == phys)
	{
	  if (EXPECT_FALSE(c->rights() == page_attribs))
	    return Insert_warn_exists;

	  c->add_rights(page_attribs);
	  return Insert_warn_attrib_upgrade;
	}
      else
	return Insert_err_exists;
    }

  c->set(phys, page_attribs);
  return Insert_ok;
}
Obj_space_virt<SPACE>::v_insert(Phys_addr phys, V_pfn const &virt, Order size,
                                Attr page_attribs)
{
  (void)size;
  assert (size == Order(0));

  Entry *c;

  if (Optimize_local
      && SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
    {
      c = cap_virt(virt);
      if (!c)
	return Obj::Insert_err_nomem;

      Capability cap;
      if (!Mem_layout::read_special_safe((Capability*)c, cap)
	  && !caps_alloc(virt))
	return Obj::Insert_err_nomem;
    }
  else
    {
      c = get_cap(virt);
      if (!c && !(c = caps_alloc(virt)))
	return Obj::Insert_err_nomem;
      Obj::set_entry(virt, c);
    }

  if (c->valid())
    {
      if (c->obj() == phys)
	{
	  if (EXPECT_FALSE(c->rights() == page_attribs))
	    return Obj::Insert_warn_exists;

	  c->add_rights(page_attribs);
	  return Obj::Insert_warn_attrib_upgrade;
	}
      else
	return Obj::Insert_err_exists;
    }

  c->set(phys, page_attribs);
  return Obj::Insert_ok;
}
/*inline NEEDS["kmem_alloc.h", <cstring>, "ram_quota.h",
                     Obj_space_virt::cap_virt]*/
typename Obj_space_virt<SPACE>::Entry *
Obj_space_virt<SPACE>::caps_alloc(Cap_index virt)
{
  Address cv = (Address)cap_virt(virt);
  void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(SPACE::ram_quota(this), Config::PAGE_SIZE);

  if (!mem)
    return 0;

  Obj::add_cap_page_dbg_info(mem, SPACE::get_space(this), cxx::int_value<Cap_index>(virt));

  Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword));

  Mem_space::Status s;
  s = SPACE::mem_space(this)->v_insert(
      Mem_space::Phys_addr(Mem_space::kernel_space()->virt_to_phys((Address)mem)),
      cxx::mask_lsb(Virt_addr(cv), Mem_space::Page_order(Config::PAGE_SHIFT)),
      Mem_space::Page_order(Config::PAGE_SHIFT),
      Mem_space::Attr(L4_fpage::Rights::RW()));
      //| Mem_space::Page_referenced | Mem_space::Page_dirty);

  switch (s)
    {
    case Mem_space::Insert_ok:
      break;
    case Mem_space::Insert_warn_exists:
    case Mem_space::Insert_warn_attrib_upgrade:
      assert (false);
      break;
    case Mem_space::Insert_err_exists:
    case Mem_space::Insert_err_nomem:
      Kmem_alloc::allocator()->q_unaligned_free(SPACE::ram_quota(this),
          Config::PAGE_SIZE, mem);
      return 0;
    };

  unsigned long cap = cv & (Config::PAGE_SIZE - 1) | (unsigned long)mem;

  return reinterpret_cast<Entry*>(cap);
}
/*inline NEEDS["mapped_alloc.h", <cstring>, "ram_quota.h",
                     Generic_obj_space::cap_virt]*/
typename Generic_obj_space<SPACE>::Entry *
Generic_obj_space<SPACE>::caps_alloc(Address virt)
{
  Address cv = (Address)cap_virt(virt);
  void *mem = Mapped_allocator::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);

  if (!mem)
    return 0;

  add_dbg_info(mem, this, virt);

  Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword));

  Mem_space::Status s;
  s = mem_space()->v_insert(
      Mem_space::Phys_addr::create(Mem_space::kernel_space()->virt_to_phys((Address)mem)),
      Mem_space::Addr::create(cv).trunc(Mem_space::Size::create(Config::PAGE_SIZE)),
      Mem_space::Size::create(Config::PAGE_SIZE),
      Mem_space::Page_cacheable | Mem_space::Page_writable
      | Mem_space::Page_referenced | Mem_space::Page_dirty);

  switch (s)
    {
    case Insert_ok:
    case Insert_warn_exists:
    case Insert_warn_attrib_upgrade:
    case Insert_err_exists:
      break;
    case Insert_err_nomem:
      Mapped_allocator::allocator()->q_unaligned_free(ram_quota(),
          Config::PAGE_SIZE, mem);
      return 0;
    };

  unsigned long cap = cv & (Config::PAGE_SIZE - 1) | (unsigned long)mem;

  return reinterpret_cast<Entry*>(cap);
}
Obj_space_virt<SPACE>::v_lookup(V_pfn const &virt, Phys_addr *phys,
                                   Page_order *size, Attr *attribs)
{
  if (size) *size = Order(0);
  Entry *cap;

  if (Optimize_local
      && SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
    cap = cap_virt(virt);
  else
    cap = get_cap(virt);

  if (EXPECT_FALSE(!cap))
    {
      if (size) *size = Order(Obj::Caps_per_page_ld2);
      return false;
    }

  if (Optimize_local)
    {
      Capability c = Mem_layout::read_special_safe((Capability*)cap);

      if (phys) *phys = c.obj();
      if (c.valid() && attribs)
        *attribs = Attr(c.rights());
      return c.valid();
    }
  else
    {
      Obj::set_entry(virt, cap);
      if (phys) *phys = cap->obj();
      if (cap->valid() && attribs)
        *attribs = Attr(cap->rights());
      return cap->valid();
    }
}