genode/repos/ports/src/virtualbox5/spec/nova/vcpu_svm.h
Norman Feske 9d67f9fc8e Remove Allocator_guard
This patch removes old 'Allocator_guard' utility and replaces its use
with the modern 'Constrained_ram_allocator'.

The adjustment of core in this respect has the side effect of a more
accurate capability accounting in core's CPU, TRACE, and RM services.
In particular, the dataspace capabilities needed for core-internal
allocations via the 'Sliced_heap' are accounted to the client now.
The same goes for nitpicker and nic_dump as other former users of the
allocator guard. Hence, the patch also touches code at the client and
server sides related to these services.

The only remaining user of the 'Allocator_guard' is the Intel GPU
driver. As the adaptation of this component would be too invasive
without testing, this patch leaves this component unchanged by keeping a
copy of the 'allocator_guard.h' locally at the component.

Fixes #3750
2020-05-18 10:16:12 +02:00

148 lines
3.8 KiB
C++

/*
* \brief Genode/Nova specific VirtualBox SUPLib supplements
* \author Alexander Boettcher
* \date 2013-11-18
*/
/*
* Copyright (C) 2013-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _VIRTUALBOX__SPEC__NOVA__VCPU_SVM_H_
#define _VIRTUALBOX__SPEC__NOVA__VCPU_SVM_H_
/* Genode's VirtualBox includes */
#include "vcpu.h"
#include "svm.h"
class Vcpu_handler_svm : public Vcpu_handler
{
private:
__attribute__((noreturn)) void _svm_default() { _default_handler(); }
__attribute__((noreturn)) void _svm_vintr()
{
_fpu_save();
_irq_window();
}
__attribute__((noreturn)) void _svm_ioio()
{
using namespace Nova;
using namespace Genode;
Thread *myself = Thread::myself();
Utcb *utcb = reinterpret_cast<Utcb *>(myself->utcb());
if (utcb->qual[0] & 0x4) {
unsigned ctrl0 = utcb->ctrl[0];
Vmm::warning("invalid gueststate");
utcb->ctrl[0] = ctrl0;
utcb->ctrl[1] = 0;
utcb->mtd = Mtd::CTRL;
Nova::reply(_stack_reply);
}
_default_handler();
}
template <unsigned X>
__attribute__((noreturn)) void _svm_npt()
{
using namespace Nova;
using namespace Genode;
Thread *myself = Thread::myself();
Utcb *utcb = reinterpret_cast<Utcb *>(myself->utcb());
_exc_memory<X>(myself, utcb, utcb->qual[0] & 1,
utcb->qual[1], utcb->qual[0]);
}
__attribute__((noreturn)) void _svm_startup()
{
using namespace Nova;
/* enable VM exits for CPUID */
next_utcb.mtd = Nova::Mtd::CTRL;
next_utcb.ctrl[0] = SVM_CTRL1_INTERCEPT_CPUID;
next_utcb.ctrl[1] = 0;
void *exit_status = _start_routine(_start_routine_arg);
pthread_exit(exit_status);
Nova::reply(nullptr);
}
__attribute__((noreturn)) void _svm_recall()
{
_fpu_save();
Vcpu_handler::_recall_handler();
}
public:
Vcpu_handler_svm(Genode::Env &env, size_t stack_size,
void *(*start_routine) (void *), void *arg,
Genode::Cpu_connection * cpu_connection,
Genode::Affinity::Location location,
unsigned int cpu_id, const char * name,
Genode::Pd_session_capability pd_vcpu)
:
Vcpu_handler(env, stack_size, start_routine, arg, cpu_connection,
location, cpu_id, name, pd_vcpu)
{
using namespace Nova;
Genode::addr_t const exc_base = vcpu().exc_base();
typedef Vcpu_handler_svm This;
register_handler<RECALL, This,
&This::_svm_recall> (exc_base, Mtd::ALL | Mtd::FPU);
register_handler<SVM_EXIT_IOIO, This,
&This::_svm_ioio> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_VINTR, This,
&This::_svm_vintr> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_RDTSC, This,
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_MSR, This,
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_NPT, This,
&This::_svm_npt<SVM_NPT>> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_HLT, This,
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
register_handler<SVM_EXIT_CPUID, This,
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
register_handler<VCPU_STARTUP, This,
&This::_svm_startup> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
start();
}
bool hw_save_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu) {
return svm_save_state(utcb, pVM, pVCpu);
}
bool hw_load_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu) {
return svm_load_state(utcb, pVM, pVCpu);
}
int vm_exit_requires_instruction_emulation(PCPUMCTX)
{
if (exit_reason == RECALL)
return VINF_SUCCESS;
return VINF_EM_RAW_EMULATE_INSTR;
}
};
#endif /* _VIRTUALBOX__SPEC__NOVA__VCPU_SVM_H_ */