diff --git a/base-nova/include/base/cap_map.h b/base-nova/include/base/cap_map.h
new file mode 100644
index 0000000000..9493b6d30f
--- /dev/null
+++ b/base-nova/include/base/cap_map.h
@@ -0,0 +1,129 @@
+/*
+ * \brief Mapping of Genode's capability names to capabilities selectors.
+ * \author Alexander Boettcher
+ * \date 2013-08-26
+ *
+ */
+
+/*
+ * Copyright (C) 2013-2013 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _INCLUDE__BASE__CAP_MAP_H_
+#define _INCLUDE__BASE__CAP_MAP_H_
+
+/* Genode includes */
+#include
+
+#include
+
+#include
+#include
+
+namespace Genode {
+
+ class Cap_range : public Avl_node {
+
+ private:
+
+ Lock _lock;
+ addr_t _base;
+ addr_t _last;
+
+ enum {
+ HEADER = sizeof(_base) + sizeof(_lock) + sizeof(_last),
+ CAP_RANGE_SIZE = 4096,
+ WORDS = (CAP_RANGE_SIZE - HEADER - sizeof(Avl_node)) / sizeof(addr_t),
+ };
+
+ uint8_t _cap_array[WORDS * sizeof(addr_t)];
+
+ bool _match(addr_t id) {
+ return _base <= id && id < _base + sizeof(_cap_array); };
+
+ public:
+
+ Cap_range(addr_t base) : _base(base), _last(0) {
+
+ static_assert(sizeof(*this) == CAP_RANGE_SIZE,
+ "Cap_range misconfigured");
+
+ for (unsigned i=0; i < sizeof(_cap_array); i++)
+ _cap_array[i] = 0;
+ }
+
+ addr_t const base() const { return _base; }
+ unsigned const elements() { return sizeof(_cap_array); }
+
+ Cap_range *find_by_id(addr_t);
+
+ void inc(unsigned id, bool inc_if_one = false);
+ void dec(unsigned id, bool revoke = true);
+
+ addr_t alloc(size_t const num_log2);
+
+ /************************
+ ** Avl node interface **
+ ************************/
+
+ bool higher(Cap_range *n) { return n->_base > _base; }
+
+ };
+
+
+ class Cap_index
+ {
+ private:
+
+ Cap_range * _range;
+ addr_t _local_name;
+
+ public:
+
+ Cap_index(Cap_range *range, addr_t local_name)
+ : _range(range), _local_name(local_name) {}
+
+ bool valid() const { return _range; }
+
+ inline void inc(bool inc_if_one = false)
+ {
+ if (_range)
+ _range->inc(_local_name - _range->base(), inc_if_one);
+ }
+
+ inline void dec()
+ {
+ if (_range)
+ _range->dec(_local_name - _range->base());
+ }
+ };
+
+
+ class Capability_map : Noncopyable
+ {
+ private:
+
+ Avl_tree _tree;
+
+ public:
+
+ Cap_index find(addr_t local_sel);
+
+ void insert(Cap_range * range) { _tree.insert(range); }
+
+ addr_t insert(size_t num_log_2 = 0, addr_t cap = ~0UL);
+
+ void remove(addr_t sel, uint8_t num_log_2 = 0, bool revoke = true);
+ };
+
+
+ /**
+ * Get the global Capability_map of the process.
+ */
+ Capability_map *cap_map();
+}
+
+#endif /* _INCLUDE__BASE__CAP_MAP_H_ */
diff --git a/base-nova/lib/mk/base-common.inc b/base-nova/lib/mk/base-common.inc
index 94e8c0b6e9..99f94cfec6 100644
--- a/base-nova/lib/mk/base-common.inc
+++ b/base-nova/lib/mk/base-common.inc
@@ -20,6 +20,7 @@ SRC_CC += lock/lock.cc
SRC_CC += signal/signal.cc signal/common.cc
SRC_CC += server/server.cc
SRC_CC += thread/thread.cc thread/thread_context.cc thread/trace.cc
+SRC_CC += env/cap_map.cc
INC_DIR += $(REP_DIR)/src/base/lock
INC_DIR += $(BASE_DIR)/src/base/lock
diff --git a/base-nova/src/base/env/cap_map.cc b/base-nova/src/base/env/cap_map.cc
new file mode 100644
index 0000000000..524f6e8a02
--- /dev/null
+++ b/base-nova/src/base/env/cap_map.cc
@@ -0,0 +1,157 @@
+/*
+ * \brief Mapping of Genode's capability names to kernel capabilities.
+ * \author Alexander Boettcher
+ * \date 2013-08-26
+ */
+
+/*
+ * Copyright (C) 2013-2013 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#include
+
+/* base-nova specific include */
+#include
+
+using namespace Genode;
+
+
+Capability_map *Genode::cap_map() {
+ static Genode::Capability_map map;
+ return ↦
+}
+
+
+/***********************
+ ** Cap_index class **
+ ***********************/
+
+
+Cap_range *Cap_range::find_by_id(addr_t id)
+{
+ if (_match(id)) return this;
+
+ Cap_range *obj = this->child(id > _base);
+ return obj ? obj->find_by_id(id) : 0;
+}
+
+
+void Cap_range::inc(unsigned id, bool inc_if_one) {
+
+ Lock::Guard guard(_lock);
+
+ if (inc_if_one && _cap_array[id] != 1)
+ return;
+
+ if (_cap_array[id] == 255) {
+// PERR("cap overflow - selector %lx - return address %p",
+// _base + id, __builtin_return_address(0));
+ *reinterpret_cast(0) = 0xdead;
+ }
+
+ _cap_array[id]++;
+}
+
+
+void Cap_range::dec(unsigned id, bool revoke) {
+
+ Lock::Guard guard(_lock);
+
+ if (_cap_array[id] == 0)
+ *reinterpret_cast(0) = 0xdead;
+
+ if (revoke && _cap_array[id] == 1)
+ Nova::revoke(Nova::Obj_crd(_base + id, 0));
+
+ _cap_array[id]--;
+}
+
+
+addr_t Cap_range::alloc(size_t const num_log2)
+{
+ addr_t const step = 1UL << num_log2;
+
+ {
+ Lock::Guard guard(_lock);
+
+ unsigned max = elements();
+ addr_t last = _last;
+
+ do {
+
+ /* align i to num_log2 */
+ unsigned i = ((_base + last + step - 1) & ~(step - 1)) - _base;
+ unsigned j;
+ for (; i + step < max; i += step) {
+ for (j = 0; j < step; j++)
+ if (_cap_array[i+j])
+ break;
+ if (j < step)
+ continue;
+
+ for (j = 0; j < step; j++)
+ _cap_array[i+j] = 1;
+
+ _last = i;
+ return _base + i;
+ }
+
+ max = last;
+ last = 0;
+
+ } while (max);
+ }
+
+ Cap_range *child = this->child(LEFT);
+ if (child) {
+ addr_t res = child->alloc(num_log2);
+ if (res != ~0UL)
+ return res;
+ }
+ child = this->child(RIGHT);
+ if (child) {
+ addr_t res = child->alloc(num_log2);
+ return res;
+ }
+
+ return ~0UL;
+}
+
+
+/****************************
+ ** Capability_map class **
+ ****************************/
+
+
+Cap_index Capability_map::find(Genode::addr_t id) {
+ return Cap_index(_tree.first() ? _tree.first()->find_by_id(id) : 0, id); }
+
+
+addr_t Capability_map::insert(size_t const num_log_2, addr_t const sel)
+{
+ if (sel == ~0UL)
+ return _tree.first() ? _tree.first()->alloc(num_log_2) : ~0UL;
+
+ Cap_range * range = _tree.first() ? _tree.first()->find_by_id(sel) : 0;
+ if (!range)
+ return ~0UL;
+
+ for (unsigned i = 0; i < 1UL << num_log_2; i++)
+ range->inc(sel + i - range->base());
+
+ return sel;
+}
+
+
+void Capability_map::remove(Genode::addr_t sel, uint8_t num_log_2, bool revoke)
+{
+ Cap_range * range = _tree.first() ? _tree.first()->find_by_id(sel) : 0;
+ if (!range)
+ return;
+
+ for (unsigned i = 0; i < 1UL << num_log_2; i++)
+ range->dec(sel + i - range->base(), revoke);
+}