diff options
-rw-r--r-- | target-i386/exec.h | 1 | ||||
-rw-r--r-- | target-i386/helper.c | 12 | ||||
-rw-r--r-- | target-i386/op.c | 5 | ||||
-rw-r--r-- | target-i386/translate.c | 4 |
4 files changed, 22 insertions, 0 deletions
diff --git a/target-i386/exec.h b/target-i386/exec.h index 70fac64fc3..20153f7279 100644 --- a/target-i386/exec.h +++ b/target-i386/exec.h @@ -199,6 +199,7 @@ void helper_sysexit(void); void helper_syscall(int next_eip_addend); void helper_sysret(int dflag); void helper_rdtsc(void); +void helper_rdpmc(void); void helper_rdmsr(void); void helper_wrmsr(void); void helper_lsl(void); diff --git a/target-i386/helper.c b/target-i386/helper.c index a2f465c736..07ff3563cc 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -2743,6 +2743,18 @@ void helper_rdtsc(void) EDX = (uint32_t)(val >> 32); } +void helper_rdpmc(void) +{ + if ((env->cr[4] & CR4_PCE_MASK) && ((env->hflags & HF_CPL_MASK) != 0)) { + raise_exception(EXCP0D_GPF); + } + + if (!svm_check_intercept_param(SVM_EXIT_RDPMC, 0)) { + /* currently unimplemented */ + raise_exception_err(EXCP06_ILLOP, 0); + } +} + #if defined(CONFIG_USER_ONLY) void helper_wrmsr(void) { diff --git a/target-i386/op.c b/target-i386/op.c index 7d8950e079..77930db125 100644 --- a/target-i386/op.c +++ b/target-i386/op.c @@ -953,6 +953,11 @@ void OPPROTO op_rdtsc(void) helper_rdtsc(); } +void OPPROTO op_rdpmc(void) +{ + helper_rdpmc(); +} + void OPPROTO op_cpuid(void) { helper_cpuid(); diff --git a/target-i386/translate.c b/target-i386/translate.c index 02dc6cf61c..579831ef7a 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -5658,6 +5658,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_jmp_im(pc_start - s->cs_base); gen_op_rdtsc(); break; + case 0x133: /* rdpmc */ + gen_jmp_im(pc_start - s->cs_base); + gen_op_rdpmc(); + break; case 0x134: /* sysenter */ if (CODE64(s)) goto illegal_op; |