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
148 lines
3.8 KiB
C++
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_ */
|