nova: support multidimensional affinity space

Fixes #3635
This commit is contained in:
Alexander Boettcher 2020-02-03 16:19:11 +01:00 committed by Norman Feske
parent 685bd763f9
commit 2064ffd64b
8 changed files with 181 additions and 246 deletions

View File

@ -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));

View File

@ -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_ */

View File

@ -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);
}
}
}
};
}

View File

@ -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);
});
}

View File

@ -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());
}

View File

@ -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)

View File

@ -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();
}

View File

@ -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();
};