From patchwork Tue Jun 3 20:27:46 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bandan Das X-Patchwork-Id: 4290811 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 6E513BEEA7 for ; Tue, 3 Jun 2014 20:28:13 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 93F1A201F2 for ; Tue, 3 Jun 2014 20:28:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9E0D52021A for ; Tue, 3 Jun 2014 20:28:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933299AbaFCU2F (ORCPT ); Tue, 3 Jun 2014 16:28:05 -0400 Received: from mx1.redhat.com ([209.132.183.28]:40968 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932597AbaFCU2D (ORCPT ); Tue, 3 Jun 2014 16:28:03 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s53KRvb6026871 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 3 Jun 2014 16:27:57 -0400 Received: from nelium.bos.redhat.com ([10.18.17.224]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s53KRsYD004001; Tue, 3 Jun 2014 16:27:57 -0400 From: Bandan Das To: kvm@vger.kernel.org Cc: Paolo Bonzini , Jan Kiszka Subject: [PATCH kvm-unit-tests 2/2] VMX: Add test for interrupt acknowledgement Date: Tue, 3 Jun 2014 16:27:46 -0400 Message-Id: <1401827266-28769-3-git-send-email-bsd@redhat.com> In-Reply-To: <1401827266-28769-1-git-send-email-bsd@redhat.com> References: <1401827266-28769-1-git-send-email-bsd@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP If the hypervisor has the interrupt acknowledgement bit set, vector information is already present in intr_info during a vmexit. The hypervisor then uses it to call the appropriate handler. Signed-off-by: Bandan Das --- lib/x86/isr.c | 32 ++++++++++++++++++++++++++++++++ lib/x86/isr.h | 2 +- x86/vmx_tests.c | 26 +++++++++++++++++++++++--- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/lib/x86/isr.c b/lib/x86/isr.c index 7dcd38a..b0c6f53 100644 --- a/lib/x86/isr.c +++ b/lib/x86/isr.c @@ -90,3 +90,35 @@ void handle_irq(unsigned vec, void (*func)(isr_regs_t *regs)) *(u32 *)thunk = (ulong)isr_entry_point - (ulong)(thunk + 4); #endif } + +void handle_external_interrupt(int vector) +{ +#ifdef __x86_64__ + unsigned long tmp; +#endif + idt_entry_t *idt = &boot_idt[vector]; + unsigned long entry = + idt->offset0 | ((unsigned long)idt->offset1 << 16) | + ((unsigned long)idt->offset2 << 32); + + asm volatile( +#ifdef __x86_64__ + "mov %%rsp, %[sp]\n\t" + "and $0xfffffffffffffff0, %%rsp\n\t" + "push $%c[ss]\n\t" + "push %[sp]\n\t" +#endif + "pushf\n\t" + "orl $0x200, (%%rsp)\n\t" + "push $%c[cs]\n\t" + "call *%[entry]\n\t" + : +#ifdef __x86_64__ + [sp]"=&r"(tmp) +#endif + : + [entry]"r"(entry), + [ss]"i"(KERNEL_DS), + [cs]"i"(KERNEL_CS) + ); +} diff --git a/lib/x86/isr.h b/lib/x86/isr.h index b07a32a..a509291 100644 --- a/lib/x86/isr.h +++ b/lib/x86/isr.h @@ -10,5 +10,5 @@ typedef struct { } isr_regs_t; void handle_irq(unsigned vec, void (*func)(isr_regs_t *regs)); - +void handle_external_interrupt(int vector); #endif diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 324f074..a40cb18 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -1290,6 +1290,16 @@ static void interrupt_main(void) report("intercepted interrupt + activity state hlt", rdtsc() - start > 10000 && timer_fired); + + apic_write(APIC_TMICT, 0); + irq_disable(); + set_stage(7); + vmcall(); + timer_fired = false; + apic_write(APIC_TMICT, 1); + for (loops = 0; loops < 10000000 && !timer_fired; loops++) + asm volatile ("nop"); + report("running a guest with interrupt acknowledgement set", timer_fired); } static int interrupt_exit_handler(void) @@ -1307,6 +1317,11 @@ static int interrupt_exit_handler(void) vmcs_write(PIN_CONTROLS, vmcs_read(PIN_CONTROLS) | PIN_EXTINT); break; + case 7: + vmcs_write(EXI_CONTROLS, vmcs_read(EXI_CONTROLS) | EXI_INTA); + vmcs_write(PIN_CONTROLS, + vmcs_read(PIN_CONTROLS) | PIN_EXTINT); + break; case 1: case 3: vmcs_write(PIN_CONTROLS, @@ -1321,9 +1336,14 @@ static int interrupt_exit_handler(void) vmcs_write(GUEST_RIP, guest_rip + insn_len); return VMX_TEST_RESUME; case VMX_EXTINT: - irq_enable(); - asm volatile ("nop"); - irq_disable(); + if (vmcs_read(EXI_CONTROLS) & EXI_INTA) { + int vector = vmcs_read(EXI_INTR_INFO) & 0xff; + handle_external_interrupt(vector); + } else { + irq_enable(); + asm volatile ("nop"); + irq_disable(); + } if (get_stage() >= 2) { vmcs_write(GUEST_ACTV_STATE, ACTV_ACTIVE); vmcs_write(GUEST_RIP, guest_rip + insn_len);