From patchwork Thu Dec 21 20:46:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jim Mattson X-Patchwork-Id: 10128385 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 85F2F603B5 for ; Thu, 21 Dec 2017 20:47:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7960729E09 for ; Thu, 21 Dec 2017 20:47:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6E51929E10; Thu, 21 Dec 2017 20:47:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D348129E09 for ; Thu, 21 Dec 2017 20:47:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755557AbdLUUrR (ORCPT ); Thu, 21 Dec 2017 15:47:17 -0500 Received: from mail-io0-f196.google.com ([209.85.223.196]:42867 "EHLO mail-io0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753178AbdLUUrP (ORCPT ); Thu, 21 Dec 2017 15:47:15 -0500 Received: by mail-io0-f196.google.com with SMTP id x67so16265788ioi.9 for ; Thu, 21 Dec 2017 12:47:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=4hbeQxO6d4e5g+9amCxOzcEXueIc+uosIDC52XZAXqw=; b=mLtgwSGq0gLNQvuf5uAkoS7jGWi3SQvdEsCowf9yNUg1jqsLc39V0zMiBhX4+ZySp3 AtT3BuF6XgHRsBJe2rA1hXPQPo8wxwMG7+tvHxx5BKmonNBujSxsFW/Eoh7Koghg/wfH yqByraYGEceBqWSzKGzPXohc2zXY6AckfTCzBeABvnW2AuATelLfkO9DF5Ks6IQli5MS 8d/OyhB+KiVEtPkSoFBuyUqsyxnEmoKI+IPJ+bjQTuGp9CABV68tXJ7hxw3WnjN3N/Dm JHDXuvo5bx2ujiV4oyG69f6qbzny8nYRLWYZM/BkPwWYYIikW/L0jrN+UaTA0BxzbdrF qjdQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=4hbeQxO6d4e5g+9amCxOzcEXueIc+uosIDC52XZAXqw=; b=RBF5HLuwePRzkedsZOatOE45ju4s3mIfB9qe3WLBslF/kc0H1sQlXT/2oPVb52v7yT OsgcLHEBGaIZxnYKmRG9kahtKM7cYj8O96iN+72Ufq4BUxqC2eXtuilBk8PpcOytXEP0 Vc7krYPKgG3qTZ4E9TrYJjKG80u9kLCLUki8wfDpJBSn4O8pPdoIUYf6APwO+yfRClug YI7nbtiGR+4N3/yrg3E29+7eetWgdCmNHyBN6k113+W/0BscQvf3d9mmPKlrRtrpab2O dQXR1cZ4MQozxtsqpJWIclqoxkGrKxnFhPov9FQ3D/jLEQYavaLnMs42wWXeAou10/lW 9QAg== X-Gm-Message-State: AKGB3mL4eF+C27fWf0Kn4/Hq8wtlAyhlHYPJ3ckbK6yheF3uWqEQwgyx 77/6dQnx7VnYh0SfVzbfcQRsgPOOrlE= X-Google-Smtp-Source: ACJfBovxcROZ+C+Y91q8O95seCE8gtsMP9t5N8R7lB9pWrx7SDFd2h5jnXQvwJFsYSoZs+SXhf3/mQ== X-Received: by 10.107.19.195 with SMTP id 64mr9620037iot.5.1513889234890; Thu, 21 Dec 2017 12:47:14 -0800 (PST) Received: from turtle.sea.corp.google.com ([100.100.207.61]) by smtp.gmail.com with ESMTPSA id s4sm4622920ita.12.2017.12.21.12.47.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 21 Dec 2017 12:47:14 -0800 (PST) From: Jim Mattson To: kvm@vger.kernel.org Cc: Jim Mattson Subject: [PATCH 3/3] kvm: vmx: Reduce size of vmcs_field_to_offset_table Date: Thu, 21 Dec 2017 12:46:23 -0800 Message-Id: <20171221204623.164581-4-jmattson@google.com> X-Mailer: git-send-email 2.15.1.620.gb9897f4670-goog In-Reply-To: <20171221204623.164581-1-jmattson@google.com> References: <20171221204623.164581-1-jmattson@google.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The vmcs_field_to_offset_table was a rather sparse table of short integers with a maximum index of 0x6c16, amounting to 55342 bytes. Now that we are considering support for multiple VMCS12 formats, it would be unfortunate to replicate that large, sparse table. Using a three-dimensional table indexed by VMCS field index, VMCS field type, and VMCS field width, it's relatively easy to reduce that table to 768 bytes. Signed-off-by: Jim Mattson --- arch/x86/kvm/vmx.c | 145 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 88 insertions(+), 57 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 1847000fbb0c..bd601b0984d1 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -714,11 +714,15 @@ static struct pi_desc *vcpu_to_pi_desc(struct kvm_vcpu *vcpu) return &(to_vmx(vcpu)->pi_desc); } -#define VMCS12_OFFSET(x) offsetof(struct vmcs12, x) -#define FIELD(number, name) [number] = VMCS12_OFFSET(name) -#define FIELD64(number, name) [number] = VMCS12_OFFSET(name), \ - [number##_HIGH] = VMCS12_OFFSET(name)+4 +#define VMCS_FIELD_HIGH(field) ((field) & 1) +#define VMCS_FIELD_INDEX(field) (((field) >> 1) & 0x1ff) +#define VMCS_FIELD_TYPE(field) (((field) >> 10) & 3) +#define VMCS_FIELD_WIDTH(field) (((field) >> 13) & 3) +#define VMCS12_OFFSET(x) offsetof(struct vmcs12, x) +#define FIELD(n, name) \ + [VMCS_FIELD_INDEX(n)][VMCS_FIELD_TYPE(n)][VMCS_FIELD_WIDTH(n)] = \ + VMCS12_OFFSET(name) static unsigned long shadow_read_only_fields[] = { /* @@ -779,7 +783,7 @@ static unsigned long shadow_read_write_fields[] = { static int max_shadow_read_write_fields = ARRAY_SIZE(shadow_read_write_fields); -static const unsigned short vmcs_field_to_offset_table[] = { +static const unsigned short vmcs_field_to_offset_table[][4][4] = { FIELD(VIRTUAL_PROCESSOR_ID, virtual_processor_id), FIELD(POSTED_INTR_NV, posted_intr_nv), FIELD(GUEST_ES_SELECTOR, guest_es_selector), @@ -799,39 +803,39 @@ static const unsigned short vmcs_field_to_offset_table[] = { FIELD(HOST_FS_SELECTOR, host_fs_selector), FIELD(HOST_GS_SELECTOR, host_gs_selector), FIELD(HOST_TR_SELECTOR, host_tr_selector), - FIELD64(IO_BITMAP_A, io_bitmap_a), - FIELD64(IO_BITMAP_B, io_bitmap_b), - FIELD64(MSR_BITMAP, msr_bitmap), - FIELD64(VM_EXIT_MSR_STORE_ADDR, vm_exit_msr_store_addr), - FIELD64(VM_EXIT_MSR_LOAD_ADDR, vm_exit_msr_load_addr), - FIELD64(VM_ENTRY_MSR_LOAD_ADDR, vm_entry_msr_load_addr), - FIELD64(TSC_OFFSET, tsc_offset), - FIELD64(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr), - FIELD64(APIC_ACCESS_ADDR, apic_access_addr), - FIELD64(POSTED_INTR_DESC_ADDR, posted_intr_desc_addr), - FIELD64(VM_FUNCTION_CONTROL, vm_function_control), - FIELD64(EPT_POINTER, ept_pointer), - FIELD64(EOI_EXIT_BITMAP0, eoi_exit_bitmap0), - FIELD64(EOI_EXIT_BITMAP1, eoi_exit_bitmap1), - FIELD64(EOI_EXIT_BITMAP2, eoi_exit_bitmap2), - FIELD64(EOI_EXIT_BITMAP3, eoi_exit_bitmap3), - FIELD64(EPTP_LIST_ADDRESS, eptp_list_address), - FIELD64(XSS_EXIT_BITMAP, xss_exit_bitmap), - FIELD64(GUEST_PHYSICAL_ADDRESS, guest_physical_address), - FIELD64(VMCS_LINK_POINTER, vmcs_link_pointer), - FIELD64(PML_ADDRESS, pml_address), - FIELD64(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl), - FIELD64(GUEST_IA32_PAT, guest_ia32_pat), - FIELD64(GUEST_IA32_EFER, guest_ia32_efer), - FIELD64(GUEST_IA32_PERF_GLOBAL_CTRL, guest_ia32_perf_global_ctrl), - FIELD64(GUEST_PDPTR0, guest_pdptr0), - FIELD64(GUEST_PDPTR1, guest_pdptr1), - FIELD64(GUEST_PDPTR2, guest_pdptr2), - FIELD64(GUEST_PDPTR3, guest_pdptr3), - FIELD64(GUEST_BNDCFGS, guest_bndcfgs), - FIELD64(HOST_IA32_PAT, host_ia32_pat), - FIELD64(HOST_IA32_EFER, host_ia32_efer), - FIELD64(HOST_IA32_PERF_GLOBAL_CTRL, host_ia32_perf_global_ctrl), + FIELD(IO_BITMAP_A, io_bitmap_a), + FIELD(IO_BITMAP_B, io_bitmap_b), + FIELD(MSR_BITMAP, msr_bitmap), + FIELD(VM_EXIT_MSR_STORE_ADDR, vm_exit_msr_store_addr), + FIELD(VM_EXIT_MSR_LOAD_ADDR, vm_exit_msr_load_addr), + FIELD(VM_ENTRY_MSR_LOAD_ADDR, vm_entry_msr_load_addr), + FIELD(TSC_OFFSET, tsc_offset), + FIELD(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr), + FIELD(APIC_ACCESS_ADDR, apic_access_addr), + FIELD(POSTED_INTR_DESC_ADDR, posted_intr_desc_addr), + FIELD(VM_FUNCTION_CONTROL, vm_function_control), + FIELD(EPT_POINTER, ept_pointer), + FIELD(EOI_EXIT_BITMAP0, eoi_exit_bitmap0), + FIELD(EOI_EXIT_BITMAP1, eoi_exit_bitmap1), + FIELD(EOI_EXIT_BITMAP2, eoi_exit_bitmap2), + FIELD(EOI_EXIT_BITMAP3, eoi_exit_bitmap3), + FIELD(EPTP_LIST_ADDRESS, eptp_list_address), + FIELD(XSS_EXIT_BITMAP, xss_exit_bitmap), + FIELD(GUEST_PHYSICAL_ADDRESS, guest_physical_address), + FIELD(VMCS_LINK_POINTER, vmcs_link_pointer), + FIELD(PML_ADDRESS, pml_address), + FIELD(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl), + FIELD(GUEST_IA32_PAT, guest_ia32_pat), + FIELD(GUEST_IA32_EFER, guest_ia32_efer), + FIELD(GUEST_IA32_PERF_GLOBAL_CTRL, guest_ia32_perf_global_ctrl), + FIELD(GUEST_PDPTR0, guest_pdptr0), + FIELD(GUEST_PDPTR1, guest_pdptr1), + FIELD(GUEST_PDPTR2, guest_pdptr2), + FIELD(GUEST_PDPTR3, guest_pdptr3), + FIELD(GUEST_BNDCFGS, guest_bndcfgs), + FIELD(HOST_IA32_PAT, host_ia32_pat), + FIELD(HOST_IA32_EFER, host_ia32_efer), + FIELD(HOST_IA32_PERF_GLOBAL_CTRL, host_ia32_perf_global_ctrl), FIELD(PIN_BASED_VM_EXEC_CONTROL, pin_based_vm_exec_control), FIELD(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control), FIELD(EXCEPTION_BITMAP, exception_bitmap), @@ -923,15 +927,56 @@ static const unsigned short vmcs_field_to_offset_table[] = { FIELD(HOST_RIP, host_rip), }; +enum vmcs_field_width { + VMCS_FIELD_WIDTH_U16 = 0, + VMCS_FIELD_WIDTH_U64 = 1, + VMCS_FIELD_WIDTH_U32 = 2, + VMCS_FIELD_WIDTH_NATURAL_WIDTH = 3 +}; + +static inline int vmcs_field_width(unsigned long field) +{ + if (VMCS_FIELD_HIGH(field)) /* the *_HIGH fields are all 32 bit */ + return VMCS_FIELD_WIDTH_U32; + return VMCS_FIELD_WIDTH(field); +} + +enum vmcs_field_type { + VMCS_FIELD_TYPE_CONTROL = 0, + VMCS_FIELD_TYPE_INFO = 1, + VMCS_FIELD_TYPE_GUEST = 2, + VMCS_FIELD_TYPE_HOST = 3 +}; + +static inline int vmcs_field_type(unsigned long field) +{ + return VMCS_FIELD_TYPE(field); +} + static inline short vmcs_field_to_offset(unsigned long field) { - BUILD_BUG_ON(ARRAY_SIZE(vmcs_field_to_offset_table) > SHRT_MAX); + unsigned index = VMCS_FIELD_INDEX(field); + unsigned type = VMCS_FIELD_TYPE(field); + unsigned width = VMCS_FIELD_WIDTH(field); + short offset; - if (field >= ARRAY_SIZE(vmcs_field_to_offset_table) || - vmcs_field_to_offset_table[field] == 0) + BUILD_BUG_ON(ARRAY_SIZE(vmcs_field_to_offset_table) > + VMCS12_MAX_FIELD_INDEX + 1); + if (VMCS_FIELD_HIGH(field) && width != VMCS_FIELD_WIDTH_U64) return -ENOENT; - return vmcs_field_to_offset_table[field]; + if (index >= ARRAY_SIZE(vmcs_field_to_offset_table)) + return -ENOENT; + + offset = vmcs_field_to_offset_table[index][type][width]; + + if (offset == 0) + return -ENOENT; + + if (VMCS_FIELD_HIGH(field)) + offset += sizeof(u32); + + return offset; } static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu) @@ -4050,23 +4095,9 @@ static void free_kvm_area(void) } } -enum vmcs_field_width { - VMCS_FIELD_WIDTH_U16 = 0, - VMCS_FIELD_WIDTH_U64 = 1, - VMCS_FIELD_WIDTH_U32 = 2, - VMCS_FIELD_WIDTH_NATURAL_WIDTH = 3 -}; - -static inline int vmcs_field_width(unsigned long field) -{ - if (0x1 & field) /* the *_HIGH fields are all 32 bit */ - return VMCS_FIELD_WIDTH_U32; - return (field >> 13) & 0x3 ; -} - static inline int vmcs_field_readonly(unsigned long field) { - return (((field >> 10) & 0x3) == 1); + return VMCS_FIELD_TYPE(field) == VMCS_FIELD_TYPE_INFO; } static void init_vmcs_shadow_fields(void)