aboutsummaryrefslogtreecommitdiffstats
path: root/target-i386/kvm.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-i386/kvm.c')
-rw-r--r--target-i386/kvm.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 981192ddf..9a732078f 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1635,8 +1635,10 @@ void kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
}
if (!kvm_irqchip_in_kernel()) {
- /* Force the VCPU out of its inner loop to process the INIT request */
- if (env->interrupt_request & CPU_INTERRUPT_INIT) {
+ /* Force the VCPU out of its inner loop to process any INIT requests
+ * or pending TPR access reports. */
+ if (env->interrupt_request &
+ (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) {
env->exit_request = 1;
}
@@ -1730,6 +1732,12 @@ int kvm_arch_process_async_events(CPUState *env)
kvm_cpu_synchronize_state(env);
do_cpu_sipi(env);
}
+ if (env->interrupt_request & CPU_INTERRUPT_TPR) {
+ env->interrupt_request &= ~CPU_INTERRUPT_TPR;
+ kvm_cpu_synchronize_state(env);
+ apic_handle_tpr_access_report(env->apic_state, env->eip,
+ env->tpr_access_type);
+ }
return env->halted;
}
@@ -1746,6 +1754,16 @@ static int kvm_handle_halt(CPUState *env)
return 0;
}
+static int kvm_handle_tpr_access(CPUState *env)
+{
+ struct kvm_run *run = env->kvm_run;
+
+ apic_handle_tpr_access_report(env->apic_state, run->tpr_access.rip,
+ run->tpr_access.is_write ? TPR_ACCESS_WRITE
+ : TPR_ACCESS_READ);
+ return 1;
+}
+
int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
{
static const uint8_t int3 = 0xcc;
@@ -1950,6 +1968,9 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
case KVM_EXIT_SET_TPR:
ret = 0;
break;
+ case KVM_EXIT_TPR_ACCESS:
+ ret = kvm_handle_tpr_access(env);
+ break;
case KVM_EXIT_FAIL_ENTRY:
code = run->fail_entry.hardware_entry_failure_reason;
fprintf(stderr, "KVM: entry failed, hardware error 0x%" PRIx64 "\n",
@@ -1987,6 +2008,7 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
bool kvm_arch_stop_on_emulation_error(CPUState *env)
{
+ kvm_cpu_synchronize_state(env);
return !(env->cr[0] & CR0_PE_MASK) ||
((env->segs[R_CS].selector & 3) != 3);
}