muen: Update sinfo to variant resources API

This commit is contained in:
Reto Buerki 2018-03-27 14:46:26 +02:00 committed by Christian Helmuth
parent 5c3461a851
commit 810f59b555
9 changed files with 227 additions and 394 deletions

View File

@ -19,8 +19,8 @@
#include <base/stdint.h> #include <base/stdint.h>
struct subject_info_type; struct Subject_info_type;
struct scheduling_info_type; struct Scheduling_info_type;
namespace Genode namespace Genode
{ {
@ -35,14 +35,27 @@ class Genode::Sinfo
public: public:
enum Config { enum Config {
PHYSICAL_BASE_ADDR = 0xe00000000, MUEN_SUBJECT_INFO_MAGIC = 0x02006f666e69756dULL,
SIZE = 0x9000, MAX_RESOURCE_COUNT = 255,
MAX_NAME_LENGTH = 63, MAX_NAME_LENGTH = 63,
HASH_LENGTH = 32, PHYSICAL_BASE_ADDR = 0xe00000000,
SIZE = 0x8000,
HASH_LENGTH = 32,
MEM_WRITABLE_FLAG = (1 << 0),
MEM_EXECUTABLE_FLAG = (1 << 1),
MEM_CHANNEL_FLAG = (1 << 2),
DEV_MSI_FLAG = (1 << 0),
}; };
Sinfo(const addr_t base_addr); Sinfo(const addr_t base_addr);
/* Resource name */
struct Name_type {
uint8_t length;
char data[MAX_NAME_LENGTH];
uint8_t null_term;
} __attribute__((packed));
enum Content { enum Content {
CONTENT_UNINITIALIZED, CONTENT_UNINITIALIZED,
CONTENT_FILL, CONTENT_FILL,
@ -50,42 +63,67 @@ class Genode::Sinfo
}; };
/* Structure holding information about a memory region */ /* Structure holding information about a memory region */
struct Memregion_info { struct Memregion_type {
enum Content content; enum Content content;
char name[MAX_NAME_LENGTH + 1];
uint64_t address; uint64_t address;
uint64_t size; uint64_t size;
bool writable;
bool executable;
uint8_t hash[HASH_LENGTH]; uint8_t hash[HASH_LENGTH];
uint8_t flags;
uint16_t pattern; uint16_t pattern;
}; char padding[1];
} __attribute__((packed));
/* Structure holding information about a Muen channel */ /*
struct Channel_info { * Structure holding information about a PCI device,
char name[MAX_NAME_LENGTH + 1]; * explicitly padded to the size of the largest resource variant
uint64_t address; */
uint64_t size; struct Device_type {
uint8_t event_number;
uint8_t vector;
bool writable;
bool has_event;
bool has_vector;
};
/* Structure holding information about PCI devices */
struct Dev_info {
uint16_t sid; uint16_t sid;
uint16_t irte_start; uint16_t irte_start;
uint8_t irq_start; uint8_t irq_start;
uint8_t ir_count; uint8_t ir_count;
bool msi_capable; uint8_t flags;
char padding[sizeof(struct Memregion_type) - 7];
} __attribute__((packed));
/* Currently known resource types */
enum Resource_kind {
RES_NONE,
RES_MEMORY,
RES_EVENT,
RES_VECTOR,
RES_DEVICE
}; };
/* Resource data depending on the kind of resource */
union Resource_data {
struct Memregion_type mem;
struct Device_type dev;
uint8_t number;
};
/* Exported resource with associated name */
struct Resource_type {
enum Resource_kind kind;
struct Name_type name;
char padding[3];
union Resource_data data;
} __attribute__((packed));
/* Muen subject information (sinfo) structure */
struct Subject_info_type {
uint64_t magic;
uint32_t tsc_khz;
struct Name_type name;
uint16_t resource_count;
char padding[1];
struct Resource_type resources[MAX_RESOURCE_COUNT];
} __attribute__((packed));
/* /*
* Check Muen sinfo Magic. * Check Muen sinfo Magic.
*/ */
bool check_magic(void); bool check_magic(void) const;
/* /*
* Return subject name. * Return subject name.
@ -95,83 +133,55 @@ class Genode::Sinfo
const char * get_subject_name(void); const char * get_subject_name(void);
/* /*
* Return information for a channel given by name. * Return resource with given name and kind.
* *
* If no channel with given name exists, False is returned. The * If no resource with given name exists, null is returned.
* event_number and vector parameters are only valid if indicated by
* the has_[event|vector] struct members.
*/ */
bool get_channel_info(const char * const name, const struct Resource_type *
struct Channel_info *channel); get_resource(const char *const name, enum Resource_kind kind) const;
/*
* Return information for a memory region given by name.
*
* If no memory region with given name exists, False is returned.
*/
bool get_memregion_info(const char * const name,
struct Memregion_info *memregion);
/* /*
* Return information for PCI device with given SID. * Return information for PCI device with given SID.
* *
* The function returns false if no device information for the * The function returns null if no device information for the specified device
* specified device exists. * exists.
*/ */
bool get_dev_info(const uint16_t sid, struct Dev_info *dev); const struct Device_type * get_device(const uint16_t sid) const;
/* /*
* Channel callback. * Resource callback.
* *
* Used in the muen_for_each_channel function. The optional void data pointer * Used in the for_each_resource function. The optional void data
* can be used to pass additional data. * pointer can be used to pass additional data.
*/ */
typedef bool (*Channel_cb)(const struct Channel_info * const channel, typedef bool (*resource_cb)(const struct Resource_type *const res,
void *data); void *data);
/* /*
* Invoke given callback function for each available channel. * Invoke given callback function for each available resource.
* *
* Channel information and the optional data argument are passed to each * Resource information and the optional data argument are passed to each
* invocation of the callback. If a callback invocation returns false, * invocation of the callback. If a callback invocation returns false,
* processing is aborted and false is returned to the caller. * processing is aborted and false is returned to the caller.
*/ */
bool for_each_channel(Channel_cb func, void *data); bool for_each_resource(resource_cb func, void *data) const;
/*
* 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.
*/
bool for_each_memregion(Memregion_cb func, void *data);
/* /*
* Return TSC tick rate in kHz. * Return TSC tick rate in kHz.
* *
* The function returns 0 if the TSC tick rate cannot be retrieved. * The function returns 0 if the TSC tick rate cannot be retrieved.
*/ */
uint64_t get_tsc_khz(void); uint64_t get_tsc_khz(void) const;
/* /*
* Return start time of current minor frame in TSC ticks. * Return start time of current minor frame in TSC ticks.
*/ */
uint64_t get_sched_start(void); uint64_t get_sched_start(void) const;
/* /*
* Return end time of current minor frame in TSC ticks. * Return end time of current minor frame in TSC ticks.
*/ */
uint64_t get_sched_end(void); uint64_t get_sched_end(void) const;
/* /*
* Log sinfo status. * Log sinfo status.
@ -180,25 +190,22 @@ class Genode::Sinfo
private: private:
subject_info_type * sinfo = nullptr; Subject_info_type * sinfo = nullptr;
scheduling_info_type * sched_info = nullptr; Scheduling_info_type * sched_info = nullptr;
char subject_name[MAX_NAME_LENGTH + 1]; char subject_name[MAX_NAME_LENGTH + 1];
bool subject_name_set = false; bool subject_name_set = false;
/* /*
* Fill memregion struct with memory region info from resource given by * Iterate over all resources beginning at given start resource. If the res
* index. * member of the iterator is nil, the function (re)starts the iteration at the first
* resource.
*/ */
void fill_memregion_data(uint8_t idx, struct Memregion_info *region); struct iterator {
const struct Resource_type *res;
unsigned int idx;
};
/* bool iterate_resources(struct iterator *const iter) const;
* Fill channel struct with channel information from resource given by
* index.
*/
void fill_channel_data(uint8_t idx, struct Channel_info *channel);
/* Fill dev struct with data from PCI device info given by index. */
void fill_dev_data(uint8_t idx, struct Dev_info *dev);
}; };
#endif /* _INCLUDE__SPEC__X86_64__MUEN__SINFO_H_ */ #endif /* _INCLUDE__SPEC__X86_64__MUEN__SINFO_H_ */

View File

@ -32,13 +32,15 @@ Bootstrap::Platform::Board::Board()
Memory_region { TIMER_BASE_ADDR, TIMER_SIZE }, Memory_region { TIMER_BASE_ADDR, TIMER_SIZE },
Memory_region { TIMER_PREEMPT_BASE_ADDR, TIMER_PREEMPT_SIZE }) Memory_region { TIMER_PREEMPT_BASE_ADDR, TIMER_PREEMPT_SIZE })
{ {
struct Sinfo::Memregion_info region;
Sinfo sinfo(Sinfo::PHYSICAL_BASE_ADDR); Sinfo sinfo(Sinfo::PHYSICAL_BASE_ADDR);
if (!sinfo.get_memregion_info("ram", &region)) const struct Sinfo::Resource_type *
region = sinfo.get_resource("ram", Sinfo::RES_MEMORY);
if (!region)
Genode::error("Unable to retrieve base-hw ram region"); Genode::error("Unable to retrieve base-hw ram region");
else else
early_ram_regions.add(Memory_region { region.address, region.size }); early_ram_regions.add(Memory_region
{ region->data.mem.address, region->data.mem.size });
} }

View File

@ -66,27 +66,27 @@ bool Platform::get_msi_params(const addr_t mmconf, addr_t &address,
addr_t &data, unsigned &irq_number) addr_t &data, unsigned &irq_number)
{ {
const unsigned sid = Mmconf_address::to_sid(mmconf); const unsigned sid = Mmconf_address::to_sid(mmconf);
const struct Sinfo::Device_type *dev = sinfo()->get_device(sid);
struct Sinfo::Dev_info dev_info; if (!dev) {
if (!sinfo()->get_dev_info(sid, &dev_info)) {
error("error retrieving Muen info for device with SID ", Hex(sid)); error("error retrieving Muen info for device with SID ", Hex(sid));
return false; return false;
} }
if (!dev_info.ir_count) { if (!dev->ir_count) {
error("device ", Hex(sid), " has no IRQ assigned"); error("device ", Hex(sid), " has no IRQ assigned");
return false; return false;
} }
if (!dev_info.msi_capable) { if (!(dev->flags & Sinfo::DEV_MSI_FLAG)) {
error("device ", Hex(sid), " not configured for MSI"); error("device ", Hex(sid), " not configured for MSI");
return false; return false;
} }
data = 0; data = 0;
address = Msi_address::to_msi_addr(dev_info.irte_start); address = Msi_address::to_msi_addr(dev->irte_start);
irq_number = dev_info.irq_start; irq_number = dev->irq_start;
log("enabling MSI for device with SID ", Hex(sid), ": " log("enabling MSI for device with SID ", Hex(sid), ": "
"IRTE ", dev_info.irte_start, ", IRQ ", irq_number); "IRTE ", dev->irte_start, ", IRQ ", irq_number);
return true; return true;
} }

View File

@ -30,22 +30,26 @@ Timer_driver::Timer_driver(unsigned) : ticks_per_ms(sinfo()->get_tsc_khz())
/* first sinfo instance, output status */ /* first sinfo instance, output status */
sinfo()->log_status(); sinfo()->log_status();
struct Sinfo::Memregion_info region; const struct Sinfo::Resource_type *
if (!sinfo()->get_memregion_info("timed_event", &region)) { region = sinfo()->get_resource("timed_event", Sinfo::RES_MEMORY);
if (!region) {
error("muen-timer: Unable to retrieve timed event region"); error("muen-timer: Unable to retrieve timed event region");
throw Invalid_region(); throw Invalid_region();
} }
event_page = (Subject_timed_event *)Platform::mmio_to_virt(region.address); event_page = (Subject_timed_event *)
Platform::mmio_to_virt(region->data.mem.address);
event_page->event_nr = Board::TIMER_EVENT_KERNEL; event_page->event_nr = Board::TIMER_EVENT_KERNEL;
log("muen-timer: Page @", Hex(region.address), ", " log("muen-timer: Page @", Hex(region->data.mem.address), ", "
"frequency ", ticks_per_ms, " kHz, " "frequency ", ticks_per_ms, " kHz, "
"event ", (unsigned)event_page->event_nr); "event ", (unsigned)event_page->event_nr);
if (sinfo()->get_memregion_info("monitor_timed_event", &region)) { region = sinfo()->get_resource("monitor_timed_event", Sinfo::RES_MEMORY);
log("muen-timer: Found guest timed event page @", Hex(region.address), if (region) {
log("muen-timer: Found guest timed event page @", Hex(region->data.mem.address),
" -> enabling preemption"); " -> enabling preemption");
guest_event_page = (Subject_timed_event *)Platform::mmio_to_virt(region.address); guest_event_page = (Subject_timed_event *)
Platform::mmio_to_virt(region->data.mem.address);
guest_event_page->event_nr = Board::TIMER_EVENT_PREEMPT; guest_event_page->event_nr = Board::TIMER_EVENT_PREEMPT;
} }
} }

View File

@ -16,9 +16,9 @@
#include <base/stdint.h> #include <base/stdint.h>
struct scheduling_info_type { struct Scheduling_info_type {
uint64_t tsc_schedule_start; Genode::uint64_t tsc_schedule_start;
uint64_t tsc_schedule_end; Genode::uint64_t tsc_schedule_end;
} __attribute__((packed, aligned (8))); } __attribute__((packed, aligned (8)));
#endif /* _BASE__MUEN_MUSCHEDINFO_H_ */ #endif /* _BASE__MUEN_MUSCHEDINFO_H_ */

View File

@ -1,88 +0,0 @@
/*
* \brief Muen subject info
* \author Reto Buerki
* \date 2015-04-21
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _LIB__MUEN__MUSINFO_H_
#define _LIB__MUEN__MUSINFO_H_
#include <base/stdint.h>
#include <muen/sinfo.h>
#define MUEN_SUBJECT_INFO_MAGIC 0x01006f666e69756dULL
#define MAX_RESOURCE_COUNT 255
#define NO_RESOURCE 0
using namespace Genode;
struct name_type {
uint8_t length;
char data[Sinfo::MAX_NAME_LENGTH];
} __attribute__((packed));
#define MEM_WRITABLE_FLAG (1 << 0)
#define MEM_EXECUTABLE_FLAG (1 << 1)
struct memregion_type {
enum Sinfo::Content content;
uint64_t address;
uint64_t size;
uint8_t hash[Sinfo::HASH_LENGTH];
uint8_t flags;
uint16_t pattern;
char padding[1];
} __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 dev_info_type {
uint16_t sid;
uint16_t irte_start;
uint8_t irq_start;
uint8_t ir_count;
uint8_t flags;
char padding[1];
} __attribute__((packed, aligned (8)));
#define DEV_MSI_FLAG (1 << 0)
struct subject_info_type {
uint64_t magic;
struct name_type name;
uint8_t resource_count;
uint8_t memregion_count;
uint8_t channel_info_count;
uint8_t dev_info_count;
char padding[4];
uint64_t tsc_khz;
struct resource_type resources[MAX_RESOURCE_COUNT];
struct memregion_type memregions[MAX_RESOURCE_COUNT];
struct channel_info_type channels_info[MAX_RESOURCE_COUNT];
struct dev_info_type dev_info[MAX_RESOURCE_COUNT];
} __attribute__((packed, aligned (8)));
#endif /* _LIB__MUEN__MUSINFO_H_ */

View File

@ -17,7 +17,6 @@
#include <muen/sinfo.h> #include <muen/sinfo.h>
#include "musinfo.h"
#include "muschedinfo.h" #include "muschedinfo.h"
#define roundup(x, y) ( \ #define roundup(x, y) ( \
@ -26,28 +25,11 @@
(((x) + (__y - 1)) / __y) * __y; \ (((x) + (__y - 1)) / __y) * __y; \
}) })
static_assert(sizeof(subject_info_type) <= Sinfo::SIZE, using namespace Genode;
static_assert(sizeof(Sinfo::Subject_info_type) <= Sinfo::SIZE,
"Size of subject info type larger than Sinfo::SIZE."); "Size of subject info type larger than Sinfo::SIZE.");
/* Log channel information */
static bool log_channel(Genode::Sinfo::Channel_info const * const channel, void *)
{
if (channel->has_event || channel->has_vector) {
Genode::log("muen-sinfo: [",
channel->writable ? "writer" : "reader", " with ",
channel->has_event ? "event " : "vector", " ",
channel->has_event ? channel->event_number : channel->vector,
"] ", Genode::Cstring(channel->name));
} else {
Genode::log("muen-sinfo: [",
channel->writable ? "writer" : "reader", " with no ",
channel->writable ? "event " : "vector", " ",
"] ", Genode::Cstring(channel->name));
}
return true;
}
static const char * const content_names[] = { static const char * const content_names[] = {
"uninitialized", "fill", "file", "uninitialized", "fill", "file",
@ -62,6 +44,13 @@ static bool hash_available(const uint8_t * const first)
} }
static bool names_equal(const struct Sinfo::Name_type *const n1,
const char *const n2)
{
return n1->length == strlen(n2) && strcmp(n1->data, n2) == 0;
}
/* Convert given hash to hex string */ /* Convert given hash to hex string */
static char *hash_to_hex(char *buffer, const unsigned char *first) static char *hash_to_hex(char *buffer, const unsigned char *first)
{ {
@ -72,48 +61,60 @@ static char *hash_to_hex(char *buffer, const unsigned char *first)
} }
/* Log memory region information */ static bool log_resource(const struct Sinfo::Resource_type *const res, void *)
static bool log_memregion(Genode::Sinfo::Memregion_info const * const region, void *)
{ {
char hash_str[65]; char hash_str[65];
Genode::log("muen-sinfo: [", content_names[region->content], switch (res->kind) {
", addr ", Genode::Hex(region->address), case Sinfo::RES_MEMORY:
" size ", Genode::Hex(region->size), " ", Genode::log("muen-sinfo: memory [",
region->writable ? "rw" : "ro", content_names[res->data.mem.content],
region->executable ? "x" : "-", ", addr ", Genode::Hex(res->data.mem.address),
"] ", Genode::Cstring(region->name)); " size ", Genode::Hex(res->data.mem.size), " ",
res->data.mem.flags & Sinfo::MEM_WRITABLE_FLAG ? "rw" : "ro",
res->data.mem.flags & Sinfo::MEM_EXECUTABLE_FLAG ? "x" : "-",
res->data.mem.flags & Sinfo::MEM_CHANNEL_FLAG ? "c" : "-",
"] ", res->name.data);
if (region->content == Sinfo::CONTENT_FILL) if (res->data.mem.content == Sinfo::CONTENT_FILL)
Genode::log("muen-sinfo: [pattern ", region->pattern, "]"); Genode::log("muen-sinfo: [pattern ", res->data.mem.pattern, "]");
if (hash_available(region->hash))
Genode::log("muen-sinfo: [hash 0x", if (hash_available(res->data.mem.hash))
Genode::Cstring(hash_to_hex(hash_str, region->hash)), "]"); Genode::log("muen-sinfo: [hash 0x",
Genode::Cstring(hash_to_hex(hash_str, res->data.mem.hash)),
"]");
break;
case Sinfo::RES_DEVICE:
Genode::log("muen-sinfo: device [sid ", Genode::Hex(res->data.dev.sid),
" IRTE/IRQ start ", res->data.dev.irte_start,
"/", res->data.dev.irq_start,
" IR count ", res->data.dev.ir_count,
" flags ", res->data.dev.flags, "] ", res->name.data);
break;
case Sinfo::RES_EVENT:
Genode::log("muen-sinfo: event [number ", res->data.number, "] ", res->name.data);
break;
case Sinfo::RES_VECTOR:
Genode::log("muen-sinfo: vector [number ", res->data.number, "] ", res->name.data);
break;
case Sinfo::RES_NONE:
break;
default:
Genode::log("muen-sinfo: UNKNOWN resource at address %p\n",
res);
break;
}
return true; return true;
} }
/* 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(const addr_t base_addr) Sinfo::Sinfo(const addr_t base_addr)
: :
sinfo((subject_info_type *)base_addr) sinfo((Subject_info_type *)base_addr)
{ {
const uint64_t sinfo_page_size = roundup(sizeof(subject_info_type), 0x1000); const uint64_t sinfo_page_size = roundup(sizeof(Subject_info_type), 0x1000);
sched_info = ((scheduling_info_type *)(base_addr + sinfo_page_size)); sched_info = ((Scheduling_info_type *)(base_addr + sinfo_page_size));
if (!check_magic()) { if (!check_magic()) {
Genode::error("muen-sinfo: Subject information MAGIC mismatch"); Genode::error("muen-sinfo: Subject information MAGIC mismatch");
@ -122,7 +123,7 @@ Sinfo::Sinfo(const addr_t base_addr)
} }
bool Sinfo::check_magic(void) bool Sinfo::check_magic(void) const
{ {
return sinfo != 0 && sinfo->magic == MUEN_SUBJECT_INFO_MAGIC; return sinfo != 0 && sinfo->magic == MUEN_SUBJECT_INFO_MAGIC;
} }
@ -144,100 +145,58 @@ const char * Sinfo::get_subject_name(void)
} }
bool Sinfo::get_channel_info(const char * const name, bool Sinfo::iterate_resources(struct iterator *const iter) const
struct Channel_info *channel)
{ {
int i; if (!iter->res) {
iter->res = &sinfo->resources[0];
if (!check_magic()) iter->idx = 0;
return false; } else {
iter->res++;
for (i = 0; i < sinfo->resource_count; i++) { iter->idx++;
if (is_channel(&sinfo->resources[i]) &&
strcmp(sinfo->resources[i].name.data, name) == 0) {
fill_channel_data(i, channel);
return true;
}
} }
return false; return iter->idx < sinfo->resource_count
&& iter->res->kind != RES_NONE;
} }
bool Sinfo::get_memregion_info(const char * const name, const struct Sinfo::Resource_type *
struct Memregion_info *memregion) Sinfo::get_resource(const char *const name, enum Resource_kind kind) const
{ {
int i; struct iterator i = { nullptr, 0 };
if (!check_magic()) while (iterate_resources(&i))
return false; if (i.res->kind == kind && names_equal(&i.res->name, name))
return i.res;
for (i = 0; i < sinfo->resource_count; i++) { return nullptr;
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::get_dev_info(const uint16_t sid, struct Dev_info *dev) const struct Sinfo::Device_type * Sinfo::get_device(const uint16_t sid) const
{ {
int i; struct iterator i = { nullptr, 0 };
if (!check_magic()) while (iterate_resources(&i))
return false; if (i.res->kind == RES_DEVICE && i.res->data.dev.sid == sid)
return &i.res->data.dev;
for (i = 0; i < sinfo->dev_info_count; i++) { return nullptr;
if (sinfo->dev_info[i].sid == sid) {
fill_dev_data(i, dev);
return true;
}
}
return false;
} }
bool Sinfo::for_each_channel(Channel_cb func, void *data) bool Sinfo::for_each_resource(resource_cb func, void *data) const
{ {
int i; struct iterator i = { nullptr, 0 };
struct Channel_info current_channel;
if (!check_magic()) while (iterate_resources(&i))
return false; if (!func(i.res, data))
return 0;
for (i = 0; i < sinfo->resource_count; i++) { return 1;
if (is_channel(&sinfo->resources[i])) {
fill_channel_data(i, &current_channel);
if (!func(&current_channel, data))
return false;
}
}
return true;
} }
bool Sinfo::for_each_memregion(Memregion_cb func, void *data) uint64_t Sinfo::get_tsc_khz(void) const
{
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, &current_region);
if (!func(&current_region, data))
return false;
}
}
return true;
}
uint64_t Sinfo::get_tsc_khz(void)
{ {
if (!check_magic()) if (!check_magic())
return 0; return 0;
@ -246,7 +205,7 @@ uint64_t Sinfo::get_tsc_khz(void)
} }
uint64_t Sinfo::get_sched_start(void) uint64_t Sinfo::get_sched_start(void) const
{ {
if (!check_magic()) if (!check_magic())
return 0; return 0;
@ -255,7 +214,7 @@ uint64_t Sinfo::get_sched_start(void)
} }
uint64_t Sinfo::get_sched_end(void) uint64_t Sinfo::get_sched_end(void) const
{ {
if (!check_magic()) if (!check_magic())
return 0; return 0;
@ -275,66 +234,10 @@ void Sinfo::log_status()
return; return;
} }
const uint16_t count = sinfo->resource_count;
Genode::log("muen-sinfo: Subject name is '", Genode::log("muen-sinfo: Subject name is '",
Sinfo::get_subject_name(), "'"); Sinfo::get_subject_name(), "'");
Genode::log("muen-sinfo: Subject information exports ", Genode::log("muen-sinfo: Subject exports ", count, " resources");
sinfo->memregion_count, " memory region(s)"); for_each_resource(log_resource, nullptr);
for_each_memregion(log_memregion, nullptr);
Genode::log("muen-sinfo: Subject information exports ",
sinfo->channel_info_count, " channel(s)");
for_each_channel(log_channel, 0);
}
void Sinfo::fill_memregion_data(uint8_t idx, struct Memregion_info *region)
{
const struct resource_type resource = sinfo->resources[idx];
const struct memregion_type memregion =
sinfo->memregions[resource.memregion_idx - 1];
memset(&region->name, 0, MAX_NAME_LENGTH + 1);
memcpy(&region->name, resource.name.data, resource.name.length);
memcpy(&region->hash, memregion.hash, HASH_LENGTH);
region->content = memregion.content;
region->address = memregion.address;
region->size = memregion.size;
region->pattern = memregion.pattern;
region->writable = memregion.flags & MEM_WRITABLE_FLAG;
region->executable = memregion.flags & MEM_EXECUTABLE_FLAG;
}
void Sinfo::fill_channel_data(uint8_t idx, struct 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;
}
void Sinfo::fill_dev_data(uint8_t idx, struct Dev_info *dev)
{
const struct dev_info_type dev_info = sinfo->dev_info[idx];
dev->sid = dev_info.sid;
dev->irte_start = dev_info.irte_start;
dev->irq_start = dev_info.irq_start;
dev->ir_count = dev_info.ir_count;
dev->msi_capable = dev_info.flags & DEV_MSI_FLAG;
} }

View File

@ -79,18 +79,23 @@ struct Mem_region : Genode::List<Mem_region>::Element,
Genode::Rom_connection sinfo_rom(env, "subject_info_page"); Genode::Rom_connection sinfo_rom(env, "subject_info_page");
Genode::Sinfo sinfo ((addr_t)env.rm().attach (sinfo_rom.dataspace())); Genode::Sinfo sinfo ((addr_t)env.rm().attach (sinfo_rom.dataspace()));
struct Genode::Sinfo::Memregion_info region1, region4; const struct Genode::Sinfo::Resource_type *region1
if (!sinfo.get_memregion_info("vm_ram_1", &region1)) { = sinfo.get_resource("vm_ram_1", Genode::Sinfo::RES_MEMORY);
const struct Genode::Sinfo::Resource_type *region4
= sinfo.get_resource("vm_ram_4", Genode::Sinfo::RES_MEMORY);
if (!region1) {
Genode::error("unable to retrieve vm_ram_1 region"); Genode::error("unable to retrieve vm_ram_1 region");
return 0; return 0;
} }
if (!sinfo.get_memregion_info("vm_ram_4", &region4)) { if (!region4) {
Genode::error("unable to retrieve vm_ram_4 region"); Genode::error("unable to retrieve vm_ram_4 region");
return 0; return 0;
} }
cur_region.base = region1.address; cur_region.base = region1->data.mem.address;
cur_region.size = region4.address + region4.size - region1.address; cur_region.size = region4->data.mem.address + region4->data.mem.size
- region1->data.mem.address;
counter++; counter++;
_clear = false; _clear = false;

View File

@ -113,17 +113,17 @@ bool setup_subject_state()
if (cur_state) if (cur_state)
return true; return true;
struct Sinfo::Memregion_info region; const struct Sinfo::Resource_type *region
= sinfo()->get_resource("monitor_state", Sinfo::RES_MEMORY);
if (!sinfo()->get_memregion_info("monitor_state", &region)) { if (!region) {
error("unable to retrieve monitor state region"); error("unable to retrieve monitor state region");
return false; return false;
} }
try { try {
static Attached_io_mem_dataspace subject_ds(genode_env(), static Attached_io_mem_dataspace subject_ds
region.address, (genode_env(), region->data.mem.address, region->data.mem.size);
region.size);
cur_state = subject_ds.local_addr<struct Subject_state>(); cur_state = subject_ds.local_addr<struct Subject_state>();
return true; return true;
} catch (...) { } catch (...) {
@ -143,17 +143,17 @@ bool setup_subject_interrupts()
if (guest_interrupts) if (guest_interrupts)
return true; return true;
struct Sinfo::Memregion_info region; const struct Sinfo::Resource_type *region
= sinfo()->get_resource("monitor_interrupts", Sinfo::RES_MEMORY);
if (!sinfo()->get_memregion_info("monitor_interrupts", &region)) { if (!region) {
error("unable to retrieve monitor interrupts region"); error("unable to retrieve monitor interrupts region");
return false; return false;
} }
try { try {
static Attached_io_mem_dataspace subject_intrs(genode_env(), static Attached_io_mem_dataspace subject_intrs
region.address, (genode_env(), region->data.mem.address, region->data.mem.size);
region.size);
static Guest_interrupts g((addr_t)subject_intrs.local_addr<addr_t>()); static Guest_interrupts g((addr_t)subject_intrs.local_addr<addr_t>());
guest_interrupts = &g; guest_interrupts = &g;
return true; return true;