mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
muen: Update sinfo to variant resources API
This commit is contained in:
parent
5c3461a851
commit
810f59b555
@ -19,8 +19,8 @@
|
||||
|
||||
#include <base/stdint.h>
|
||||
|
||||
struct subject_info_type;
|
||||
struct scheduling_info_type;
|
||||
struct Subject_info_type;
|
||||
struct Scheduling_info_type;
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
@ -35,14 +35,27 @@ class Genode::Sinfo
|
||||
public:
|
||||
|
||||
enum Config {
|
||||
PHYSICAL_BASE_ADDR = 0xe00000000,
|
||||
SIZE = 0x9000,
|
||||
MAX_NAME_LENGTH = 63,
|
||||
HASH_LENGTH = 32,
|
||||
MUEN_SUBJECT_INFO_MAGIC = 0x02006f666e69756dULL,
|
||||
MAX_RESOURCE_COUNT = 255,
|
||||
MAX_NAME_LENGTH = 63,
|
||||
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);
|
||||
|
||||
/* Resource name */
|
||||
struct Name_type {
|
||||
uint8_t length;
|
||||
char data[MAX_NAME_LENGTH];
|
||||
uint8_t null_term;
|
||||
} __attribute__((packed));
|
||||
|
||||
enum Content {
|
||||
CONTENT_UNINITIALIZED,
|
||||
CONTENT_FILL,
|
||||
@ -50,42 +63,67 @@ class Genode::Sinfo
|
||||
};
|
||||
|
||||
/* Structure holding information about a memory region */
|
||||
struct Memregion_info {
|
||||
struct Memregion_type {
|
||||
enum Content content;
|
||||
char name[MAX_NAME_LENGTH + 1];
|
||||
uint64_t address;
|
||||
uint64_t size;
|
||||
bool writable;
|
||||
bool executable;
|
||||
uint8_t hash[HASH_LENGTH];
|
||||
uint8_t flags;
|
||||
uint16_t pattern;
|
||||
};
|
||||
char padding[1];
|
||||
} __attribute__((packed));
|
||||
|
||||
/* 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;
|
||||
};
|
||||
|
||||
/* Structure holding information about PCI devices */
|
||||
struct Dev_info {
|
||||
/*
|
||||
* Structure holding information about a PCI device,
|
||||
* explicitly padded to the size of the largest resource variant
|
||||
*/
|
||||
struct Device_type {
|
||||
uint16_t sid;
|
||||
uint16_t irte_start;
|
||||
uint8_t irq_start;
|
||||
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.
|
||||
*/
|
||||
bool check_magic(void);
|
||||
bool check_magic(void) const;
|
||||
|
||||
/*
|
||||
* Return subject name.
|
||||
@ -95,83 +133,55 @@ class Genode::Sinfo
|
||||
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
|
||||
* event_number and vector parameters are only valid if indicated by
|
||||
* the has_[event|vector] struct members.
|
||||
* If no resource with given name exists, null is returned.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
bool get_memregion_info(const char * const name,
|
||||
struct Memregion_info *memregion);
|
||||
const struct Resource_type *
|
||||
get_resource(const char *const name, enum Resource_kind kind) const;
|
||||
|
||||
/*
|
||||
* Return information for PCI device with given SID.
|
||||
*
|
||||
* The function returns false if no device information for the
|
||||
* specified device exists.
|
||||
* The function returns null if no device information for the specified device
|
||||
* 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
|
||||
* can be used to pass additional data.
|
||||
* Used in the for_each_resource function. The optional void 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);
|
||||
|
||||
/*
|
||||
* 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,
|
||||
* processing is aborted and false is returned to the caller.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
bool for_each_memregion(Memregion_cb func, void *data);
|
||||
bool for_each_resource(resource_cb func, void *data) const;
|
||||
|
||||
/*
|
||||
* Return TSC tick rate in kHz.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
uint64_t get_sched_start(void);
|
||||
uint64_t get_sched_start(void) const;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
@ -180,25 +190,22 @@ class Genode::Sinfo
|
||||
|
||||
private:
|
||||
|
||||
subject_info_type * sinfo = nullptr;
|
||||
scheduling_info_type * sched_info = nullptr;
|
||||
Subject_info_type * sinfo = nullptr;
|
||||
Scheduling_info_type * sched_info = nullptr;
|
||||
char subject_name[MAX_NAME_LENGTH + 1];
|
||||
bool subject_name_set = false;
|
||||
|
||||
/*
|
||||
* Fill memregion struct with memory region info from resource given by
|
||||
* index.
|
||||
* Iterate over all resources beginning at given start resource. If the res
|
||||
* 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;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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);
|
||||
bool iterate_resources(struct iterator *const iter) const;
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__SPEC__X86_64__MUEN__SINFO_H_ */
|
||||
|
@ -32,13 +32,15 @@ Bootstrap::Platform::Board::Board()
|
||||
Memory_region { TIMER_BASE_ADDR, TIMER_SIZE },
|
||||
Memory_region { TIMER_PREEMPT_BASE_ADDR, TIMER_PREEMPT_SIZE })
|
||||
{
|
||||
struct Sinfo::Memregion_info region;
|
||||
|
||||
Sinfo sinfo(Sinfo::PHYSICAL_BASE_ADDR);
|
||||
if (!sinfo.get_memregion_info("ram", ®ion))
|
||||
const struct Sinfo::Resource_type *
|
||||
region = sinfo.get_resource("ram", Sinfo::RES_MEMORY);
|
||||
|
||||
if (!region)
|
||||
Genode::error("Unable to retrieve base-hw ram region");
|
||||
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 });
|
||||
}
|
||||
|
||||
|
||||
|
@ -66,27 +66,27 @@ bool Platform::get_msi_params(const addr_t mmconf, addr_t &address,
|
||||
addr_t &data, unsigned &irq_number)
|
||||
{
|
||||
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 (!sinfo()->get_dev_info(sid, &dev_info)) {
|
||||
if (!dev) {
|
||||
error("error retrieving Muen info for device with SID ", Hex(sid));
|
||||
return false;
|
||||
}
|
||||
if (!dev_info.ir_count) {
|
||||
if (!dev->ir_count) {
|
||||
error("device ", Hex(sid), " has no IRQ assigned");
|
||||
return false;
|
||||
}
|
||||
if (!dev_info.msi_capable) {
|
||||
if (!(dev->flags & Sinfo::DEV_MSI_FLAG)) {
|
||||
error("device ", Hex(sid), " not configured for MSI");
|
||||
return false;
|
||||
}
|
||||
|
||||
data = 0;
|
||||
address = Msi_address::to_msi_addr(dev_info.irte_start);
|
||||
irq_number = dev_info.irq_start;
|
||||
address = Msi_address::to_msi_addr(dev->irte_start);
|
||||
irq_number = dev->irq_start;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -30,22 +30,26 @@ Timer_driver::Timer_driver(unsigned) : ticks_per_ms(sinfo()->get_tsc_khz())
|
||||
/* first sinfo instance, output status */
|
||||
sinfo()->log_status();
|
||||
|
||||
struct Sinfo::Memregion_info region;
|
||||
if (!sinfo()->get_memregion_info("timed_event", ®ion)) {
|
||||
const struct Sinfo::Resource_type *
|
||||
region = sinfo()->get_resource("timed_event", Sinfo::RES_MEMORY);
|
||||
if (!region) {
|
||||
error("muen-timer: Unable to retrieve timed event 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;
|
||||
log("muen-timer: Page @", Hex(region.address), ", "
|
||||
log("muen-timer: Page @", Hex(region->data.mem.address), ", "
|
||||
"frequency ", ticks_per_ms, " kHz, "
|
||||
"event ", (unsigned)event_page->event_nr);
|
||||
|
||||
if (sinfo()->get_memregion_info("monitor_timed_event", ®ion)) {
|
||||
log("muen-timer: Found guest timed event page @", Hex(region.address),
|
||||
region = sinfo()->get_resource("monitor_timed_event", Sinfo::RES_MEMORY);
|
||||
if (region) {
|
||||
log("muen-timer: Found guest timed event page @", Hex(region->data.mem.address),
|
||||
" -> 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;
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,9 @@
|
||||
|
||||
#include <base/stdint.h>
|
||||
|
||||
struct scheduling_info_type {
|
||||
uint64_t tsc_schedule_start;
|
||||
uint64_t tsc_schedule_end;
|
||||
struct Scheduling_info_type {
|
||||
Genode::uint64_t tsc_schedule_start;
|
||||
Genode::uint64_t tsc_schedule_end;
|
||||
} __attribute__((packed, aligned (8)));
|
||||
|
||||
#endif /* _BASE__MUEN_MUSCHEDINFO_H_ */
|
||||
|
@ -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_ */
|
@ -17,7 +17,6 @@
|
||||
|
||||
#include <muen/sinfo.h>
|
||||
|
||||
#include "musinfo.h"
|
||||
#include "muschedinfo.h"
|
||||
|
||||
#define roundup(x, y) ( \
|
||||
@ -26,28 +25,11 @@
|
||||
(((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.");
|
||||
|
||||
/* 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[] = {
|
||||
"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 */
|
||||
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_memregion(Genode::Sinfo::Memregion_info const * const region, void *)
|
||||
static bool log_resource(const struct Sinfo::Resource_type *const res, void *)
|
||||
{
|
||||
char hash_str[65];
|
||||
|
||||
Genode::log("muen-sinfo: [", content_names[region->content],
|
||||
", addr ", Genode::Hex(region->address),
|
||||
" size ", Genode::Hex(region->size), " ",
|
||||
region->writable ? "rw" : "ro",
|
||||
region->executable ? "x" : "-",
|
||||
"] ", Genode::Cstring(region->name));
|
||||
switch (res->kind) {
|
||||
case Sinfo::RES_MEMORY:
|
||||
Genode::log("muen-sinfo: memory [",
|
||||
content_names[res->data.mem.content],
|
||||
", addr ", Genode::Hex(res->data.mem.address),
|
||||
" 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)
|
||||
Genode::log("muen-sinfo: [pattern ", region->pattern, "]");
|
||||
if (hash_available(region->hash))
|
||||
Genode::log("muen-sinfo: [hash 0x",
|
||||
Genode::Cstring(hash_to_hex(hash_str, region->hash)), "]");
|
||||
if (res->data.mem.content == Sinfo::CONTENT_FILL)
|
||||
Genode::log("muen-sinfo: [pattern ", res->data.mem.pattern, "]");
|
||||
|
||||
if (hash_available(res->data.mem.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;
|
||||
}
|
||||
|
||||
|
||||
/* 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((subject_info_type *)base_addr)
|
||||
sinfo((Subject_info_type *)base_addr)
|
||||
{
|
||||
const uint64_t sinfo_page_size = roundup(sizeof(subject_info_type), 0x1000);
|
||||
sched_info = ((scheduling_info_type *)(base_addr + sinfo_page_size));
|
||||
const uint64_t sinfo_page_size = roundup(sizeof(Subject_info_type), 0x1000);
|
||||
sched_info = ((Scheduling_info_type *)(base_addr + sinfo_page_size));
|
||||
|
||||
if (!check_magic()) {
|
||||
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;
|
||||
}
|
||||
@ -144,100 +145,58 @@ const char * Sinfo::get_subject_name(void)
|
||||
}
|
||||
|
||||
|
||||
bool Sinfo::get_channel_info(const char * const name,
|
||||
struct Channel_info *channel)
|
||||
bool Sinfo::iterate_resources(struct iterator *const iter) const
|
||||
{
|
||||
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;
|
||||
}
|
||||
if (!iter->res) {
|
||||
iter->res = &sinfo->resources[0];
|
||||
iter->idx = 0;
|
||||
} else {
|
||||
iter->res++;
|
||||
iter->idx++;
|
||||
}
|
||||
return false;
|
||||
return iter->idx < sinfo->resource_count
|
||||
&& iter->res->kind != RES_NONE;
|
||||
}
|
||||
|
||||
|
||||
bool Sinfo::get_memregion_info(const char * const name,
|
||||
struct Memregion_info *memregion)
|
||||
const struct Sinfo::Resource_type *
|
||||
Sinfo::get_resource(const char *const name, enum Resource_kind kind) const
|
||||
{
|
||||
int i;
|
||||
struct iterator i = { nullptr, 0 };
|
||||
|
||||
if (!check_magic())
|
||||
return false;
|
||||
while (iterate_resources(&i))
|
||||
if (i.res->kind == kind && names_equal(&i.res->name, name))
|
||||
return i.res;
|
||||
|
||||
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;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
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())
|
||||
return false;
|
||||
while (iterate_resources(&i))
|
||||
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++) {
|
||||
if (sinfo->dev_info[i].sid == sid) {
|
||||
fill_dev_data(i, dev);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool Sinfo::for_each_channel(Channel_cb func, void *data)
|
||||
bool Sinfo::for_each_resource(resource_cb func, void *data) const
|
||||
{
|
||||
int i;
|
||||
struct Channel_info current_channel;
|
||||
struct iterator i = { nullptr, 0 };
|
||||
|
||||
if (!check_magic())
|
||||
return false;
|
||||
while (iterate_resources(&i))
|
||||
if (!func(i.res, data))
|
||||
return 0;
|
||||
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
uint64_t Sinfo::get_tsc_khz(void) const
|
||||
{
|
||||
if (!check_magic())
|
||||
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())
|
||||
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())
|
||||
return 0;
|
||||
@ -275,66 +234,10 @@ void Sinfo::log_status()
|
||||
return;
|
||||
}
|
||||
|
||||
const uint16_t count = sinfo->resource_count;
|
||||
|
||||
Genode::log("muen-sinfo: Subject name is '",
|
||||
Sinfo::get_subject_name(), "'");
|
||||
Genode::log("muen-sinfo: Subject information exports ",
|
||||
sinfo->memregion_count, " memory region(s)");
|
||||
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(®ion->name, 0, MAX_NAME_LENGTH + 1);
|
||||
memcpy(®ion->name, resource.name.data, resource.name.length);
|
||||
|
||||
memcpy(®ion->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;
|
||||
Genode::log("muen-sinfo: Subject exports ", count, " resources");
|
||||
for_each_resource(log_resource, nullptr);
|
||||
}
|
||||
|
@ -79,18 +79,23 @@ struct Mem_region : Genode::List<Mem_region>::Element,
|
||||
Genode::Rom_connection sinfo_rom(env, "subject_info_page");
|
||||
Genode::Sinfo sinfo ((addr_t)env.rm().attach (sinfo_rom.dataspace()));
|
||||
|
||||
struct Genode::Sinfo::Memregion_info region1, region4;
|
||||
if (!sinfo.get_memregion_info("vm_ram_1", ®ion1)) {
|
||||
const struct Genode::Sinfo::Resource_type *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");
|
||||
return 0;
|
||||
}
|
||||
if (!sinfo.get_memregion_info("vm_ram_4", ®ion4)) {
|
||||
if (!region4) {
|
||||
Genode::error("unable to retrieve vm_ram_4 region");
|
||||
return 0;
|
||||
}
|
||||
|
||||
cur_region.base = region1.address;
|
||||
cur_region.size = region4.address + region4.size - region1.address;
|
||||
cur_region.base = region1->data.mem.address;
|
||||
cur_region.size = region4->data.mem.address + region4->data.mem.size
|
||||
- region1->data.mem.address;
|
||||
counter++;
|
||||
_clear = false;
|
||||
|
||||
|
@ -113,17 +113,17 @@ bool setup_subject_state()
|
||||
if (cur_state)
|
||||
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", ®ion)) {
|
||||
if (!region) {
|
||||
error("unable to retrieve monitor state region");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
static Attached_io_mem_dataspace subject_ds(genode_env(),
|
||||
region.address,
|
||||
region.size);
|
||||
static Attached_io_mem_dataspace subject_ds
|
||||
(genode_env(), region->data.mem.address, region->data.mem.size);
|
||||
cur_state = subject_ds.local_addr<struct Subject_state>();
|
||||
return true;
|
||||
} catch (...) {
|
||||
@ -143,17 +143,17 @@ bool setup_subject_interrupts()
|
||||
if (guest_interrupts)
|
||||
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", ®ion)) {
|
||||
if (!region) {
|
||||
error("unable to retrieve monitor interrupts region");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
static Attached_io_mem_dataspace subject_intrs(genode_env(),
|
||||
region.address,
|
||||
region.size);
|
||||
static Attached_io_mem_dataspace subject_intrs
|
||||
(genode_env(), region->data.mem.address, region->data.mem.size);
|
||||
static Guest_interrupts g((addr_t)subject_intrs.local_addr<addr_t>());
|
||||
guest_interrupts = &g;
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user