aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target/i386/svm.h3
-rw-r--r--target/i386/tcg/sysemu/svm_helper.c15
2 files changed, 18 insertions, 0 deletions
diff --git a/target/i386/svm.h b/target/i386/svm.h
index 5098733053..adc058dc76 100644
--- a/target/i386/svm.h
+++ b/target/i386/svm.h
@@ -137,6 +137,9 @@
#define SVM_CR0_RESERVED_MASK 0xffffffff00000000U
+#define SVM_MSRPM_SIZE (1ULL << 13)
+#define SVM_IOPM_SIZE ((1ULL << 13) + 1)
+
struct QEMU_PACKED vmcb_control_area {
uint16_t intercept_cr_read;
uint16_t intercept_cr_write;
diff --git a/target/i386/tcg/sysemu/svm_helper.c b/target/i386/tcg/sysemu/svm_helper.c
index 1c2dbc1862..fa701829e5 100644
--- a/target/i386/tcg/sysemu/svm_helper.c
+++ b/target/i386/tcg/sysemu/svm_helper.c
@@ -68,6 +68,7 @@ static inline void svm_load_seg_cache(CPUX86State *env, hwaddr addr,
void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
{
CPUState *cs = env_cpu(env);
+ X86CPU *cpu = env_archcpu(env);
target_ulong addr;
uint64_t nested_ctl;
uint32_t event_inj;
@@ -159,6 +160,20 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
asid = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb,
control.asid));
+ uint64_t msrpm_base_pa = x86_ldq_phys(cs, env->vm_vmcb +
+ offsetof(struct vmcb,
+ control.msrpm_base_pa));
+ uint64_t iopm_base_pa = x86_ldq_phys(cs, env->vm_vmcb +
+ offsetof(struct vmcb, control.iopm_base_pa));
+
+ if ((msrpm_base_pa & ~0xfff) >= (1ull << cpu->phys_bits) - SVM_MSRPM_SIZE) {
+ cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
+ }
+
+ if ((iopm_base_pa & ~0xfff) >= (1ull << cpu->phys_bits) - SVM_IOPM_SIZE) {
+ cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
+ }
+
env->nested_pg_mode = 0;
if (!cpu_svm_has_intercept(env, SVM_EXIT_VMRUN)) {