From patchwork Thu Apr 7 08:20:22 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Suthikulpanit, Suravee" X-Patchwork-Id: 8769621 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.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A0581C0553 for ; Thu, 7 Apr 2016 08:26:34 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0B986201EC for ; Thu, 7 Apr 2016 08:26:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6184D201BC for ; Thu, 7 Apr 2016 08:26:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755413AbcDGIVT (ORCPT ); Thu, 7 Apr 2016 04:21:19 -0400 Received: from mail-by2on0099.outbound.protection.outlook.com ([207.46.100.99]:18880 "EHLO na01-by2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751231AbcDGIVO (ORCPT ); Thu, 7 Apr 2016 04:21:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector1-amd-com; h=From:To:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=yRn678u7ZPyAlSCazsTGbHMakxhbiEUWV6/hV3g7XvU=; b=O7BQtyCNPP4zH1SdvS54xnRmzD0dFruJ+2AdiTZNAndV2cqcN9wk8T8AcN3vw2O9FbtXBkp9i3cWC3bPlKjbNVUv4yqD8xLfzO4BKp9dt6BuEJFeJe/E6DdeiVOGbMkhwnNsq0Wrbrq+a6XBxMnwXDddMMTW/ixWazFFCTltu70= Authentication-Results: redhat.com; dkim=none (message not signed) header.d=none; redhat.com; dmarc=none action=none header.from=amd.com; Received: from localhost.localdomain (124.121.8.20) by SN1PR12MB0445.namprd12.prod.outlook.com (10.162.105.139) with Microsoft SMTP Server (TLS) id 15.1.447.15; Thu, 7 Apr 2016 08:21:00 +0000 From: Suravee Suthikulpanit To: , , , , , CC: , , , , Suravee Suthikulpanit , Suravee Suthikulpanit Subject: [PART1 RFC v4 01/11] KVM: x86: Misc LAPIC changes to expose helper functions Date: Thu, 7 Apr 2016 03:20:22 -0500 Message-ID: <1460017232-17429-2-git-send-email-Suravee.Suthikulpanit@amd.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1460017232-17429-1-git-send-email-Suravee.Suthikulpanit@amd.com> References: <1460017232-17429-1-git-send-email-Suravee.Suthikulpanit@amd.com> MIME-Version: 1.0 X-Originating-IP: [124.121.8.20] X-ClientProxiedBy: KL1PR02CA0009.apcprd02.prod.outlook.com (10.165.15.19) To SN1PR12MB0445.namprd12.prod.outlook.com (10.162.105.139) X-MS-Office365-Filtering-Correlation-Id: 8208eaf6-93b7-4dad-0ae5-08d35ebd92b2 X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB0445; 2:JFwSNcurQX9EU3xTIzboLsnwRZJTejqy86d/MKyULnL7Ida1+ABl8W83i2UI1n29e7X+ABagIUt04BBgwc19Q4To61EoY5ClVsbKASsjub14M3kNZeu39U+uAOvRX95gaxmiGaCnz7eAX/hUwGx+g2zXj3FTdCthoYwyXe75oBKo/Pmb2PqGc8Btd2DXVlxI; 3:d1Q4ySCE/keJKiOncBXOFVJdOzGyITTLUQFSgE3B53JRuVqHoqGFdiSjLjS+/eS2PQ4JWyGWxA5mvFBmS+KmlWwb25Th28guVXy29Kh2hxUQnqCGH4+TH4wa3trsPp2I; 25:h/nN6ugVJdz8ifB6V3zsJjQNAiJJh04lddtXkRbdDf/a+71s96TI+Xv6uAF4MuEufglOLUmcuWFheuQCa9ftYMrGzqGon9UHU+vLM2ZvOvhN0j/cRN0bKV1kkQZR/ly5TozkjGXdODNocZiwxiCZUnBof7fzPJMoQUq/MThymryCjDQzcm/9VAz3BLNEhuKoJA8MO0SRBKLLmN6X6ABD1TJPPqDaTRFGGFqRa3u+1ixETNyoI4193pkylQ4RyDA0MPFwAyCz+nWw2ADnTjWAtdX5l9CfeHRyiOMZ1FWvAP/d0fqT5f+rFGb+MUplzwKkgeJpYmxWh30t/o7HGGFDqVEDgoLaWkOv/JvXcgk+A7KM2y17tXLj9kgfv+dgTLi1Vl/kU3ewhodOcrwn8k5fCpbSpuWE27Bf45NlcFZ7ymxpgSAjbK57qymdyk75lhdGaQ+HGHFfN+JKUhIn4Kftq/a49i0NdqCXXep9AUnfKi7mtVTk5M4brwJrmVA5EayFAJOWWZsOTh83571FEb+3MNEOmCWgfFy52Zedoaz1wEwD7M4hWBNNTiI48Kct0RWTND7Pl+Q3IiwdrQJOw4Cf/SjpFzejLPoPBxs 4Z+HW6rw= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:SN1PR12MB0445; X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB0445; 20:GyjCQxbY1goLNakx8VHnJrtgnB1Os9hWIra2DASpyPViSyw6mCzKArfGzPAeiCUBV7U28LssOZmMvpvIF6gjP7DKLE5rT7rL5ggwz7yu8VJnirX9+PxZ2kT398+khH0FLFgATrs0igTFw6MZ8sLmbSeep6OhmIfmtXGKVvjYbVJtVmMbOY/ggMvVjnw3qo4WAYhj+MGss9J9T4P/5evhXRmvs4wdrHdvd0IhKfdXyaCzVXuwqbIM91KNawsg2w8DjJvXdi6y103d86IjDOi58tbO9qs0gtPihzNVrF2WqVmfF1L9F/7eCxaEzWL5Ny9v3jLaheXhpD7ODu/IGGnPtNd7Nsdl3keRSFgskFL5cE55KcE3Kb1x29m3HofW2HI67rg/Hl0fUzjzROl1R27nRKwhckpNzIt3wka+e6bPNOUisIZYY6VwnpbicSCSdNmiphqcCbtEZd07SD0sdc/qtpKvpPlllKaVbUnZi0hWIWm1kO8JUJN0SvhPLBiSp4VV; 4:H3ZdOWC4Z8Hh5eF8w2DcMX6NXL9RVMKdZ+6LSjKGvJ3HZ1RxUKPsOzHjC9+0/ROgv1oWD4hDslmK8cvRBT7SA2xFM1hYaJlvvIsX6lJ+Z+3mDzS0suOqX1+5Mrw2aVhh1YWdwMcH56+czTn4p0oCEW8xzgelXgTwKcbTCK0iUaPaNPuFKSktRGz4sQGCCzqSJ9gz18aYyb0MX2fAQGgODwnFZNg+4IZRykJT9jdDdTjg4oMc0S1c88RQjOpgZi6akd6iSqFxiaU9/65Q6mm1wdNsOibI0l+S8eXrD4N5VYhaOlLmbFQ10dzkxdpSFFiAZbBluWoBOJLPs4uZ6/E+qAxJtCe6QvsRI3Z6LaJ+w73p1JIsrVFgWFqmqfBpk9kN X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(5005006)(8121501046)(10201501046)(3002001); SRVR:SN1PR12MB0445; BCL:0; PCL:0; RULEID:; SRVR:SN1PR12MB0445; X-Forefront-PRVS: 0905A6B2C7 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6069001)(6009001)(50226001)(86362001)(19580395003)(2201001)(229853001)(19580405001)(81166005)(66066001)(5008740100001)(6116002)(1096002)(586003)(42186005)(3846002)(48376002)(2906002)(50466002)(5001770100001)(4326007)(36756003)(2950100001)(47776003)(5003940100001)(76176999)(92566002)(50986999)(575784001)(77096005)(189998001); DIR:OUT; SFP:1101; SCL:1; SRVR:SN1PR12MB0445; H:localhost.localdomain; FPR:; SPF:None; MLV:sfv; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB0445; 23:URghGl+DlPFIGnyNsD7I8YyoSrQ7XKJRWZdkZaaQdAB2+nRm5gMeAnJ5SQHkASQb9GYu57dDF4BzONJjrih1KxAdWwrss5TlDmQTYs4MYYpCO9X5V41MoQTpE82CH23HI85Zfkf+Fym+f2cqq3iVkMMpioq9X/hvgEOxWJkGzrb9nvC5iolSM/e1RqVHYdVshf+ezAVdGXWfUB66bN6bvdLJaCdapyO4LHm7AlxYagWG4tL+FHyHz/oSQtPahnT/3z0cPiMkKe7Xq33JbpSzMGIYZAu+gDAd7uMB1VxI3l18GlgEzuwbJYEhFUy5OpudymHBWkAct4vQrsoOspC3RFF8DaXA7aN+EAa1olBxa1PNUl9Xz5fppnfNBTfddT+RdX3NrRY59FIfBz9XGDOj+quKQiMD4M8Q9tHFUIgVwhA7GEbzyfvW1dqanMHuKHoPIEoaX9LU1yhtyhV6i/g7PAS2nhzFX4utC9jh39mtHZcI/wU7VzAJwW2xY/TnzB92eyPUuVaPwFFoBKMTkg7n36f6wRlZnaSu6gq+1eEUzgjwUyjMpVl3/nHt1iX5xJI5bSXgpDsluvWUlrjsBymOEkMgPPcOecnftfDtu0pgDUMwkQ4O3pou0Yl6tJIrbVuYNIjEOGmT5txXa4KqelzemGnsYgFUkorrN/vcEUgecU88JeukPPamcqjlCpftgOcL2TC6v+iOGUgL7WKedJnp8WjsN9DF19bvQRy55Jr7yQfxsx2hFuTFGIsfqGxN9nHGQx3Pgw18/xgw8RgYoxRkE0VM+VDfDWgGOHZS/dK/3aTOqU4HIuTCeyaY6nupNI2LHPKwpmpf+voK/MhOMq36OmNufQcEVUq0wpfmylIRjRU4KvLy0q3wmIKw4BXdiX2R X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB0445; 5:jUuyYxFdTm0oekeJEyTYrOtMCH5+B/b8nIlKNO0+7k8to2c1jC+5pbP6ioMn0/XnbuZk/KZGra86L1offid+nLCE1QzVgwjVamHBdIU4AMgt7PS7OGmOznh/i0Q11xGcTStrUS6AXdJzQvMDjQpqkA==; 24:6bGj1GFlT3g2l/eGsmVT+A9vW93VSXdkd47zu3+plSngw9w7ZXkSwnqiMAHc9Ifxe+/A0lNJb4kA4AH0ciSmEmgxfAhkoqT+5AjlYoX6QjU=; 20:tMea6WQyWpHlyiEgKFAFAG2UVO7XQtwDtf0+l4lHkHbKFf40BaIDE7UTGCqrK4M8FsGD2urJonQYnNBflrTmlo89JGhv7Q5JjTNxT/mzO+VWRHVawlWEhW+ttG54QCRVU9BX9kWAPdPblS6jtQwJQPAAS7aOOWqGNUlQPN1YJsmK3nvgNs5B+Hz3f+hWn6Eyb/pEVwkFXEm+ifpe6rcH9lVoQK+61/7kqCpK9tl/YVkIrA5tvDIJvMv0so+NkmpS X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Apr 2016 08:21:00.5308 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN1PR12MB0445 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-7.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,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 Exporting LAPIC utility functions and macros for re-use in SVM code. Signed-off-by: Suravee Suthikulpanit Reviewed-by: Radim Kr?má? --- arch/x86/kvm/lapic.c | 127 +++++++++++++++++++++------------------------------ arch/x86/kvm/lapic.h | 29 ++++++++++++ 2 files changed, 82 insertions(+), 74 deletions(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 443d2a5..99c9757 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -59,9 +59,8 @@ /* #define apic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) */ #define apic_debug(fmt, arg...) -#define APIC_LVT_NUM 6 /* 14 is the version for Xeon and Pentium 8.4.8*/ -#define APIC_VERSION (0x14UL | ((APIC_LVT_NUM - 1) << 16)) +#define APIC_VERSION (0x14UL | ((KVM_APIC_LVT_NUM - 1) << 16)) #define LAPIC_MMIO_LENGTH (1 << 12) /* followed define is not in apicdef.h */ #define APIC_SHORT_MASK 0xc0000 @@ -73,14 +72,6 @@ #define APIC_BROADCAST 0xFF #define X2APIC_BROADCAST 0xFFFFFFFFul -#define VEC_POS(v) ((v) & (32 - 1)) -#define REG_POS(v) (((v) >> 5) << 4) - -static inline void apic_set_reg(struct kvm_lapic *apic, int reg_off, u32 val) -{ - *((u32 *) (apic->regs + reg_off)) = val; -} - static inline int apic_test_vector(int vec, void *bitmap) { return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); @@ -94,11 +85,6 @@ bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector) apic_test_vector(vector, apic->regs + APIC_IRR); } -static inline void apic_set_vector(int vec, void *bitmap) -{ - set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); -} - static inline void apic_clear_vector(int vec, void *bitmap) { clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); @@ -212,7 +198,7 @@ static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val) { bool enabled = val & APIC_SPIV_APIC_ENABLED; - apic_set_reg(apic, APIC_SPIV, val); + kvm_lapic_set_reg(apic, APIC_SPIV, val); if (enabled != apic->sw_enabled) { apic->sw_enabled = enabled; @@ -226,13 +212,13 @@ static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val) static inline void kvm_apic_set_id(struct kvm_lapic *apic, u8 id) { - apic_set_reg(apic, APIC_ID, id << 24); + kvm_lapic_set_reg(apic, APIC_ID, id << 24); recalculate_apic_map(apic->vcpu->kvm); } static inline void kvm_apic_set_ldr(struct kvm_lapic *apic, u32 id) { - apic_set_reg(apic, APIC_LDR, id); + kvm_lapic_set_reg(apic, APIC_LDR, id); recalculate_apic_map(apic->vcpu->kvm); } @@ -240,8 +226,8 @@ static inline void kvm_apic_set_x2apic_id(struct kvm_lapic *apic, u8 id) { u32 ldr = ((id >> 4) << 16) | (1 << (id & 0xf)); - apic_set_reg(apic, APIC_ID, id << 24); - apic_set_reg(apic, APIC_LDR, ldr); + kvm_lapic_set_reg(apic, APIC_ID, id << 24); + kvm_lapic_set_reg(apic, APIC_LDR, ldr); recalculate_apic_map(apic->vcpu->kvm); } @@ -287,10 +273,10 @@ void kvm_apic_set_version(struct kvm_vcpu *vcpu) feat = kvm_find_cpuid_entry(apic->vcpu, 0x1, 0); if (feat && (feat->ecx & (1 << (X86_FEATURE_X2APIC & 31)))) v |= APIC_LVR_DIRECTED_EOI; - apic_set_reg(apic, APIC_LVR, v); + kvm_lapic_set_reg(apic, APIC_LVR, v); } -static const unsigned int apic_lvt_mask[APIC_LVT_NUM] = { +static const unsigned int apic_lvt_mask[KVM_APIC_LVT_NUM] = { LVT_MASK , /* part LVTT mask, timer mode mask added at runtime */ LVT_MASK | APIC_MODE_MASK, /* LVTTHMR */ LVT_MASK | APIC_MODE_MASK, /* LVTPC */ @@ -349,16 +335,6 @@ void kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir) } EXPORT_SYMBOL_GPL(kvm_apic_update_irr); -static inline void apic_set_irr(int vec, struct kvm_lapic *apic) -{ - apic_set_vector(vec, apic->regs + APIC_IRR); - /* - * irr_pending must be true if any interrupt is pending; set it after - * APIC_IRR to avoid race with apic_clear_irr - */ - apic->irr_pending = true; -} - static inline int apic_search_irr(struct kvm_lapic *apic) { return find_highest_vector(apic->regs + APIC_IRR); @@ -563,7 +539,7 @@ static void apic_update_ppr(struct kvm_lapic *apic) apic, ppr, isr, isrv); if (old_ppr != ppr) { - apic_set_reg(apic, APIC_PROCPRI, ppr); + kvm_lapic_set_reg(apic, APIC_PROCPRI, ppr); if (ppr < old_ppr) kvm_make_request(KVM_REQ_EVENT, apic->vcpu); } @@ -571,7 +547,7 @@ static void apic_update_ppr(struct kvm_lapic *apic) static void apic_set_tpr(struct kvm_lapic *apic, u32 tpr) { - apic_set_reg(apic, APIC_TASKPRI, tpr); + kvm_lapic_set_reg(apic, APIC_TASKPRI, tpr); apic_update_ppr(apic); } @@ -668,6 +644,7 @@ bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, return false; } } +EXPORT_SYMBOL_GPL(kvm_apic_match_dest); int kvm_vector_to_index(u32 vector, u32 dest_vcpus, const unsigned long *bitmap, u32 bitmap_size) @@ -921,7 +898,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, if (apic_test_vector(vector, apic->regs + APIC_TMR) != !!trig_mode) { if (trig_mode) - apic_set_vector(vector, apic->regs + APIC_TMR); + kvm_lapic_set_vector(vector, apic->regs + APIC_TMR); else apic_clear_vector(vector, apic->regs + APIC_TMR); } @@ -929,7 +906,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, if (vcpu->arch.apicv_active) kvm_x86_ops->deliver_posted_interrupt(vcpu, vector); else { - apic_set_irr(vector, apic); + kvm_lapic_set_irr(vector, apic); kvm_make_request(KVM_REQ_EVENT, vcpu); kvm_vcpu_kick(vcpu); @@ -1186,7 +1163,7 @@ static inline struct kvm_lapic *to_lapic(struct kvm_io_device *dev) return container_of(dev, struct kvm_lapic, dev); } -static int apic_reg_read(struct kvm_lapic *apic, u32 offset, int len, +int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len, void *data) { unsigned char alignment = offset & 0xf; @@ -1223,6 +1200,7 @@ static int apic_reg_read(struct kvm_lapic *apic, u32 offset, int len, } return 0; } +EXPORT_SYMBOL_GPL(kvm_lapic_reg_read); static int apic_mmio_in_range(struct kvm_lapic *apic, gpa_t addr) { @@ -1240,7 +1218,7 @@ static int apic_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this, if (!apic_mmio_in_range(apic, address)) return -EOPNOTSUPP; - apic_reg_read(apic, offset, len, data); + kvm_lapic_reg_read(apic, offset, len, data); return 0; } @@ -1425,7 +1403,7 @@ static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val) } } -static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) +int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) { int ret = 0; @@ -1457,7 +1435,7 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) case APIC_DFR: if (!apic_x2apic_mode(apic)) { - apic_set_reg(apic, APIC_DFR, val | 0x0FFFFFFF); + kvm_lapic_set_reg(apic, APIC_DFR, val | 0x0FFFFFFF); recalculate_apic_map(apic->vcpu->kvm); } else ret = 1; @@ -1472,10 +1450,10 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) int i; u32 lvt_val; - for (i = 0; i < APIC_LVT_NUM; i++) { + for (i = 0; i < KVM_APIC_LVT_NUM; i++) { lvt_val = kvm_apic_get_reg(apic, APIC_LVTT + 0x10 * i); - apic_set_reg(apic, APIC_LVTT + 0x10 * i, + kvm_lapic_set_reg(apic, APIC_LVTT + 0x10 * i, lvt_val | APIC_LVT_MASKED); } apic_update_lvtt(apic); @@ -1486,14 +1464,14 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) } case APIC_ICR: /* No delay here, so we always clear the pending bit */ - apic_set_reg(apic, APIC_ICR, val & ~(1 << 12)); + kvm_lapic_set_reg(apic, APIC_ICR, val & ~(1 << 12)); apic_send_ipi(apic); break; case APIC_ICR2: if (!apic_x2apic_mode(apic)) val &= 0xff000000; - apic_set_reg(apic, APIC_ICR2, val); + kvm_lapic_set_reg(apic, APIC_ICR2, val); break; case APIC_LVT0: @@ -1507,7 +1485,7 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) val |= APIC_LVT_MASKED; val &= apic_lvt_mask[(reg - APIC_LVTT) >> 4]; - apic_set_reg(apic, reg, val); + kvm_lapic_set_reg(apic, reg, val); break; @@ -1515,7 +1493,7 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) if (!kvm_apic_sw_enabled(apic)) val |= APIC_LVT_MASKED; val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask); - apic_set_reg(apic, APIC_LVTT, val); + kvm_lapic_set_reg(apic, APIC_LVTT, val); apic_update_lvtt(apic); break; @@ -1524,14 +1502,14 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) break; hrtimer_cancel(&apic->lapic_timer.timer); - apic_set_reg(apic, APIC_TMICT, val); + kvm_lapic_set_reg(apic, APIC_TMICT, val); start_apic_timer(apic); break; case APIC_TDCR: if (val & 4) apic_debug("KVM_WRITE:TDCR %x\n", val); - apic_set_reg(apic, APIC_TDCR, val); + kvm_lapic_set_reg(apic, APIC_TDCR, val); update_divide_count(apic); break; @@ -1544,7 +1522,7 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) case APIC_SELF_IPI: if (apic_x2apic_mode(apic)) { - apic_reg_write(apic, APIC_ICR, 0x40000 | (val & 0xff)); + kvm_lapic_reg_write(apic, APIC_ICR, 0x40000 | (val & 0xff)); } else ret = 1; break; @@ -1556,6 +1534,7 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) apic_debug("Local APIC Write to read-only register %x\n", reg); return ret; } +EXPORT_SYMBOL_GPL(kvm_lapic_reg_write); static int apic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this, gpa_t address, int len, const void *data) @@ -1585,14 +1564,14 @@ static int apic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this, apic_debug("%s: offset 0x%x with length 0x%x, and value is " "0x%x\n", __func__, offset, len, val); - apic_reg_write(apic, offset & 0xff0, val); + kvm_lapic_reg_write(apic, offset & 0xff0, val); return 0; } void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu) { - apic_reg_write(vcpu->arch.apic, APIC_EOI, 0); + kvm_lapic_reg_write(vcpu->arch.apic, APIC_EOI, 0); } EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi); @@ -1604,10 +1583,10 @@ void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset) /* hw has done the conditional check and inst decode */ offset &= 0xff0; - apic_reg_read(vcpu->arch.apic, offset, 4, &val); + kvm_lapic_reg_read(vcpu->arch.apic, offset, 4, &val); /* TODO: optimize to just emulate side effect w/o one more write */ - apic_reg_write(vcpu->arch.apic, offset, val); + kvm_lapic_reg_write(vcpu->arch.apic, offset, val); } EXPORT_SYMBOL_GPL(kvm_apic_write_nodecode); @@ -1740,28 +1719,28 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event) kvm_apic_set_id(apic, vcpu->vcpu_id); kvm_apic_set_version(apic->vcpu); - for (i = 0; i < APIC_LVT_NUM; i++) - apic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED); + for (i = 0; i < KVM_APIC_LVT_NUM; i++) + kvm_lapic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED); apic_update_lvtt(apic); if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_LINT0_REENABLED)) - apic_set_reg(apic, APIC_LVT0, + kvm_lapic_set_reg(apic, APIC_LVT0, SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT)); apic_manage_nmi_watchdog(apic, kvm_apic_get_reg(apic, APIC_LVT0)); - apic_set_reg(apic, APIC_DFR, 0xffffffffU); + kvm_lapic_set_reg(apic, APIC_DFR, 0xffffffffU); apic_set_spiv(apic, 0xff); - apic_set_reg(apic, APIC_TASKPRI, 0); + kvm_lapic_set_reg(apic, APIC_TASKPRI, 0); if (!apic_x2apic_mode(apic)) kvm_apic_set_ldr(apic, 0); - apic_set_reg(apic, APIC_ESR, 0); - apic_set_reg(apic, APIC_ICR, 0); - apic_set_reg(apic, APIC_ICR2, 0); - apic_set_reg(apic, APIC_TDCR, 0); - apic_set_reg(apic, APIC_TMICT, 0); + kvm_lapic_set_reg(apic, APIC_ESR, 0); + kvm_lapic_set_reg(apic, APIC_ICR, 0); + kvm_lapic_set_reg(apic, APIC_ICR2, 0); + kvm_lapic_set_reg(apic, APIC_TDCR, 0); + kvm_lapic_set_reg(apic, APIC_TMICT, 0); for (i = 0; i < 8; i++) { - apic_set_reg(apic, APIC_IRR + 0x10 * i, 0); - apic_set_reg(apic, APIC_ISR + 0x10 * i, 0); - apic_set_reg(apic, APIC_TMR + 0x10 * i, 0); + kvm_lapic_set_reg(apic, APIC_IRR + 0x10 * i, 0); + kvm_lapic_set_reg(apic, APIC_ISR + 0x10 * i, 0); + kvm_lapic_set_reg(apic, APIC_TMR + 0x10 * i, 0); } apic->irr_pending = vcpu->arch.apicv_active; apic->isr_count = vcpu->arch.apicv_active ? 1 : 0; @@ -2139,8 +2118,8 @@ int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data) /* if this is ICR write vector before command */ if (reg == APIC_ICR) - apic_reg_write(apic, APIC_ICR2, (u32)(data >> 32)); - return apic_reg_write(apic, reg, (u32)data); + kvm_lapic_reg_write(apic, APIC_ICR2, (u32)(data >> 32)); + return kvm_lapic_reg_write(apic, reg, (u32)data); } int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data) @@ -2157,10 +2136,10 @@ int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data) return 1; } - if (apic_reg_read(apic, reg, 4, &low)) + if (kvm_lapic_reg_read(apic, reg, 4, &low)) return 1; if (reg == APIC_ICR) - apic_reg_read(apic, APIC_ICR2, 4, &high); + kvm_lapic_reg_read(apic, APIC_ICR2, 4, &high); *data = (((u64)high) << 32) | low; @@ -2176,8 +2155,8 @@ int kvm_hv_vapic_msr_write(struct kvm_vcpu *vcpu, u32 reg, u64 data) /* if this is ICR write vector before command */ if (reg == APIC_ICR) - apic_reg_write(apic, APIC_ICR2, (u32)(data >> 32)); - return apic_reg_write(apic, reg, (u32)data); + kvm_lapic_reg_write(apic, APIC_ICR2, (u32)(data >> 32)); + return kvm_lapic_reg_write(apic, reg, (u32)data); } int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data) @@ -2188,10 +2167,10 @@ int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data) if (!lapic_in_kernel(vcpu)) return 1; - if (apic_reg_read(apic, reg, 4, &low)) + if (kvm_lapic_reg_read(apic, reg, 4, &low)) return 1; if (reg == APIC_ICR) - apic_reg_read(apic, APIC_ICR2, 4, &high); + kvm_lapic_reg_read(apic, APIC_ICR2, 4, &high); *data = (((u64)high) << 32) | low; diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index f71183e..a70cb62 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -7,6 +7,7 @@ #define KVM_APIC_INIT 0 #define KVM_APIC_SIPI 1 +#define KVM_APIC_LVT_NUM 6 struct kvm_timer { struct hrtimer timer; @@ -59,6 +60,11 @@ void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu); void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value); u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu); void kvm_apic_set_version(struct kvm_vcpu *vcpu); +int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val); +int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len, + void *data); +bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, + int short_hand, unsigned int dest, int dest_mode); void __kvm_apic_update_irr(u32 *pir, void *regs); void kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir); @@ -99,11 +105,34 @@ static inline bool kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu) int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data); void kvm_lapic_init(void); +#define VEC_POS(v) ((v) & (32 - 1)) +#define REG_POS(v) (((v) >> 5) << 4) + +static inline void kvm_lapic_set_vector(int vec, void *bitmap) +{ + set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); +} + +static inline void kvm_lapic_set_irr(int vec, struct kvm_lapic *apic) +{ + kvm_lapic_set_vector(vec, apic->regs + APIC_IRR); + /* + * irr_pending must be true if any interrupt is pending; set it after + * APIC_IRR to avoid race with apic_clear_irr + */ + apic->irr_pending = true; +} + static inline u32 kvm_apic_get_reg(struct kvm_lapic *apic, int reg_off) { return *((u32 *) (apic->regs + reg_off)); } +static inline void kvm_lapic_set_reg(struct kvm_lapic *apic, int reg_off, u32 val) +{ + *((u32 *) (apic->regs + reg_off)) = val; +} + extern struct static_key kvm_no_apic_vcpu; static inline bool lapic_in_kernel(struct kvm_vcpu *vcpu)