nova: add guarded access to MSRs

via Genode Pd::system_control interface

Issue #5009
This commit is contained in:
Alexander Boettcher 2023-10-04 11:32:42 +02:00 committed by Christian Helmuth
parent fe3a958dbf
commit e36170c997
11 changed files with 128 additions and 29 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -1 +1 @@
3f6464b9126ffc77fdfd4b670ed7b4d3d3d0aff8
e104241c249b88b6e0a4ff74bda67996dfa200c4

View File

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

View File

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

View File

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

View File

@ -16,22 +16,30 @@
#include <assertion.h>
#include <nova_util.h> /* kernel_hip */
#include <nova_msr.h>
using namespace Core;
bool Pd_session_component::assign_pci(addr_t pci_config_memory, uint16_t bdf)
template <typename FUNC>
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<addr_t>(mapping.dst_addr, 1UL << mapping.size_log2) , " "
@ -191,16 +194,9 @@ Capability<Pd_session::System_control> 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<Nova::Utcb *>(Thread::myself()->utcb());
return msr_access(request, utcb, msr_cap);
}
return State();
}

View File

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

View File

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