Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932758AbcDHMuH (ORCPT ); Fri, 8 Apr 2016 08:50:07 -0400 Received: from mail-by2on0081.outbound.protection.outlook.com ([207.46.100.81]:35616 "EHLO na01-by2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754469AbcDHMuD (ORCPT ); Fri, 8 Apr 2016 08:50:03 -0400 Authentication-Results: redhat.com; dkim=none (message not signed) header.d=none;redhat.com; dmarc=none action=none header.from=amd.com; From: Suravee Suthikulpanit To: , , , , , CC: , , , , Suravee Suthikulpanit Subject: [PART2 RFC v1 1/9] iommu/amd: Detect and enable guest vAPIC support Date: Fri, 8 Apr 2016 07:49:22 -0500 Message-ID: <1460119770-2896-2-git-send-email-Suravee.Suthikulpanit@amd.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1460119770-2896-1-git-send-email-Suravee.Suthikulpanit@amd.com> References: <1460119770-2896-1-git-send-email-Suravee.Suthikulpanit@amd.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [124.121.8.20] X-ClientProxiedBy: HKNPR06CA0022.apcprd06.prod.outlook.com (10.141.16.12) To SN1PR12MB0446.namprd12.prod.outlook.com (10.162.105.14) X-MS-Office365-Filtering-Correlation-Id: 3e61a687-31a7-4768-b0a8-08d35fac4b47 X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0446;2:qtXJR68BObuHLryEbO39mRsS0npzdGoPCyTqr4cilDF8WVI7k+gv0wYDRIzfyi+n4yHCLtHi/CDRUqop7ibP/+mU5JbVF5Nyyo6JGe8z5LRKicziwxFfhSHNzT8bfemXprpNrH4T9rnenkOBR6d1Jk7clzCwtDrG0DQBuk523L3HEb6fIgunjdgvzh8SJcuw;3:QG029HwLLyzj1bKnY6MOsnfwn9bn+/5vn9XKBt8OwSLeYX1RiEH/dFV9Z6o0B7RPVA1qDzyKR1kzDGJ/YpTftLNqoE77a8naSrjb72CnjNIWdTjBS+C4Wx/ESnHnk1LV;25:fPg2XBXR1+zELTazGf0KjrvegtM0vTNBmQoFinU1ip1skL7lPZZ1ZnRRxQWgAyF6/WJnyCeWUlKyJ/uiUZIBkpQrY5hA/iVq1FEirZexUhRWUuI3ldYKJnWsLI3ZFIte2Nn+OgtKZ2LGQcARD+I7+MehXxtp5gp4YS/VmWqf8p29URSJFgd+mg7phzXsQOgyszoeh2ENQ3VXIEHFkeuvxOAJtsoMqXXQ+ltgjEiKmnH0gPVwol9QwLq2TvhYCZCXcDMK/BfgjSW0hgXsq9ol9GltUWo/tEIzuD2kejGjvkp2QgrwQEbxMLsXV5YubdPYVKmRylOvAGP/pr+cqa8IXA== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:SN1PR12MB0446; X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0446;20:AlbjZLCVsrjQbSh6VOq1pQFITNr3FxqZ73SvULm3rrYLcBXsIGswza9B9JH4hpOXe/3XXP8AwUvVZwE7NGDKX5aEo2RB+NKWX4ETSSLJtDxcMJCXzXlGt3GreWF6xd3VZ2z+6S7TreN0PITKEomI1S6YMpq5RaShs1yHgcFcE735auhQjMSozdC1K1j7PQGHk4FnGHAXMuMrWiaUhsovKWEIpoQf4fwbqW9rQbLmJ26yNFF+r1l6fum1R+Uu9XbAtIN5Izn6cO8lqJseIVyofCOu6R+dRCtEcMXLTI41RZ/fSfivloQ+0KmDaeYyM5ceQQS78ms/cID2dexSWsOFPKqzZeu/o7Ckpyu3HaFycy3O2Fl4aMXxj7c4QCbt5rBgnNJKuYI4pHYCLDEeEPcs/gDvdYfMb2YP13rQAxpk1WCsXEusL3Wf/QA8WAb0wzhms5r9qmnd48IMJ6jEUnmpxEh5QMLK/C+tKtHX2CdUgKn6o/zOjkZDdL46Ny9t2bPF;4:TTnsErw+QXNGqZuYiXXEOg7oYltk+HmYSz18sk5G8JujbNzrLJsoPCaIT84I+OdNWRp+zA9dhbtAcTlYdzwYD4QT+ZT4/MOPI8DxVvpOQLd4IQx5AAIBwdEQHaWDy9ohyrJmE0qwqkW9Xlr9YutJJZgvy/NtOKdhB5i0Mf1rzfMiesYAH/Qn30UH2MDA/9fA2xUAdvBjBU1uD/eHkDmWthPAvP1w+57NvHFyf0dmqFr6X89UVaEEsoV/iTPebYANe4AZEoc2ek+ypsvOCbcHrk170LTvdsUn3sYA14GWm2oD+9i0X1CFyD18MZOtk3dx9QzJzuiHCfGCZH4iB0TO54c3r9VhqdpY3KUXjJtI/R6foZvc3aqIjGlzISLb8eLH 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)(3002001)(10201501046);SRVR:SN1PR12MB0446;BCL:0;PCL:0;RULEID:;SRVR:SN1PR12MB0446; X-Forefront-PRVS: 0906E83A25 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(4630300001)(6069001)(6009001)(50466002)(48376002)(77096005)(47776003)(66066001)(229853001)(36756003)(86362001)(575784001)(1096002)(42186005)(19580405001)(19580395003)(92566002)(6116002)(3846002)(586003)(5004730100002)(50986999)(76176999)(4326007)(189998001)(5003940100001)(2950100001)(2201001)(2906002)(5008740100001)(5001770100001)(81166005)(50226001);DIR:OUT;SFP:1101;SCL:1;SRVR:SN1PR12MB0446;H:localhost.localdomain;FPR:;SPF:None;MLV:sfv;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0446;23:MbqkLSJBWVWxBdRX6yDL6HvpVefMLTfJgaHsf8RzNHIdpxKeRuUT5Mllk02cspTXPRyhV/Wu9sEHJFlAiKeG7nNctI1oFvvwARubZcu45eIhrwhPcWw/hGTCVy5fxJ2obGkuN6zvP7lUIwmrGsrkC9gBUZQSctZpEJZMZhdHw9IGMtKS7Mok90BuHimL5ECmrMDggrNoosi+NFtMMXsXaVT4c7rYL5vtPwXge7kEuCVIwbXtUJOi+IrU+2HBWgkhi95yHofPMvtphU4WojnPKZ9I8R8PPnqWvUCmXb7mPAN9QjHk8TLt0VUWNz0qxiTa6oeuSUEXkW2j4/kxxhCmD5g3/SdBxIbeK2fLO6VxF3mT37bEzZOC2sWp2RrLUik3qHkZKZNOh1NEQ1uCT4BXW1AFDQpyw+8iNowDsDm2dPQPm9DdCSDEo2IW9sYqOSuS1ixxiOqfwd8g82hwr9MCoAaiX5a2ONnS6mKzSqqjLSK/bm5IzKUZmaxn0ci7NmBE3ADNzD1gqzJbRDgLARZjF5ArcJVGsdXYwnnXuVHozE2uyHF4M+HDJNZ6XNRhDbD0akjK5EQDLCkyoM5sRErUx3Ydbm8URgW9pbf35Uv1nq3Hsadsv929NasRmXFFsAOdzi2XFkyYMdL5o1Ar2OGp1X1Gd1ILGdrMbKay3Pke/Vj0bzpJmX/RHuAH7W8UaDQZFo8/HYyhLU4xir06NT5/i7d7gTlsBjEJSDQmi1acm2QwB/ghOjC//7Hr7aJN6a68Dq47WlrhWT1j4Yr1911hhIsa0LbuMZtAvzhxd+44zEZHqY+rDfbtAgV/+Ifv7Qm/Xsc8XrcQDDRs3ciF/hiWAe21OmFYrl9qD0tTtb/wus8rUGyVVZXZmWzvzH+mQfGMt/wyS93OhtUgGxqcGPEEufPaXOZBeYNpF+5OeGamU1U= X-Microsoft-Exchange-Diagnostics: 1;SN1PR12MB0446;5:m0EjZJf77KDOGUiPBqlcf/qwP14Zfxk/3dk86tEVqQDNzoSguoYCOjY2ilDmeV+APulIwmeGoqTZ3HtTGpvVo5Qdhqm06uJaUTZCZNVItsbVI+lsSgjXpWpS8kipTelSJbZMwovEe4mHYzePexe/4Q==;24:CukgX6D99w0MjwiO6FKNEuDS/Cnx5ofOUPLuE1O8Zjr/GgO4hyxWpSvFIchHidCHV4w/i3UUKCQB16q/9xonvko7Fly5yAuyPWBPdn7DfNs=;20:hTkd99XxX3+9lvLOec0rHSlHTVdk147aD5IAVv1t8JlNo48KD8NLn7CZ4Xcbey3f3dNFf0NRjTAMRacULTEKHhOKufO7I5FfZSg+wgHVlC1Kjen5RIlIufLeGlT60dtxkcQ5mrOmh/jJLhkhqp2asVu2VQzPe6/ssXR9YAJvXfrUErCO3Eohfo4R9s/XFG32Y4IqTndgIPtiWRqq0hXdKdhNm1ec1WoNAe8izsj4szNiT+LbcH+M0FCX49YvViOw X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 08 Apr 2016 12:49:55.6998 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN1PR12MB0446 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7368 Lines: 236 From: Suravee Suthikulpanit This patch introduces a new IOMMU driver parameter, amd_iommu_guest_ir, which can be used to specify different interrupt remapping mode for passthrough devices to VM guest: * legacy: Legacy interrupt remapping mode (w/ 32-bit IRTE) * ga : Guest vAPIC interrupt remapping mode (w/ 128-bit IRTE) Note that the GA mode also supports legacy interrupt remapping for non-passthrough devices with the 128-bit IRTE. Signed-off-by: Suravee Suthikulpanit --- drivers/iommu/amd_iommu_init.c | 74 +++++++++++++++++++++++++++++++++++++---- drivers/iommu/amd_iommu_proto.h | 1 + drivers/iommu/amd_iommu_types.h | 14 ++++++++ 3 files changed, 83 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index bf4959f..83a5300 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -131,6 +131,7 @@ struct ivmd_header { bool amd_iommu_dump; bool amd_iommu_irq_remap __read_mostly; +int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_GA; static bool amd_iommu_detected; static bool __initdata amd_iommu_disabled; @@ -1087,6 +1088,9 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET; } + if (((h->efr & (0x1 << 6)) == 0)) + amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY; + iommu->mmio_base = iommu_map_mmio_space(iommu->mmio_phys, iommu->mmio_phys_end); if (!iommu->mmio_base) @@ -1283,6 +1287,14 @@ static int iommu_init_pci(struct amd_iommu *iommu) if (iommu_feature(iommu, FEATURE_PPR) && alloc_ppr_log(iommu)) return -ENOMEM; + /* Note: We have already checked GASup from IVRS table. + * Now, we need to make sure that GAMSup is set. + */ + if (amd_iommu_guest_ir >= AMD_IOMMU_GUEST_IR_GA && + !iommu_feature(iommu, FEATURE_GAM_VAPIC)) + amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY_GA; + + if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE)) amd_iommu_np_cache = true; @@ -1340,16 +1352,23 @@ static void print_iommu_info(void) dev_name(&iommu->dev->dev), iommu->cap_ptr); if (iommu->cap & (1 << IOMMU_CAP_EFR)) { - pr_info("AMD-Vi: Extended features: "); + pr_info("AMD-Vi: Extended features (%#llx):\n", + iommu->features); for (i = 0; i < ARRAY_SIZE(feat_str); ++i) { if (iommu_feature(iommu, (1ULL << i))) pr_cont(" %s", feat_str[i]); } + + if (iommu->features & FEATURE_GAM_VAPIC) + pr_cont(" GA_vAPIC"); + pr_cont("\n"); } } if (irq_remapping_enabled) pr_info("AMD-Vi: Interrupt remapping enabled\n"); + if (amd_iommu_guest_ir) + pr_info("AMD-Vi: AVIC enabled (%#x)\n", amd_iommu_guest_ir); } static int __init amd_iommu_init_pci(void) @@ -1647,6 +1666,20 @@ static void iommu_apply_resume_quirks(struct amd_iommu *iommu) iommu->stored_addr_lo | 1); } +static void iommu_enable_ga(struct amd_iommu *iommu) +{ + switch (amd_iommu_guest_ir) { + case AMD_IOMMU_GUEST_IR_GA: + iommu_feature_enable(iommu, CONTROL_GAM_EN); + /* Fall through */ + case AMD_IOMMU_GUEST_IR_LEGACY_GA: + iommu_feature_enable(iommu, CONTROL_GA_EN); + break; + default: + break; + } +} + /* * This function finally enables all IOMMUs found in the system after * they have been initialized @@ -1662,9 +1695,13 @@ static void early_enable_iommus(void) iommu_enable_command_buffer(iommu); iommu_enable_event_buffer(iommu); iommu_set_exclusion_range(iommu); + iommu_enable_ga(iommu); iommu_enable(iommu); iommu_flush_all_caches(iommu); } + + if (amd_iommu_guest_ir >= AMD_IOMMU_GUEST_IR_GA) + amd_iommu_irq_ops.capability |= (1 << IRQ_POSTING_CAP); } static void enable_iommus_v2(void) @@ -1690,6 +1727,9 @@ static void disable_iommus(void) for_each_iommu(iommu) iommu_disable(iommu); + + if (amd_iommu_guest_ir >= AMD_IOMMU_GUEST_IR_GA) + amd_iommu_irq_ops.capability &= ~(1 << IRQ_POSTING_CAP); } /* @@ -1929,10 +1969,16 @@ static int __init early_amd_iommu_init(void) * remapping tables. */ ret = -ENOMEM; - amd_iommu_irq_cache = kmem_cache_create("irq_remap_cache", - MAX_IRQS_PER_TABLE * sizeof(u32), - IRQ_TABLE_ALIGNMENT, - 0, NULL); + if (amd_iommu_guest_ir == AMD_IOMMU_GUEST_IR_LEGACY) + amd_iommu_irq_cache = kmem_cache_create("irq_remap_cache", + MAX_IRQS_PER_TABLE * sizeof(u32), + IRQ_TABLE_ALIGNMENT, + 0, NULL); + else + amd_iommu_irq_cache = kmem_cache_create("irq_remap_cache", + MAX_IRQS_PER_TABLE * (sizeof(u64) * 2), + IRQ_TABLE_ALIGNMENT, + 0, NULL); if (!amd_iommu_irq_cache) goto out; @@ -2128,7 +2174,7 @@ static int __init amd_iommu_init(void) ret = iommu_go_to_state(IOMMU_INITIALIZED); if (ret) { free_dma_resources(); - if (!irq_remapping_enabled) { + if (!irq_remapping_enabled && !amd_iommu_guest_ir) { disable_iommus(); free_on_init_error(); } else { @@ -2185,6 +2231,21 @@ static int __init parse_amd_iommu_dump(char *str) return 1; } +static int __init parse_amd_iommu_intr(char *str) +{ + for (; *str; ++str) { + if (strncmp(str, "legacy", 6) == 0) { + amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY; + break; + } + if (strncmp(str, "ga", 2) == 0) { + amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_GA; + break; + } + } + return 1; +} + static int __init parse_amd_iommu_options(char *str) { for (; *str; ++str) { @@ -2261,6 +2322,7 @@ static int __init parse_ivrs_hpet(char *str) __setup("amd_iommu_dump", parse_amd_iommu_dump); __setup("amd_iommu=", parse_amd_iommu_options); +__setup("amd_iommu_intr=", parse_amd_iommu_intr); __setup("ivrs_ioapic", parse_ivrs_ioapic); __setup("ivrs_hpet", parse_ivrs_hpet); diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h index 0bd9eb3..faa3b48 100644 --- a/drivers/iommu/amd_iommu_proto.h +++ b/drivers/iommu/amd_iommu_proto.h @@ -38,6 +38,7 @@ extern int amd_iommu_enable(void); extern void amd_iommu_disable(void); extern int amd_iommu_reenable(int); extern int amd_iommu_enable_faulting(void); +extern int amd_iommu_guest_ir; /* IOMMUv2 specific functions */ struct iommu_domain; diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index 9d32b20..95414120 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -92,6 +92,7 @@ #define FEATURE_GA (1ULL<<7) #define FEATURE_HE (1ULL<<8) #define FEATURE_PC (1ULL<<9) +#define FEATURE_GAM_VAPIC (1ULL<<21) #define FEATURE_PASID_SHIFT 32 #define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT) @@ -146,6 +147,8 @@ #define CONTROL_PPFINT_EN 0x0eULL #define CONTROL_PPR_EN 0x0fULL #define CONTROL_GT_EN 0x10ULL +#define CONTROL_GA_EN 0x11ULL +#define CONTROL_GAM_EN 0x19ULL #define CTRL_INV_TO_MASK (7 << CONTROL_INV_TIMEOUT) #define CTRL_INV_TO_NONE 0 @@ -694,4 +697,15 @@ struct __iommu_counter { #endif /* CONFIG_AMD_IOMMU_STATS */ +enum amd_iommu_intr_mode_type { + AMD_IOMMU_GUEST_IR_LEGACY, + + /* This mode is not visible to users. It is used when + * we cannot fully enable GA and fallback to only support + * legacy interrupt remapping via 128-bit IRTE. + */ + AMD_IOMMU_GUEST_IR_LEGACY_GA, + AMD_IOMMU_GUEST_IR_GA, +}; + #endif /* _ASM_X86_AMD_IOMMU_TYPES_H */ -- 1.9.1