aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2008-11-25 14:17:04 -0500
committerAvi Kivity <avi@redhat.com>2009-03-24 05:02:46 -0400
commit1371d90460189d02bf1bcca19dbfe6bd10dc6031 (patch)
tree2f1f8d6bf0cd55e253784a061332c02e8e2d9e9d /arch/x86
parentc0725420cfdcf6dd9705b164a8c6cba86684080d (diff)
KVM: SVM: Implement GIF, clgi and stgi
This patch implements the GIF flag and the clgi and stgi instructions that set this flag. Only if the flag is set (default), interrupts can be received by the CPU. To keep the information about that somewhere, this patch adds a new hidden flags vector. that is used to store information that does not go into the vmcb, but is SVM specific. I tried to write some code to make -no-kvm-irqchip work too, but the first level guest won't even boot with that atm, so I ditched it. v2 moves the hflags to x86 generic code v3 makes use of the new permission helper v6 only enables interrupt_window if GIF=1 Acked-by: Joerg Roedel <joro@8bytes.org> Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/include/asm/kvm_host.h3
-rw-r--r--arch/x86/kvm/svm.c47
2 files changed, 45 insertions, 5 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 2998efe89278..29e4157732db 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -259,6 +259,7 @@ struct kvm_vcpu_arch {
259 unsigned long cr3; 259 unsigned long cr3;
260 unsigned long cr4; 260 unsigned long cr4;
261 unsigned long cr8; 261 unsigned long cr8;
262 u32 hflags;
262 u64 pdptrs[4]; /* pae */ 263 u64 pdptrs[4]; /* pae */
263 u64 shadow_efer; 264 u64 shadow_efer;
264 u64 apic_base; 265 u64 apic_base;
@@ -738,6 +739,8 @@ enum {
738 TASK_SWITCH_GATE = 3, 739 TASK_SWITCH_GATE = 3,
739}; 740};
740 741
742#define HF_GIF_MASK (1 << 0)
743
741/* 744/*
742 * Hardware virtualization extension instructions may fault if a 745 * Hardware virtualization extension instructions may fault if a
743 * reboot turns off virtualization while processes are running. 746 * reboot turns off virtualization while processes are running.
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 87debdcd1b90..79cc06bfe57c 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -251,7 +251,7 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
251 kvm_rip_write(vcpu, svm->next_rip); 251 kvm_rip_write(vcpu, svm->next_rip);
252 svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK; 252 svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK;
253 253
254 vcpu->arch.interrupt_window_open = 1; 254 vcpu->arch.interrupt_window_open = (svm->vcpu.arch.hflags & HF_GIF_MASK);
255} 255}
256 256
257static int has_svm(void) 257static int has_svm(void)
@@ -600,6 +600,8 @@ static void init_vmcb(struct vcpu_svm *svm)
600 save->cr4 = 0; 600 save->cr4 = 0;
601 } 601 }
602 force_new_asid(&svm->vcpu); 602 force_new_asid(&svm->vcpu);
603
604 svm->vcpu.arch.hflags = HF_GIF_MASK;
603} 605}
604 606
605static int svm_vcpu_reset(struct kvm_vcpu *vcpu) 607static int svm_vcpu_reset(struct kvm_vcpu *vcpu)
@@ -1234,6 +1236,36 @@ static int nested_svm_do(struct vcpu_svm *svm,
1234 return retval; 1236 return retval;
1235} 1237}
1236 1238
1239static int stgi_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
1240{
1241 if (nested_svm_check_permissions(svm))
1242 return 1;
1243
1244 svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
1245 skip_emulated_instruction(&svm->vcpu);
1246
1247 svm->vcpu.arch.hflags |= HF_GIF_MASK;
1248
1249 return 1;
1250}
1251
1252static int clgi_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
1253{
1254 if (nested_svm_check_permissions(svm))
1255 return 1;
1256
1257 svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
1258 skip_emulated_instruction(&svm->vcpu);
1259
1260 svm->vcpu.arch.hflags &= ~HF_GIF_MASK;
1261
1262 /* After a CLGI no interrupts should come */
1263 svm_clear_vintr(svm);
1264 svm->vmcb->control.int_ctl &= ~V_IRQ_MASK;
1265
1266 return 1;
1267}
1268
1237static int invalid_op_interception(struct vcpu_svm *svm, 1269static int invalid_op_interception(struct vcpu_svm *svm,
1238 struct kvm_run *kvm_run) 1270 struct kvm_run *kvm_run)
1239{ 1271{
@@ -1535,8 +1567,8 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
1535 [SVM_EXIT_VMMCALL] = vmmcall_interception, 1567 [SVM_EXIT_VMMCALL] = vmmcall_interception,
1536 [SVM_EXIT_VMLOAD] = invalid_op_interception, 1568 [SVM_EXIT_VMLOAD] = invalid_op_interception,
1537 [SVM_EXIT_VMSAVE] = invalid_op_interception, 1569 [SVM_EXIT_VMSAVE] = invalid_op_interception,
1538 [SVM_EXIT_STGI] = invalid_op_interception, 1570 [SVM_EXIT_STGI] = stgi_interception,
1539 [SVM_EXIT_CLGI] = invalid_op_interception, 1571 [SVM_EXIT_CLGI] = clgi_interception,
1540 [SVM_EXIT_SKINIT] = invalid_op_interception, 1572 [SVM_EXIT_SKINIT] = invalid_op_interception,
1541 [SVM_EXIT_WBINVD] = emulate_on_interception, 1573 [SVM_EXIT_WBINVD] = emulate_on_interception,
1542 [SVM_EXIT_MONITOR] = invalid_op_interception, 1574 [SVM_EXIT_MONITOR] = invalid_op_interception,
@@ -1684,6 +1716,9 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu)
1684 if (!kvm_cpu_has_interrupt(vcpu)) 1716 if (!kvm_cpu_has_interrupt(vcpu))
1685 goto out; 1717 goto out;
1686 1718
1719 if (!(svm->vcpu.arch.hflags & HF_GIF_MASK))
1720 goto out;
1721
1687 if (!(vmcb->save.rflags & X86_EFLAGS_IF) || 1722 if (!(vmcb->save.rflags & X86_EFLAGS_IF) ||
1688 (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) || 1723 (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) ||
1689 (vmcb->control.event_inj & SVM_EVTINJ_VALID)) { 1724 (vmcb->control.event_inj & SVM_EVTINJ_VALID)) {
@@ -1710,7 +1745,8 @@ static void kvm_reput_irq(struct vcpu_svm *svm)
1710 } 1745 }
1711 1746
1712 svm->vcpu.arch.interrupt_window_open = 1747 svm->vcpu.arch.interrupt_window_open =
1713 !(control->int_state & SVM_INTERRUPT_SHADOW_MASK); 1748 !(control->int_state & SVM_INTERRUPT_SHADOW_MASK) &&
1749 (svm->vcpu.arch.hflags & HF_GIF_MASK);
1714} 1750}
1715 1751
1716static void svm_do_inject_vector(struct vcpu_svm *svm) 1752static void svm_do_inject_vector(struct vcpu_svm *svm)
@@ -1734,7 +1770,8 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu,
1734 1770
1735 svm->vcpu.arch.interrupt_window_open = 1771 svm->vcpu.arch.interrupt_window_open =
1736 (!(control->int_state & SVM_INTERRUPT_SHADOW_MASK) && 1772 (!(control->int_state & SVM_INTERRUPT_SHADOW_MASK) &&
1737 (svm->vmcb->save.rflags & X86_EFLAGS_IF)); 1773 (svm->vmcb->save.rflags & X86_EFLAGS_IF) &&
1774 (svm->vcpu.arch.hflags & HF_GIF_MASK));
1738 1775
1739 if (svm->vcpu.arch.interrupt_window_open && svm->vcpu.arch.irq_summary) 1776 if (svm->vcpu.arch.interrupt_window_open && svm->vcpu.arch.irq_summary)
1740 /* 1777 /*