monitor: intercept VM session

This is needed to translate the thread capability argument of
'Vm_session::create_vcpu'.

Issue #4917
This commit is contained in:
Norman Feske 2023-07-04 15:50:49 +02:00
parent 38152d6c72
commit 3af5a0ca4e
4 changed files with 91 additions and 5 deletions

View File

@ -22,6 +22,9 @@ sessions to the parent. For example, the following start node selects the
! </route>
! </start>
In case a monitored component uses VM sessions (e.g. VirtualBox), the VM
service has to be routed to '<local/>' too.
If monitor's configuration features a <monitor> sub node, the monitor creates
a terminal session that offers access to the monitored components via the GDB
protocol. Each component appears as a distinct GDB inferior. The following

View File

@ -23,6 +23,7 @@
#include <pd_intrinsics.h>
#include <gdb_stub.h>
#include <gdb_packet_handler.h>
#include <monitored_vm.h>
namespace Monitor {
@ -64,9 +65,11 @@ struct Monitor::Main : Sandbox::State_handler
{
using Local_pd_session = Local_session<Pd_connection, Inferior_pd>;
using Local_cpu_session = Local_session<Cpu_connection, Inferior_cpu>;
using Local_vm_session = Local_session<Vm_connection, Monitored_vm_session>;
using Pd_service = Sandbox::Local_service<Local_pd_session>;
using Cpu_service = Sandbox::Local_service<Local_cpu_session>;
using Vm_service = Sandbox::Local_service<Local_vm_session>;
Env &_env;
@ -180,6 +183,7 @@ struct Monitor::Main : Sandbox::State_handler
void _handle_pd_service() { _handle_service<Pd_service> (_pd_service); }
void _handle_cpu_service() { _handle_service<Cpu_service>(_cpu_service); }
void _handle_vm_service() { _handle_service<Vm_service> (_vm_service); }
struct Service_handler : Sandbox::Local_service_base::Wakeup
{
@ -194,11 +198,13 @@ struct Monitor::Main : Sandbox::State_handler
: _main(main), _member(member) { }
};
Service_handler _pd_handler { *this, &Main::_handle_pd_service };
Service_handler _pd_handler { *this, &Main::_handle_pd_service };
Service_handler _cpu_handler { *this, &Main::_handle_cpu_service };
Service_handler _vm_handler { *this, &Main::_handle_vm_service };
Pd_service _pd_service { _sandbox, _pd_handler };
Pd_service _pd_service { _sandbox, _pd_handler };
Cpu_service _cpu_service { _sandbox, _cpu_handler };
Vm_service _vm_service { _sandbox, _vm_handler };
Local_pd_session &_create_session(Pd_service &, Session::Label const &label)
{
@ -227,6 +233,11 @@ struct Monitor::Main : Sandbox::State_handler
return session;
}
Local_vm_session &_create_session(Vm_service &, Session::Label const &label)
{
return *new (_heap) Local_vm_session(_env, label);
}
void _destroy_session(Local_pd_session &session)
{
if (_gdb_stub.constructed())
@ -240,6 +251,11 @@ struct Monitor::Main : Sandbox::State_handler
destroy(_heap, &session);
}
void _destroy_session(Local_vm_session &session)
{
destroy(_heap, &session);
}
void _apply_monitor_config_to_inferiors()
{
_config.xml().with_sub_node("monitor",

View File

@ -0,0 +1,67 @@
/*
* \brief Monitored VM session
* \author Norman Feske
* \date 2023-07-04
*/
/*
* 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 _MONITORED_VM_H_
#define _MONITORED_VM_H_
/* Genode includes */
#include <base/rpc_client.h>
#include <vm_session/connection.h>
/* local includes */
#include <monitored_thread.h>
namespace Monitor { struct Monitored_vm_session; }
struct Monitor::Monitored_vm_session : Monitored_rpc_object<Vm_session, Monitored_vm_session>
{
using Monitored_rpc_object::Monitored_rpc_object;
/**************************
** Vm_session interface **
**************************/
void attach(Dataspace_capability ds, addr_t at, Attach_attr attr) override
{
_real.call<Rpc_attach>(ds, at, attr);
}
void detach(addr_t vm_addr, size_t size) override
{
_real.call<Rpc_detach>(vm_addr, size);
}
void attach_pic(addr_t vm_addr) override
{
_real.call<Rpc_attach_pic>(vm_addr);
}
Capability<Native_vcpu> create_vcpu(Thread_capability thread_cap)
{
Capability<Native_vcpu> result { };
Monitored_thread::with_thread(_ep, thread_cap,
[&] (Monitored_thread &monitored_thread) {
result = _real.call<Rpc_create_vcpu>(monitored_thread._real);
},
[&] /* VM session not intercepted */ {
result = _real.call<Rpc_create_vcpu>(thread_cap);
});
return result;
}
};
#endif /* _MONITORED_VM_H_ */

View File

@ -24,7 +24,7 @@ namespace Monitor {
using namespace Genode;
template <typename> struct Monitored_rpc_object;
template <typename, typename> struct Monitored_rpc_object;
constexpr static uint16_t GDB_PACKET_MAX_SIZE = 16*1024;
@ -64,8 +64,8 @@ namespace Monitor {
}
template <typename IF>
struct Monitor::Monitored_rpc_object : Rpc_object<IF>
template <typename IF, typename OBJ = IF>
struct Monitor::Monitored_rpc_object : Rpc_object<IF, OBJ>
{
Entrypoint &_ep;