mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
parent
685bd763f9
commit
2064ffd64b
@ -174,8 +174,6 @@ namespace Nova {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Map kernel cpu ids to virtual cpu ids.
|
* 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 {
|
bool remap_cpu_ids(uint8_t *map_cpus, unsigned const boot_cpu) const {
|
||||||
unsigned const num_cpus = cpus();
|
unsigned const num_cpus = cpus();
|
||||||
@ -191,9 +189,9 @@ namespace Nova {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* assign remaining cores and afterwards all threads to the ids */
|
/* 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 package = 0; package < 255; package++) {
|
||||||
for (uint8_t core = 0; core < 255; core++) {
|
for (uint8_t core = 0; core < 255; core++) {
|
||||||
|
for (uint8_t thread = 0; thread < 255; thread++) {
|
||||||
for (unsigned i = 0; i < cpu_max(); i++) {
|
for (unsigned i = 0; i < cpu_max(); i++) {
|
||||||
if (i == boot_cpu || !is_cpu_enabled(i))
|
if (i == boot_cpu || !is_cpu_enabled(i))
|
||||||
continue;
|
continue;
|
||||||
@ -215,6 +213,18 @@ namespace Nova {
|
|||||||
}
|
}
|
||||||
return false;
|
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));
|
} __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
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU Affero General Public License version 3.
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
@ -364,59 +364,6 @@ namespace Genode {
|
|||||||
void print(Output &out) const;
|
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
|
* Paging entry point
|
||||||
*
|
*
|
||||||
@ -447,16 +394,6 @@ namespace Genode {
|
|||||||
*/
|
*/
|
||||||
void dissolve(Pager_object &obj);
|
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_ */
|
#endif /* _CORE__INCLUDE__PAGER_H_ */
|
||||||
|
@ -110,12 +110,30 @@ namespace Genode {
|
|||||||
/**
|
/**
|
||||||
* Return kernel CPU ID for given Genode CPU
|
* 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
|
* PD kernel capability selector of core
|
||||||
*/
|
*/
|
||||||
unsigned core_pd_sel() const { return _core_pd_sel; }
|
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
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU Affero General Public License version 3.
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <util/construct_at.h>
|
|
||||||
#include <rm_session/rm_session.h>
|
#include <rm_session/rm_session.h>
|
||||||
|
|
||||||
/* base-internal includes */
|
/* base-internal includes */
|
||||||
@ -49,26 +48,43 @@ static Nova::Hip const &kernel_hip()
|
|||||||
return *reinterpret_cast<Hip const *>(__initial_sp);
|
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];
|
* Pager threads - one thread per CPU
|
||||||
|
*/
|
||||||
|
struct Pager_thread: public Thread
|
||||||
static unsigned which_cpu(Pager_activation_base &pager)
|
|
||||||
{
|
{
|
||||||
Pager_activation_base * start = reinterpret_cast<Pager_activation_base *>(&pager_activation_mem);
|
Pager_thread(Affinity::Location location)
|
||||||
Pager_activation_base * end = start + PAGER_CPUS;
|
: Thread(Cpu_session::Weight::DEFAULT_WEIGHT, "pager", 2 * 4096, location)
|
||||||
|
{
|
||||||
|
/* creates local EC */
|
||||||
|
Thread::start();
|
||||||
|
|
||||||
if (start <= &pager && &pager < end) {
|
reinterpret_cast<Nova::Utcb *>(Thread::utcb())->crd_xlt = Obj_crd(0, ~0UL);
|
||||||
/* pager of one of the non boot CPUs */
|
|
||||||
unsigned cpu_id = &pager - start;
|
|
||||||
return cpu_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pager of boot CPU */
|
void entry() override { }
|
||||||
return 0;
|
};
|
||||||
|
|
||||||
|
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());
|
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 */
|
/* potential request to ask for EC cap or signal SM cap */
|
||||||
if (utcb.msg_words() == 1)
|
if (utcb.msg_words() == 1)
|
||||||
_invoke_handler(obj);
|
_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_thread = obj.client_thread();
|
||||||
char const * const client_pd = obj.client_pd();
|
char const * const client_pd = obj.client_pd();
|
||||||
|
|
||||||
Page_fault_info const fault_info(client_pd, client_thread,
|
unsigned const cpu_id = platform_specific().pager_index(myself.affinity());
|
||||||
which_cpu(pager_thread),
|
|
||||||
|
Page_fault_info const fault_info(client_pd, client_thread, cpu_id,
|
||||||
ipc_pager.fault_ip(),
|
ipc_pager.fault_ip(),
|
||||||
ipc_pager.fault_addr(),
|
ipc_pager.fault_addr(),
|
||||||
ipc_pager.sp(),
|
ipc_pager.sp(),
|
||||||
@ -192,7 +207,6 @@ void Pager_object::exception(uint8_t exit_id)
|
|||||||
{
|
{
|
||||||
Thread &myself = *Thread::myself();
|
Thread &myself = *Thread::myself();
|
||||||
Utcb &utcb = *reinterpret_cast<Utcb *>(myself.utcb());
|
Utcb &utcb = *reinterpret_cast<Utcb *>(myself.utcb());
|
||||||
Pager_activation_base &pager_thread = static_cast<Pager_activation_base &>(myself);
|
|
||||||
|
|
||||||
if (exit_id > PT_SEL_PARENT)
|
if (exit_id > PT_SEL_PARENT)
|
||||||
nova_die();
|
nova_die();
|
||||||
@ -218,10 +232,12 @@ void Pager_object::exception(uint8_t exit_id)
|
|||||||
/* nobody handles this exception - so thread will be stopped finally */
|
/* nobody handles this exception - so thread will be stopped finally */
|
||||||
_state.mark_dead();
|
_state.mark_dead();
|
||||||
|
|
||||||
|
unsigned const cpu_id = platform_specific().pager_index(myself.affinity());
|
||||||
|
|
||||||
warning("unresolvable exception ", exit_id, ", "
|
warning("unresolvable exception ", exit_id, ", "
|
||||||
"pd '", client_pd(), "', "
|
"pd '", client_pd(), "', "
|
||||||
"thread '", client_thread(), "', "
|
"thread '", client_thread(), "', "
|
||||||
"cpu ", which_cpu(pager_thread), ", "
|
"cpu ", cpu_id, ", "
|
||||||
"ip=", Hex(fault_ip), " "
|
"ip=", Hex(fault_ip), " "
|
||||||
"sp=", Hex(fault_sp), " "
|
"sp=", Hex(fault_sp), " "
|
||||||
"bp=", Hex(fault_bp), " ",
|
"bp=", Hex(fault_bp), " ",
|
||||||
@ -533,16 +549,7 @@ template <uint8_t EV>
|
|||||||
void Exception_handlers::register_handler(Pager_object &obj, Mtd mtd,
|
void Exception_handlers::register_handler(Pager_object &obj, Mtd mtd,
|
||||||
void (* __attribute__((regparm(1))) func)(Pager_object &))
|
void (* __attribute__((regparm(1))) func)(Pager_object &))
|
||||||
{
|
{
|
||||||
unsigned const genode_cpu_id = obj.location().xpos();
|
addr_t const ec_sel = pager_thread(obj.location(), platform_specific()).native_thread().ec_sel;
|
||||||
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;
|
|
||||||
|
|
||||||
/* compiler generates instance of exception entry if not specified */
|
/* compiler generates instance of exception entry if not specified */
|
||||||
addr_t entry = func ? (addr_t)func : (addr_t)(&_handler<EV>);
|
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)
|
Native_thread::INVALID_INDEX == _client_exc_pt_sel)
|
||||||
throw Invalid_thread();
|
throw Invalid_thread();
|
||||||
|
|
||||||
/* ypos information not supported by now */
|
addr_t const ec_sel = pager_thread(location, platform_specific()).native_thread().ec_sel;
|
||||||
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;
|
|
||||||
|
|
||||||
/* create portal for page-fault handler - 14 */
|
/* create portal for page-fault handler - 14 */
|
||||||
_exceptions.register_handler<14>(*this, Mtd::QUAL | Mtd::ESP | Mtd::EIP,
|
_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 Pager_object::get_oom_portal()
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
addr_t const pt_oom = sel_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();
|
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),
|
uint8_t res = create_portal(pt_oom, core_pd_sel, ec_sel, Mtd(0),
|
||||||
reinterpret_cast<addr_t>(_oom_handler),
|
reinterpret_cast<addr_t>(_oom_handler),
|
||||||
this);
|
this);
|
||||||
if (res == Nova::NOVA_OK)
|
if (res == Nova::NOVA_OK)
|
||||||
return pt_oom;
|
return pt_oom;
|
||||||
}
|
} catch (...) { }
|
||||||
|
|
||||||
error("creating portal for out of memory notification failed");
|
error("creating portal for out of memory notification failed");
|
||||||
return 0;
|
return 0;
|
||||||
@ -927,26 +916,6 @@ const char * Pager_object::client_pd() const
|
|||||||
return client ? client->pd_name() : "unknown";
|
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 **
|
** Pager entrypoint **
|
||||||
**********************/
|
**********************/
|
||||||
@ -961,17 +930,15 @@ Pager_entrypoint::Pager_entrypoint(Rpc_cap_factory &)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* detect enabled CPUs and create per CPU a pager thread */
|
/* detect enabled CPUs and create per CPU a pager thread */
|
||||||
typedef Pager_activation<PAGER_STACK_SIZE> Pager;
|
platform_specific().for_each_location([&](Affinity::Location &location) {
|
||||||
Pager * pager_of_cpu = reinterpret_cast<Pager *>(&pager_activation_mem);
|
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))
|
if (!kernel_hip().is_cpu_enabled(kernel_cpu_id))
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
pager_threads[i] = pager_of_cpu;
|
pager_threads[pager_index].construct(location);
|
||||||
construct_at<Pager>(pager_threads[i]);
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/sleep.h>
|
#include <base/sleep.h>
|
||||||
#include <base/thread.h>
|
#include <base/thread.h>
|
||||||
|
#include <util/bit_array.h>
|
||||||
#include <util/mmio.h>
|
#include <util/mmio.h>
|
||||||
#include <util/string.h>
|
#include <util/string.h>
|
||||||
#include <util/xml_generator.h>
|
#include <util/xml_generator.h>
|
||||||
@ -272,6 +273,27 @@ struct Resolution : Register<64>
|
|||||||
struct Width : Bitfield<40, 24> { };
|
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 **
|
** Platform **
|
||||||
**************/
|
**************/
|
||||||
@ -287,16 +309,8 @@ Platform::Platform()
|
|||||||
if (hip.api_version != 8)
|
if (hip.api_version != 8)
|
||||||
nova_die();
|
nova_die();
|
||||||
|
|
||||||
/*
|
/* determine number of available CPUs */
|
||||||
* Determine number of available CPUs
|
_cpus = setup_affinity_space(hip);
|
||||||
*
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
/* register UTCB of main thread */
|
/* register UTCB of main thread */
|
||||||
__main_thread_utcb = (Utcb *)(__initial_sp - get_page_size());
|
__main_thread_utcb = (Utcb *)(__initial_sp - get_page_size());
|
||||||
@ -393,41 +407,10 @@ Platform::Platform()
|
|||||||
/* set up page fault handler for core - for debugging */
|
/* set up page fault handler for core - for debugging */
|
||||||
addr_t const ec_core_exc_sel = init_core_page_fault_handler(core_pd_sel());
|
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 */
|
/* initialize core allocators */
|
||||||
size_t const num_mem_desc = (hip.hip_length - hip.mem_desc_offset)
|
size_t const num_mem_desc = (hip.hip_length - hip.mem_desc_offset)
|
||||||
/ hip.mem_desc_size;
|
/ 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);
|
addr_t mem_desc_base = ((addr_t)&hip + hip.mem_desc_offset);
|
||||||
|
|
||||||
/* define core's virtual address space */
|
/* define core's virtual address space */
|
||||||
@ -735,29 +718,19 @@ Platform::Platform()
|
|||||||
xml.attribute("freq_khz" , hip.tsc_freq);
|
xml.attribute("freq_khz" , hip.tsc_freq);
|
||||||
});
|
});
|
||||||
xml.node("cpus", [&] () {
|
xml.node("cpus", [&] () {
|
||||||
unsigned const cpus = hip.cpus();
|
hip.for_each_enabled_cpu([&](Hip::Cpu_desc const &cpu, unsigned i) {
|
||||||
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;
|
|
||||||
|
|
||||||
xml.node("cpu", [&] () {
|
xml.node("cpu", [&] () {
|
||||||
xml.attribute("id", i);
|
xml.attribute("id", i);
|
||||||
xml.attribute("package", cpu_desc.package);
|
xml.attribute("package", cpu.package);
|
||||||
xml.attribute("core", cpu_desc.core);
|
xml.attribute("core", cpu.core);
|
||||||
xml.attribute("thread", cpu_desc.thread);
|
xml.attribute("thread", cpu.thread);
|
||||||
xml.attribute("family", String<5>(Hex(cpu_desc.family)));
|
xml.attribute("family", String<5>(Hex(cpu.family)));
|
||||||
xml.attribute("model", String<5>(Hex(cpu_desc.model)));
|
xml.attribute("model", String<5>(Hex(cpu.model)));
|
||||||
xml.attribute("stepping", String<5>(Hex(cpu_desc.stepping)));
|
xml.attribute("stepping", String<5>(Hex(cpu.stepping)));
|
||||||
xml.attribute("platform", String<5>(Hex(cpu_desc.platform)));
|
xml.attribute("platform", String<5>(Hex(cpu.platform)));
|
||||||
xml.attribute("patch", String<12>(Hex(cpu_desc.patch)));
|
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,
|
_rom_fs.insert(new (core_mem_alloc()) Rom_module(hyp_log, hyp_log_size,
|
||||||
"kernel_log"));
|
"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) */
|
/* I/O port allocator (only meaningful for x86) */
|
||||||
_io_port_alloc.add_range(0, 0x10000);
|
_io_port_alloc.add_range(0, 0x10000);
|
||||||
|
|
||||||
@ -841,12 +841,9 @@ Platform::Platform()
|
|||||||
_max_caps = index - first_index;
|
_max_caps = index - first_index;
|
||||||
|
|
||||||
/* add idle ECs to trace sources */
|
/* add idle ECs to trace sources */
|
||||||
for (unsigned genode_cpu_id = 0; genode_cpu_id < _cpus.width(); genode_cpu_id++) {
|
for_each_location([&](Affinity::Location &location) {
|
||||||
|
unsigned const kernel_cpu_id = Platform::kernel_cpu_id(location);
|
||||||
unsigned kernel_cpu_id = Platform::kernel_cpu_id(genode_cpu_id);
|
if (!hip.cpu_desc_of_cpu(kernel_cpu_id)) return;
|
||||||
|
|
||||||
if (!hip.is_cpu_enabled(kernel_cpu_id))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
struct Trace_source : public Trace::Source::Info_accessor,
|
struct Trace_source : public Trace::Source::Info_accessor,
|
||||||
private Trace::Control,
|
private Trace::Control,
|
||||||
@ -890,24 +887,18 @@ Platform::Platform()
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
new (core_mem_alloc()) Trace_source(Trace::sources(),
|
new (core_mem_alloc()) Trace_source(Trace::sources(), location,
|
||||||
Affinity::Location(genode_cpu_id, 0,
|
|
||||||
_cpus.width(), 1),
|
|
||||||
sc_idle_base + kernel_cpu_id,
|
sc_idle_base + kernel_cpu_id,
|
||||||
"idle");
|
"idle");
|
||||||
|
|
||||||
new (core_mem_alloc()) Trace_source(Trace::sources(),
|
new (core_mem_alloc()) Trace_source(Trace::sources(), location,
|
||||||
Affinity::Location(genode_cpu_id, 0,
|
|
||||||
_cpus.width(), 1),
|
|
||||||
sc_idle_base + kernel_cpu_id,
|
sc_idle_base + kernel_cpu_id,
|
||||||
"cross");
|
"cross");
|
||||||
|
|
||||||
new (core_mem_alloc()) Trace_source(Trace::sources(),
|
new (core_mem_alloc()) Trace_source(Trace::sources(), location,
|
||||||
Affinity::Location(genode_cpu_id, 0,
|
|
||||||
_cpus.width(), 1),
|
|
||||||
sc_idle_base + kernel_cpu_id,
|
sc_idle_base + kernel_cpu_id,
|
||||||
"killed");
|
"killed");
|
||||||
}
|
});
|
||||||
|
|
||||||
/* add exception handler EC for core and EC root thread to trace sources */
|
/* add exception handler EC for core and EC root thread to trace sources */
|
||||||
struct Core_trace_source : public Trace::Source::Info_accessor,
|
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])) {
|
unsigned const cpu_id = pager_index(location);
|
||||||
error("invalid genode cpu id ", genode_cpu_id);
|
|
||||||
|
if (cpu_id >= sizeof(map_cpu_ids) / sizeof(map_cpu_ids[0])) {
|
||||||
|
error("invalid genode cpu id ", cpu_id);
|
||||||
return ~0U;
|
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());
|
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 source_pd = platform_specific().core_pd_sel();
|
||||||
|
|
||||||
addr_t const pt_oom = _pager->get_oom_portal();
|
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)
|
Affinity::Location affinity, int)
|
||||||
:
|
:
|
||||||
_pd(0), _pager(0), _id_base(cap_map().insert(2)),
|
_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),
|
_features(0),
|
||||||
_priority(scale_priority(prio, name)),
|
_priority(scale_priority(prio, name)),
|
||||||
_name(name)
|
_name(name)
|
||||||
|
@ -100,12 +100,12 @@ void Thread::start()
|
|||||||
|
|
||||||
/* create local EC */
|
/* create local EC */
|
||||||
enum { LOCAL_THREAD = false };
|
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,
|
uint8_t res = create_ec(native_thread().ec_sel,
|
||||||
platform_specific().core_pd_sel(), kernel_cpu_id,
|
platform_specific().core_pd_sel(), kernel_cpu_id,
|
||||||
(mword_t)&utcb, sp, native_thread().exc_pt_sel, LOCAL_THREAD);
|
(mword_t)&utcb, sp, native_thread().exc_pt_sel, LOCAL_THREAD);
|
||||||
if (res != NOVA_OK) {
|
if (res != NOVA_OK) {
|
||||||
error("create_ec returned ", res, " cpu=", location.xpos());
|
error("create_ec returned ", res);
|
||||||
throw Cpu_session::Thread_creation_failed();
|
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;
|
Cpu_thread_component &thread = *ptr;
|
||||||
|
|
||||||
vcpu_location = thread.platform_thread().affinity();
|
vcpu_location = thread.platform_thread().affinity();
|
||||||
addr_t genode_cpu_id = thread.platform_thread().affinity().xpos();
|
kernel_cpu_id = platform_specific().kernel_cpu_id(thread.platform_thread().affinity());
|
||||||
kernel_cpu_id = platform_specific().kernel_cpu_id(genode_cpu_id);
|
|
||||||
|
|
||||||
return thread.platform_thread().pager().pd_sel();
|
return thread.platform_thread().pager().pd_sel();
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user