diff --git a/repos/base-hw/lib/mk/x86_64_muen/core.mk b/repos/base-hw/lib/mk/x86_64_muen/core.mk
index 8497051d6..2c0d4bc96 100644
--- a/repos/base-hw/lib/mk/x86_64_muen/core.mk
+++ b/repos/base-hw/lib/mk/x86_64_muen/core.mk
@@ -18,6 +18,7 @@ SRC_S += spec/x86_64/crt0.s
# add C++ sources
SRC_CC += spec/x86_64_muen/platform_support.cc
+SRC_CC += spec/x86_64_muen/sinfo.cc
SRC_CC += spec/x86_64/kernel/thread_base.cc
SRC_CC += spec/x86_64/idt.cc
SRC_CC += spec/x86_64/tss.cc
diff --git a/repos/base-hw/src/core/include/spec/x86_64_muen/sinfo.h b/repos/base-hw/src/core/include/spec/x86_64_muen/sinfo.h
new file mode 100644
index 000000000..e889ea4cf
--- /dev/null
+++ b/repos/base-hw/src/core/include/spec/x86_64_muen/sinfo.h
@@ -0,0 +1,138 @@
+/*
+ * \brief Muen subject information API
+ * \author Reto Buerki
+ * \date 2015-04-21
+ *
+ * Defines functions to retrieve information about the execution environment of
+ * a subject running on the Muen Separation Kernel.
+ */
+
+/*
+ * Copyright (C) 2015 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 _SINFO_H
+#define _SINFO_H
+
+#include
+
+namespace Genode
+{
+ /**
+ * Muen Subject Info class
+ */
+ class Sinfo;
+}
+
+class Genode::Sinfo
+{
+ public:
+
+ enum Config {
+ MAX_NAME_LENGTH = 63,
+ };
+
+ Sinfo();
+
+ /* Structure holding information about a memory region */
+ struct Memregion_info {
+ char name[MAX_NAME_LENGTH + 1];
+ uint64_t address;
+ uint64_t size;
+ bool writable;
+ bool executable;
+ };
+
+ /* Structure holding information about a Muen channel */
+ struct Channel_info {
+ char name[MAX_NAME_LENGTH + 1];
+ uint64_t address;
+ uint64_t size;
+ uint8_t event_number;
+ uint8_t vector;
+ bool writable;
+ bool has_event;
+ bool has_vector;
+ };
+
+ /*
+ * Check Muen sinfo Magic.
+ */
+ static bool check_magic(void);
+
+ /*
+ * Return information for a channel given by name.
+ *
+ * If no channel with given name exists, False is returned. The
+ * event_number and vector parameters are only valid if indicated by
+ * the has_[event|vector] struct members.
+ */
+ static bool get_channel_info(const char * const name,
+ struct Channel_info *channel);
+
+ /*
+ * Return information for a memory region given by name.
+ *
+ * If no memory region with given name exists, False is returned.
+ */
+ static bool get_memregion_info(const char * const name,
+ struct Memregion_info *memregion);
+
+ /*
+ * Channel callback.
+ *
+ * Used in the muen_for_each_channel function. The optional void data pointer
+ * can be used to pass additional data.
+ */
+ typedef bool (*Channel_cb)(const struct Channel_info * const channel,
+ void *data);
+
+ /*
+ * Invoke given callback function for each available channel.
+ *
+ * Channel information and the optional data argument are passed to each
+ * invocation of the callback. If a callback invocation returns false,
+ * processing is aborted and false is returned to the caller.
+ */
+ static bool for_each_channel(Channel_cb func, void *data);
+
+ /*
+ * Memory region callback.
+ *
+ * Used in the muen_for_each_memregion function. The optional void data pointer
+ * can be used to pass additional data.
+ */
+ typedef bool (*Memregion_cb)(const struct Memregion_info * const memregion,
+ void *data);
+
+ /*
+ * Invoke given callback function for each available memory region.
+ *
+ * Memory region information and the optional data argument are passed to each
+ * invocation of the callback. If a callback invocation returns false,
+ * processing is aborted and false is returned to the caller.
+ */
+ static bool for_each_memregion(Memregion_cb func, void *data);
+
+ /*
+ * Return TSC tick rate in kHz.
+ *
+ * The function returns 0 if the TSC tick rate cannot be retrieved.
+ */
+ static uint64_t get_tsc_khz(void);
+
+ /*
+ * Return start time of current minor frame in TSC ticks.
+ */
+ static uint64_t get_sched_start(void);
+
+ /*
+ * Return end time of current minor frame in TSC ticks.
+ */
+ static uint64_t get_sched_end(void);
+};
+
+#endif /* _SINFO_H */
diff --git a/repos/base-hw/src/core/spec/x86_64_muen/musinfo.h b/repos/base-hw/src/core/spec/x86_64_muen/musinfo.h
new file mode 100644
index 000000000..34ce743cb
--- /dev/null
+++ b/repos/base-hw/src/core/spec/x86_64_muen/musinfo.h
@@ -0,0 +1,59 @@
+#ifndef MUSINFO_H_
+#define MUSINFO_H_
+
+#include
+
+#define MUEN_SUBJECT_INFO_MAGIC 0x01006f666e69756dULL
+#define MAX_NAME_LENGTH 63
+#define MAX_RESOURCE_COUNT 255
+#define NO_RESOURCE 0
+
+using namespace Genode;
+
+struct name_type {
+ uint8_t length;
+ char data[MAX_NAME_LENGTH];
+} __attribute__((packed));
+
+#define MEM_WRITABLE_FLAG (1 << 0)
+#define MEM_EXECUTABLE_FLAG (1 << 1)
+
+struct memregion_type {
+ uint64_t address;
+ uint64_t size;
+ uint8_t flags;
+ char padding[7];
+} __attribute__((packed, aligned (8)));
+
+#define CHAN_EVENT_FLAG (1 << 0)
+#define CHAN_VECTOR_FLAG (1 << 1)
+
+struct channel_info_type {
+ uint8_t flags;
+ uint8_t event;
+ uint8_t vector;
+ char padding[5];
+} __attribute__((packed, aligned (8)));
+
+struct resource_type {
+ struct name_type name;
+ uint8_t memregion_idx;
+ uint8_t channel_info_idx;
+ char padding[6];
+} __attribute__((packed, aligned (8)));
+
+struct subject_info_type {
+ uint64_t magic;
+ uint8_t resource_count;
+ uint8_t memregion_count;
+ uint8_t channel_info_count;
+ char padding[5];
+ uint64_t tsc_khz;
+ uint64_t tsc_schedule_start;
+ uint64_t tsc_schedule_end;
+ struct resource_type resources[MAX_RESOURCE_COUNT];
+ struct memregion_type memregions[MAX_RESOURCE_COUNT];
+ struct channel_info_type channels_info[MAX_RESOURCE_COUNT];
+} __attribute__((packed, aligned (8)));
+
+#endif /* MUSINFO_H_ */
diff --git a/repos/base-hw/src/core/spec/x86_64_muen/sinfo.cc b/repos/base-hw/src/core/spec/x86_64_muen/sinfo.cc
new file mode 100644
index 000000000..baba1e3af
--- /dev/null
+++ b/repos/base-hw/src/core/spec/x86_64_muen/sinfo.cc
@@ -0,0 +1,228 @@
+/*
+ * \brief Muen subject information API impl
+ * \author Reto Buerki
+ * \date 2015-04-21
+ */
+
+/*
+ * Copyright (C) 2015 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
+#include
+#include
+
+#include "musinfo.h"
+
+enum {
+ SINFO_BASE_ADDR = 0xe00000000,
+};
+
+static const subject_info_type *
+const sinfo = ((subject_info_type *)SINFO_BASE_ADDR);
+
+/* Log channel information */
+static bool log_channel(
+ const struct Genode::Sinfo::Channel_info * const channel,
+ void *data)
+{
+ if (channel->has_event || channel->has_vector) {
+ PDBG("muen-sinfo: [%s with %s %03d] %s\n",
+ channel->writable ? "writer" : "reader",
+ channel->has_event ? "event " : "vector",
+ channel->has_event ? channel->event_number : channel->vector,
+ channel->name);
+ } else {
+ PDBG("muen-sinfo: [%s with no %s ] %s\n",
+ channel->writable ? "writer" : "reader",
+ channel->writable ? "event " : "vector",
+ channel->name);
+ }
+
+ return true;
+}
+
+/* Log memory region information */
+static bool log_memregion(
+ const struct Genode::Sinfo::Memregion_info * const region,
+ void *data)
+{
+ PDBG("muen-sinfo: [addr 0x%016llx size 0x%016llx %s%s] %s\n",
+ region->address, region->size,
+ region->writable ? "rw" : "ro",
+ region->executable ? "x" : "-", region->name);
+ return true;
+}
+
+/* Fill channel struct with channel information from resource given by index */
+static void fill_channel_data(
+ uint8_t idx,
+ struct Genode::Sinfo::Channel_info *channel)
+{
+ const struct resource_type resource = sinfo->resources[idx];
+ const struct memregion_type memregion =
+ sinfo->memregions[resource.memregion_idx - 1];
+ const struct channel_info_type channel_info =
+ sinfo->channels_info[resource.channel_info_idx - 1];
+
+ memset(&channel->name, 0, MAX_NAME_LENGTH + 1);
+ memcpy(&channel->name, resource.name.data, resource.name.length);
+
+ channel->address = memregion.address;
+ channel->size = memregion.size;
+ channel->writable = memregion.flags & MEM_WRITABLE_FLAG;
+
+ channel->has_event = channel_info.flags & CHAN_EVENT_FLAG;
+ channel->event_number = channel_info.event;
+ channel->has_vector = channel_info.flags & CHAN_VECTOR_FLAG;
+ channel->vector = channel_info.vector;
+}
+
+/* Fill memregion struct with memory region info from resource given by index */
+static void fill_memregion_data(
+ uint8_t idx,
+ struct Genode::Sinfo::Memregion_info *region)
+{
+ const struct resource_type resource = sinfo->resources[idx];
+ const struct memregion_type memregion =
+ sinfo->memregions[resource.memregion_idx - 1];
+
+ memset(®ion->name, 0, MAX_NAME_LENGTH + 1);
+ memcpy(®ion->name, resource.name.data, resource.name.length);
+
+ region->address = memregion.address;
+ region->size = memregion.size;
+ region->writable = memregion.flags & MEM_WRITABLE_FLAG;
+ region->executable = memregion.flags & MEM_EXECUTABLE_FLAG;
+}
+
+/* Returns true if the given resource is a memory region */
+static bool is_memregion(const struct resource_type * const resource)
+{
+ return resource->memregion_idx != NO_RESOURCE;
+}
+
+/* Returns true if the given resource is a channel */
+static bool is_channel(const struct resource_type * const resource)
+{
+ return is_memregion(resource) && resource->channel_info_idx != NO_RESOURCE;
+}
+
+Sinfo::Sinfo()
+{
+ if (!check_magic()) {
+ PERR("muen-sinfo: Subject information MAGIC mismatch\n");
+ return;
+ }
+
+ PINF("muen-sinfo: Subject information exports %d memory region(s)\n",
+ sinfo->memregion_count);
+ for_each_memregion(log_memregion, 0);
+ PINF("muen-sinfo: Subject information exports %d channel(s)\n",
+ sinfo->channel_info_count);
+ for_each_channel(log_channel, 0);
+}
+
+bool Sinfo::check_magic(void)
+{
+ return sinfo != 0 && sinfo->magic == MUEN_SUBJECT_INFO_MAGIC;
+}
+
+bool Sinfo::get_channel_info(const char * const name,
+ struct Channel_info *channel)
+{
+ int i;
+
+ if (!check_magic())
+ return false;
+
+ for (i = 0; i < sinfo->resource_count; i++) {
+ if (is_channel(&sinfo->resources[i]) &&
+ strcmp(sinfo->resources[i].name.data, name) == 0) {
+ fill_channel_data(i, channel);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Sinfo::get_memregion_info(const char * const name,
+ struct Memregion_info *memregion)
+{
+ int i;
+
+ if (!check_magic())
+ return false;
+
+ for (i = 0; i < sinfo->resource_count; i++) {
+ if (is_memregion(&sinfo->resources[i]) &&
+ strcmp(sinfo->resources[i].name.data, name) == 0) {
+ fill_memregion_data(i, memregion);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Sinfo::for_each_channel(Channel_cb func, void *data)
+{
+ int i;
+ struct Channel_info current_channel;
+
+ if (!check_magic())
+ return false;
+
+ for (i = 0; i < sinfo->resource_count; i++) {
+ if (is_channel(&sinfo->resources[i])) {
+ fill_channel_data(i, ¤t_channel);
+ if (!func(¤t_channel, data))
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Sinfo::for_each_memregion(Memregion_cb func, void *data)
+{
+ int i;
+ struct Memregion_info current_region;
+
+ if (!check_magic())
+ return false;
+
+ for (i = 0; i < sinfo->resource_count; i++) {
+ if (is_memregion(&sinfo->resources[i])) {
+ fill_memregion_data(i, ¤t_region);
+ if (!func(¤t_region, data))
+ return false;
+ }
+ }
+ return true;
+}
+
+uint64_t Sinfo::get_tsc_khz(void)
+{
+ if (!check_magic())
+ return 0;
+
+ return sinfo->tsc_khz;
+}
+
+uint64_t Sinfo::get_sched_start(void)
+{
+ if (!check_magic())
+ return 0;
+
+ return sinfo->tsc_schedule_start;
+}
+
+uint64_t Sinfo::get_sched_end(void)
+{
+ if (!check_magic())
+ return 0;
+
+ return sinfo->tsc_schedule_end;
+}