mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
parent
d186e4361e
commit
d6a5a66623
@ -1 +1 @@
|
||||
667a8abdf36fece2200041dfb6e85fec3d1b5a81
|
||||
0316f8810c665d115fb860399d824a6531aa5aad
|
||||
|
@ -4,7 +4,7 @@ DOWNLOADS := nova.git
|
||||
|
||||
# r10 branch
|
||||
URL(nova) := https://github.com/alex-ab/NOVA.git
|
||||
REV(nova) := b49bc550b934d542641a86dc35590b193141c5a7
|
||||
REV(nova) := 98b501b243bcd7aa1be36454cf58a63aae362c2e
|
||||
DIR(nova) := src/kernel/nova
|
||||
|
||||
PATCHES := $(sort $(wildcard $(REP_DIR)/patches/*.patch))
|
||||
|
@ -44,6 +44,14 @@ static inline bool svm_save_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu)
|
||||
GENODE_READ_SELREG(gs);
|
||||
GENODE_READ_SELREG(ss);
|
||||
|
||||
if ( !pCtx->cs.Attr.n.u1Granularity
|
||||
&& pCtx->cs.Attr.n.u1Present
|
||||
&& pCtx->cs.u32Limit > UINT32_C(0xfffff))
|
||||
{
|
||||
Assert((pCtx->cs.u32Limit & 0xfff) == 0xfff);
|
||||
pCtx->cs.Attr.n.u1Granularity = 1;
|
||||
}
|
||||
|
||||
GENODE_SVM_ASSERT_SELREG(cs);
|
||||
GENODE_SVM_ASSERT_SELREG(ds);
|
||||
GENODE_SVM_ASSERT_SELREG(es);
|
||||
@ -54,6 +62,8 @@ static inline bool svm_save_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu)
|
||||
GENODE_READ_SELREG(ldtr);
|
||||
GENODE_READ_SELREG(tr);
|
||||
|
||||
CPUMSetGuestEFER(pVCpu, CPUMGetGuestEFER(pVCpu) & ~uint64_t(MSR_K6_EFER_SVME));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -75,14 +85,8 @@ static inline bool svm_load_state(Nova::Utcb * utcb, VM * pVM, PVMCPU pVCpu)
|
||||
{
|
||||
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
|
||||
|
||||
#ifdef __x86_64__
|
||||
utcb->mtd |= Nova::Mtd::EFER;
|
||||
utcb->efer = pCtx->msrEFER | MSR_K6_EFER_SVME;
|
||||
/* unimplemented */
|
||||
if (CPUMIsGuestInLongModeEx(pCtx))
|
||||
return false;
|
||||
utcb->efer &= ~MSR_K6_EFER_LME;
|
||||
#endif
|
||||
utcb->write_efer(utcb->read_efer() | MSR_K6_EFER_SVME);
|
||||
|
||||
utcb->mtd |= Nova::Mtd::ESDS;
|
||||
GENODE_WRITE_SELREG(es);
|
||||
|
@ -30,29 +30,6 @@ class Vcpu_handler_svm : public Vcpu_handler
|
||||
_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()
|
||||
{
|
||||
@ -72,8 +49,32 @@ class Vcpu_handler_svm : public Vcpu_handler
|
||||
|
||||
/* enable VM exits for CPUID */
|
||||
next_utcb.mtd = Nova::Mtd::CTRL;
|
||||
next_utcb.ctrl[0] = SVM_CTRL1_INTERCEPT_CPUID;
|
||||
next_utcb.ctrl[1] = 0;
|
||||
|
||||
next_utcb.ctrl[0] = SVM_CTRL1_INTERCEPT_INTR
|
||||
| SVM_CTRL1_INTERCEPT_NMI
|
||||
| SVM_CTRL1_INTERCEPT_INIT
|
||||
| SVM_CTRL1_INTERCEPT_RDPMC
|
||||
| SVM_CTRL1_INTERCEPT_CPUID
|
||||
| SVM_CTRL1_INTERCEPT_RSM
|
||||
| SVM_CTRL1_INTERCEPT_HLT
|
||||
| SVM_CTRL1_INTERCEPT_INOUT_BITMAP
|
||||
| SVM_CTRL1_INTERCEPT_MSR_SHADOW
|
||||
| SVM_CTRL1_INTERCEPT_INVLPGA
|
||||
| SVM_CTRL1_INTERCEPT_SHUTDOWN
|
||||
| SVM_CTRL1_INTERCEPT_RDTSC
|
||||
| SVM_CTRL1_INTERCEPT_FERR_FREEZE;
|
||||
|
||||
next_utcb.ctrl[1] = SVM_CTRL2_INTERCEPT_VMRUN
|
||||
| SVM_CTRL2_INTERCEPT_VMMCALL
|
||||
| SVM_CTRL2_INTERCEPT_VMLOAD
|
||||
| SVM_CTRL2_INTERCEPT_VMSAVE
|
||||
| SVM_CTRL2_INTERCEPT_STGI
|
||||
| SVM_CTRL2_INTERCEPT_CLGI
|
||||
| SVM_CTRL2_INTERCEPT_SKINIT
|
||||
| SVM_CTRL2_INTERCEPT_WBINVD
|
||||
| SVM_CTRL2_INTERCEPT_MONITOR
|
||||
| SVM_CTRL2_INTERCEPT_RDTSCP
|
||||
| SVM_CTRL2_INTERCEPT_MWAIT;
|
||||
|
||||
void *exit_status = _start_routine(_start_routine_arg);
|
||||
pthread_exit(exit_status);
|
||||
@ -81,6 +82,25 @@ class Vcpu_handler_svm : public Vcpu_handler
|
||||
Nova::reply(nullptr);
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void _svm_shutdown()
|
||||
{
|
||||
Vmm::error("shutdown exit");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void _svm_invalid()
|
||||
{
|
||||
using namespace Nova;
|
||||
using namespace Genode;
|
||||
|
||||
Thread *myself = Thread::myself();
|
||||
Utcb *utcb = reinterpret_cast<Utcb *>(myself->utcb());
|
||||
|
||||
Vmm::warning("invalid svm ip=", Genode::Hex(utcb->ip));
|
||||
|
||||
_default_handler();
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void _svm_recall()
|
||||
{
|
||||
_fpu_save();
|
||||
@ -105,14 +125,56 @@ class Vcpu_handler_svm : public Vcpu_handler
|
||||
|
||||
typedef Vcpu_handler_svm This;
|
||||
|
||||
register_handler<SVM_EXIT_READ_CR0, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_READ_CR1, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_READ_CR2, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_READ_CR3, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_READ_CR4, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_READ_CR5, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_READ_CR6, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_READ_CR7, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_READ_CR8, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
|
||||
register_handler<SVM_EXIT_WRITE_CR0, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_WRITE_CR1, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_WRITE_CR2, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_WRITE_CR3, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_WRITE_CR4, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_WRITE_CR5, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_WRITE_CR6, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_WRITE_CR7, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_WRITE_CR8, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
|
||||
register_handler<RECALL, This,
|
||||
&This::_svm_recall> (exc_base, Mtd::ALL | Mtd::FPU);
|
||||
&This::_svm_recall> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_INVLPGA, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_IOIO, This,
|
||||
&This::_svm_ioio> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
&This::_svm_default> (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_RDTSCP, 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,
|
||||
@ -121,6 +183,12 @@ class Vcpu_handler_svm : public Vcpu_handler
|
||||
&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<SVM_EXIT_SHUTDOWN, This,
|
||||
&This::_svm_shutdown> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_EXIT_WBINVD, This,
|
||||
&This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<SVM_INVALID, This,
|
||||
&This::_svm_invalid> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
register_handler<VCPU_STARTUP, This,
|
||||
&This::_svm_startup> (exc_base, Mtd(Mtd::ALL | Mtd::FPU));
|
||||
|
||||
|
@ -44,6 +44,14 @@ static inline bool svm_save_state(Genode::Vm_state * state, VM * pVM, PVMCPU pVC
|
||||
GENODE_READ_SELREG(gs);
|
||||
GENODE_READ_SELREG(ss);
|
||||
|
||||
if ( !pCtx->cs.Attr.n.u1Granularity
|
||||
&& pCtx->cs.Attr.n.u1Present
|
||||
&& pCtx->cs.u32Limit > UINT32_C(0xfffff))
|
||||
{
|
||||
Assert((pCtx->cs.u32Limit & 0xfff) == 0xfff);
|
||||
pCtx->cs.Attr.n.u1Granularity = 1;
|
||||
}
|
||||
|
||||
GENODE_SVM_ASSERT_SELREG(cs);
|
||||
GENODE_SVM_ASSERT_SELREG(ds);
|
||||
GENODE_SVM_ASSERT_SELREG(es);
|
||||
@ -54,6 +62,8 @@ static inline bool svm_save_state(Genode::Vm_state * state, VM * pVM, PVMCPU pVC
|
||||
GENODE_READ_SELREG(ldtr);
|
||||
GENODE_READ_SELREG(tr);
|
||||
|
||||
CPUMSetGuestEFER(pVCpu, CPUMGetGuestEFER(pVCpu) & ~uint64_t(MSR_K6_EFER_SVME));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -75,11 +85,7 @@ static inline bool svm_load_state(Genode::Vm_state * state, VM * pVM, PVMCPU pVC
|
||||
|
||||
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(pVCpu);
|
||||
|
||||
state->efer.value(pCtx->msrEFER | MSR_K6_EFER_SVME);
|
||||
/* unimplemented */
|
||||
if (CPUMIsGuestInLongModeEx(pCtx))
|
||||
return false;
|
||||
state->efer.value(state->efer.value() & ~MSR_K6_EFER_LME);
|
||||
state->efer.value(state->efer.value() | MSR_K6_EFER_SVME);
|
||||
|
||||
GENODE_WRITE_SELREG(es);
|
||||
GENODE_WRITE_SELREG(ds);
|
||||
|
@ -38,23 +38,6 @@ class Vcpu_handler_svm : public Vcpu_handler
|
||||
void _svm_default() { _default_handler(); }
|
||||
void _svm_vintr() { _irq_window(); }
|
||||
|
||||
void _svm_ioio()
|
||||
{
|
||||
if (_state->qual_primary.value() & 0x4) {
|
||||
unsigned ctrl0 = _state->ctrl_primary.value();
|
||||
|
||||
Genode::warning("invalid gueststate");
|
||||
|
||||
*_state = Genode::Vm_state {}; /* reset */
|
||||
|
||||
_state->ctrl_primary.value(ctrl0);
|
||||
_state->ctrl_secondary.value(0);
|
||||
|
||||
_vm_session.run(_vcpu);
|
||||
} else
|
||||
_default_handler();
|
||||
}
|
||||
|
||||
template <unsigned X>
|
||||
void _svm_npt()
|
||||
{
|
||||
@ -71,9 +54,32 @@ class Vcpu_handler_svm : public Vcpu_handler
|
||||
|
||||
void _svm_startup()
|
||||
{
|
||||
/* enable VM exits for CPUID */
|
||||
next_utcb.ctrl[0] = SVM_CTRL1_INTERCEPT_CPUID;
|
||||
next_utcb.ctrl[1] = 0;
|
||||
/* enable VM exits */
|
||||
next_utcb.ctrl[0] = SVM_CTRL1_INTERCEPT_INTR
|
||||
| SVM_CTRL1_INTERCEPT_NMI
|
||||
| SVM_CTRL1_INTERCEPT_INIT
|
||||
| SVM_CTRL1_INTERCEPT_RDPMC
|
||||
| SVM_CTRL1_INTERCEPT_CPUID
|
||||
| SVM_CTRL1_INTERCEPT_RSM
|
||||
| SVM_CTRL1_INTERCEPT_HLT
|
||||
| SVM_CTRL1_INTERCEPT_INOUT_BITMAP
|
||||
| SVM_CTRL1_INTERCEPT_MSR_SHADOW
|
||||
| SVM_CTRL1_INTERCEPT_INVLPGA
|
||||
| SVM_CTRL1_INTERCEPT_SHUTDOWN
|
||||
| SVM_CTRL1_INTERCEPT_RDTSC
|
||||
| SVM_CTRL1_INTERCEPT_FERR_FREEZE;
|
||||
|
||||
next_utcb.ctrl[1] = SVM_CTRL2_INTERCEPT_VMRUN
|
||||
| SVM_CTRL2_INTERCEPT_VMMCALL
|
||||
| SVM_CTRL2_INTERCEPT_VMLOAD
|
||||
| SVM_CTRL2_INTERCEPT_VMSAVE
|
||||
| SVM_CTRL2_INTERCEPT_STGI
|
||||
| SVM_CTRL2_INTERCEPT_CLGI
|
||||
| SVM_CTRL2_INTERCEPT_SKINIT
|
||||
| SVM_CTRL2_INTERCEPT_WBINVD
|
||||
| SVM_CTRL2_INTERCEPT_MONITOR
|
||||
| SVM_CTRL2_INTERCEPT_RDTSCP
|
||||
| SVM_CTRL2_INTERCEPT_MWAIT;
|
||||
}
|
||||
|
||||
void _handle_vm_exception()
|
||||
@ -82,13 +88,27 @@ class Vcpu_handler_svm : public Vcpu_handler
|
||||
bool recall_wait = true;
|
||||
|
||||
switch (exit) {
|
||||
case SVM_EXIT_IOIO: _svm_ioio(); break;
|
||||
case SVM_EXIT_VINTR: _svm_vintr(); break;
|
||||
// case SVM_EXIT_RDTSC: _svm_default(); break;
|
||||
case SVM_EXIT_MSR: _svm_default(); break;
|
||||
case SVM_NPT: _svm_npt<SVM_NPT>(); break;
|
||||
case SVM_EXIT_HLT: _svm_default(); break;
|
||||
case SVM_EXIT_CPUID: _svm_default(); break;
|
||||
case SVM_EXIT_CPUID:
|
||||
case SVM_EXIT_HLT:
|
||||
case SVM_EXIT_INVLPGA:
|
||||
case SVM_EXIT_IOIO:
|
||||
case SVM_EXIT_MSR:
|
||||
case SVM_EXIT_READ_CR0 ... SVM_EXIT_WRITE_CR15:
|
||||
case SVM_EXIT_RDTSC:
|
||||
case SVM_EXIT_RDTSCP:
|
||||
case SVM_EXIT_WBINVD:
|
||||
_svm_default();
|
||||
break;
|
||||
case SVM_INVALID:
|
||||
Genode::warning("invalid svm ip=", _state->ip.value());
|
||||
_svm_default();
|
||||
break;
|
||||
case SVM_EXIT_SHUTDOWN:
|
||||
Genode::error("shutdown exit");
|
||||
::exit(-1);
|
||||
break;
|
||||
case RECALL:
|
||||
recall_wait = Vcpu_handler::_recall_handler();
|
||||
break;
|
||||
@ -134,13 +154,17 @@ class Vcpu_handler_svm : public Vcpu_handler
|
||||
{
|
||||
switch (exit) {
|
||||
case RECALL:
|
||||
case SVM_EXIT_INVLPGA:
|
||||
case SVM_EXIT_IOIO:
|
||||
case SVM_EXIT_VINTR:
|
||||
case SVM_EXIT_READ_CR0 ... SVM_EXIT_WRITE_CR15:
|
||||
case SVM_EXIT_RDTSC:
|
||||
case SVM_EXIT_RDTSCP:
|
||||
case SVM_EXIT_MSR:
|
||||
case SVM_NPT:
|
||||
case SVM_EXIT_HLT:
|
||||
case SVM_EXIT_CPUID:
|
||||
case SVM_EXIT_WBINVD:
|
||||
case VCPU_STARTUP:
|
||||
/* todo - touch all members */
|
||||
Genode::memset(&state, ~0U, sizeof(state));
|
||||
|
Loading…
x
Reference in New Issue
Block a user