From patchwork Mon Feb 3 14:43:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 11362827 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 56842139A for ; Mon, 3 Feb 2020 14:45:03 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 279112082E for ; Mon, 3 Feb 2020 14:45:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="K60vhV/k" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 279112082E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iycxF-0006Hj-KY; Mon, 03 Feb 2020 14:44:01 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iycxE-0006H7-7E for xen-devel@lists.xenproject.org; Mon, 03 Feb 2020 14:44:00 +0000 X-Inumbo-ID: 95ab8e2e-4693-11ea-8e6a-12813bfff9fa Received: from esa6.hc3370-68.iphmx.com (unknown [216.71.155.175]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 95ab8e2e-4693-11ea-8e6a-12813bfff9fa; Mon, 03 Feb 2020 14:43:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1580741027; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=XGCP2UQj7McQZRN9P3GDAy1a6u80rdEVPNlJzwemXzI=; b=K60vhV/kZ5JJBcEyxc2NYKqRhVb2wwAAIZP5/NjMuhxPRiuU23alTPn7 uHI6XzDTVFPUBnL8ZxjBdDiu4EW5ZZBBJ81z3EI+hF+tTb5NuwpGOuk2E a8/efpEWHO9i7GpDhvPt/1nI4reW5cdorPtJTRk8XHiQGXJQ2T9qSkjUx g=; Authentication-Results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=andrew.cooper3@citrix.com; spf=Pass smtp.mailfrom=Andrew.Cooper3@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa6.hc3370-68.iphmx.com: no sender authenticity information available from domain of andrew.cooper3@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="andrew.cooper3@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa6.hc3370-68.iphmx.com: domain of Andrew.Cooper3@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="Andrew.Cooper3@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ip4:168.245.78.127 ~all" Received-SPF: None (esa6.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: AcpfAQDJWKUmZ/gkd5VvU2bbJQppIbbpQjm2pY+dUhnzI0p+Oq9V9eshFruuOEwi5tttYVeUYg pkVwNkrwoQNXkCnf47h4plLR9VMvalMn9S/kS0xS/2jfEKwp6D61dlQQo+nSyhG0KAxzSqy6JQ WsD25S/1Wi+UZgwmuKStNiYfJiIyUVziPZDA4yn4kJ7ujoIg2AuLFuhmebdBEHRpqhMbzxBCEJ PO3LxOOEaaOtbBTvbV8XwbVfv9BloSb7MApv4Z+Ym2ONn1eVREOhCjI0BF7ZztrDeBZH1zhrQg L60= X-SBRS: 2.7 X-MesageID: 12285436 X-Ironport-Server: esa6.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.70,398,1574139600"; d="scan'208";a="12285436" From: Andrew Cooper To: Xen-devel Date: Mon, 3 Feb 2020 14:43:37 +0000 Message-ID: <20200203144340.4614-2-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200203144340.4614-1-andrew.cooper3@citrix.com> References: <20200203144340.4614-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 1/4] AMD/IOMMU: Move headers to be local X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: George Dunlap , Andrew Cooper , Wei Liu , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" We currently have amd-iommu-defs.h, amd-iommu-proto.h and amd-iommu.h, and no references outside of the AMD IOMMU driver. Keep iommu-defs.h as is, but merge amd-iommu.h and amd-iommu-proto.h to just iommu.h, and move them both into drivers/passthrough/amd/. (While merging, drop the bogus #pragma pack around the *_entry structures.) Take the opportunity to trim the include lists, including x86/mm/p2m.c which (AFAICT) hasn't needed this include since c/s aef3f2275 "x86/mm/p2m: break into common, pt-implementation and pod parts" in 2011. No functional change. Signed-off-by: Andrew Cooper Acked-by: George Dunlap Acked-by: Jan Beulich --- CC: Jan Beulich CC: Wei Liu CC: Roger Pau Monné CC: George Dunlap --- xen/arch/x86/mm/p2m.c | 1 - .../passthrough/amd/iommu-defs.h} | 6 +- .../passthrough/amd/iommu.h} | 179 ++++++++++++++++++- xen/drivers/passthrough/amd/iommu_acpi.c | 7 +- xen/drivers/passthrough/amd/iommu_cmd.c | 4 +- xen/drivers/passthrough/amd/iommu_detect.c | 7 +- xen/drivers/passthrough/amd/iommu_guest.c | 4 +- xen/drivers/passthrough/amd/iommu_init.c | 13 +- xen/drivers/passthrough/amd/iommu_intr.c | 9 +- xen/drivers/passthrough/amd/iommu_map.c | 8 +- xen/drivers/passthrough/amd/pci_amd_iommu.c | 9 +- xen/include/asm-x86/amd-iommu.h | 190 --------------------- 12 files changed, 194 insertions(+), 243 deletions(-) rename xen/{include/asm-x86/hvm/svm/amd-iommu-defs.h => drivers/passthrough/amd/iommu-defs.h} (99%) rename xen/{include/asm-x86/hvm/svm/amd-iommu-proto.h => drivers/passthrough/amd/iommu.h} (70%) delete mode 100644 xen/include/asm-x86/amd-iommu.h diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index def13f657b..fd9f09536d 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h b/xen/drivers/passthrough/amd/iommu-defs.h similarity index 99% rename from xen/include/asm-x86/hvm/svm/amd-iommu-defs.h rename to xen/drivers/passthrough/amd/iommu-defs.h index 78368f16d9..f8b62cb033 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +++ b/xen/drivers/passthrough/amd/iommu-defs.h @@ -17,8 +17,8 @@ * along with this program; If not, see . */ -#ifndef _ASM_X86_64_AMD_IOMMU_DEFS_H -#define _ASM_X86_64_AMD_IOMMU_DEFS_H +#ifndef AMD_IOMMU_DEFS_H +#define AMD_IOMMU_DEFS_H /* IOMMU Command Buffer entries: in power of 2 increments, minimum of 256 */ #define IOMMU_CMD_BUFFER_DEFAULT_ENTRIES 512 @@ -506,7 +506,7 @@ struct amd_iommu_pte { #define IOMMU_REG_BASE_ADDR_HIGH_MASK 0x000FFFFF #define IOMMU_REG_BASE_ADDR_HIGH_SHIFT 0 -#endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */ +#endif /* AMD_IOMMU_DEFS_H */ /* * Local variables: diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h b/xen/drivers/passthrough/amd/iommu.h similarity index 70% rename from xen/include/asm-x86/hvm/svm/amd-iommu-proto.h rename to xen/drivers/passthrough/amd/iommu.h index b5c0d50119..f590de8cbf 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +++ b/xen/drivers/passthrough/amd/iommu.h @@ -16,15 +16,180 @@ * You should have received a copy of the GNU General Public License * along with this program; If not, see . */ - -#ifndef _ASM_X86_64_AMD_IOMMU_PROTO_H -#define _ASM_X86_64_AMD_IOMMU_PROTO_H - +#ifndef AMD_IOMMU_H +#define AMD_IOMMU_H + +#include +#include +#include +#include +#include #include -#include -#include #include +#include +#include + +#include "iommu-defs.h" + +#define iommu_found() (!list_empty(&amd_iommu_head)) + +extern struct list_head amd_iommu_head; + +typedef struct event_entry +{ + uint32_t data[4]; +} event_entry_t; + +typedef struct ppr_entry +{ + uint32_t data[4]; +} ppr_entry_t; + +typedef struct cmd_entry +{ + uint32_t data[4]; +} cmd_entry_t; + +struct table_struct { + void *buffer; + unsigned long entries; + unsigned long alloc_size; +}; + +struct ring_buffer { + void *buffer; + unsigned long entries; + unsigned long alloc_size; + uint32_t tail; + uint32_t head; + spinlock_t lock; /* protect buffer pointers */ +}; + +typedef struct iommu_cap { + uint32_t header; /* offset 00h */ + uint32_t base_low; /* offset 04h */ + uint32_t base_hi; /* offset 08h */ + uint32_t range; /* offset 0Ch */ + uint32_t misc; /* offset 10h */ +} iommu_cap_t; + +struct amd_iommu { + struct list_head list; + spinlock_t lock; /* protect iommu */ + + u16 seg; + u16 bdf; + struct msi_desc msi; + + u16 cap_offset; + iommu_cap_t cap; + + u8 ht_flags; + union amd_iommu_ext_features features; + + void *mmio_base; + unsigned long mmio_base_phys; + + union amd_iommu_control ctrl; + + struct table_struct dev_table; + struct ring_buffer cmd_buffer; + struct ring_buffer event_log; + struct ring_buffer ppr_log; + + int exclusion_enable; + int exclusion_allow_all; + uint64_t exclusion_base; + uint64_t exclusion_limit; + + int enabled; + + struct list_head ats_devices; +}; + +struct ivrs_mappings { + uint16_t dte_requestor_id; + bool valid:1; + bool dte_allow_exclusion:1; + bool unity_map_enable:1; + bool write_permission:1; + bool read_permission:1; + + /* ivhd device data settings */ + uint8_t device_flags; + + unsigned long addr_range_start; + unsigned long addr_range_length; + struct amd_iommu *iommu; + + /* per device interrupt remapping table */ + void *intremap_table; + unsigned long *intremap_inuse; + spinlock_t intremap_lock; +}; + +extern unsigned int ivrs_bdf_entries; +extern u8 ivhd_type; + +struct ivrs_mappings *get_ivrs_mappings(u16 seg); +int iterate_ivrs_mappings(int (*)(u16 seg, struct ivrs_mappings *)); +int iterate_ivrs_entries(int (*)(const struct amd_iommu *, + struct ivrs_mappings *, uint16_t)); + +/* iommu tables in guest space */ +struct mmio_reg { + uint32_t lo; + uint32_t hi; +}; + +struct guest_dev_table { + struct mmio_reg reg_base; + uint32_t size; +}; + +struct guest_buffer { + struct mmio_reg reg_base; + struct mmio_reg reg_tail; + struct mmio_reg reg_head; + uint32_t entries; +}; + +struct guest_iommu_msi { + uint8_t vector; + uint8_t dest; + uint8_t dest_mode; + uint8_t delivery_mode; + uint8_t trig_mode; +}; + +/* virtual IOMMU structure */ +struct guest_iommu { + + struct domain *domain; + spinlock_t lock; + bool_t enabled; + + struct guest_dev_table dev_table; + struct guest_buffer cmd_buffer; + struct guest_buffer event_log; + struct guest_buffer ppr_log; + + struct tasklet cmd_buffer_tasklet; + + uint64_t mmio_base; /* MMIO base address */ + + /* MMIO regs */ + union amd_iommu_control reg_ctrl; /* MMIO offset 0018h */ + struct mmio_reg reg_status; /* MMIO offset 2020h */ + union amd_iommu_ext_features reg_ext_feature; /* MMIO offset 0030h */ + + /* guest interrupt settings */ + struct guest_iommu_msi msi; +}; + +extern bool_t iommuv2_enabled; + struct acpi_ivrs_hardware; #define for_each_amd_iommu(amd_iommu) \ @@ -281,4 +446,4 @@ static inline void iommu_set_addr_hi_to_reg(uint32_t *reg, uint32_t addr) IOMMU_REG_BASE_ADDR_HIGH_SHIFT, reg); } -#endif /* _ASM_X86_64_AMD_IOMMU_PROTO_H */ +#endif /* AMD_IOMMU_H */ diff --git a/xen/drivers/passthrough/amd/iommu_acpi.c b/xen/drivers/passthrough/amd/iommu_acpi.c index 6c5f8e46ec..f4abbfd9dc 100644 --- a/xen/drivers/passthrough/amd/iommu_acpi.c +++ b/xen/drivers/passthrough/amd/iommu_acpi.c @@ -17,13 +17,12 @@ * along with this program; If not, see . */ -#include #include #include -#include + #include -#include -#include + +#include "iommu.h" /* Some helper structures, particularly to deal with ranges. */ diff --git a/xen/drivers/passthrough/amd/iommu_cmd.c b/xen/drivers/passthrough/amd/iommu_cmd.c index af3a1fb865..92eaab407b 100644 --- a/xen/drivers/passthrough/amd/iommu_cmd.c +++ b/xen/drivers/passthrough/amd/iommu_cmd.c @@ -17,9 +17,7 @@ * along with this program; If not, see . */ -#include -#include -#include +#include "iommu.h" #include "../ats.h" static int queue_iommu_command(struct amd_iommu *iommu, u32 cmd[]) diff --git a/xen/drivers/passthrough/amd/iommu_detect.c b/xen/drivers/passthrough/amd/iommu_detect.c index d782e66eee..8312bb4b6f 100644 --- a/xen/drivers/passthrough/amd/iommu_detect.c +++ b/xen/drivers/passthrough/amd/iommu_detect.c @@ -17,13 +17,10 @@ * along with this program; If not, see . */ -#include #include -#include #include -#include -#include -#include + +#include "iommu.h" static int __init get_iommu_msi_capabilities( u16 seg, u8 bus, u8 dev, u8 func, struct amd_iommu *iommu) diff --git a/xen/drivers/passthrough/amd/iommu_guest.c b/xen/drivers/passthrough/amd/iommu_guest.c index 4ed6519e6e..aaf12fe1cb 100644 --- a/xen/drivers/passthrough/amd/iommu_guest.c +++ b/xen/drivers/passthrough/amd/iommu_guest.c @@ -16,11 +16,9 @@ * along with this program; If not, see . */ -#include #include -#include -#include +#include "iommu.h" #define IOMMU_MMIO_SIZE 0x8000 #define IOMMU_MMIO_PAGE_NR 0x8 diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c index 2f26fed4a3..0ffc83a843 100644 --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -17,18 +17,11 @@ * along with this program; If not, see . */ -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include + +#include "iommu.h" static int __initdata nr_amd_iommus; static bool __initdata pci_init; diff --git a/xen/drivers/passthrough/amd/iommu_intr.c b/xen/drivers/passthrough/amd/iommu_intr.c index 5e92c023f8..e1cc13b873 100644 --- a/xen/drivers/passthrough/amd/iommu_intr.c +++ b/xen/drivers/passthrough/amd/iommu_intr.c @@ -16,13 +16,12 @@ * along with this program; If not, see . */ -#include -#include -#include -#include -#include #include +#include + +#include "iommu.h" + union irte32 { uint32_t raw; struct { diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c index 4e041b960f..2f3b47b366 100644 --- a/xen/drivers/passthrough/amd/iommu_map.c +++ b/xen/drivers/passthrough/amd/iommu_map.c @@ -18,12 +18,8 @@ */ #include -#include -#include -#include -#include -#include "../ats.h" -#include + +#include "iommu.h" /* Given pfn and page table level, return pde index */ static unsigned int pfn_to_pde_idx(unsigned long pfn, unsigned int level) diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c index dd3401f0dc..3112653960 100644 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -17,15 +17,12 @@ * along with this program; If not, see . */ -#include #include -#include -#include -#include #include + #include -#include -#include + +#include "iommu.h" #include "../ats.h" static bool_t __read_mostly init_done; diff --git a/xen/include/asm-x86/amd-iommu.h b/xen/include/asm-x86/amd-iommu.h deleted file mode 100644 index 83ababdc8c..0000000000 --- a/xen/include/asm-x86/amd-iommu.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2007 Advanced Micro Devices, Inc. - * Author: Leo Duran - * Author: Wei Wang - adapted to xen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; If not, see . - */ -#ifndef _ASM_X86_64_AMD_IOMMU_H -#define _ASM_X86_64_AMD_IOMMU_H - -#include -#include -#include -#include -#include -#include -#include - -#define iommu_found() (!list_empty(&amd_iommu_head)) - -extern struct list_head amd_iommu_head; - -#pragma pack(1) -typedef struct event_entry -{ - uint32_t data[4]; -} event_entry_t; - -typedef struct ppr_entry -{ - uint32_t data[4]; -} ppr_entry_t; - -typedef struct cmd_entry -{ - uint32_t data[4]; -} cmd_entry_t; -#pragma pack() - -struct table_struct { - void *buffer; - unsigned long entries; - unsigned long alloc_size; -}; - -struct ring_buffer { - void *buffer; - unsigned long entries; - unsigned long alloc_size; - uint32_t tail; - uint32_t head; - spinlock_t lock; /* protect buffer pointers */ -}; - -typedef struct iommu_cap { - uint32_t header; /* offset 00h */ - uint32_t base_low; /* offset 04h */ - uint32_t base_hi; /* offset 08h */ - uint32_t range; /* offset 0Ch */ - uint32_t misc; /* offset 10h */ -} iommu_cap_t; - -struct amd_iommu { - struct list_head list; - spinlock_t lock; /* protect iommu */ - - u16 seg; - u16 bdf; - struct msi_desc msi; - - u16 cap_offset; - iommu_cap_t cap; - - u8 ht_flags; - union amd_iommu_ext_features features; - - void *mmio_base; - unsigned long mmio_base_phys; - - union amd_iommu_control ctrl; - - struct table_struct dev_table; - struct ring_buffer cmd_buffer; - struct ring_buffer event_log; - struct ring_buffer ppr_log; - - int exclusion_enable; - int exclusion_allow_all; - uint64_t exclusion_base; - uint64_t exclusion_limit; - - int enabled; - - struct list_head ats_devices; -}; - -struct ivrs_mappings { - uint16_t dte_requestor_id; - bool valid:1; - bool dte_allow_exclusion:1; - bool unity_map_enable:1; - bool write_permission:1; - bool read_permission:1; - - /* ivhd device data settings */ - uint8_t device_flags; - - unsigned long addr_range_start; - unsigned long addr_range_length; - struct amd_iommu *iommu; - - /* per device interrupt remapping table */ - void *intremap_table; - unsigned long *intremap_inuse; - spinlock_t intremap_lock; -}; - -extern unsigned int ivrs_bdf_entries; -extern u8 ivhd_type; - -struct ivrs_mappings *get_ivrs_mappings(u16 seg); -int iterate_ivrs_mappings(int (*)(u16 seg, struct ivrs_mappings *)); -int iterate_ivrs_entries(int (*)(const struct amd_iommu *, - struct ivrs_mappings *, uint16_t)); - -/* iommu tables in guest space */ -struct mmio_reg { - uint32_t lo; - uint32_t hi; -}; - -struct guest_dev_table { - struct mmio_reg reg_base; - uint32_t size; -}; - -struct guest_buffer { - struct mmio_reg reg_base; - struct mmio_reg reg_tail; - struct mmio_reg reg_head; - uint32_t entries; -}; - -struct guest_iommu_msi { - uint8_t vector; - uint8_t dest; - uint8_t dest_mode; - uint8_t delivery_mode; - uint8_t trig_mode; -}; - -/* virtual IOMMU structure */ -struct guest_iommu { - - struct domain *domain; - spinlock_t lock; - bool_t enabled; - - struct guest_dev_table dev_table; - struct guest_buffer cmd_buffer; - struct guest_buffer event_log; - struct guest_buffer ppr_log; - - struct tasklet cmd_buffer_tasklet; - - uint64_t mmio_base; /* MMIO base address */ - - /* MMIO regs */ - union amd_iommu_control reg_ctrl; /* MMIO offset 0018h */ - struct mmio_reg reg_status; /* MMIO offset 2020h */ - union amd_iommu_ext_features reg_ext_feature; /* MMIO offset 0030h */ - - /* guest interrupt settings */ - struct guest_iommu_msi msi; -}; - -extern bool_t iommuv2_enabled; - -#endif /* _ASM_X86_64_AMD_IOMMU_H */ From patchwork Mon Feb 3 14:43:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 11362825 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4BB0814B4 for ; Mon, 3 Feb 2020 14:44:56 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1D4942082E for ; Mon, 3 Feb 2020 14:44:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="FfXh1D4E" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1D4942082E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iycxA-0006Eh-2G; Mon, 03 Feb 2020 14:43:56 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iycx9-0006EN-5m for xen-devel@lists.xenproject.org; Mon, 03 Feb 2020 14:43:55 +0000 X-Inumbo-ID: 94727aae-4693-11ea-8e6a-12813bfff9fa Received: from esa6.hc3370-68.iphmx.com (unknown [216.71.155.175]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 94727aae-4693-11ea-8e6a-12813bfff9fa; Mon, 03 Feb 2020 14:43:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1580741025; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ySpxWaYY87WscRywKVgyPixDepJAUhGcjKyYslrsji4=; b=FfXh1D4EOabDlb6l3pMmzBy6c6iQxokCs2g9oNlkPGQiCtFQ3O1YDb2r 1V9HRvyYr44l6bnDefMivIq2e4XaR4AwfxIpRdkPEwRhX9Rg33dSMxlH8 40kFXhRkkd9g6k00JVttJUcfbxT9HuQuELnpImSHlFZXd8OJFgPEeSIqY A=; Authentication-Results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=andrew.cooper3@citrix.com; spf=Pass smtp.mailfrom=Andrew.Cooper3@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa6.hc3370-68.iphmx.com: no sender authenticity information available from domain of andrew.cooper3@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="andrew.cooper3@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa6.hc3370-68.iphmx.com: domain of Andrew.Cooper3@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="Andrew.Cooper3@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ip4:168.245.78.127 ~all" Received-SPF: None (esa6.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: o63/oPUJvIBOBAK2wgQzS+907ozI3iU36e9J33keAmOiRA6dNr2xHKGoNVKTaminORkPmaWxS8 sq6KYtCr1diHZtkWbBkZrGdsy+9SwA+S8D7j15fBVb88nZYdT+Tyg3LYYxVMlhk0KTMe1xPAPx ie5non7kMv8mpKofs8NPEkAj2RelPBidZYXU8vbufuHjRHRonYlJKTbNV2iMPnaeGxlRDPDkg/ QmGRfYtjdFBKOEmsPq53r5sNIcZGyb5l8pBfk2/Xs3NZuREJ28MeZ8RsrtPQUpl+nYShjbYjaW 4XI= X-SBRS: 2.7 X-MesageID: 12285435 X-Ironport-Server: esa6.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.70,398,1574139600"; d="scan'208";a="12285435" From: Andrew Cooper To: Xen-devel Date: Mon, 3 Feb 2020 14:43:38 +0000 Message-ID: <20200203144340.4614-3-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200203144340.4614-1-andrew.cooper3@citrix.com> References: <20200203144340.4614-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 2/4] AMD/IOMMU: Delete iommu_{get, set, clear}_bit() helpers X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Andrew Cooper , Wei Liu , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" These are obfuscations around simple bit operations, and the compiler really can do a better job when it can see them normally: add/remove: 0/0 grow/shrink: 0/5 up/down: 0/-181 (-181) Function old new delta guest_iommu_add_ppr_log 266 251 -15 guest_iommu_add_event_log 266 251 -15 iommu_reset_log 274 250 -24 guest_iommu_process_command 1602 1544 -58 guest_iommu_mmio_write 1123 1054 -69 Total: Before=3014099, After=3013918, chg -0.01% Drop all status register MASK/SHIFT constants, and enumerate the bits normally. Rename EVENT_OVERFLOW to EVENT_LOG_OVERFLOW for consistency. (The field name in the spec is inconsistent, despite the description referring to an overflow of the event log.) The only semantic change is in iommu_reset_log() where 'run_bit' changes from being a bit position to being a single-bit mask. No functional change. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich --- CC: Jan Beulich CC: Wei Liu CC: Roger Pau Monné --- xen/drivers/passthrough/amd/iommu-defs.h | 34 +++++++++--------------- xen/drivers/passthrough/amd/iommu.h | 15 ----------- xen/drivers/passthrough/amd/iommu_cmd.c | 8 +++--- xen/drivers/passthrough/amd/iommu_guest.c | 43 +++++++++++++------------------ xen/drivers/passthrough/amd/iommu_init.c | 21 +++++++-------- 5 files changed, 43 insertions(+), 78 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu-defs.h b/xen/drivers/passthrough/amd/iommu-defs.h index f8b62cb033..963009de6a 100644 --- a/xen/drivers/passthrough/amd/iommu-defs.h +++ b/xen/drivers/passthrough/amd/iommu-defs.h @@ -437,28 +437,18 @@ union amd_iommu_x2apic_control { /* Status Register*/ #define IOMMU_STATUS_MMIO_OFFSET 0x2020 -#define IOMMU_STATUS_EVENT_OVERFLOW_MASK 0x00000001 -#define IOMMU_STATUS_EVENT_OVERFLOW_SHIFT 0 -#define IOMMU_STATUS_EVENT_LOG_INT_MASK 0x00000002 -#define IOMMU_STATUS_EVENT_LOG_INT_SHIFT 1 -#define IOMMU_STATUS_COMP_WAIT_INT_MASK 0x00000004 -#define IOMMU_STATUS_COMP_WAIT_INT_SHIFT 2 -#define IOMMU_STATUS_EVENT_LOG_RUN_MASK 0x00000008 -#define IOMMU_STATUS_EVENT_LOG_RUN_SHIFT 3 -#define IOMMU_STATUS_CMD_BUFFER_RUN_MASK 0x00000010 -#define IOMMU_STATUS_CMD_BUFFER_RUN_SHIFT 4 -#define IOMMU_STATUS_PPR_LOG_OVERFLOW_MASK 0x00000020 -#define IOMMU_STATUS_PPR_LOG_OVERFLOW_SHIFT 5 -#define IOMMU_STATUS_PPR_LOG_INT_MASK 0x00000040 -#define IOMMU_STATUS_PPR_LOG_INT_SHIFT 6 -#define IOMMU_STATUS_PPR_LOG_RUN_MASK 0x00000080 -#define IOMMU_STATUS_PPR_LOG_RUN_SHIFT 7 -#define IOMMU_STATUS_GAPIC_LOG_OVERFLOW_MASK 0x00000100 -#define IOMMU_STATUS_GAPIC_LOG_OVERFLOW_SHIFT 8 -#define IOMMU_STATUS_GAPIC_LOG_INT_MASK 0x00000200 -#define IOMMU_STATUS_GAPIC_LOG_INT_SHIFT 9 -#define IOMMU_STATUS_GAPIC_LOG_RUN_MASK 0x00000400 -#define IOMMU_STATUS_GAPIC_LOG_RUN_SHIFT 10 + +#define IOMMU_STATUS_EVENT_LOG_OVERFLOW 0x00000001 +#define IOMMU_STATUS_EVENT_LOG_INT 0x00000002 +#define IOMMU_STATUS_COMP_WAIT_INT 0x00000004 +#define IOMMU_STATUS_EVENT_LOG_RUN 0x00000008 +#define IOMMU_STATUS_CMD_BUFFER_RUN 0x00000010 +#define IOMMU_STATUS_PPR_LOG_OVERFLOW 0x00000020 +#define IOMMU_STATUS_PPR_LOG_INT 0x00000040 +#define IOMMU_STATUS_PPR_LOG_RUN 0x00000080 +#define IOMMU_STATUS_GAPIC_LOG_OVERFLOW 0x00000100 +#define IOMMU_STATUS_GAPIC_LOG_INT 0x00000200 +#define IOMMU_STATUS_GAPIC_LOG_RUN 0x00000400 /* I/O Page Table */ #define IOMMU_PAGE_TABLE_ENTRY_SIZE 8 diff --git a/xen/drivers/passthrough/amd/iommu.h b/xen/drivers/passthrough/amd/iommu.h index f590de8cbf..81b6812d3a 100644 --- a/xen/drivers/passthrough/amd/iommu.h +++ b/xen/drivers/passthrough/amd/iommu.h @@ -374,21 +374,6 @@ static inline void __free_amd_iommu_tables(void *table, int order) free_xenheap_pages(table, order); } -static inline void iommu_set_bit(uint32_t *reg, uint32_t bit) -{ - set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, *reg, 1U << bit, bit, reg); -} - -static inline void iommu_clear_bit(uint32_t *reg, uint32_t bit) -{ - set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, *reg, 1U << bit, bit, reg); -} - -static inline uint32_t iommu_get_bit(uint32_t reg, uint32_t bit) -{ - return get_field_from_reg_u32(reg, 1U << bit, bit); -} - static inline int iommu_has_cap(struct amd_iommu *iommu, uint32_t bit) { return !!(iommu->cap.header & (1u << bit)); diff --git a/xen/drivers/passthrough/amd/iommu_cmd.c b/xen/drivers/passthrough/amd/iommu_cmd.c index 92eaab407b..166f0e7263 100644 --- a/xen/drivers/passthrough/amd/iommu_cmd.c +++ b/xen/drivers/passthrough/amd/iommu_cmd.c @@ -68,7 +68,7 @@ static void flush_command_buffer(struct amd_iommu *iommu) int loop_count, comp_wait; /* RW1C 'ComWaitInt' in status register */ - writel(IOMMU_STATUS_COMP_WAIT_INT_MASK, + writel(IOMMU_STATUS_COMP_WAIT_INT, iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); /* send an empty COMPLETION_WAIT command to flush command buffer */ @@ -85,16 +85,14 @@ static void flush_command_buffer(struct amd_iommu *iommu) loop_count = 1000; do { status = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); - comp_wait = get_field_from_reg_u32(status, - IOMMU_STATUS_COMP_WAIT_INT_MASK, - IOMMU_STATUS_COMP_WAIT_INT_SHIFT); + comp_wait = status & IOMMU_STATUS_COMP_WAIT_INT; --loop_count; } while ( !comp_wait && loop_count ); if ( comp_wait ) { /* RW1C 'ComWaitInt' in status register */ - writel(IOMMU_STATUS_COMP_WAIT_INT_MASK, + writel(IOMMU_STATUS_COMP_WAIT_INT, iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); return; } diff --git a/xen/drivers/passthrough/amd/iommu_guest.c b/xen/drivers/passthrough/amd/iommu_guest.c index aaf12fe1cb..d05901d348 100644 --- a/xen/drivers/passthrough/amd/iommu_guest.c +++ b/xen/drivers/passthrough/amd/iommu_guest.c @@ -30,12 +30,6 @@ #define GUEST_ADDRESS_SIZE_6_LEVEL 0x2 #define HOST_ADDRESS_SIZE_6_LEVEL 0x2 -#define guest_iommu_set_status(iommu, bit) \ - iommu_set_bit(&((iommu)->reg_status.lo), bit) - -#define guest_iommu_clear_status(iommu, bit) \ - iommu_clear_bit(&((iommu)->reg_status.lo), bit) - #define reg_to_u64(reg) (((uint64_t)reg.hi << 32) | reg.lo ) #define u64_to_reg(reg, val) \ do \ @@ -183,7 +177,7 @@ void guest_iommu_add_ppr_log(struct domain *d, u32 entry[]) if ( ++tail >= iommu->ppr_log.entries ) { tail = 0; - guest_iommu_set_status(iommu, IOMMU_STATUS_PPR_LOG_OVERFLOW_SHIFT); + iommu->reg_status.lo |= IOMMU_STATUS_PPR_LOG_OVERFLOW; } iommu_set_rb_pointer(&iommu->ppr_log.reg_tail.lo, tail); unmap_domain_page(log_base); @@ -231,7 +225,7 @@ void guest_iommu_add_event_log(struct domain *d, u32 entry[]) if ( ++tail >= iommu->event_log.entries ) { tail = 0; - guest_iommu_set_status(iommu, IOMMU_STATUS_EVENT_OVERFLOW_SHIFT); + iommu->reg_status.lo |= IOMMU_STATUS_EVENT_LOG_OVERFLOW; } iommu_set_rb_pointer(&iommu->event_log.reg_tail.lo, tail); @@ -322,11 +316,11 @@ static int do_completion_wait(struct domain *d, cmd_entry_t *cmd) iommu = domain_iommu(d); - i = iommu_get_bit(cmd->data[0], IOMMU_COMP_WAIT_I_FLAG_SHIFT); - s = iommu_get_bit(cmd->data[0], IOMMU_COMP_WAIT_S_FLAG_SHIFT); + i = cmd->data[0] & IOMMU_COMP_WAIT_I_FLAG_MASK; + s = cmd->data[0] & IOMMU_COMP_WAIT_S_FLAG_MASK; if ( i ) - guest_iommu_set_status(iommu, IOMMU_STATUS_COMP_WAIT_INT_SHIFT); + iommu->reg_status.lo |= IOMMU_STATUS_COMP_WAIT_INT; if ( s ) { @@ -352,8 +346,7 @@ static int do_completion_wait(struct domain *d, cmd_entry_t *cmd) unmap_domain_page(vaddr); } - com_wait_int = iommu_get_bit(iommu->reg_status.lo, - IOMMU_STATUS_COMP_WAIT_INT_SHIFT); + com_wait_int = iommu->reg_status.lo & IOMMU_STATUS_COMP_WAIT_INT; if ( iommu->reg_ctrl.com_wait_int_en && com_wait_int ) guest_iommu_deliver_msi(d); @@ -539,16 +532,16 @@ static int guest_iommu_write_ctrl(struct guest_iommu *iommu, uint64_t val) { guest_iommu_enable_ring_buffer(iommu, &iommu->event_log, sizeof(event_entry_t)); - guest_iommu_set_status(iommu, IOMMU_STATUS_EVENT_LOG_RUN_SHIFT); - guest_iommu_clear_status(iommu, IOMMU_STATUS_EVENT_OVERFLOW_SHIFT); + iommu->reg_status.lo |= IOMMU_STATUS_EVENT_LOG_RUN; + iommu->reg_status.lo &= ~IOMMU_STATUS_EVENT_LOG_OVERFLOW; } if ( newctrl.iommu_en && newctrl.ppr_en && newctrl.ppr_log_en ) { guest_iommu_enable_ring_buffer(iommu, &iommu->ppr_log, sizeof(ppr_entry_t)); - guest_iommu_set_status(iommu, IOMMU_STATUS_PPR_LOG_RUN_SHIFT); - guest_iommu_clear_status(iommu, IOMMU_STATUS_PPR_LOG_OVERFLOW_SHIFT); + iommu->reg_status.lo |= IOMMU_STATUS_PPR_LOG_RUN; + iommu->reg_status.lo &= ~IOMMU_STATUS_PPR_LOG_OVERFLOW; } if ( newctrl.iommu_en && iommu->reg_ctrl.cmd_buf_en && @@ -559,7 +552,7 @@ static int guest_iommu_write_ctrl(struct guest_iommu *iommu, uint64_t val) } if ( iommu->reg_ctrl.event_log_en && !newctrl.event_log_en ) - guest_iommu_clear_status(iommu, IOMMU_STATUS_EVENT_LOG_RUN_SHIFT); + iommu->reg_status.lo &= ~IOMMU_STATUS_EVENT_LOG_RUN; if ( iommu->reg_ctrl.iommu_en && !newctrl.iommu_en ) guest_iommu_disable(iommu); @@ -698,13 +691,13 @@ static void guest_iommu_mmio_write64(struct guest_iommu *iommu, u64_to_reg(&iommu->ppr_log.reg_tail, val); break; case IOMMU_STATUS_MMIO_OFFSET: - val &= IOMMU_STATUS_EVENT_OVERFLOW_MASK | - IOMMU_STATUS_EVENT_LOG_INT_MASK | - IOMMU_STATUS_COMP_WAIT_INT_MASK | - IOMMU_STATUS_PPR_LOG_OVERFLOW_MASK | - IOMMU_STATUS_PPR_LOG_INT_MASK | - IOMMU_STATUS_GAPIC_LOG_OVERFLOW_MASK | - IOMMU_STATUS_GAPIC_LOG_INT_MASK; + val &= IOMMU_STATUS_EVENT_LOG_OVERFLOW | + IOMMU_STATUS_EVENT_LOG_INT | + IOMMU_STATUS_COMP_WAIT_INT | + IOMMU_STATUS_PPR_LOG_OVERFLOW | + IOMMU_STATUS_PPR_LOG_INT | + IOMMU_STATUS_GAPIC_LOG_OVERFLOW | + IOMMU_STATUS_GAPIC_LOG_INT; u64_to_reg(&iommu->reg_status, reg_to_u64(iommu->reg_status) & ~val); break; diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c index 0ffc83a843..7bf6fef3ee 100644 --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -351,13 +351,12 @@ static void iommu_reset_log(struct amd_iommu *iommu, BUG_ON(!iommu || ((log != &iommu->event_log) && (log != &iommu->ppr_log))); run_bit = ( log == &iommu->event_log ) ? - IOMMU_STATUS_EVENT_LOG_RUN_SHIFT : - IOMMU_STATUS_PPR_LOG_RUN_SHIFT; + IOMMU_STATUS_EVENT_LOG_RUN : IOMMU_STATUS_PPR_LOG_RUN; /* wait until EventLogRun bit = 0 */ do { entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); - log_run = iommu_get_bit(entry, run_bit); + log_run = entry & run_bit; loop_count--; } while ( log_run && loop_count ); @@ -371,8 +370,8 @@ static void iommu_reset_log(struct amd_iommu *iommu, ctrl_func(iommu, IOMMU_CONTROL_DISABLED); /* RW1C overflow bit */ - writel(log == &iommu->event_log ? IOMMU_STATUS_EVENT_OVERFLOW_MASK - : IOMMU_STATUS_PPR_LOG_OVERFLOW_MASK, + writel(log == &iommu->event_log ? IOMMU_STATUS_EVENT_LOG_OVERFLOW + : IOMMU_STATUS_PPR_LOG_OVERFLOW, iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); /*reset event log base address */ @@ -589,7 +588,7 @@ static void iommu_check_event_log(struct amd_iommu *iommu) unsigned long flags; /* RW1C interrupt status bit */ - writel(IOMMU_STATUS_EVENT_LOG_INT_MASK, + writel(IOMMU_STATUS_EVENT_LOG_INT, iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); iommu_read_log(iommu, &iommu->event_log, @@ -599,7 +598,7 @@ static void iommu_check_event_log(struct amd_iommu *iommu) /* Check event overflow. */ entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); - if ( iommu_get_bit(entry, IOMMU_STATUS_EVENT_OVERFLOW_SHIFT) ) + if ( entry & IOMMU_STATUS_EVENT_LOG_OVERFLOW ) iommu_reset_log(iommu, &iommu->event_log, set_iommu_event_log_control); else { @@ -621,7 +620,7 @@ static void iommu_check_event_log(struct amd_iommu *iommu) * Re-check to make sure the bit has been cleared. */ entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); - if ( entry & IOMMU_STATUS_EVENT_LOG_INT_MASK ) + if ( entry & IOMMU_STATUS_EVENT_LOG_INT ) tasklet_schedule(&amd_iommu_irq_tasklet); spin_unlock_irqrestore(&iommu->lock, flags); @@ -678,7 +677,7 @@ static void iommu_check_ppr_log(struct amd_iommu *iommu) unsigned long flags; /* RW1C interrupt status bit */ - writel(IOMMU_STATUS_PPR_LOG_INT_MASK, + writel(IOMMU_STATUS_PPR_LOG_INT, iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); iommu_read_log(iommu, &iommu->ppr_log, @@ -688,7 +687,7 @@ static void iommu_check_ppr_log(struct amd_iommu *iommu) /* Check event overflow. */ entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); - if ( iommu_get_bit(entry, IOMMU_STATUS_PPR_LOG_OVERFLOW_SHIFT) ) + if ( entry & IOMMU_STATUS_PPR_LOG_OVERFLOW ) iommu_reset_log(iommu, &iommu->ppr_log, set_iommu_ppr_log_control); else { @@ -710,7 +709,7 @@ static void iommu_check_ppr_log(struct amd_iommu *iommu) * Re-check to make sure the bit has been cleared. */ entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); - if ( entry & IOMMU_STATUS_PPR_LOG_INT_MASK ) + if ( entry & IOMMU_STATUS_PPR_LOG_INT ) tasklet_schedule(&amd_iommu_irq_tasklet); spin_unlock_irqrestore(&iommu->lock, flags); From patchwork Mon Feb 3 14:43:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 11362823 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8DBA31395 for ; Mon, 3 Feb 2020 14:44:52 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5F4822082E for ; Mon, 3 Feb 2020 14:44:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="AD+VStpo" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5F4822082E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iycx5-0006Ck-N1; Mon, 03 Feb 2020 14:43:51 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iycx4-0006C1-5j for xen-devel@lists.xenproject.org; Mon, 03 Feb 2020 14:43:50 +0000 X-Inumbo-ID: 94727aaf-4693-11ea-8e6a-12813bfff9fa Received: from esa1.hc3370-68.iphmx.com (unknown [216.71.145.142]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 94727aaf-4693-11ea-8e6a-12813bfff9fa; Mon, 03 Feb 2020 14:43:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1580741026; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=FfU9MZI/ojg3SsfVC2RfFMTHV6FmZYYVJt+bQ8PV4Hs=; b=AD+VStpozkpboFoX82ugAZhZDqssrt+QBecqWR63eIfFuG2efwOPFvQz Oy3ey/Aub8B57b2vs58pLU1YuBIkPp05EfeSekEZMmK407US4Qg+L6Rfj FeOGuNMujhHcPj1og69PUfmE9LCn0GXBFIa/4WjcTDqLkMx9gdqrQ9zMb c=; Authentication-Results: esa1.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=andrew.cooper3@citrix.com; spf=Pass smtp.mailfrom=Andrew.Cooper3@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa1.hc3370-68.iphmx.com: no sender authenticity information available from domain of andrew.cooper3@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="andrew.cooper3@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa1.hc3370-68.iphmx.com: domain of Andrew.Cooper3@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="Andrew.Cooper3@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ip4:168.245.78.127 ~all" Received-SPF: None (esa1.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa1.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: 96PiWZXpb9fwwkrcodzvYVTc3OkL6jPTXtogDhEkU9J6vS9DPN5M+W4wyewLh90NSQoQM6LyRJ 8Q4bawlW5xT286yStSE4oWO8tWP0Gfx1DU4TIYx2eEbWp7tafvWCvtm/L4r3cPLYbWfAT3mTSb SiQSJdiMtuPz/PkURZmqj1RzUbDYsR8wOHFY3/bBZz/L04gVZ4FTLFQDcTzweHsMtcAXNI4ZKn pBAf6StDnpOmF+e2Mh/xxJLqw4pt663VK0wDHdFdd6D5crncpFc+gZeCXlytvCclFHvVIshVtc WVw= X-SBRS: 2.7 X-MesageID: 12023812 X-Ironport-Server: esa1.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.70,398,1574139600"; d="scan'208";a="12023812" From: Andrew Cooper To: Xen-devel Date: Mon, 3 Feb 2020 14:43:39 +0000 Message-ID: <20200203144340.4614-4-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200203144340.4614-1-andrew.cooper3@citrix.com> References: <20200203144340.4614-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 3/4] AMD/IOMMU: Treat guest head/tail pointers as byte offsets X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Andrew Cooper , Wei Liu , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" The MMIO registers as already byte offsets. By masking out the reserved bits suitably in guest_iommu_mmio_write64(), we can use the values directly, instead of masking/shifting on every use. Store the buffer size, rather than the number of entries, to keep the same units for comparison purposes. This simplifies guest_iommu_get_table_mfn() by dropping the entry_size parameter, and simplifies the map_domain_page() handling by being able to drop the log_base variables. No functional change. Signed-off-by: Andrew Cooper Acked-by: Jan Beulich --- CC: Jan Beulich CC: Wei Liu CC: Roger Pau Monné Untested - this is all dead code, and there are plenty of security issues which need adjusting before it can start being used again. --- xen/drivers/passthrough/amd/iommu.h | 2 +- xen/drivers/passthrough/amd/iommu_guest.c | 85 +++++++++++++++---------------- 2 files changed, 42 insertions(+), 45 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu.h b/xen/drivers/passthrough/amd/iommu.h index 81b6812d3a..0b598d06f8 100644 --- a/xen/drivers/passthrough/amd/iommu.h +++ b/xen/drivers/passthrough/amd/iommu.h @@ -152,7 +152,7 @@ struct guest_buffer { struct mmio_reg reg_base; struct mmio_reg reg_tail; struct mmio_reg reg_head; - uint32_t entries; + uint32_t size; }; struct guest_iommu_msi { diff --git a/xen/drivers/passthrough/amd/iommu_guest.c b/xen/drivers/passthrough/amd/iommu_guest.c index d05901d348..ef9c4a4d29 100644 --- a/xen/drivers/passthrough/amd/iommu_guest.c +++ b/xen/drivers/passthrough/amd/iommu_guest.c @@ -103,14 +103,13 @@ static void guest_iommu_deliver_msi(struct domain *d) static unsigned long guest_iommu_get_table_mfn(struct domain *d, uint64_t base_raw, - unsigned int entry_size, unsigned int pos) { unsigned long idx, gfn, mfn; p2m_type_t p2mt; gfn = get_gfn_from_base_reg(base_raw); - idx = (pos * entry_size) >> PAGE_SHIFT; + idx = pos >> PAGE_SHIFT; mfn = mfn_x(get_gfn(d, gfn + idx, &p2mt)); put_gfn(d, gfn); @@ -133,14 +132,14 @@ static void guest_iommu_enable_ring_buffer(struct guest_iommu *iommu, uint32_t length_raw = get_field_from_reg_u32(buffer->reg_base.hi, RING_BF_LENGTH_MASK, RING_BF_LENGTH_SHIFT); - buffer->entries = 1 << length_raw; + buffer->size = entry_size << length_raw; } void guest_iommu_add_ppr_log(struct domain *d, u32 entry[]) { uint16_t gdev_id; unsigned long mfn, tail, head; - ppr_entry_t *log, *log_base; + ppr_entry_t *log; struct guest_iommu *iommu; if ( !is_hvm_domain(d) ) @@ -150,10 +149,10 @@ void guest_iommu_add_ppr_log(struct domain *d, u32 entry[]) if ( !iommu ) return; - tail = iommu_get_rb_pointer(iommu->ppr_log.reg_tail.lo); - head = iommu_get_rb_pointer(iommu->ppr_log.reg_head.lo); + tail = iommu->ppr_log.reg_tail.lo; + head = iommu->ppr_log.reg_head.lo; - if ( tail >= iommu->ppr_log.entries || head >= iommu->ppr_log.entries ) + if ( tail >= iommu->ppr_log.size || head >= iommu->ppr_log.size ) { AMD_IOMMU_DEBUG("Error: guest iommu ppr log overflows\n"); guest_iommu_disable(iommu); @@ -161,11 +160,10 @@ void guest_iommu_add_ppr_log(struct domain *d, u32 entry[]) } mfn = guest_iommu_get_table_mfn(d, reg_to_u64(iommu->ppr_log.reg_base), - sizeof(ppr_entry_t), tail); + tail); ASSERT(mfn_valid(_mfn(mfn))); - log_base = map_domain_page(_mfn(mfn)); - log = log_base + tail % (PAGE_SIZE / sizeof(ppr_entry_t)); + log = map_domain_page(_mfn(mfn)) + (tail & PAGE_MASK); /* Convert physical device id back into virtual device id */ gdev_id = guest_bdf(d, iommu_get_devid_from_cmd(entry[0])); @@ -174,13 +172,15 @@ void guest_iommu_add_ppr_log(struct domain *d, u32 entry[]) memcpy(log, entry, sizeof(ppr_entry_t)); /* Now shift ppr log tail pointer */ - if ( ++tail >= iommu->ppr_log.entries ) + tail += sizeof(ppr_entry_t); + if ( tail >= iommu->ppr_log.size ) { tail = 0; iommu->reg_status.lo |= IOMMU_STATUS_PPR_LOG_OVERFLOW; } - iommu_set_rb_pointer(&iommu->ppr_log.reg_tail.lo, tail); - unmap_domain_page(log_base); + + iommu->ppr_log.reg_tail.lo = tail; + unmap_domain_page(log); guest_iommu_deliver_msi(d); } @@ -189,7 +189,7 @@ void guest_iommu_add_event_log(struct domain *d, u32 entry[]) { uint16_t dev_id; unsigned long mfn, tail, head; - event_entry_t *log, *log_base; + event_entry_t *log; struct guest_iommu *iommu; if ( !is_hvm_domain(d) ) @@ -199,10 +199,10 @@ void guest_iommu_add_event_log(struct domain *d, u32 entry[]) if ( !iommu ) return; - tail = iommu_get_rb_pointer(iommu->event_log.reg_tail.lo); - head = iommu_get_rb_pointer(iommu->event_log.reg_head.lo); + tail = iommu->event_log.reg_tail.lo; + head = iommu->event_log.reg_head.lo; - if ( tail >= iommu->event_log.entries || head >= iommu->event_log.entries ) + if ( tail >= iommu->event_log.size || head >= iommu->event_log.size ) { AMD_IOMMU_DEBUG("Error: guest iommu event overflows\n"); guest_iommu_disable(iommu); @@ -210,11 +210,10 @@ void guest_iommu_add_event_log(struct domain *d, u32 entry[]) } mfn = guest_iommu_get_table_mfn(d, reg_to_u64(iommu->event_log.reg_base), - sizeof(event_entry_t), tail); + tail); ASSERT(mfn_valid(_mfn(mfn))); - log_base = map_domain_page(_mfn(mfn)); - log = log_base + tail % (PAGE_SIZE / sizeof(event_entry_t)); + log = map_domain_page(_mfn(mfn)) + (tail & PAGE_MASK); /* re-write physical device id into virtual device id */ dev_id = guest_bdf(d, iommu_get_devid_from_cmd(entry[0])); @@ -222,14 +221,15 @@ void guest_iommu_add_event_log(struct domain *d, u32 entry[]) memcpy(log, entry, sizeof(event_entry_t)); /* Now shift event log tail pointer */ - if ( ++tail >= iommu->event_log.entries ) + tail += sizeof(event_entry_t); + if ( tail >= iommu->event_log.size ) { tail = 0; iommu->reg_status.lo |= IOMMU_STATUS_EVENT_LOG_OVERFLOW; } - iommu_set_rb_pointer(&iommu->event_log.reg_tail.lo, tail); - unmap_domain_page(log_base); + iommu->event_log.reg_tail.lo = tail; + unmap_domain_page(log); guest_iommu_deliver_msi(d); } @@ -379,7 +379,7 @@ static int do_invalidate_dte(struct domain *d, cmd_entry_t *cmd) dte_mfn = guest_iommu_get_table_mfn(d, reg_to_u64(g_iommu->dev_table.reg_base), - sizeof(struct amd_iommu_dte), gbdf); + sizeof(struct amd_iommu_dte) * gbdf); ASSERT(mfn_valid(_mfn(dte_mfn))); /* Read guest dte information */ @@ -428,8 +428,8 @@ static int do_invalidate_dte(struct domain *d, cmd_entry_t *cmd) static void guest_iommu_process_command(void *data) { - unsigned long opcode, tail, head, entries_per_page, cmd_mfn; - cmd_entry_t *cmd, *cmd_base; + unsigned long opcode, tail, head, cmd_mfn; + cmd_entry_t *cmd; struct domain *d = data; struct guest_iommu *iommu; @@ -438,34 +438,30 @@ static void guest_iommu_process_command(void *data) if ( !iommu->enabled ) return; - head = iommu_get_rb_pointer(iommu->cmd_buffer.reg_head.lo); - tail = iommu_get_rb_pointer(iommu->cmd_buffer.reg_tail.lo); + head = iommu->cmd_buffer.reg_head.lo; + tail = iommu->cmd_buffer.reg_tail.lo; /* Tail pointer is rolled over by guest driver, value outside * cmd_buffer_entries cause iommu disabled */ - if ( tail >= iommu->cmd_buffer.entries || - head >= iommu->cmd_buffer.entries ) + if ( tail >= iommu->cmd_buffer.size || head >= iommu->cmd_buffer.size ) { AMD_IOMMU_DEBUG("Error: guest iommu cmd buffer overflows\n"); guest_iommu_disable(iommu); return; } - entries_per_page = PAGE_SIZE / sizeof(cmd_entry_t); - while ( head != tail ) { int ret = 0; cmd_mfn = guest_iommu_get_table_mfn(d, reg_to_u64(iommu->cmd_buffer.reg_base), - sizeof(cmd_entry_t), head); + head); ASSERT(mfn_valid(_mfn(cmd_mfn))); - cmd_base = map_domain_page(_mfn(cmd_mfn)); - cmd = cmd_base + head % entries_per_page; + cmd = map_domain_page(_mfn(cmd_mfn)) + (head & PAGE_MASK); opcode = get_field_from_reg_u32(cmd->data[1], IOMMU_CMD_OPCODE_MASK, @@ -498,15 +494,16 @@ static void guest_iommu_process_command(void *data) break; } - unmap_domain_page(cmd_base); - if ( ++head >= iommu->cmd_buffer.entries ) + unmap_domain_page(cmd); + head += sizeof(cmd_entry_t); + if ( head >= iommu->cmd_buffer.size ) head = 0; if ( ret ) guest_iommu_disable(iommu); } /* Now shift cmd buffer head pointer */ - iommu_set_rb_pointer(&iommu->cmd_buffer.reg_head.lo, head); + iommu->cmd_buffer.reg_head.lo = head; return; } @@ -672,23 +669,23 @@ static void guest_iommu_mmio_write64(struct guest_iommu *iommu, guest_iommu_write_ctrl(iommu, val); break; case IOMMU_CMD_BUFFER_HEAD_OFFSET: - u64_to_reg(&iommu->cmd_buffer.reg_head, val); + iommu->cmd_buffer.reg_head.lo = val & IOMMU_RING_BUFFER_PTR_MASK; break; case IOMMU_CMD_BUFFER_TAIL_OFFSET: - u64_to_reg(&iommu->cmd_buffer.reg_tail, val); + iommu->cmd_buffer.reg_tail.lo = val & IOMMU_RING_BUFFER_PTR_MASK; tasklet_schedule(&iommu->cmd_buffer_tasklet); break; case IOMMU_EVENT_LOG_HEAD_OFFSET: - u64_to_reg(&iommu->event_log.reg_head, val); + iommu->event_log.reg_head.lo = val & IOMMU_RING_BUFFER_PTR_MASK; break; case IOMMU_EVENT_LOG_TAIL_OFFSET: - u64_to_reg(&iommu->event_log.reg_tail, val); + iommu->event_log.reg_tail.lo = val & IOMMU_RING_BUFFER_PTR_MASK; break; case IOMMU_PPR_LOG_HEAD_OFFSET: - u64_to_reg(&iommu->ppr_log.reg_head, val); + iommu->ppr_log.reg_head.lo = val & IOMMU_RING_BUFFER_PTR_MASK; break; case IOMMU_PPR_LOG_TAIL_OFFSET: - u64_to_reg(&iommu->ppr_log.reg_tail, val); + iommu->ppr_log.reg_tail.lo = val & IOMMU_RING_BUFFER_PTR_MASK; break; case IOMMU_STATUS_MMIO_OFFSET: val &= IOMMU_STATUS_EVENT_LOG_OVERFLOW | From patchwork Mon Feb 3 14:43:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew Cooper X-Patchwork-Id: 11362821 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 27DEE1395 for ; Mon, 3 Feb 2020 14:44:51 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id EDA4A2082E for ; Mon, 3 Feb 2020 14:44:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="e5USQzLB" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org EDA4A2082E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iycx4-0006C5-AA; Mon, 03 Feb 2020 14:43:50 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iycx2-0006Bh-MI for xen-devel@lists.xenproject.org; Mon, 03 Feb 2020 14:43:48 +0000 X-Inumbo-ID: 95b3aca8-4693-11ea-a933-bc764e2007e4 Received: from esa6.hc3370-68.iphmx.com (unknown [216.71.155.175]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 95b3aca8-4693-11ea-a933-bc764e2007e4; Mon, 03 Feb 2020 14:43:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1580741027; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=rzhlrZ6V5p5NSQFknGK68fglT5wG/u1QFxy5g2VbrtI=; b=e5USQzLBAPYQ4EHrj07WDCKVnmJsZtG0mXfpi0CaTo+q6CbgekeHWIn+ AmkKlwBp7PSscUNwJ0OlhdK1x7KM7qGvahnzZDTvWsz1y7ON1PuDLMdg7 uK3ezTYn7Sd+/sEKcOSarS7FClhEQbUWGm819Dk6QrEf3Bnp1J54sMWXp M=; Authentication-Results: esa6.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=andrew.cooper3@citrix.com; spf=Pass smtp.mailfrom=Andrew.Cooper3@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: None (esa6.hc3370-68.iphmx.com: no sender authenticity information available from domain of andrew.cooper3@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="andrew.cooper3@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa6.hc3370-68.iphmx.com: domain of Andrew.Cooper3@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="Andrew.Cooper3@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ip4:168.245.78.127 ~all" Received-SPF: None (esa6.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa6.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: Att/ZydR5zMLdmObFVHJXIAK1/YyKlZHCudrRw+l2dYYcRUmyVMtKyl22A6qkLt7W0Y1qMTodo sHSEkQBT2ND9Sf9sytTz1ZDrLIuhpbCw1+vUDkqh/H/pT4pTd466t2ma5t21Nz3EEyTuxFdySc CyDTDUaGYJ97aMN5nooijpgO1uG4ZXyfk2AFt3Iq7aREcI4EiOOzyTzeOjDfWA9gUp8pQ+iDCb aUj9kBa5caX0KJfPWfdhG4vnG5Ju03JX5cRCqMMlFGzoXsyW7MhnDPyDmsf+3fzMn88wiJsgtC 3bk= X-SBRS: 2.7 X-MesageID: 12285437 X-Ironport-Server: esa6.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.70,398,1574139600"; d="scan'208";a="12285437" From: Andrew Cooper To: Xen-devel Date: Mon, 3 Feb 2020 14:43:40 +0000 Message-ID: <20200203144340.4614-5-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20200203144340.4614-1-andrew.cooper3@citrix.com> References: <20200203144340.4614-1-andrew.cooper3@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 4/4] AMD/IOMMU: Treat head/tail pointers as byte offsets X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Andrew Cooper , Wei Liu , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" The MMIO registers as already byte offsets. Using them in this form removes the need to shift their values for use. It is also inefficient to store both entries and alloc_size (which differ by a fixed entry_size). Rename alloc_size to size, and drop entries entirely, which simplifies the allocation/deallocation helpers slightly. Mark send_iommu_command() and invalidate_iommu_all() as static, as they have no external declaration or callers. Overall, this simplification allows GCC to optimise sufficiently to construct commands directly in the command ring, rather than on the stack and copying them into place. Signed-off-by: Andrew Cooper --- CC: Jan Beulich CC: Wei Liu CC: Roger Pau Monné Tested on a Rome system. --- xen/drivers/passthrough/amd/iommu-defs.h | 1 - xen/drivers/passthrough/amd/iommu.h | 18 ++---------------- xen/drivers/passthrough/amd/iommu_cmd.c | 20 ++++++++------------ xen/drivers/passthrough/amd/iommu_init.c | 30 +++++++++++++----------------- 4 files changed, 23 insertions(+), 46 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu-defs.h b/xen/drivers/passthrough/amd/iommu-defs.h index 963009de6a..50613ca150 100644 --- a/xen/drivers/passthrough/amd/iommu-defs.h +++ b/xen/drivers/passthrough/amd/iommu-defs.h @@ -481,7 +481,6 @@ struct amd_iommu_pte { #define INV_IOMMU_ALL_PAGES_ADDRESS ((1ULL << 63) - 1) #define IOMMU_RING_BUFFER_PTR_MASK 0x0007FFF0 -#define IOMMU_RING_BUFFER_PTR_SHIFT 4 #define IOMMU_CMD_DEVICE_ID_MASK 0x0000FFFF #define IOMMU_CMD_DEVICE_ID_SHIFT 0 diff --git a/xen/drivers/passthrough/amd/iommu.h b/xen/drivers/passthrough/amd/iommu.h index 0b598d06f8..1abfdc685a 100644 --- a/xen/drivers/passthrough/amd/iommu.h +++ b/xen/drivers/passthrough/amd/iommu.h @@ -58,12 +58,11 @@ struct table_struct { }; struct ring_buffer { + spinlock_t lock; /* protect buffer pointers */ void *buffer; - unsigned long entries; - unsigned long alloc_size; uint32_t tail; uint32_t head; - spinlock_t lock; /* protect buffer pointers */ + uint32_t size; }; typedef struct iommu_cap { @@ -379,19 +378,6 @@ static inline int iommu_has_cap(struct amd_iommu *iommu, uint32_t bit) return !!(iommu->cap.header & (1u << bit)); } -/* access tail or head pointer of ring buffer */ -static inline uint32_t iommu_get_rb_pointer(uint32_t reg) -{ - return get_field_from_reg_u32(reg, IOMMU_RING_BUFFER_PTR_MASK, - IOMMU_RING_BUFFER_PTR_SHIFT); -} - -static inline void iommu_set_rb_pointer(uint32_t *reg, uint32_t val) -{ - set_field_in_reg_u32(val, *reg, IOMMU_RING_BUFFER_PTR_MASK, - IOMMU_RING_BUFFER_PTR_SHIFT, reg); -} - /* access device id field from iommu cmd */ static inline uint16_t iommu_get_devid_from_cmd(uint32_t cmd) { diff --git a/xen/drivers/passthrough/amd/iommu_cmd.c b/xen/drivers/passthrough/amd/iommu_cmd.c index 166f0e7263..24ef59d436 100644 --- a/xen/drivers/passthrough/amd/iommu_cmd.c +++ b/xen/drivers/passthrough/amd/iommu_cmd.c @@ -24,16 +24,14 @@ static int queue_iommu_command(struct amd_iommu *iommu, u32 cmd[]) { uint32_t tail, head; - tail = iommu->cmd_buffer.tail; - if ( ++tail == iommu->cmd_buffer.entries ) + tail = iommu->cmd_buffer.tail + IOMMU_CMD_BUFFER_ENTRY_SIZE; + if ( tail == iommu->cmd_buffer.size ) tail = 0; - head = iommu_get_rb_pointer(readl(iommu->mmio_base + - IOMMU_CMD_BUFFER_HEAD_OFFSET)); + head = readl(iommu->mmio_base + IOMMU_CMD_BUFFER_HEAD_OFFSET); if ( head != tail ) { - memcpy(iommu->cmd_buffer.buffer + - (iommu->cmd_buffer.tail * IOMMU_CMD_BUFFER_ENTRY_SIZE), + memcpy(iommu->cmd_buffer.buffer + iommu->cmd_buffer.tail, cmd, IOMMU_CMD_BUFFER_ENTRY_SIZE); iommu->cmd_buffer.tail = tail; @@ -45,13 +43,11 @@ static int queue_iommu_command(struct amd_iommu *iommu, u32 cmd[]) static void commit_iommu_command_buffer(struct amd_iommu *iommu) { - u32 tail = 0; - - iommu_set_rb_pointer(&tail, iommu->cmd_buffer.tail); - writel(tail, iommu->mmio_base+IOMMU_CMD_BUFFER_TAIL_OFFSET); + writel(iommu->cmd_buffer.tail, + iommu->mmio_base + IOMMU_CMD_BUFFER_TAIL_OFFSET); } -int send_iommu_command(struct amd_iommu *iommu, u32 cmd[]) +static int send_iommu_command(struct amd_iommu *iommu, u32 cmd[]) { if ( queue_iommu_command(iommu, cmd) ) { @@ -261,7 +257,7 @@ static void invalidate_interrupt_table(struct amd_iommu *iommu, u16 device_id) send_iommu_command(iommu, cmd); } -void invalidate_iommu_all(struct amd_iommu *iommu) +static void invalidate_iommu_all(struct amd_iommu *iommu) { u32 cmd[4], entry; diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c index 7bf6fef3ee..cfdeeefc2d 100644 --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -117,7 +117,7 @@ static void register_iommu_cmd_buffer_in_mmio_space(struct amd_iommu *iommu) iommu_set_addr_lo_to_reg(&entry, addr_lo >> PAGE_SHIFT); writel(entry, iommu->mmio_base + IOMMU_CMD_BUFFER_BASE_LOW_OFFSET); - power_of2_entries = get_order_from_bytes(iommu->cmd_buffer.alloc_size) + + power_of2_entries = get_order_from_bytes(iommu->cmd_buffer.size) + IOMMU_CMD_BUFFER_POWER_OF2_ENTRIES_PER_PAGE; entry = 0; @@ -145,7 +145,7 @@ static void register_iommu_event_log_in_mmio_space(struct amd_iommu *iommu) iommu_set_addr_lo_to_reg(&entry, addr_lo >> PAGE_SHIFT); writel(entry, iommu->mmio_base + IOMMU_EVENT_LOG_BASE_LOW_OFFSET); - power_of2_entries = get_order_from_bytes(iommu->event_log.alloc_size) + + power_of2_entries = get_order_from_bytes(iommu->event_log.size) + IOMMU_EVENT_LOG_POWER_OF2_ENTRIES_PER_PAGE; entry = 0; @@ -173,7 +173,7 @@ static void register_iommu_ppr_log_in_mmio_space(struct amd_iommu *iommu) iommu_set_addr_lo_to_reg(&entry, addr_lo >> PAGE_SHIFT); writel(entry, iommu->mmio_base + IOMMU_PPR_LOG_BASE_LOW_OFFSET); - power_of2_entries = get_order_from_bytes(iommu->ppr_log.alloc_size) + + power_of2_entries = get_order_from_bytes(iommu->ppr_log.size) + IOMMU_PPR_LOG_POWER_OF2_ENTRIES_PER_PAGE; entry = 0; @@ -300,7 +300,7 @@ static int iommu_read_log(struct amd_iommu *iommu, unsigned int entry_size, void (*parse_func)(struct amd_iommu *, u32 *)) { - u32 tail, head, *entry, tail_offest, head_offset; + u32 tail, *entry, tail_offest, head_offset; BUG_ON(!iommu || ((log != &iommu->event_log) && (log != &iommu->ppr_log))); @@ -316,22 +316,20 @@ static int iommu_read_log(struct amd_iommu *iommu, IOMMU_PPR_LOG_HEAD_OFFSET; tail = readl(iommu->mmio_base + tail_offest); - tail = iommu_get_rb_pointer(tail); while ( tail != log->head ) { /* read event log entry */ - entry = (u32 *)(log->buffer + log->head * entry_size); + entry = (u32 *)(log->buffer + log->head); parse_func(iommu, entry); - if ( ++log->head == log->entries ) + + log->head += entry_size; + if ( log->head == log->size ) log->head = 0; /* update head pointer */ - head = 0; - iommu_set_rb_pointer(&head, log->head); - - writel(head, iommu->mmio_base + head_offset); + writel(log->head, iommu->mmio_base + head_offset); } spin_unlock(&log->lock); @@ -1001,7 +999,7 @@ static void __init deallocate_buffer(void *buf, unsigned long sz) static void __init deallocate_ring_buffer(struct ring_buffer *ring_buf) { - deallocate_buffer(ring_buf->buffer, ring_buf->alloc_size); + deallocate_buffer(ring_buf->buffer, ring_buf->size); ring_buf->buffer = NULL; ring_buf->head = 0; ring_buf->tail = 0; @@ -1036,11 +1034,9 @@ static void *__init allocate_ring_buffer(struct ring_buffer *ring_buf, ring_buf->tail = 0; spin_lock_init(&ring_buf->lock); - - ring_buf->alloc_size = PAGE_SIZE << get_order_from_bytes(entries * - entry_size); - ring_buf->entries = ring_buf->alloc_size / entry_size; - ring_buf->buffer = allocate_buffer(ring_buf->alloc_size, name, clear); + + ring_buf->size = PAGE_SIZE << get_order_from_bytes(entries * entry_size); + ring_buf->buffer = allocate_buffer(ring_buf->size, name, clear); return ring_buf->buffer; }