From 0e83b0b093126da42f0e003cac6ee2baa8d990c8 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Wed, 10 Jul 2013 14:35:54 +0200 Subject: [PATCH] nova: create core threads on boot cpu The boot CPU is not necessarily 0 as currently assumed for base-nova. Replace all hard coded values by the actual boot cpu number. Issue #814 --- base-nova/src/base/server/server.cc | 5 ++--- base-nova/src/core/echo.cc | 7 ++++--- base-nova/src/core/include/nova_util.h | 18 ++++++++++++++++++ base-nova/src/core/irq_session_component.cc | 9 ++++----- base-nova/src/core/platform.cc | 9 ++++----- base-nova/src/core/platform_thread.cc | 2 +- base-nova/src/core/thread_start.cc | 4 ++++ 7 files changed, 37 insertions(+), 17 deletions(-) diff --git a/base-nova/src/base/server/server.cc b/base-nova/src/base/server/server.cc index 8662a2823..598e60c78 100644 --- a/base-nova/src/base/server/server.cc +++ b/base-nova/src/base/server/server.cc @@ -253,9 +253,8 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, _tid.ec_sel = ec_cap.local_name(); } else { - enum { CPU_NO = 0 }; //XXX find out the boot cpu - /* tell thread starting code on which CPU to let run the server thread */ - *reinterpret_cast(stack_top()) = CPU_NO; + /* tell thread starting code to use boot CPU */ + *reinterpret_cast(stack_top()) = ~0UL; /* * Required for core threads (creates local EC) diff --git a/base-nova/src/core/echo.cc b/base-nova/src/core/echo.cc index 7df8596b1..8beea8701 100644 --- a/base-nova/src/core/echo.cc +++ b/base-nova/src/core/echo.cc @@ -20,10 +20,10 @@ /* local includes */ #include +#include enum { ECHO_STACK_SIZE = 1024, - ECHO_CPU_NO = 0, ECHO_GLOBAL = false, ECHO_EXC_BASE = 0 }; @@ -72,8 +72,9 @@ Echo::Echo(Genode::addr_t utcb_addr) /* create echo EC */ Genode::addr_t pd_sel = Genode::Platform_pd::pd_core_sel(); - uint8_t res = create_ec(_ec_sel, pd_sel, ECHO_CPU_NO, utcb_addr, - (mword_t)echo_stack_top(), ECHO_EXC_BASE, ECHO_GLOBAL); + uint8_t res = create_ec(_ec_sel, pd_sel, boot_cpu(), utcb_addr, + reinterpret_cast(echo_stack_top()), + ECHO_EXC_BASE, ECHO_GLOBAL); /* make error condition visible by raising an unhandled page fault */ if (res) { ((void (*)())(res*0x10000UL))(); } diff --git a/base-nova/src/core/include/nova_util.h b/base-nova/src/core/include/nova_util.h index f6d26b9dd..a2af56819 100644 --- a/base-nova/src/core/include/nova_util.h +++ b/base-nova/src/core/include/nova_util.h @@ -28,6 +28,24 @@ enum { verbose_local_map = false }; +/** + * Return boot CPU number. It is required if threads in core should be placed + * on the same CPU as the main thread. + */ +inline Genode::addr_t boot_cpu() +{ + /** + * Initial value of ax and di register, saved by the crt0 startup code + * and SOLELY VALID in 'core' !!! + * + * For x86_32 - __initial_ax contains the number of the boot CPU. + * For x86_64 - __initial_di contains the number of the boot CPU. + */ + extern Genode::addr_t __initial_ax; + extern Genode::addr_t __initial_di; + + return (sizeof(void *) > 4) ? __initial_di : __initial_ax; +} /** * Establish a mapping diff --git a/base-nova/src/core/irq_session_component.cc b/base-nova/src/core/irq_session_component.cc index 53d96e741..8006e350c 100644 --- a/base-nova/src/core/irq_session_component.cc +++ b/base-nova/src/core/irq_session_component.cc @@ -67,8 +67,8 @@ class Irq_thread : public Thread_base *sp = reinterpret_cast(_thread_start); /* create global EC */ - enum { CPU_NO = 0, GLOBAL = true }; - uint8_t res = create_ec(_tid.ec_sel, pd_sel, CPU_NO, + enum { GLOBAL = true }; + uint8_t res = create_ec(_tid.ec_sel, pd_sel, boot_cpu(), utcb, (mword_t)sp, _tid.exc_pt_sel, GLOBAL); if (res != NOVA_OK) { PERR("%p - create_ec returned %d", this, res); @@ -139,11 +139,10 @@ class Genode::Irq_proxy_component : public Irq_proxy } /* assign IRQ to CPU */ - enum { CPU = 0 }; addr_t msi_addr = 0; addr_t msi_data = 0; - uint8_t res = Nova::assign_gsi(_irq_sel, _dev_mem, CPU, msi_addr, msi_data); - + uint8_t res = Nova::assign_gsi(_irq_sel, _dev_mem, boot_cpu(), + msi_addr, msi_data); if (res != Nova::NOVA_OK) PERR("Error: assign_pci failed -irq:dev:msi_addr:msi_data " "%lx:%lx:%lx:%lx", _irq_number, _dev_mem, msi_addr, diff --git a/base-nova/src/core/platform.cc b/base-nova/src/core/platform.cc index 6fdd202f9..21450f97f 100644 --- a/base-nova/src/core/platform.cc +++ b/base-nova/src/core/platform.cc @@ -38,8 +38,7 @@ Native_utcb *main_thread_utcb(); /** - * Initial value of esp register, saved by the crt0 startup code - * + * Initial value of esp register, saved by the crt0 startup code. * This value contains the address of the hypervisor information page. */ extern addr_t __initial_sp; @@ -255,14 +254,13 @@ static void init_core_page_fault_handler() { /* create echo EC */ enum { - CPU_NO = 0, GLOBAL = false, EXC_BASE = 0 }; addr_t ec_sel = cap_selector_allocator()->alloc(); - uint8_t ret = create_ec(ec_sel, __core_pd_sel, CPU_NO, + uint8_t ret = create_ec(ec_sel, __core_pd_sel, boot_cpu(), CORE_PAGER_UTCB_ADDR, core_pager_stack_top(), EXC_BASE, GLOBAL); if (ret) @@ -341,7 +339,8 @@ Platform::Platform() : if (verbose_boot_info) { printf("Hypervisor %s VMX\n", hip->has_feature_vmx() ? "features" : "does not feature"); printf("Hypervisor %s SVM\n", hip->has_feature_svm() ? "features" : "does not feature"); - printf("Hypervisor reports %u CPU%c\n", _cpus, _cpus > 1 ? 's' : ' '); + printf("Hypervisor reports %u CPU%c - boot CPU is %lu\n", + _cpus, _cpus > 1 ? 's' : ' ', boot_cpu()); } /* initialize core allocators */ diff --git a/base-nova/src/core/platform_thread.cc b/base-nova/src/core/platform_thread.cc index 1f93bc65c..f0dc2d049 100644 --- a/base-nova/src/core/platform_thread.cc +++ b/base-nova/src/core/platform_thread.cc @@ -326,7 +326,7 @@ Weak_ptr Platform_thread::address_space() Platform_thread::Platform_thread(const char *name, unsigned, int thread_id) : _pd(0), _pager(0), _id_base(cap_selector_allocator()->alloc(1)), - _sel_exc_base(Native_thread::INVALID_INDEX), _cpu_no(0), //XXX find out boot CPU + _sel_exc_base(Native_thread::INVALID_INDEX), _cpu_no(boot_cpu()), _is_main_thread(false), _is_vcpu(false) { strncpy(_name, name, sizeof(_name)); diff --git a/base-nova/src/core/thread_start.cc b/base-nova/src/core/thread_start.cc index ae49c18a4..a5a50f401 100644 --- a/base-nova/src/core/thread_start.cc +++ b/base-nova/src/core/thread_start.cc @@ -84,6 +84,10 @@ void Thread_base::start() addr_t pd_sel = Platform_pd::pd_core_sel(); addr_t cpu_no = *reinterpret_cast(stack_top()); + /* server code sets this value */ + if (cpu_no == ~0UL) + cpu_no = boot_cpu(); + /* create local EC */ enum { LOCAL_THREAD = false }; uint8_t res = create_ec(_tid.ec_sel, pd_sel, cpu_no,