diff --git a/repos/base-nova/include/nova/syscall-generic.h b/repos/base-nova/include/nova/syscall-generic.h index cff0532830..4aca61e523 100644 --- a/repos/base-nova/include/nova/syscall-generic.h +++ b/repos/base-nova/include/nova/syscall-generic.h @@ -287,6 +287,7 @@ namespace Nova { EC_TIME = 5U, EC_GET_VCPU_STATE = 6U, EC_SET_VCPU_STATE = 7U, + EC_MSR_ACCESS = 8U }; enum Sc_op { @@ -759,7 +760,7 @@ namespace Nova { * Calling this function has the side effect of removing all typed * message items from the message buffer. */ - void set_msg_word(unsigned num) { items = num; } + void set_msg_word(mword_t const num) { items = num; } /** * Return current number of message word in UTCB diff --git a/repos/base-nova/lib/mk/core-nova.inc b/repos/base-nova/lib/mk/core-nova.inc index 9df0b67e8f..206f936546 100644 --- a/repos/base-nova/lib/mk/core-nova.inc +++ b/repos/base-nova/lib/mk/core-nova.inc @@ -45,7 +45,7 @@ SRC_CC += stack_area.cc \ vm_session_common.cc \ heartbeat.cc -INC_DIR = $(REP_DIR)/src/core/include \ +INC_DIR += $(REP_DIR)/src/core/include \ $(REP_DIR)/src/include \ $(BASE_DIR)/src/include \ $(GEN_CORE_DIR)/include diff --git a/repos/base-nova/lib/mk/spec/x86_32/core-nova.mk b/repos/base-nova/lib/mk/spec/x86_32/core-nova.mk index 7c08a9d1e7..a28dad3028 100644 --- a/repos/base-nova/lib/mk/spec/x86_32/core-nova.mk +++ b/repos/base-nova/lib/mk/spec/x86_32/core-nova.mk @@ -1,3 +1,5 @@ SRC_CC += spec/x86_32/pager.cc +INC_DIR += $(REP_DIR)/src/core/include/spec/x86_32 + include $(REP_DIR)/lib/mk/core-nova.inc diff --git a/repos/base-nova/lib/mk/spec/x86_64/core-nova.mk b/repos/base-nova/lib/mk/spec/x86_64/core-nova.mk index 0424e85c4f..7ecaebd8f7 100644 --- a/repos/base-nova/lib/mk/spec/x86_64/core-nova.mk +++ b/repos/base-nova/lib/mk/spec/x86_64/core-nova.mk @@ -1,3 +1,5 @@ SRC_CC += spec/x86_64/pager.cc +INC_DIR += $(REP_DIR)/src/core/include/spec/x86_64 + include $(REP_DIR)/lib/mk/core-nova.inc diff --git a/repos/base-nova/ports/nova.hash b/repos/base-nova/ports/nova.hash index 05e7c3d6a6..3e6a854a0e 100644 --- a/repos/base-nova/ports/nova.hash +++ b/repos/base-nova/ports/nova.hash @@ -1 +1 @@ -3f6464b9126ffc77fdfd4b670ed7b4d3d3d0aff8 +e104241c249b88b6e0a4ff74bda67996dfa200c4 diff --git a/repos/base-nova/ports/nova.port b/repos/base-nova/ports/nova.port index a73583628e..26e801c482 100644 --- a/repos/base-nova/ports/nova.port +++ b/repos/base-nova/ports/nova.port @@ -4,7 +4,7 @@ DOWNLOADS := nova.git # r10 branch URL(nova) := https://github.com/alex-ab/NOVA.git -REV(nova) := 89f714dcb32c7f4e97d29a8651e55862b8362df1 +REV(nova) := 3e34fa6c35c55566ae57a1fd654262964ffcf544 DIR(nova) := src/kernel/nova PATCHES := $(sort $(wildcard $(REP_DIR)/patches/*.patch)) diff --git a/repos/base-nova/src/core/include/spec/x86_32/nova_msr.h b/repos/base-nova/src/core/include/spec/x86_32/nova_msr.h new file mode 100644 index 0000000000..35e7768230 --- /dev/null +++ b/repos/base-nova/src/core/include/spec/x86_32/nova_msr.h @@ -0,0 +1,26 @@ +/* + * \brief Guarded MSR access on NOVA + * \author Alexander Boettcher + * \date 2023-10-03 + */ + +/* + * Copyright (C) 2023 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. + */ + +#ifndef _CORE__INCLUDE__SPEC_X86_32__NOVA_MSR_H_ +#define _CORE__INCLUDE__SPEC_X86_32__NOVA_MSR_H_ + +#include + +static Genode::Pd_session::Managing_system_state msr_access(Genode::Pd_session::Managing_system_state const &, + Nova::Utcb &, + Genode::addr_t const) +{ + return { }; /* not supported for now on x86_32 */ +} + +#endif /* _CORE__INCLUDE__SPEC_X86_32__NOVA_MSR_H_ */ diff --git a/repos/base-nova/src/core/include/spec/x86_64/nova_msr.h b/repos/base-nova/src/core/include/spec/x86_64/nova_msr.h new file mode 100644 index 0000000000..b374f1b010 --- /dev/null +++ b/repos/base-nova/src/core/include/spec/x86_64/nova_msr.h @@ -0,0 +1,55 @@ +/* + * \brief Guarded MSR access on NOVA + * \author Alexander Boettcher + * \date 2023-10-03 + */ + +/* + * Copyright (C) 2023 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. + */ + +#ifndef _CORE__INCLUDE__SPEC_X86_64__NOVA_MSR_H_ +#define _CORE__INCLUDE__SPEC_X86_64__NOVA_MSR_H_ + +#include + +static Genode::Pd_session::Managing_system_state msr_access(Genode::Pd_session::Managing_system_state const &state, + Nova::Utcb &utcb, + Genode::addr_t const msr_cap) +{ + Genode::Pd_session::Managing_system_state result { }; + + utcb.set_msg_word(state.ip); /* count */ + utcb.msg()[0] = state.r8; + utcb.msg()[1] = state.r9; + utcb.msg()[2] = state.r10; + utcb.msg()[3] = state.r11; + utcb.msg()[4] = state.r12; + utcb.msg()[5] = state.r13; + utcb.msg()[6] = state.r14; + utcb.msg()[7] = state.r15; + + auto const res = Nova::ec_ctrl(Nova::Ec_op::EC_MSR_ACCESS, msr_cap); + + result.trapno = (res == Nova::NOVA_OK) ? 1 : 0; + + if (res != Nova::NOVA_OK) + return result; + + result.ip = utcb.msg_words(); /* bitmap about valid returned words */ + result.r8 = utcb.msg()[0]; + result.r9 = utcb.msg()[1]; + result.r10 = utcb.msg()[2]; + result.r11 = utcb.msg()[3]; + result.r12 = utcb.msg()[4]; + result.r13 = utcb.msg()[5]; + result.r14 = utcb.msg()[6]; + result.r15 = utcb.msg()[7]; + + return result; +} + +#endif /* _CORE__INCLUDE__SPEC_X86_64__NOVA_MSR_H_ */ diff --git a/repos/base-nova/src/core/pd_session_support.cc b/repos/base-nova/src/core/pd_session_support.cc index 327cb8cb53..37d4a9e429 100644 --- a/repos/base-nova/src/core/pd_session_support.cc +++ b/repos/base-nova/src/core/pd_session_support.cc @@ -16,22 +16,30 @@ #include #include /* kernel_hip */ +#include using namespace Core; - -bool Pd_session_component::assign_pci(addr_t pci_config_memory, uint16_t bdf) +template +inline Nova::uint8_t retry_syscall(addr_t pd_sel, FUNC func) { - uint8_t res = Nova::NOVA_PD_OOM; + Nova::uint8_t res; do { - res = Nova::assign_pci(_pd->pd_sel(), pci_config_memory, bdf); + res = func(); } while (res == Nova::NOVA_PD_OOM && Nova::NOVA_OK == Pager_object::handle_oom(Pager_object::SRC_CORE_PD, - _pd->pd_sel(), + pd_sel, "core", "ep", Pager_object::Policy::UPGRADE_CORE_TO_DST)); - return res == Nova::NOVA_OK; + return res; +} + +bool Pd_session_component::assign_pci(addr_t pci_config_memory, uint16_t bdf) +{ + return retry_syscall(_pd->pd_sel(), [&]() { + return Nova::assign_pci(_pd->pd_sel(), pci_config_memory, bdf); + }) == Nova::NOVA_OK; } @@ -45,8 +53,7 @@ void Pd_session_component::map(addr_t virt, addr_t size) auto map_memory = [&] (Mapping const &mapping) { /* asynchronously map memory */ - uint8_t err = Nova::NOVA_PD_OOM; - do { + uint8_t err = retry_syscall(_pd->pd_sel(), [&]() { utcb.set_msg_word(0); bool res = utcb.append_item(nova_src_crd(mapping), 0, true, false, @@ -57,13 +64,9 @@ void Pd_session_component::map(addr_t virt, addr_t size) /* one item ever fits on the UTCB */ (void)res; - err = Nova::delegate(pd_core, pd_dst, nova_dst_crd(mapping)); + return Nova::delegate(pd_core, pd_dst, nova_dst_crd(mapping)); + }); - } while (err == Nova::NOVA_PD_OOM && - Nova::NOVA_OK == Pager_object::handle_oom(Pager_object::SRC_CORE_PD, - target_pd.pd_sel(), - "core", "ep", - Pager_object::Policy::UPGRADE_CORE_TO_DST)); if (err != Nova::NOVA_OK) { error("could not eagerly map memory ", Hex_range(mapping.dst_addr, 1UL << mapping.size_log2) , " " @@ -191,16 +194,9 @@ Capability System_control_impl::control_cap(Affinity } -State System_control_component::system_control(State const &request) +static State acpi_suspend(State const &request) { - bool const suspend = (request.trapno == State::ACPI_SUSPEND_REQUEST); - State respond { }; - - if (!suspend) { - /* report failed attempt */ - respond.trapno = 0; - return respond; - } + State respond { .trapno = 0 }; /* * The trapno/ip/sp registers used below are just convention to transfer @@ -224,3 +220,18 @@ State System_control_component::system_control(State const &request) return respond; } + + +State System_control_component::system_control(State const &request) +{ + if (request.trapno == State::ACPI_SUSPEND_REQUEST) + return acpi_suspend(request); + + if (request.trapno == State::MSR_ACCESS) { + auto const msr_cap = platform_specific().core_pd_sel() + 4; + Nova::Utcb &utcb = *reinterpret_cast(Thread::myself()->utcb()); + return msr_access(request, utcb, msr_cap); + } + + return State(); +} diff --git a/repos/base/include/spec/x86_32/cpu/cpu_state.h b/repos/base/include/spec/x86_32/cpu/cpu_state.h index 61d459021a..e1c6417eb3 100644 --- a/repos/base/include/spec/x86_32/cpu/cpu_state.h +++ b/repos/base/include/spec/x86_32/cpu/cpu_state.h @@ -38,7 +38,8 @@ struct Genode::Cpu_state addr_t trapno = 0; enum { - ACPI_SUSPEND_REQUEST = 0x100, /* convention for managing_system() */ + ACPI_SUSPEND_REQUEST = 0x100, /* convention for system_control() */ + MSR_ACCESS = 0x101, /* convention for system_control() */ }; }; diff --git a/repos/base/include/spec/x86_64/cpu/cpu_state.h b/repos/base/include/spec/x86_64/cpu/cpu_state.h index f27e293a2f..5002e93d3e 100644 --- a/repos/base/include/spec/x86_64/cpu/cpu_state.h +++ b/repos/base/include/spec/x86_64/cpu/cpu_state.h @@ -63,7 +63,8 @@ struct Genode::Cpu_state addr_t ss = 0; enum { - ACPI_SUSPEND_REQUEST = 0x100, /* convention for managing_system() */ + ACPI_SUSPEND_REQUEST = 0x100, /* convention for system_control() */ + MSR_ACCESS = 0x101, /* convention for system_control() */ }; };