163 lines
5.2 KiB
Diff
163 lines
5.2 KiB
Diff
--- sys/amd64/vmm/amd/svm.c.orig
|
|
+++ sys/amd64/vmm/amd/svm.c
|
|
@@ -488,10 +488,23 @@
|
|
svm_enable_intercept(sc, vcpu, VMCB_CTRL1_INTCPT, VMCB_INTCPT_SHUTDOWN);
|
|
svm_enable_intercept(sc, vcpu, VMCB_CTRL1_INTCPT,
|
|
VMCB_INTCPT_FERR_FREEZE);
|
|
+ svm_enable_intercept(sc, vcpu, VMCB_CTRL1_INTCPT, VMCB_INTCPT_INVD);
|
|
+ svm_enable_intercept(sc, vcpu, VMCB_CTRL1_INTCPT, VMCB_INTCPT_INVLPGA);
|
|
|
|
svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_MONITOR);
|
|
svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_MWAIT);
|
|
|
|
+ /*
|
|
+ * Intercept SVM instructions since AMD enables them in guests otherwise.
|
|
+ * Non-intercepted VMMCALL causes #UD, skip it.
|
|
+ */
|
|
+ svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_VMLOAD);
|
|
+ svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_VMSAVE);
|
|
+ svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_STGI);
|
|
+ svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_CLGI);
|
|
+ svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_SKINIT);
|
|
+ svm_enable_intercept(sc, vcpu, VMCB_CTRL2_INTCPT, VMCB_INTCPT_ICEBP);
|
|
+
|
|
/*
|
|
* From section "Canonicalization and Consistency Checks" in APMv2
|
|
* the VMRUN intercept bit must be set to pass the consistency check.
|
|
@@ -1236,43 +1249,45 @@
|
|
static const char *
|
|
exit_reason_to_str(uint64_t reason)
|
|
{
|
|
+ int i;
|
|
static char reasonbuf[32];
|
|
-
|
|
- switch (reason) {
|
|
- case VMCB_EXIT_INVALID:
|
|
- return ("invalvmcb");
|
|
- case VMCB_EXIT_SHUTDOWN:
|
|
- return ("shutdown");
|
|
- case VMCB_EXIT_NPF:
|
|
- return ("nptfault");
|
|
- case VMCB_EXIT_PAUSE:
|
|
- return ("pause");
|
|
- case VMCB_EXIT_HLT:
|
|
- return ("hlt");
|
|
- case VMCB_EXIT_CPUID:
|
|
- return ("cpuid");
|
|
- case VMCB_EXIT_IO:
|
|
- return ("inout");
|
|
- case VMCB_EXIT_MC:
|
|
- return ("mchk");
|
|
- case VMCB_EXIT_INTR:
|
|
- return ("extintr");
|
|
- case VMCB_EXIT_NMI:
|
|
- return ("nmi");
|
|
- case VMCB_EXIT_VINTR:
|
|
- return ("vintr");
|
|
- case VMCB_EXIT_MSR:
|
|
- return ("msr");
|
|
- case VMCB_EXIT_IRET:
|
|
- return ("iret");
|
|
- case VMCB_EXIT_MONITOR:
|
|
- return ("monitor");
|
|
- case VMCB_EXIT_MWAIT:
|
|
- return ("mwait");
|
|
- default:
|
|
- snprintf(reasonbuf, sizeof(reasonbuf), "%#lx", reason);
|
|
- return (reasonbuf);
|
|
+ static const struct {
|
|
+ int reason;
|
|
+ const char *str;
|
|
+ } reasons[] = {
|
|
+ { .reason = VMCB_EXIT_INVALID, .str = "invalvmcb" },
|
|
+ { .reason = VMCB_EXIT_SHUTDOWN, .str = "shutdown" },
|
|
+ { .reason = VMCB_EXIT_NPF, .str = "nptfault" },
|
|
+ { .reason = VMCB_EXIT_PAUSE, .str = "pause" },
|
|
+ { .reason = VMCB_EXIT_HLT, .str = "hlt" },
|
|
+ { .reason = VMCB_EXIT_CPUID, .str = "cpuid" },
|
|
+ { .reason = VMCB_EXIT_IO, .str = "inout" },
|
|
+ { .reason = VMCB_EXIT_MC, .str = "mchk" },
|
|
+ { .reason = VMCB_EXIT_INTR, .str = "extintr" },
|
|
+ { .reason = VMCB_EXIT_NMI, .str = "nmi" },
|
|
+ { .reason = VMCB_EXIT_VINTR, .str = "vintr" },
|
|
+ { .reason = VMCB_EXIT_MSR, .str = "msr" },
|
|
+ { .reason = VMCB_EXIT_IRET, .str = "iret" },
|
|
+ { .reason = VMCB_EXIT_MONITOR, .str = "monitor" },
|
|
+ { .reason = VMCB_EXIT_MWAIT, .str = "mwait" },
|
|
+ { .reason = VMCB_EXIT_VMRUN, .str = "vmrun" },
|
|
+ { .reason = VMCB_EXIT_VMMCALL, .str = "vmmcall" },
|
|
+ { .reason = VMCB_EXIT_VMLOAD, .str = "vmload" },
|
|
+ { .reason = VMCB_EXIT_VMSAVE, .str = "vmsave" },
|
|
+ { .reason = VMCB_EXIT_STGI, .str = "stgi" },
|
|
+ { .reason = VMCB_EXIT_CLGI, .str = "clgi" },
|
|
+ { .reason = VMCB_EXIT_SKINIT, .str = "skinit" },
|
|
+ { .reason = VMCB_EXIT_ICEBP, .str = "icebp" },
|
|
+ { .reason = VMCB_EXIT_INVD, .str = "invd" },
|
|
+ { .reason = VMCB_EXIT_INVLPGA, .str = "invlpga" },
|
|
+ };
|
|
+
|
|
+ for (i = 0; i < nitems(reasons); i++) {
|
|
+ if (reasons[i].reason == reason)
|
|
+ return (reasons[i].str);
|
|
}
|
|
+ snprintf(reasonbuf, sizeof(reasonbuf), "%#lx", reason);
|
|
+ return (reasonbuf);
|
|
}
|
|
#endif /* KTR */
|
|
|
|
@@ -1524,6 +1539,20 @@
|
|
case VMCB_EXIT_MWAIT:
|
|
vmexit->exitcode = VM_EXITCODE_MWAIT;
|
|
break;
|
|
+ case VMCB_EXIT_SHUTDOWN:
|
|
+ case VMCB_EXIT_VMRUN:
|
|
+ case VMCB_EXIT_VMMCALL:
|
|
+ case VMCB_EXIT_VMLOAD:
|
|
+ case VMCB_EXIT_VMSAVE:
|
|
+ case VMCB_EXIT_STGI:
|
|
+ case VMCB_EXIT_CLGI:
|
|
+ case VMCB_EXIT_SKINIT:
|
|
+ case VMCB_EXIT_ICEBP:
|
|
+ case VMCB_EXIT_INVD:
|
|
+ case VMCB_EXIT_INVLPGA:
|
|
+ vm_inject_ud(svm_sc->vm, vcpu);
|
|
+ handled = 1;
|
|
+ break;
|
|
default:
|
|
vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_UNKNOWN, 1);
|
|
break;
|
|
--- sys/amd64/vmm/amd/vmcb.h.orig
|
|
+++ sys/amd64/vmm/amd/vmcb.h
|
|
@@ -71,8 +71,8 @@
|
|
#define VMCB_INTCPT_INVD BIT(22)
|
|
#define VMCB_INTCPT_PAUSE BIT(23)
|
|
#define VMCB_INTCPT_HLT BIT(24)
|
|
-#define VMCB_INTCPT_INVPG BIT(25)
|
|
-#define VMCB_INTCPT_INVPGA BIT(26)
|
|
+#define VMCB_INTCPT_INVLPG BIT(25)
|
|
+#define VMCB_INTCPT_INVLPGA BIT(26)
|
|
#define VMCB_INTCPT_IO BIT(27)
|
|
#define VMCB_INTCPT_MSR BIT(28)
|
|
#define VMCB_INTCPT_TASK_SWITCH BIT(29)
|
|
@@ -134,12 +134,21 @@
|
|
#define VMCB_EXIT_POPF 0x71
|
|
#define VMCB_EXIT_CPUID 0x72
|
|
#define VMCB_EXIT_IRET 0x74
|
|
+#define VMCB_EXIT_INVD 0x76
|
|
#define VMCB_EXIT_PAUSE 0x77
|
|
#define VMCB_EXIT_HLT 0x78
|
|
+#define VMCB_EXIT_INVLPGA 0x7A
|
|
#define VMCB_EXIT_IO 0x7B
|
|
#define VMCB_EXIT_MSR 0x7C
|
|
#define VMCB_EXIT_SHUTDOWN 0x7F
|
|
+#define VMCB_EXIT_VMRUN 0x80
|
|
+#define VMCB_EXIT_VMMCALL 0x81
|
|
+#define VMCB_EXIT_VMLOAD 0x82
|
|
#define VMCB_EXIT_VMSAVE 0x83
|
|
+#define VMCB_EXIT_STGI 0x84
|
|
+#define VMCB_EXIT_CLGI 0x85
|
|
+#define VMCB_EXIT_SKINIT 0x86
|
|
+#define VMCB_EXIT_ICEBP 0x88
|
|
#define VMCB_EXIT_MONITOR 0x8A
|
|
#define VMCB_EXIT_MWAIT 0x8B
|
|
#define VMCB_EXIT_NPF 0x400
|