base: extend PD session by system_control_cap

Per Affinity::Location a system control cap can be requested. The capability
provides an RPC interface to request and set Cpu_state, as provided by the
former Pd::managing_system(Cpu_state) method. Invocation of those system
control capabilities then *can* (see below) be executed on the desired CPU
as described by Affinity::Location.

The system control cap will be invalid for kernels that don't support
system_control/managing_system functionality at all.

The system control cap will be ever by the same, e.g. ignoring the
Affinity::Location parameter, if the used kernel doesn't support or doesn't
require the feature to execute the system control per CPU.

The commit is a preparation step to add guarded and selective x86 MSR
access per CPU.

Fixes #5009
This commit is contained in:
Alexander Boettcher 2023-09-26 10:55:06 +02:00 committed by Christian Helmuth
parent ffc25fde53
commit 916bd88e5e
15 changed files with 220 additions and 38 deletions

View File

@ -19,20 +19,47 @@ using namespace Core;
using State = Genode::Pd_session::Managing_system_state;
State Pd_session_component::managing_system(State const & s)
class System_control_component : public Genode::Rpc_object<Pd_session::System_control>,
public Core::System_control
{
static constexpr addr_t SMCCC_NOT_SUPPORTED = 0xffffffffUL;
public:
State system_control(State const &) override;
Capability<Pd_session::System_control> control_cap(Affinity::Location const) const override;
};
State System_control_component::system_control(State const &s)
{
State ret;
ret.r[0] = (_managing_system == Managing_system::DENIED)
? SMCCC_NOT_SUPPORTED
: Hw::Psci_smc_functor::call(s.r[0], s.r[1], s.r[2], s.r[3]);
ret.r[0] = Hw::Psci_smc_functor::call(s.r[0], s.r[1], s.r[2], s.r[3]);
return ret;
}
static System_control_component &system_instance()
{
static System_control_component system_component { };
return system_component;
}
System_control & Core::init_system_control(Allocator &, Rpc_entrypoint &ep)
{
ep.manage(&system_instance());
return system_instance();
}
Capability<Pd_session::System_control> System_control_component::control_cap(Affinity::Location const) const
{
return system_instance().cap();
}
/***************************
** Dummy implementations **
***************************/

View File

@ -18,10 +18,20 @@ using namespace Core;
using State = Genode::Pd_session::Managing_system_state;
State Pd_session_component::managing_system(State const &request)
class System_control_component : public Genode::Rpc_object<Pd_session::System_control>,
public Core::System_control
{
bool const suspend = (_managing_system == Managing_system::PERMITTED) &&
(request.trapno == State::ACPI_SUSPEND_REQUEST);
public:
State system_control(State const &) override;
Capability<Pd_session::System_control> control_cap(Affinity::Location const) const override;
};
State System_control_component::system_control(State const &request)
{
bool const suspend = (request.trapno == State::ACPI_SUSPEND_REQUEST);
State respond { };
if (!suspend) {
@ -49,6 +59,26 @@ State Pd_session_component::managing_system(State const &request)
}
static System_control_component &system_instance()
{
static System_control_component system_component { };
return system_component;
}
System_control & Core::init_system_control(Allocator &, Rpc_entrypoint &ep)
{
ep.manage(&system_instance());
return system_instance();
}
Capability<Pd_session::System_control> System_control_component::control_cap(Affinity::Location const) const
{
return system_instance().cap();
}
/***************************
** Dummy implementations **
***************************/
@ -57,4 +87,3 @@ bool Pd_session_component::assign_pci(addr_t, uint16_t) { return true; }
void Pd_session_component::map(addr_t, addr_t) { }

View File

@ -101,10 +101,41 @@ void Pd_session_component::map(addr_t virt, addr_t size)
using State = Genode::Pd_session::Managing_system_state;
State Pd_session_component::managing_system(State const &request)
class System_control_component : public Genode::Rpc_object<Pd_session::System_control>,
public Core::System_control
{
bool const suspend = (_managing_system == Managing_system::PERMITTED) &&
(request.trapno == State::ACPI_SUSPEND_REQUEST);
public:
State system_control(State const &) override;
Capability<Pd_session::System_control> control_cap(Affinity::Location const) const override;
};
static System_control_component &system_instance()
{
static System_control_component system_component { };
return system_component;
}
System_control & Core::init_system_control(Allocator &, Rpc_entrypoint &ep)
{
ep.manage(&system_instance());
return system_instance();
}
Capability<Pd_session::System_control> System_control_component::control_cap(Affinity::Location const) const
{
return system_instance().cap();
}
State System_control_component::system_control(State const &request)
{
bool const suspend = (request.trapno == State::ACPI_SUSPEND_REQUEST);
State respond { };
if (!suspend) {

View File

@ -93,8 +93,8 @@ struct Genode::Pd_session_client : Rpc_client<Pd_session>
Capability<Native_pd> native_pd() override { return call<Rpc_native_pd>(); }
Managing_system_state managing_system(Managing_system_state const & state) override {
return call<Rpc_managing_system>(state); }
Capability<System_control> system_control_cap(Affinity::Location const location) override {
return call<Rpc_system_control_cap>(location); }
addr_t dma_addr(Ram_dataspace_capability ds) override { return call<Rpc_dma_addr>(ds); }

View File

@ -16,6 +16,7 @@
#define _INCLUDE__PD_SESSION__PD_SESSION_H_
#include <util/attempt.h>
#include <base/affinity.h>
#include <base/exception.h>
#include <cpu/cpu_state.h>
#include <session/session.h>
@ -305,12 +306,26 @@ struct Genode::Pd_session : Session, Ram_allocator
** Access to system management interface **
*******************************************/
struct System_control : Interface
{
using System_control_state = Cpu_state;
virtual System_control_state system_control(System_control_state const &) = 0;
GENODE_RPC(Rpc_system_control, System_control_state, system_control,
System_control_state const &);
GENODE_RPC_INTERFACE(Rpc_system_control);
};
using Managing_system_state = Cpu_state;
/**
* Call privileged system management functionality of kernel or firmware
* Call privileged system control functionality of kernel or firmware
*/
virtual Managing_system_state managing_system(Managing_system_state const &) = 0;
virtual Capability<System_control> system_control_cap(Affinity::Location const) = 0;
/*******************************************
@ -391,8 +406,9 @@ struct Genode::Pd_session : Session, Ram_allocator
GENODE_RPC(Rpc_native_pd, Capability<Native_pd>, native_pd);
GENODE_RPC(Rpc_managing_system, Managing_system_state, managing_system,
Managing_system_state const &);
GENODE_RPC(Rpc_system_control_cap, Capability<System_control>,
system_control_cap, Affinity::Location);
GENODE_RPC(Rpc_dma_addr, addr_t, dma_addr, Ram_dataspace_capability);
GENODE_RPC(Rpc_attach_dma, Attach_dma_result, attach_dma,
Dataspace_capability, addr_t);
@ -405,7 +421,7 @@ struct Genode::Pd_session : Session, Ram_allocator
Rpc_transfer_cap_quota, Rpc_cap_quota, Rpc_used_caps,
Rpc_try_alloc, Rpc_free,
Rpc_transfer_ram_quota, Rpc_ram_quota, Rpc_used_ram,
Rpc_native_pd, Rpc_managing_system,
Rpc_native_pd, Rpc_system_control_cap,
Rpc_dma_addr, Rpc_attach_dma);
};

View File

@ -75,7 +75,8 @@ class Core::Core_env : public Noncopyable
_region_map,
*((Pager_entrypoint *)nullptr),
"" /* args to native PD */,
platform_specific().core_mem_alloc())
platform_specific().core_mem_alloc(),
*((Core::System_control *)nullptr))
{
_pd_session.init_cap_and_ram_accounts();
}

View File

@ -33,6 +33,7 @@ class Core::Pd_root : public Root_component<Pd_session_component>
Range_allocator &_phys_alloc;
Region_map &_local_rm;
Range_allocator &_core_mem;
System_control &_system_control;
/**
* The RAM allocations of system management components are getting
@ -91,7 +92,7 @@ class Core::Pd_root : public Root_component<Pd_session_component>
_virt_range_from_args(args),
_managing_system(args),
_local_rm, _pager_ep, args,
_core_mem);
_core_mem, _system_control);
}
void _upgrade_session(Pd_session_component *pd, const char *args) override
@ -111,11 +112,13 @@ class Core::Pd_root : public Root_component<Pd_session_component>
Range_allocator &phys_alloc,
Region_map &local_rm,
Allocator &md_alloc,
Range_allocator &core_mem)
Range_allocator &core_mem,
System_control &system_control)
:
Root_component<Pd_session_component>(&ep, &md_alloc),
_ep(ep), _signal_ep(signal_ep), _pager_ep(pager_ep),
_phys_alloc(phys_alloc), _local_rm(local_rm), _core_mem(core_mem)
_phys_alloc(phys_alloc), _local_rm(local_rm), _core_mem(core_mem),
_system_control(system_control)
{ }
};

View File

@ -30,6 +30,7 @@
#include <constrained_core_ram.h>
#include <platform_pd.h>
#include <signal_broker.h>
#include <system_control.h>
#include <rpc_cap_factory.h>
#include <ram_dataspace_factory.h>
#include <native_pd_component.h>
@ -52,6 +53,7 @@ class Core::Pd_session_component : public Session_object<Pd_session>
Constructible<Account<Ram_quota> > _ram_account { };
Rpc_entrypoint &_ep;
Core::System_control &_system_control;
Constrained_ram_allocator _constrained_md_ram_alloc;
Constrained_core_ram _constrained_core_ram_alloc;
Sliced_heap _sliced_heap;
@ -131,10 +133,12 @@ class Core::Pd_session_component : public Session_object<Pd_session>
Region_map &local_rm,
Pager_entrypoint &pager_ep,
char const *args,
Range_allocator &core_mem)
Range_allocator &core_mem,
Core::System_control &system_control)
:
Session_object(ep, resources, label, diag),
_ep(ep),
_system_control(system_control),
_constrained_md_ram_alloc(*this, _ram_quota_guard(), _cap_quota_guard()),
_constrained_core_ram_alloc(_ram_quota_guard(), _cap_quota_guard(), core_mem),
_sliced_heap(_constrained_md_ram_alloc, local_rm),
@ -329,11 +333,17 @@ class Core::Pd_session_component : public Session_object<Pd_session>
Capability<Native_pd> native_pd() override { return _native_pd.cap(); }
/*******************************
** Managing system interface **
*******************************/
/******************************
** System control interface **
******************************/
Managing_system_state managing_system(Managing_system_state const &) override;
Capability<System_control> system_control_cap(Affinity::Location const location) override
{
if (_managing_system == Managing_system::PERMITTED)
return _system_control.control_cap(location);
return { };
}
/*******************************************

View File

@ -0,0 +1,36 @@
/*
* \brief Interface to get access to privileged system control capability
* \author Alexander Boettcher
* \date 2023-09-25
*/
/*
* 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__SYSTEM_CONTROL_H_
#define _CORE__INCLUDE__SYSTEM_CONTROL_H_
#include <base/rpc_server.h>
namespace Core {
class System_control;
System_control & init_system_control(Allocator &, Rpc_entrypoint &);
}
class Core::System_control : Interface
{
public:
virtual Capability<Pd_session::System_control> control_cap(Affinity::Location) const = 0;
};
#endif /* _CORE__INCLUDE__SYSTEM_CONTROL_H_ */

View File

@ -29,6 +29,7 @@
#include <core_env.h>
#include <core_service.h>
#include <signal_transmitter.h>
#include <system_control.h>
#include <rom_root.h>
#include <rm_root.h>
#include <cpu_root.h>
@ -255,6 +256,8 @@ void Genode::bootstrap_component(Genode::Platform &)
using Trace_root = Core::Trace::Root;
using Trace_session_component = Core::Trace::Session_component;
static Core::System_control &system_control = init_system_control(sliced_heap, ep);
static Rom_root rom_root (ep, ep, platform().rom_fs(), sliced_heap);
static Rm_root rm_root (ep, sliced_heap, core_ram_alloc, local_rm, pager_ep);
static Cpu_root cpu_root (core_ram_alloc, local_rm, ep, ep, pager_ep,
@ -262,7 +265,8 @@ void Genode::bootstrap_component(Genode::Platform &)
static Pd_root pd_root (ep, core_env().signal_ep(), pager_ep,
platform().ram_alloc(),
local_rm, sliced_heap,
platform_specific().core_mem_alloc());
platform_specific().core_mem_alloc(),
system_control);
static Log_root log_root (ep, sliced_heap);
static Io_mem_root io_mem_root (ep, ep, platform().io_mem_alloc(),
platform().ram_alloc(), sliced_heap);

View File

@ -22,6 +22,20 @@ bool Pd_session_component::assign_pci(addr_t, uint16_t) { return true; }
void Pd_session_component::map(addr_t, addr_t) { }
using State = Genode::Pd_session::Managing_system_state;
State Pd_session_component::managing_system(State const &) { return State(); }
class System_control_dummy : public System_control
{
public:
Capability<Pd_session::System_control> control_cap(Affinity::Location) const override
{
return { };
}
};
System_control & Core::init_system_control(Allocator &, Rpc_entrypoint &)
{
static System_control_dummy dummy { };
return dummy;
}

View File

@ -34,6 +34,17 @@ class Suspend
uint8_t s3_sleep_typeb { };
bool s3_sleep_valid { };
Capability<Pd_session::System_control> _control_cap { _env.pd().system_control_cap(Affinity::Location()) };
struct Client: Genode::Rpc_client<Pd_session::System_control>
{
explicit Client(Genode::Capability<Pd_session::System_control> cap)
: Rpc_client<Pd_session::System_control>(cap) { }
Pd_session::Managing_system_state system_control(Pd_session::Managing_system_state const &state) override {
return call<Rpc_system_control>(state); }
} _system_control { _control_cap };
void suspend()
{
/*
@ -58,7 +69,7 @@ class Suspend
in.ip = s3_sleep_typea;
in.sp = s3_sleep_typeb;
out = _env.pd().managing_system (in);
out = _system_control.system_control (in);
if (!out.trapno)
log("suspend failed");

View File

@ -267,8 +267,8 @@ struct Monitor::Inferior_pd : Monitored_pd_session
Capability<Native_pd> native_pd() override {
return _real.call<Rpc_native_pd>(); }
Managing_system_state managing_system(Managing_system_state const & state) override {
return _real.call<Rpc_managing_system>(state); }
Capability<System_control> system_control_cap(Affinity::Location const location) override {
return _real.call<Rpc_system_control_cap>(location); }
addr_t dma_addr(Ram_dataspace_capability ds) override {
return _real.call<Rpc_dma_addr>(ds); }

View File

@ -39,6 +39,7 @@ struct Monitor::Pd_intrinsics : Sandbox::Pd_intrinsics
using Sig_ctx_cap = Signal_context_capability;
using Ram_ds_cap = Ram_dataspace_capability;
using Mng_sys_state = Managing_system_state;
using Control_cap = Capability<System_control>;
void assign_parent(Capability<Parent>) override { never_called(__func__); };
bool assign_pci(addr_t, uint16_t) override { never_called(__func__); };
@ -61,7 +62,7 @@ struct Monitor::Pd_intrinsics : Sandbox::Pd_intrinsics
Ram_quota ram_quota() const override { never_called(__func__); };
Ram_quota used_ram() const override { never_called(__func__); };
Capability<Native_pd> native_pd() override { never_called(__func__); };
Mng_sys_state managing_system(Mng_sys_state const &) override { never_called(__func__); };
Control_cap system_control_cap(Affinity::Location) override { never_called(__func__); };
addr_t dma_addr(Ram_ds_cap) override { never_called(__func__); };
Attach_dma_result attach_dma(Dataspace_capability, addr_t) override { never_called(__func__); };

View File

@ -145,9 +145,8 @@ class Gdb_monitor::Pd_session_component : public Rpc_object<Pd_session>
Capability<Native_pd> native_pd() override {
return _pd.native_pd(); }
Managing_system_state
managing_system(Managing_system_state const & state) override {
return _pd.managing_system(state); }
Capability<System_control> system_control_cap(Affinity::Location const location) override {
return _pd.system_control_cap(location); }
addr_t dma_addr(Ram_dataspace_capability ds) override {
return _pd.dma_addr(ds); }