mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 02:40:08 +00:00
parent
685bd763f9
commit
2064ffd64b
@ -174,8 +174,6 @@ namespace Nova {
|
||||
|
||||
/**
|
||||
* Map kernel cpu ids to virtual cpu ids.
|
||||
* Assign first all cores on all packages with thread 0 to virtual
|
||||
* cpu id numbers, afterwards all (hyper-)threads.
|
||||
*/
|
||||
bool remap_cpu_ids(uint8_t *map_cpus, unsigned const boot_cpu) const {
|
||||
unsigned const num_cpus = cpus();
|
||||
@ -191,9 +189,9 @@ namespace Nova {
|
||||
return true;
|
||||
|
||||
/* assign remaining cores and afterwards all threads to the ids */
|
||||
for (uint8_t thread = 0; thread < 255; thread++) {
|
||||
for (uint8_t package = 0; package < 255; package++) {
|
||||
for (uint8_t core = 0; core < 255; core++) {
|
||||
for (uint8_t package = 0; package < 255; package++) {
|
||||
for (uint8_t core = 0; core < 255; core++) {
|
||||
for (uint8_t thread = 0; thread < 255; thread++) {
|
||||
for (unsigned i = 0; i < cpu_max(); i++) {
|
||||
if (i == boot_cpu || !is_cpu_enabled(i))
|
||||
continue;
|
||||
@ -215,6 +213,18 @@ namespace Nova {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename FUNC>
|
||||
void for_each_enabled_cpu(FUNC const &func) const
|
||||
{
|
||||
for (unsigned i = 0; i < cpu_max(); i++) {
|
||||
Cpu_desc const * cpu = cpu_desc_of_cpu(i);
|
||||
if (!is_cpu_enabled(i)) continue;
|
||||
if (!cpu) return;
|
||||
func(*cpu, i);
|
||||
}
|
||||
}
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2006-2020 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.
|
||||
@ -364,59 +364,6 @@ namespace Genode {
|
||||
void print(Output &out) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* A 'Pager_activation' processes one page fault of a 'Pager_object' at a time.
|
||||
*/
|
||||
class Pager_entrypoint;
|
||||
class Pager_activation_base: public Thread
|
||||
{
|
||||
private:
|
||||
|
||||
Native_capability _cap;
|
||||
Pager_entrypoint *_ep; /* entry point to which the
|
||||
activation belongs */
|
||||
/**
|
||||
* Lock used for blocking until '_cap' is initialized
|
||||
*/
|
||||
Lock _cap_valid;
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Pager_activation_base(Pager_activation_base const &);
|
||||
Pager_activation_base &operator = (Pager_activation_base const &);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param name name of the new thread
|
||||
* \param stack_size stack size of the new thread
|
||||
*/
|
||||
Pager_activation_base(char const * const name,
|
||||
size_t const stack_size);
|
||||
|
||||
/**
|
||||
* Thread interface
|
||||
*/
|
||||
void entry() override;
|
||||
|
||||
/**
|
||||
* Return capability to this activation
|
||||
*
|
||||
* This function should only be called from 'Pager_entrypoint'
|
||||
*/
|
||||
Native_capability cap()
|
||||
{
|
||||
/* ensure that the initialization of our 'Ipc_pager' is done */
|
||||
if (!_cap.valid())
|
||||
_cap_valid.lock();
|
||||
return _cap;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Paging entry point
|
||||
*
|
||||
@ -447,16 +394,6 @@ namespace Genode {
|
||||
*/
|
||||
void dissolve(Pager_object &obj);
|
||||
};
|
||||
|
||||
|
||||
template <int STACK_SIZE>
|
||||
class Pager_activation : public Pager_activation_base
|
||||
{
|
||||
public:
|
||||
|
||||
Pager_activation() : Pager_activation_base("pager", STACK_SIZE)
|
||||
{ }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__PAGER_H_ */
|
||||
|
@ -110,12 +110,30 @@ namespace Genode {
|
||||
/**
|
||||
* Return kernel CPU ID for given Genode CPU
|
||||
*/
|
||||
unsigned kernel_cpu_id(unsigned genode_cpu_id);
|
||||
unsigned pager_index(Affinity::Location location) const;
|
||||
unsigned kernel_cpu_id(Affinity::Location location) const;
|
||||
|
||||
Affinity::Location sanitize(Affinity::Location location) {
|
||||
return Affinity::Location(location.xpos() % _cpus.width(),
|
||||
location.ypos() % _cpus.height(),
|
||||
location.width(), location.height());
|
||||
}
|
||||
|
||||
/**
|
||||
* PD kernel capability selector of core
|
||||
*/
|
||||
unsigned core_pd_sel() const { return _core_pd_sel; }
|
||||
|
||||
template <typename FUNC>
|
||||
void for_each_location(FUNC const &fn)
|
||||
{
|
||||
for (unsigned x = 0; x < _cpus.width(); x++) {
|
||||
for (unsigned y = 0; y < _cpus.height(); y++) {
|
||||
Affinity::Location location(x, y, 1, 1);
|
||||
fn(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -7,14 +7,13 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2010-2020 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/construct_at.h>
|
||||
#include <rm_session/rm_session.h>
|
||||
|
||||
/* base-internal includes */
|
||||
@ -49,26 +48,43 @@ static Nova::Hip const &kernel_hip()
|
||||
return *reinterpret_cast<Hip const *>(__initial_sp);
|
||||
}
|
||||
|
||||
/* pager activation threads storage and handling - one thread per CPU */
|
||||
enum { PAGER_CPUS = Platform::MAX_SUPPORTED_CPUS, PAGER_STACK_SIZE = 2*4096 };
|
||||
|
||||
static char pager_activation_mem[sizeof (Pager_activation<PAGER_STACK_SIZE>) * PAGER_CPUS];
|
||||
static Pager_activation_base * pager_threads[PAGER_CPUS];
|
||||
|
||||
|
||||
static unsigned which_cpu(Pager_activation_base &pager)
|
||||
/**
|
||||
* Pager threads - one thread per CPU
|
||||
*/
|
||||
struct Pager_thread: public Thread
|
||||
{
|
||||
Pager_activation_base * start = reinterpret_cast<Pager_activation_base *>(&pager_activation_mem);
|
||||
Pager_activation_base * end = start + PAGER_CPUS;
|
||||
Pager_thread(Affinity::Location location)
|
||||
: Thread(Cpu_session::Weight::DEFAULT_WEIGHT, "pager", 2 * 4096, location)
|
||||
{
|
||||
/* creates local EC */
|
||||
Thread::start();
|
||||
|
||||
if (start <= &pager && &pager < end) {
|
||||
/* pager of one of the non boot CPUs */
|
||||
unsigned cpu_id = &pager - start;
|
||||
return cpu_id;
|
||||
reinterpret_cast<Nova::Utcb *>(Thread::utcb())->crd_xlt = Obj_crd(0, ~0UL);
|
||||
}
|
||||
|
||||
/* pager of boot CPU */
|
||||
return 0;
|
||||
void entry() override { }
|
||||
};
|
||||
|
||||
enum { PAGER_CPUS = Platform::MAX_SUPPORTED_CPUS };
|
||||
static Constructible<Pager_thread> pager_threads[PAGER_CPUS];
|
||||
|
||||
static Pager_thread &pager_thread(Affinity::Location location,
|
||||
Platform &platform)
|
||||
{
|
||||
unsigned const pager_index = platform.pager_index(location);
|
||||
unsigned const kernel_cpu_id = platform.kernel_cpu_id(location);
|
||||
|
||||
if (kernel_hip().is_cpu_enabled(kernel_cpu_id) &&
|
||||
pager_index < PAGER_CPUS && pager_threads[pager_index].constructed())
|
||||
return *pager_threads[pager_index];
|
||||
|
||||
warning("invalid CPU parameter used in pager object: ",
|
||||
pager_index, "->", kernel_cpu_id, " location=",
|
||||
location.xpos(), "x", location.ypos(), " ",
|
||||
location.width(), "x", location.height());
|
||||
|
||||
throw Invalid_thread();
|
||||
}
|
||||
|
||||
|
||||
@ -113,8 +129,6 @@ void Pager_object::_page_fault_handler(Pager_object &obj)
|
||||
|
||||
Ipc_pager ipc_pager(utcb, obj.pd_sel(), platform_specific().core_pd_sel());
|
||||
|
||||
Pager_activation_base &pager_thread = static_cast<Pager_activation_base &>(myself);
|
||||
|
||||
/* potential request to ask for EC cap or signal SM cap */
|
||||
if (utcb.msg_words() == 1)
|
||||
_invoke_handler(obj);
|
||||
@ -171,8 +185,9 @@ void Pager_object::_page_fault_handler(Pager_object &obj)
|
||||
char const * const client_thread = obj.client_thread();
|
||||
char const * const client_pd = obj.client_pd();
|
||||
|
||||
Page_fault_info const fault_info(client_pd, client_thread,
|
||||
which_cpu(pager_thread),
|
||||
unsigned const cpu_id = platform_specific().pager_index(myself.affinity());
|
||||
|
||||
Page_fault_info const fault_info(client_pd, client_thread, cpu_id,
|
||||
ipc_pager.fault_ip(),
|
||||
ipc_pager.fault_addr(),
|
||||
ipc_pager.sp(),
|
||||
@ -190,9 +205,8 @@ void Pager_object::_page_fault_handler(Pager_object &obj)
|
||||
|
||||
void Pager_object::exception(uint8_t exit_id)
|
||||
{
|
||||
Thread &myself = *Thread::myself();
|
||||
Utcb &utcb = *reinterpret_cast<Utcb *>(myself.utcb());
|
||||
Pager_activation_base &pager_thread = static_cast<Pager_activation_base &>(myself);
|
||||
Thread &myself = *Thread::myself();
|
||||
Utcb &utcb = *reinterpret_cast<Utcb *>(myself.utcb());
|
||||
|
||||
if (exit_id > PT_SEL_PARENT)
|
||||
nova_die();
|
||||
@ -218,10 +232,12 @@ void Pager_object::exception(uint8_t exit_id)
|
||||
/* nobody handles this exception - so thread will be stopped finally */
|
||||
_state.mark_dead();
|
||||
|
||||
unsigned const cpu_id = platform_specific().pager_index(myself.affinity());
|
||||
|
||||
warning("unresolvable exception ", exit_id, ", "
|
||||
"pd '", client_pd(), "', "
|
||||
"thread '", client_thread(), "', "
|
||||
"cpu ", which_cpu(pager_thread), ", "
|
||||
"cpu ", cpu_id, ", "
|
||||
"ip=", Hex(fault_ip), " "
|
||||
"sp=", Hex(fault_sp), " "
|
||||
"bp=", Hex(fault_bp), " ",
|
||||
@ -533,16 +549,7 @@ template <uint8_t EV>
|
||||
void Exception_handlers::register_handler(Pager_object &obj, Mtd mtd,
|
||||
void (* __attribute__((regparm(1))) func)(Pager_object &))
|
||||
{
|
||||
unsigned const genode_cpu_id = obj.location().xpos();
|
||||
unsigned const kernel_cpu_id = platform_specific().kernel_cpu_id(genode_cpu_id);
|
||||
|
||||
if (!kernel_hip().is_cpu_enabled(kernel_cpu_id) ||
|
||||
!pager_threads[genode_cpu_id]) {
|
||||
warning("invalid CPU parameter used in pager object");
|
||||
throw Invalid_thread();
|
||||
}
|
||||
|
||||
addr_t const ec_sel = pager_threads[genode_cpu_id]->native_thread().ec_sel;
|
||||
addr_t const ec_sel = pager_thread(obj.location(), platform_specific()).native_thread().ec_sel;
|
||||
|
||||
/* compiler generates instance of exception entry if not specified */
|
||||
addr_t entry = func ? (addr_t)func : (addr_t)(&_handler<EV>);
|
||||
@ -623,22 +630,7 @@ Pager_object::Pager_object(Cpu_session_capability cpu_session_cap,
|
||||
Native_thread::INVALID_INDEX == _client_exc_pt_sel)
|
||||
throw Invalid_thread();
|
||||
|
||||
/* ypos information not supported by now */
|
||||
if (location.ypos()) {
|
||||
warning("unsupported location ", location.xpos(), "x", location.ypos());
|
||||
throw Invalid_thread();
|
||||
}
|
||||
|
||||
/* place Pager_object on specified CPU by selecting proper pager thread */
|
||||
unsigned const genode_cpu_id = location.xpos();
|
||||
unsigned const kernel_cpu_id = platform_specific().kernel_cpu_id(genode_cpu_id);
|
||||
if (!kernel_hip().is_cpu_enabled(kernel_cpu_id) ||
|
||||
!pager_threads[genode_cpu_id]) {
|
||||
warning("invalid CPU parameter used in pager object");
|
||||
throw Invalid_thread();
|
||||
}
|
||||
|
||||
addr_t ec_sel = pager_threads[genode_cpu_id]->native_thread().ec_sel;
|
||||
addr_t const ec_sel = pager_thread(location, platform_specific()).native_thread().ec_sel;
|
||||
|
||||
/* create portal for page-fault handler - 14 */
|
||||
_exceptions.register_handler<14>(*this, Mtd::QUAL | Mtd::ESP | Mtd::EIP,
|
||||
@ -893,21 +885,18 @@ void Pager_object::_oom_handler(addr_t pager_dst, addr_t pager_src,
|
||||
|
||||
addr_t Pager_object::get_oom_portal()
|
||||
{
|
||||
addr_t const pt_oom = sel_oom_portal();
|
||||
unsigned const genode_cpu_id = _location.xpos();
|
||||
unsigned const kernel_cpu_id = platform_specific().kernel_cpu_id(genode_cpu_id);
|
||||
addr_t const core_pd_sel = platform_specific().core_pd_sel();
|
||||
try {
|
||||
addr_t const pt_oom = sel_oom_portal();
|
||||
addr_t const core_pd_sel = platform_specific().core_pd_sel();
|
||||
Pager_thread &thread = pager_thread(_location, platform_specific());
|
||||
addr_t const ec_sel = thread.native_thread().ec_sel;
|
||||
|
||||
if (kernel_hip().is_cpu_enabled(kernel_cpu_id) &&
|
||||
pager_threads[genode_cpu_id]) {
|
||||
|
||||
addr_t const ec_sel = pager_threads[genode_cpu_id]->native_thread().ec_sel;
|
||||
uint8_t res = create_portal(pt_oom, core_pd_sel, ec_sel, Mtd(0),
|
||||
reinterpret_cast<addr_t>(_oom_handler),
|
||||
this);
|
||||
if (res == Nova::NOVA_OK)
|
||||
return pt_oom;
|
||||
}
|
||||
} catch (...) { }
|
||||
|
||||
error("creating portal for out of memory notification failed");
|
||||
return 0;
|
||||
@ -927,26 +916,6 @@ const char * Pager_object::client_pd() const
|
||||
return client ? client->pd_name() : "unknown";
|
||||
}
|
||||
|
||||
/**********************
|
||||
** Pager activation **
|
||||
**********************/
|
||||
|
||||
Pager_activation_base::Pager_activation_base(const char *name, size_t stack_size)
|
||||
:
|
||||
Thread(Cpu_session::Weight::DEFAULT_WEIGHT, name, stack_size,
|
||||
Affinity::Location(which_cpu(*this), 0)),
|
||||
_cap(Native_capability()), _ep(0), _cap_valid(Lock::LOCKED)
|
||||
{
|
||||
/* creates local EC */
|
||||
Thread::start();
|
||||
|
||||
reinterpret_cast<Nova::Utcb *>(Thread::utcb())->crd_xlt = Obj_crd(0, ~0UL);
|
||||
}
|
||||
|
||||
|
||||
void Pager_activation_base::entry() { }
|
||||
|
||||
|
||||
/**********************
|
||||
** Pager entrypoint **
|
||||
**********************/
|
||||
@ -961,17 +930,15 @@ Pager_entrypoint::Pager_entrypoint(Rpc_cap_factory &)
|
||||
}
|
||||
|
||||
/* detect enabled CPUs and create per CPU a pager thread */
|
||||
typedef Pager_activation<PAGER_STACK_SIZE> Pager;
|
||||
Pager * pager_of_cpu = reinterpret_cast<Pager *>(&pager_activation_mem);
|
||||
platform_specific().for_each_location([&](Affinity::Location &location) {
|
||||
unsigned const pager_index = platform_specific().pager_index(location);
|
||||
unsigned const kernel_cpu_id = platform_specific().kernel_cpu_id(location);
|
||||
|
||||
for (unsigned i = 0; i < kernel_hip().cpus(); i++, pager_of_cpu++) {
|
||||
unsigned const kernel_cpu_id = platform_specific().kernel_cpu_id(i);
|
||||
if (!kernel_hip().is_cpu_enabled(kernel_cpu_id))
|
||||
continue;
|
||||
return;
|
||||
|
||||
pager_threads[i] = pager_of_cpu;
|
||||
construct_at<Pager>(pager_threads[i]);
|
||||
}
|
||||
pager_threads[pager_index].construct(location);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
/* Genode includes */
|
||||
#include <base/sleep.h>
|
||||
#include <base/thread.h>
|
||||
#include <util/bit_array.h>
|
||||
#include <util/mmio.h>
|
||||
#include <util/string.h>
|
||||
#include <util/xml_generator.h>
|
||||
@ -272,6 +273,27 @@ struct Resolution : Register<64>
|
||||
struct Width : Bitfield<40, 24> { };
|
||||
};
|
||||
|
||||
static Affinity::Space setup_affinity_space(Hip const &hip)
|
||||
{
|
||||
unsigned cpus = 0;
|
||||
unsigned ids_thread = 0;
|
||||
Genode::Bit_array<1 << (sizeof(Hip::Cpu_desc::thread) * 8)> threads;
|
||||
|
||||
hip.for_each_enabled_cpu([&](Hip::Cpu_desc const &cpu, unsigned) {
|
||||
cpus ++;
|
||||
if (threads.get(cpu.thread, 1)) return;
|
||||
|
||||
threads.set(cpu.thread, 1);
|
||||
ids_thread ++;
|
||||
});
|
||||
|
||||
if (ids_thread && ((cpus % ids_thread) == 0))
|
||||
return Affinity::Space(cpus / ids_thread, ids_thread);
|
||||
|
||||
/* mixture of system with cores with and without hyperthreads ? */
|
||||
return Affinity::Space(cpus, 1);
|
||||
}
|
||||
|
||||
/**************
|
||||
** Platform **
|
||||
**************/
|
||||
@ -287,16 +309,8 @@ Platform::Platform()
|
||||
if (hip.api_version != 8)
|
||||
nova_die();
|
||||
|
||||
/*
|
||||
* Determine number of available CPUs
|
||||
*
|
||||
* XXX As of now, we assume a one-dimensional affinity space, ignoring
|
||||
* the y component of the affinity location. When adding support
|
||||
* for two-dimensional affinity spaces, look out and adjust the use of
|
||||
* 'Platform_thread::_location' in 'platform_thread.cc'. Also look
|
||||
* at the 'Thread::start' function in core/thread_start.cc.
|
||||
*/
|
||||
_cpus = Affinity::Space(hip.cpus(), 1);
|
||||
/* determine number of available CPUs */
|
||||
_cpus = setup_affinity_space(hip);
|
||||
|
||||
/* register UTCB of main thread */
|
||||
__main_thread_utcb = (Utcb *)(__initial_sp - get_page_size());
|
||||
@ -393,41 +407,10 @@ Platform::Platform()
|
||||
/* set up page fault handler for core - for debugging */
|
||||
addr_t const ec_core_exc_sel = init_core_page_fault_handler(core_pd_sel());
|
||||
|
||||
if (verbose_boot_info) {
|
||||
if (hip.has_feature_vmx())
|
||||
log("Hypervisor features VMX");
|
||||
if (hip.has_feature_svm())
|
||||
log("Hypervisor features SVM");
|
||||
log("Hypervisor reports ", _cpus.width(), "x", _cpus.height(), " "
|
||||
"CPU", _cpus.total() > 1 ? "s" : " ");
|
||||
if (!cpuid_invariant_tsc())
|
||||
warning("CPU has no invariant TSC.");
|
||||
|
||||
log("CPU ID (genode->kernel:package:core:thread) remapping");
|
||||
unsigned const cpus = hip.cpus();
|
||||
for (unsigned i = 0; i < cpus; i++) {
|
||||
|
||||
Hip::Cpu_desc const * const cpu_desc_ptr = hip.cpu_desc_of_cpu(map_cpu_ids[i]);
|
||||
|
||||
if (cpu_desc_ptr) {
|
||||
log(" remap (", i, "->", map_cpu_ids[i], ":",
|
||||
cpu_desc_ptr->package, ":",
|
||||
cpu_desc_ptr->core, ":",
|
||||
cpu_desc_ptr->thread, ") ",
|
||||
boot_cpu() == map_cpu_ids[i] ? "boot cpu" : "");
|
||||
} else {
|
||||
error("missing descriptor for CPU ", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize core allocators */
|
||||
size_t const num_mem_desc = (hip.hip_length - hip.mem_desc_offset)
|
||||
/ hip.mem_desc_size;
|
||||
|
||||
if (verbose_boot_info)
|
||||
log("Hypervisor info page contains ", num_mem_desc, " memory descriptors:");
|
||||
|
||||
addr_t mem_desc_base = ((addr_t)&hip + hip.mem_desc_offset);
|
||||
|
||||
/* define core's virtual address space */
|
||||
@ -735,29 +718,19 @@ Platform::Platform()
|
||||
xml.attribute("freq_khz" , hip.tsc_freq);
|
||||
});
|
||||
xml.node("cpus", [&] () {
|
||||
unsigned const cpus = hip.cpus();
|
||||
for (unsigned i = 0; i < cpus; i++) {
|
||||
|
||||
Hip::Cpu_desc const * const cpu_desc_ptr =
|
||||
hip.cpu_desc_of_cpu(Platform::kernel_cpu_id(i));
|
||||
|
||||
if (!cpu_desc_ptr)
|
||||
continue;
|
||||
|
||||
Hip::Cpu_desc const &cpu_desc = *cpu_desc_ptr;
|
||||
|
||||
hip.for_each_enabled_cpu([&](Hip::Cpu_desc const &cpu, unsigned i) {
|
||||
xml.node("cpu", [&] () {
|
||||
xml.attribute("id", i);
|
||||
xml.attribute("package", cpu_desc.package);
|
||||
xml.attribute("core", cpu_desc.core);
|
||||
xml.attribute("thread", cpu_desc.thread);
|
||||
xml.attribute("family", String<5>(Hex(cpu_desc.family)));
|
||||
xml.attribute("model", String<5>(Hex(cpu_desc.model)));
|
||||
xml.attribute("stepping", String<5>(Hex(cpu_desc.stepping)));
|
||||
xml.attribute("platform", String<5>(Hex(cpu_desc.platform)));
|
||||
xml.attribute("patch", String<12>(Hex(cpu_desc.patch)));
|
||||
xml.attribute("package", cpu.package);
|
||||
xml.attribute("core", cpu.core);
|
||||
xml.attribute("thread", cpu.thread);
|
||||
xml.attribute("family", String<5>(Hex(cpu.family)));
|
||||
xml.attribute("model", String<5>(Hex(cpu.model)));
|
||||
xml.attribute("stepping", String<5>(Hex(cpu.stepping)));
|
||||
xml.attribute("platform", String<5>(Hex(cpu.platform)));
|
||||
xml.attribute("patch", String<12>(Hex(cpu.patch)));
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -802,6 +775,33 @@ Platform::Platform()
|
||||
_rom_fs.insert(new (core_mem_alloc()) Rom_module(hyp_log, hyp_log_size,
|
||||
"kernel_log"));
|
||||
|
||||
if (verbose_boot_info) {
|
||||
if (hip.has_feature_vmx())
|
||||
log("Hypervisor features VMX");
|
||||
if (hip.has_feature_svm())
|
||||
log("Hypervisor features SVM");
|
||||
log("Hypervisor reports ", _cpus.width(), "x", _cpus.height(), " "
|
||||
"CPU", _cpus.total() > 1 ? "s" : " ");
|
||||
if (!cpuid_invariant_tsc())
|
||||
warning("CPU has no invariant TSC.");
|
||||
|
||||
log("mapping: affinity space -> kernel cpu id - package:core:thread");
|
||||
|
||||
for_each_location([&](Affinity::Location &location) {
|
||||
unsigned const kernel_cpu_id = Platform::kernel_cpu_id(location);
|
||||
Hip::Cpu_desc const * cpu = hip.cpu_desc_of_cpu(kernel_cpu_id);
|
||||
|
||||
Genode::String<16> text ("failure");
|
||||
if (cpu)
|
||||
text = Genode::String<16>(cpu->package, ":",
|
||||
cpu->core, ":", cpu->thread);
|
||||
|
||||
log(" remap (", location.xpos(), "x", location.ypos(),") -> ",
|
||||
kernel_cpu_id, " - ", text, ") ",
|
||||
boot_cpu() == kernel_cpu_id ? "boot cpu" : "");
|
||||
});
|
||||
}
|
||||
|
||||
/* I/O port allocator (only meaningful for x86) */
|
||||
_io_port_alloc.add_range(0, 0x10000);
|
||||
|
||||
@ -841,12 +841,9 @@ Platform::Platform()
|
||||
_max_caps = index - first_index;
|
||||
|
||||
/* add idle ECs to trace sources */
|
||||
for (unsigned genode_cpu_id = 0; genode_cpu_id < _cpus.width(); genode_cpu_id++) {
|
||||
|
||||
unsigned kernel_cpu_id = Platform::kernel_cpu_id(genode_cpu_id);
|
||||
|
||||
if (!hip.is_cpu_enabled(kernel_cpu_id))
|
||||
continue;
|
||||
for_each_location([&](Affinity::Location &location) {
|
||||
unsigned const kernel_cpu_id = Platform::kernel_cpu_id(location);
|
||||
if (!hip.cpu_desc_of_cpu(kernel_cpu_id)) return;
|
||||
|
||||
struct Trace_source : public Trace::Source::Info_accessor,
|
||||
private Trace::Control,
|
||||
@ -871,7 +868,7 @@ Platform::Platform()
|
||||
uint8_t res = Nova::sc_ctrl(sc_sel, sc_time, syscall_op);
|
||||
if (res != Nova::NOVA_OK)
|
||||
warning("sc_ctrl on idle SC cap, op=", syscall_op,
|
||||
", res=", res);
|
||||
", res=", res);
|
||||
|
||||
return { Session_label("kernel"), Trace::Thread_name(name),
|
||||
Trace::Execution_time(sc_time, sc_time), affinity };
|
||||
@ -890,24 +887,18 @@ Platform::Platform()
|
||||
}
|
||||
};
|
||||
|
||||
new (core_mem_alloc()) Trace_source(Trace::sources(),
|
||||
Affinity::Location(genode_cpu_id, 0,
|
||||
_cpus.width(), 1),
|
||||
new (core_mem_alloc()) Trace_source(Trace::sources(), location,
|
||||
sc_idle_base + kernel_cpu_id,
|
||||
"idle");
|
||||
|
||||
new (core_mem_alloc()) Trace_source(Trace::sources(),
|
||||
Affinity::Location(genode_cpu_id, 0,
|
||||
_cpus.width(), 1),
|
||||
new (core_mem_alloc()) Trace_source(Trace::sources(), location,
|
||||
sc_idle_base + kernel_cpu_id,
|
||||
"cross");
|
||||
|
||||
new (core_mem_alloc()) Trace_source(Trace::sources(),
|
||||
Affinity::Location(genode_cpu_id, 0,
|
||||
_cpus.width(), 1),
|
||||
new (core_mem_alloc()) Trace_source(Trace::sources(), location,
|
||||
sc_idle_base + kernel_cpu_id,
|
||||
"killed");
|
||||
}
|
||||
});
|
||||
|
||||
/* add exception handler EC for core and EC root thread to trace sources */
|
||||
struct Core_trace_source : public Trace::Source::Info_accessor,
|
||||
@ -965,13 +956,25 @@ addr_t Platform::_rom_module_phys(addr_t virt)
|
||||
}
|
||||
|
||||
|
||||
unsigned Platform::kernel_cpu_id(unsigned genode_cpu_id)
|
||||
unsigned Platform::kernel_cpu_id(Affinity::Location location) const
|
||||
{
|
||||
if (genode_cpu_id >= sizeof(map_cpu_ids) / sizeof(map_cpu_ids[0])) {
|
||||
error("invalid genode cpu id ", genode_cpu_id);
|
||||
unsigned const cpu_id = pager_index(location);
|
||||
|
||||
if (cpu_id >= sizeof(map_cpu_ids) / sizeof(map_cpu_ids[0])) {
|
||||
error("invalid genode cpu id ", cpu_id);
|
||||
return ~0U;
|
||||
}
|
||||
return map_cpu_ids[genode_cpu_id];
|
||||
|
||||
return map_cpu_ids[cpu_id];
|
||||
}
|
||||
|
||||
|
||||
unsigned Platform::pager_index(Affinity::Location location) const
|
||||
{
|
||||
if (!location.valid()) return 0;
|
||||
|
||||
return (location.xpos() * _cpus.height() + location.ypos())
|
||||
% (_cpus.width() * _cpus.height());
|
||||
}
|
||||
|
||||
|
||||
|
@ -90,7 +90,7 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
}
|
||||
|
||||
Utcb &utcb = *reinterpret_cast<Utcb *>(Thread::myself()->utcb());
|
||||
unsigned const kernel_cpu_id = platform_specific().kernel_cpu_id(_location.xpos());
|
||||
unsigned const kernel_cpu_id = platform_specific().kernel_cpu_id(_location);
|
||||
addr_t const source_pd = platform_specific().core_pd_sel();
|
||||
|
||||
addr_t const pt_oom = _pager->get_oom_portal();
|
||||
@ -341,7 +341,8 @@ Platform_thread::Platform_thread(size_t, const char *name, unsigned prio,
|
||||
Affinity::Location affinity, int)
|
||||
:
|
||||
_pd(0), _pager(0), _id_base(cap_map().insert(2)),
|
||||
_sel_exc_base(Native_thread::INVALID_INDEX), _location(affinity),
|
||||
_sel_exc_base(Native_thread::INVALID_INDEX),
|
||||
_location(platform_specific().sanitize(affinity)),
|
||||
_features(0),
|
||||
_priority(scale_priority(prio, name)),
|
||||
_name(name)
|
||||
|
@ -100,12 +100,12 @@ void Thread::start()
|
||||
|
||||
/* create local EC */
|
||||
enum { LOCAL_THREAD = false };
|
||||
unsigned const kernel_cpu_id = platform_specific().kernel_cpu_id(location.xpos());
|
||||
unsigned const kernel_cpu_id = platform_specific().kernel_cpu_id(location);
|
||||
uint8_t res = create_ec(native_thread().ec_sel,
|
||||
platform_specific().core_pd_sel(), kernel_cpu_id,
|
||||
(mword_t)&utcb, sp, native_thread().exc_pt_sel, LOCAL_THREAD);
|
||||
if (res != NOVA_OK) {
|
||||
error("create_ec returned ", res, " cpu=", location.xpos());
|
||||
error("create_ec returned ", res);
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
}
|
||||
|
||||
|
@ -170,8 +170,7 @@ Vcpu_id Vm_session_component::_create_vcpu(Thread_capability cap)
|
||||
Cpu_thread_component &thread = *ptr;
|
||||
|
||||
vcpu_location = thread.platform_thread().affinity();
|
||||
addr_t genode_cpu_id = thread.platform_thread().affinity().xpos();
|
||||
kernel_cpu_id = platform_specific().kernel_cpu_id(genode_cpu_id);
|
||||
kernel_cpu_id = platform_specific().kernel_cpu_id(thread.platform_thread().affinity());
|
||||
|
||||
return thread.platform_thread().pager().pd_sel();
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user