diff --git a/repos/base-nova/ports/nova.hash b/repos/base-nova/ports/nova.hash index ad2cd1486f..5d669bdde3 100644 --- a/repos/base-nova/ports/nova.hash +++ b/repos/base-nova/ports/nova.hash @@ -1 +1 @@ -667a8abdf36fece2200041dfb6e85fec3d1b5a81 +0316f8810c665d115fb860399d824a6531aa5aad diff --git a/repos/base-nova/ports/nova.port b/repos/base-nova/ports/nova.port index a5a1256498..d2a033db56 100644 --- a/repos/base-nova/ports/nova.port +++ b/repos/base-nova/ports/nova.port @@ -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)) diff --git a/repos/ports/src/virtualbox5/spec/nova/svm.h b/repos/ports/src/virtualbox5/spec/nova/svm.h index 0e147f9c38..70123687ed 100644 --- a/repos/ports/src/virtualbox5/spec/nova/svm.h +++ b/repos/ports/src/virtualbox5/spec/nova/svm.h @@ -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); diff --git a/repos/ports/src/virtualbox5/spec/nova/vcpu_svm.h b/repos/ports/src/virtualbox5/spec/nova/vcpu_svm.h index 63156ab159..f9fed7089f 100644 --- a/repos/ports/src/virtualbox5/spec/nova/vcpu_svm.h +++ b/repos/ports/src/virtualbox5/spec/nova/vcpu_svm.h @@ -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(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 __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(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 (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd::ALL | Mtd::FPU); + &This::_svm_recall> (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + &This::_svm_default> (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); + register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); register_handler (exc_base, Mtd(Mtd::ALL | Mtd::FPU)); diff --git a/repos/ports/src/virtualbox5/svm.h b/repos/ports/src/virtualbox5/svm.h index e7b1e0e303..e0db55912b 100644 --- a/repos/ports/src/virtualbox5/svm.h +++ b/repos/ports/src/virtualbox5/svm.h @@ -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); diff --git a/repos/ports/src/virtualbox5/vcpu_svm.h b/repos/ports/src/virtualbox5/vcpu_svm.h index 3a93f4f7c5..8de022967e 100644 --- a/repos/ports/src/virtualbox5/vcpu_svm.h +++ b/repos/ports/src/virtualbox5/vcpu_svm.h @@ -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 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(); 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));