0ca199f89a
As far as possible remove usage of warning/error/log in the kernel, otherwise the kernel context might try to take a lock hold by a core thread, which results in a syscall to block. Fix #3277
244 lines
5.4 KiB
C++
244 lines
5.4 KiB
C++
/*
|
|
* \brief Muen subject information API impl
|
|
* \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.
|
|
*/
|
|
|
|
#include <base/log.h>
|
|
#include <base/snprintf.h>
|
|
#include <util/string.h>
|
|
|
|
#include <muen/sinfo.h>
|
|
|
|
#include "muschedinfo.h"
|
|
|
|
#define roundup(x, y) ( \
|
|
{ \
|
|
const typeof(y) __y = y; \
|
|
(((x) + (__y - 1)) / __y) * __y; \
|
|
})
|
|
|
|
using namespace Genode;
|
|
|
|
static_assert(sizeof(Sinfo::Subject_info_type) <= Sinfo::SIZE,
|
|
"Size of subject info type larger than Sinfo::SIZE.");
|
|
|
|
|
|
static const char * const content_names[] = {
|
|
"uninitialized", "fill", "file",
|
|
};
|
|
|
|
uint8_t no_hash[Sinfo::HASH_LENGTH] = {0};
|
|
|
|
/* Return true if given buffer contains a hash */
|
|
static bool hash_available(const uint8_t * const first)
|
|
{
|
|
return memcmp(first, no_hash, Sinfo::HASH_LENGTH) != 0;
|
|
}
|
|
|
|
|
|
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)
|
|
{
|
|
int i;
|
|
for (i = 0; i < Sinfo::HASH_LENGTH; i++)
|
|
snprintf(&buffer[i * 2], 3, "%02x", (unsigned int)*first++);
|
|
return buffer;
|
|
}
|
|
|
|
|
|
static bool log_resource(const struct Sinfo::Resource_type *const res, void *)
|
|
{
|
|
char hash_str[65];
|
|
|
|
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 (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;
|
|
}
|
|
|
|
|
|
Sinfo::Sinfo(const addr_t 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));
|
|
|
|
if (!check_magic()) {
|
|
Genode::warning("muen-sinfo: Subject information MAGIC mismatch");
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
bool Sinfo::check_magic(void) const
|
|
{
|
|
return sinfo != 0 && sinfo->magic == MUEN_SUBJECT_INFO_MAGIC;
|
|
}
|
|
|
|
|
|
const char * Sinfo::get_subject_name(void)
|
|
{
|
|
if (!check_magic())
|
|
return nullptr;
|
|
|
|
if (!subject_name_set)
|
|
{
|
|
memset(subject_name, 0, MAX_NAME_LENGTH + 1);
|
|
memcpy(subject_name, &sinfo->name.data, sinfo->name.length);
|
|
subject_name_set = true;
|
|
}
|
|
|
|
return subject_name;
|
|
}
|
|
|
|
|
|
bool Sinfo::iterate_resources(struct iterator *const iter) const
|
|
{
|
|
if (!iter->res) {
|
|
iter->res = &sinfo->resources[0];
|
|
iter->idx = 0;
|
|
} else {
|
|
iter->res++;
|
|
iter->idx++;
|
|
}
|
|
return iter->idx < sinfo->resource_count
|
|
&& iter->res->kind != RES_NONE;
|
|
}
|
|
|
|
|
|
const struct Sinfo::Resource_type *
|
|
Sinfo::get_resource(const char *const name, enum Resource_kind kind) const
|
|
{
|
|
struct iterator i = { nullptr, 0 };
|
|
|
|
while (iterate_resources(&i))
|
|
if (i.res->kind == kind && names_equal(&i.res->name, name))
|
|
return i.res;
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
const struct Sinfo::Device_type * Sinfo::get_device(const uint16_t sid) const
|
|
{
|
|
struct iterator i = { nullptr, 0 };
|
|
|
|
while (iterate_resources(&i))
|
|
if (i.res->kind == RES_DEVICE && i.res->data.dev.sid == sid)
|
|
return &i.res->data.dev;
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
bool Sinfo::for_each_resource(resource_cb func, void *data) const
|
|
{
|
|
struct iterator i = { nullptr, 0 };
|
|
|
|
while (iterate_resources(&i))
|
|
if (!func(i.res, data))
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
uint64_t Sinfo::get_tsc_khz(void) const
|
|
{
|
|
if (!check_magic())
|
|
return 0;
|
|
|
|
return sinfo->tsc_khz;
|
|
}
|
|
|
|
|
|
uint64_t Sinfo::get_sched_start(void) const
|
|
{
|
|
if (!check_magic())
|
|
return 0;
|
|
|
|
return sched_info->tsc_schedule_start;
|
|
}
|
|
|
|
|
|
uint64_t Sinfo::get_sched_end(void) const
|
|
{
|
|
if (!check_magic())
|
|
return 0;
|
|
|
|
return sched_info->tsc_schedule_end;
|
|
}
|
|
|
|
|
|
void Sinfo::log_status()
|
|
{
|
|
if (!sinfo) {
|
|
Genode::log("Sinfo API not initialized");
|
|
return;
|
|
}
|
|
if (!check_magic()) {
|
|
Genode::log("Sinfo MAGIC not found");
|
|
return;
|
|
}
|
|
|
|
const uint16_t count = sinfo->resource_count;
|
|
|
|
Genode::log("muen-sinfo: Subject name is '",
|
|
Sinfo::get_subject_name(), "'");
|
|
Genode::log("muen-sinfo: Subject exports ", count, " resources");
|
|
for_each_resource(log_resource, nullptr);
|
|
}
|