summaryrefslogtreecommitdiff
path: root/target-i386
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2011-10-16 13:23:26 +0200
committerJan Kiszka <jan.kiszka@siemens.com>2012-01-19 12:14:42 +0100
commit680c1c6fd73c0cb3971938944936f18bbb7bad1b (patch)
tree82f323ff3cd5432f07a58139384688e453f3db7c /target-i386
parent9b5b76d44930dc9266bb6d30862704cb3c86d2ca (diff)
downloadqemu-680c1c6fd73c0cb3971938944936f18bbb7bad1b.tar.gz
kvm: x86: Add user space part for in-kernel APIC
This introduces the alternative APIC device which makes use of KVM's in-kernel device model. External NMI injection via LINT1 is emulated by checking the current state of the in-kernel APIC, only injecting a NMI into the VCPU if LINT1 is unmasked and configured to DM_NMI. MSI is not yet supported, so we disable this when the in-kernel model is in use. CC: Lai Jiangshan <laijs@cn.fujitsu.com> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Diffstat (limited to 'target-i386')
-rw-r--r--target-i386/kvm.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index f6f4189f4d..e41de394d2 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1337,6 +1337,36 @@ static int kvm_get_mp_state(CPUState *env)
return 0;
}
+static int kvm_get_apic(CPUState *env)
+{
+ DeviceState *apic = env->apic_state;
+ struct kvm_lapic_state kapic;
+ int ret;
+
+ if (apic && kvm_enabled() && kvm_irqchip_in_kernel()) {
+ ret = kvm_vcpu_ioctl(env, KVM_GET_LAPIC, &kapic);
+ if (ret < 0) {
+ return ret;
+ }
+
+ kvm_get_apic_state(apic, &kapic);
+ }
+ return 0;
+}
+
+static int kvm_put_apic(CPUState *env)
+{
+ DeviceState *apic = env->apic_state;
+ struct kvm_lapic_state kapic;
+
+ if (apic && kvm_enabled() && kvm_irqchip_in_kernel()) {
+ kvm_put_apic_state(apic, &kapic);
+
+ return kvm_vcpu_ioctl(env, KVM_SET_LAPIC, &kapic);
+ }
+ return 0;
+}
+
static int kvm_put_vcpu_events(CPUState *env, int level)
{
struct kvm_vcpu_events events;
@@ -1510,6 +1540,10 @@ int kvm_arch_put_registers(CPUState *env, int level)
if (ret < 0) {
return ret;
}
+ ret = kvm_put_apic(env);
+ if (ret < 0) {
+ return ret;
+ }
}
ret = kvm_put_vcpu_events(env, level);
if (ret < 0) {
@@ -1557,6 +1591,10 @@ int kvm_arch_get_registers(CPUState *env)
if (ret < 0) {
return ret;
}
+ ret = kvm_get_apic(env);
+ if (ret < 0) {
+ return ret;
+ }
ret = kvm_get_vcpu_events(env);
if (ret < 0) {
return ret;