The Muen Sinfo API is used to retrieve information about the execution environment of a subject running on the Muen Separation Kernel. While the C++ API is defined in sinfo.h, musinfo.h specifies the internal format of the information stored in the Sinfo pages provided by the Muen SK. It is a copy of the file contained in the libmusinfo library of the Muen project. That is the reason why the coding style in this file differs from the official style.
229 lines
5.5 KiB
C++
229 lines
5.5 KiB
C++
/*
|
|
* \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 <base/printf.h>
|
|
#include <util/string.h>
|
|
#include <sinfo.h>
|
|
|
|
#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;
|
|
}
|