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; +}