diff options
author | Eddie Dong <eddie.dong@intel.com> | 2007-07-18 05:15:21 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2007-10-13 04:18:25 -0400 |
commit | b6958ce44a11a9e9425d2b67a653b1ca2a27796f (patch) | |
tree | 503478ef27254df9b6ea21d2a6a279a7dfe2ef04 /drivers/kvm/kvm_main.c | |
parent | 1fd4f2a5ed8f80cf6e23d2bdf78554f6a1ac7997 (diff) |
KVM: Emulate hlt in the kernel
By sleeping in the kernel when hlt is executed, we simplify the in-kernel
guest interrupt path considerably.
Signed-off-by: Gregory Haskins <ghaskins@novell.com>
Signed-off-by: Yaozu (Eddie) Dong <eddie.dong@intel.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r-- | drivers/kvm/kvm_main.c | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index ffbdadd87971..4384364fc0c8 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -76,6 +76,7 @@ static struct kvm_stats_debugfs_item { | |||
76 | { "signal_exits", STAT_OFFSET(signal_exits) }, | 76 | { "signal_exits", STAT_OFFSET(signal_exits) }, |
77 | { "irq_window", STAT_OFFSET(irq_window_exits) }, | 77 | { "irq_window", STAT_OFFSET(irq_window_exits) }, |
78 | { "halt_exits", STAT_OFFSET(halt_exits) }, | 78 | { "halt_exits", STAT_OFFSET(halt_exits) }, |
79 | { "halt_wakeup", STAT_OFFSET(halt_wakeup) }, | ||
79 | { "request_irq", STAT_OFFSET(request_irq_exits) }, | 80 | { "request_irq", STAT_OFFSET(request_irq_exits) }, |
80 | { "irq_exits", STAT_OFFSET(irq_exits) }, | 81 | { "irq_exits", STAT_OFFSET(irq_exits) }, |
81 | { "light_exits", STAT_OFFSET(light_exits) }, | 82 | { "light_exits", STAT_OFFSET(light_exits) }, |
@@ -248,6 +249,7 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id) | |||
248 | vcpu->mmu.root_hpa = INVALID_PAGE; | 249 | vcpu->mmu.root_hpa = INVALID_PAGE; |
249 | vcpu->kvm = kvm; | 250 | vcpu->kvm = kvm; |
250 | vcpu->vcpu_id = id; | 251 | vcpu->vcpu_id = id; |
252 | init_waitqueue_head(&vcpu->wq); | ||
251 | 253 | ||
252 | page = alloc_page(GFP_KERNEL | __GFP_ZERO); | 254 | page = alloc_page(GFP_KERNEL | __GFP_ZERO); |
253 | if (!page) { | 255 | if (!page) { |
@@ -1307,15 +1309,41 @@ int emulate_instruction(struct kvm_vcpu *vcpu, | |||
1307 | } | 1309 | } |
1308 | EXPORT_SYMBOL_GPL(emulate_instruction); | 1310 | EXPORT_SYMBOL_GPL(emulate_instruction); |
1309 | 1311 | ||
1310 | int kvm_emulate_halt(struct kvm_vcpu *vcpu) | 1312 | /* |
1313 | * The vCPU has executed a HLT instruction with in-kernel mode enabled. | ||
1314 | */ | ||
1315 | static void kvm_vcpu_kernel_halt(struct kvm_vcpu *vcpu) | ||
1311 | { | 1316 | { |
1312 | if (vcpu->irq_summary || | 1317 | DECLARE_WAITQUEUE(wait, current); |
1313 | (irqchip_in_kernel(vcpu->kvm) && kvm_cpu_has_interrupt(vcpu))) | 1318 | |
1314 | return 1; | 1319 | add_wait_queue(&vcpu->wq, &wait); |
1320 | |||
1321 | /* | ||
1322 | * We will block until either an interrupt or a signal wakes us up | ||
1323 | */ | ||
1324 | while(!(irqchip_in_kernel(vcpu->kvm) && kvm_cpu_has_interrupt(vcpu)) | ||
1325 | && !vcpu->irq_summary | ||
1326 | && !signal_pending(current)) { | ||
1327 | set_current_state(TASK_INTERRUPTIBLE); | ||
1328 | vcpu_put(vcpu); | ||
1329 | schedule(); | ||
1330 | vcpu_load(vcpu); | ||
1331 | } | ||
1315 | 1332 | ||
1316 | vcpu->run->exit_reason = KVM_EXIT_HLT; | 1333 | remove_wait_queue(&vcpu->wq, &wait); |
1334 | set_current_state(TASK_RUNNING); | ||
1335 | } | ||
1336 | |||
1337 | int kvm_emulate_halt(struct kvm_vcpu *vcpu) | ||
1338 | { | ||
1317 | ++vcpu->stat.halt_exits; | 1339 | ++vcpu->stat.halt_exits; |
1318 | return 0; | 1340 | if (irqchip_in_kernel(vcpu->kvm)) { |
1341 | kvm_vcpu_kernel_halt(vcpu); | ||
1342 | return 1; | ||
1343 | } else { | ||
1344 | vcpu->run->exit_reason = KVM_EXIT_HLT; | ||
1345 | return 0; | ||
1346 | } | ||
1319 | } | 1347 | } |
1320 | EXPORT_SYMBOL_GPL(kvm_emulate_halt); | 1348 | EXPORT_SYMBOL_GPL(kvm_emulate_halt); |
1321 | 1349 | ||
@@ -2916,6 +2944,7 @@ static long kvm_dev_ioctl(struct file *filp, | |||
2916 | 2944 | ||
2917 | switch (ext) { | 2945 | switch (ext) { |
2918 | case KVM_CAP_IRQCHIP: | 2946 | case KVM_CAP_IRQCHIP: |
2947 | case KVM_CAP_HLT: | ||
2919 | r = 1; | 2948 | r = 1; |
2920 | break; | 2949 | break; |
2921 | default: | 2950 | default: |