From patchwork Sun May 22 00:20:27 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Suthikulpanit, Suravee" X-Patchwork-Id: 68316 Delivered-To: patch@linaro.org Received: by 10.140.92.199 with SMTP id b65csp564864qge; Sat, 21 May 2016 17:22:26 -0700 (PDT) X-Received: by 10.31.92.129 with SMTP id q123mr5744126vkb.92.1463876546743; Sat, 21 May 2016 17:22:26 -0700 (PDT) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org. [192.237.175.120]) by mx.google.com with ESMTPS id i33si15653031uai.21.2016.05.21.17.22.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 21 May 2016 17:22:26 -0700 (PDT) Received-SPF: neutral (google.com: 192.237.175.120 is neither permitted nor denied by best guess record for domain of xen-devel-bounces@lists.xen.org) client-ip=192.237.175.120; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@amdcloud.onmicrosoft.com; spf=neutral (google.com: 192.237.175.120 is neither permitted nor denied by best guess record for domain of xen-devel-bounces@lists.xen.org) smtp.mailfrom=xen-devel-bounces@lists.xen.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1b4H8X-0005Az-04; Sun, 22 May 2016 00:20:53 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1b4H8V-0005At-O9 for xen-devel@lists.xen.org; Sun, 22 May 2016 00:20:51 +0000 Received: from [85.158.137.68] by server-7.bemta-3.messagelabs.com id B4/F3-04060-26BF0475; Sun, 22 May 2016 00:20:50 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrAKsWRWlGSWpSXmKPExsXiaL7STDfxt0O 4we9dNhZLPi5mcWD0OLr7N1MAYxRrZl5SfkUCa8bqPefYC37HVZydsZm1gXGXVxcjFweLQDuz xOrfc5hAHEaBfkaJPduOsHQxcnIICRxmlJj4PB/EZhNQlVh6dx87iC0iYCQxteMWM4jNLFAss W3rajBbWMBDYsX6zWwgNgtQ/f+u1WA2r4CPxJpTHxhBbAkBOYmTxyazQsQFJU7OfMICMUdC4u CLF8wQNQoS279/Z4Ow2xgl/vcqQ9yjJXH5yEGouK/EiyfTwY6WEPjOJPFgAogDknCT+PDrESN E4iGbxMTTy9ggnIvsErsOTABazQHk5Ehs2Ae1TUti3dWPzBA1OxklOr9/ZoSokZF4tdoPIt7K InF6wjtWCOcbu8TPV9OhOj6wSjz51Qz1nITE/NONUGP9JeYtucgKYRtJvPu3AMp2kJi17AXbB Eb5WUhhMAspDBYwMq1i1ChOLSpLLdI1NNBLKspMzyjJTczMAfKM9XJTi4sT01NzEpOK9ZLzcz cxAmO/noGBcQfjti7nQ4ySHExKoryp3fbhQnxJ+SmVGYnFGfFFpTmpxYcYZTg4lCR41X45hAs JFqWmp1akZeYAkxBMWoKDR0mEVwUkzVtckJhbnJkOkTrFqMtxaOq9tUxCLHn5ealS4ryMIEUC IEUZpXlwI2AJ8RKjrJQwLyMDA4MQT0FqUW5mCar8K0ZxDkYlYV4rkCk8mXklcJteAR3BBHTEQ 2mwI0oSEVJSDYzsd7ifX9lS++6C3eSKEsubVvc6s+UvJd9I7eK5InrETsq7XHxSxF7zwhUlQt 2RPGlTOmT7FlrL2XDa6ykK+Gze7XojovWKtNUfl7C5JqceaZ2c2MSil/3u4ZkKpXWTnn7T172 uoVMR3SS19mOEE+sHK64ck68N0mcPeEYcEjuc89slb/lbZyWW4oxEQy3mouJEAAD9MnWDAwAA X-Env-Sender: Suravee.Suthikulpanit@amd.com X-Msg-Ref: server-7.tower-31.messagelabs.com!1463876448!33852686!1 X-Originating-IP: [65.55.169.54] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 8.34; banners=-,-,- X-VirusChecked: Checked Received: (qmail 39062 invoked from network); 22 May 2016 00:20:49 -0000 Received: from mail-bl2on0054.outbound.protection.outlook.com (HELO na01-bl2-obe.outbound.protection.outlook.com) (65.55.169.54) by server-7.tower-31.messagelabs.com with AES256-SHA256 encrypted SMTP; 22 May 2016 00:20:49 -0000 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=6+i4n3cBqqmhtsxzCdsllwuo5NI5nTdyRIaipFrsYn8=; b=OLBvgKUlSSw/NGUakCiQlj9n0FnFd1WvtWBlwUnVwRf+7j7Z7/fN0U1aIhrizJnAmvDgyFhtqNlUQeFH4kO8pQibr19JXlke3UO4FpYcX9gUcZl7fTTEEIZo2B92Ohm7WP7aqyP+k64zTvLewywaJ8Nkztn/txNbiZKzjgq2UMw= Received: from ssuthiku-cz-dev.amd.com (165.204.77.1) by BY1PR12MB0438.namprd12.prod.outlook.com (10.162.147.14) with Microsoft SMTP Server (TLS) id 15.1.497.12; Sun, 22 May 2016 00:20:41 +0000 From: To: , Date: Sat, 21 May 2016 19:20:27 -0500 Message-ID: <1463876427-7552-1-git-send-email-suravee.suthikulpanit@amd.com> X-Mailer: git-send-email 1.9.1 MIME-Version: 1.0 X-Originating-IP: [165.204.77.1] X-ClientProxiedBy: BY2PR21CA0022.namprd21.prod.outlook.com (10.162.74.160) To BY1PR12MB0438.namprd12.prod.outlook.com (10.162.147.14) X-MS-Office365-Filtering-Correlation-Id: 9b2cd46e-cd60-482e-8941-08d381d6ebbd X-Microsoft-Exchange-Diagnostics: 1; BY1PR12MB0438; 2:xJMFdVxGcsS4u9a1jQBxtaSzlnpd2sHBXXonpi0aU/XSRik1340JljAKURvNwWH4812WuvrhCDI39PmOTVpz3KK8jnY4R3SjR2bwChdNMXi6a+7tGUwkUiyY1l99kiez8EUd0pR+s9LfbzzTelY+9/IN6EwtnVdoqmWMRhtl9py3nKhWjFiOyyk3FZ+iXDkK; 3:s657Ru/VZQXeJfoM66cGr6UGvucBZtSCWPkfM6SGv2Pl5Q0t+hP4RMBDoP1G6RakBrZ2Ss/Bb6SopdtoSemfySHm1GCyz0sxzrC+eeVokXuvR9/zKhBOBlDMhMCzeu/1 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY1PR12MB0438; X-Microsoft-Exchange-Diagnostics: 1; BY1PR12MB0438; 25:zWKxa7zoR3IyvNxfZK1V8zAins6jvDmy6tk+RYvTxjFT51yrowA/14+vPJnWc2jTqU1A0Wp2Pg3NqFgFzBI3KhT2B9iBSrfB6BHmC0JrE+QHambTkiRp9Y7C618etDrMk9nmzu4zNUcYDUqWj7nQb+JpAXar4nRgGoS+ptzFVmeLo3PixEV/rQ8iBhpr3ta+OkHOfYu8cKdniXxVF5b+rBYnUKagMmrK1Gc3EnT4EJmDhKZixH0zAyetef0BEFCLARuujaLuKgWoPK5WDAmy1pnIJYk6JJd9KY7DLYnw4F3ZxhDJlkgT1j9tiDbTkXUfRzVlRJQsvV0BXjhLR1WAWN6W/bWAMGUSkAfNj+ZcHjnTTYyheXC583FePiRGox3IEGFzZ8EsVlJKZxlNdZtyBaZzZhr/2HQAbp82p5cYuUbfLd0IojHWl//P92XAxqsuDIIolvtyoySg8FVzvP4+ngg16AqmOBcH9i2opeEth2iWRbSke7reFBuLIUnOz3ydIAwCQV673K/UoecQB9CfpRhnPsyz1oTmPGUD3yfuiFf6oQwfZqUyYJfNeSNI0+fB35+Kk3gHwUG/rf61i2Euu3yj2If+nS9TNdrCtcDTvjf4I2Fvg73HvE7OjcbKpujZVuJEqXQkFqJWcuUluY0RqNsrHdgS50xOkIkrRF5ElPRbfzhAuLMSODJRkEodszIfUZZjQROkwygFj+b1TBdZv2oHgwjaStTwOviQfvupUhmCnS+XHzw3Ehq3CIqxXj9u5hVapl6L0wF/YNewEz7yRxL6Tl1MMqQWo7n98MO/4YU= X-Microsoft-Exchange-Diagnostics: 1; BY1PR12MB0438; 20:kt2pe2bPOlUY6Oqn57Xrw+PrFJB59zYWHoZCMKB/Xql4inOBiWxwyCZQO0sm9aFjf3GbjrhgPQqZUOzSB5JK0EK1n5MRxurmVgESOCTSxCK2sfGnncygsn3T3EM4dRwSOjYyBQEv88kwsFRp2YMeKAvITO+Qt7RjG1kXHleLYNyQWf18H7Twg6jjtpiIB7k7q/ogpsPJtCWkM3sVmnFVTCnKJB2YJqxSBoAyoX7gyc3fBIWNBgERimXYWcz4W71rpac2+dbJBt4kNWbm39NScQRChvszvsGnBxSOY1ZdObai+QVwnwfrVP6D87b8M58lTu8kX4V4FjNclacrGi5IrVfBWLc/9oJVAu4g9Wvrq7dY8X41sU6V/WWsn9Ix6325tcaFywGuADtZ4nO0tHA4J651ZUtUqV08FQtPNqyZO6CouG5YCfgyf4LNEHe6bVRRWj9ddun8Tes1sGwUnIij9H2quSeAf82QUWM6zUqgjGZRyBeUoct6VLT6uP99h3qd; 4:JkFk+gILbRmOyAJ3ZktOqgFC4u5u+WiJ9j/rL7GCKZaiEHjCCDsdhMnHRq3I16/tAILqqH5LKXhamoewKLJYBAxMoN9Rox8bDjZO8BV6S5X18nd7yxq0VoJ3D225dq4G6o/1b0xz2hoCRETIxB5G+L0IeY5TwYtVJO/xwlptireUE20Qh9gFNPVQH1IEHQnUAcIkDae7iiNAIfSkuVIbhlHrzf1HKB1E6w1YBww0Zj566VXJ6IrOLc3r549/oKAcYL7K0RPBwsO2GRC1sJveYb9wirkzBLNIxFIbe7Obf9NRoI1Jw2gJxAbzYL0yDd/QtjwnnA7oIZ3iR25im1T0TFV0bne3hk2iCet2x5hlP1ABAeRrCrM31WHMKo068vIuX/KFYzArnF2bAazqhnxhHw== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(8121501046)(5005006)(3002001)(10201501046)(6055026); SRVR:BY1PR12MB0438; BCL:0; PCL:0; RULEID:; SRVR:BY1PR12MB0438; X-Forefront-PRVS: 0950706AC1 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6009001)(243025005)(19580405001)(19580395003)(8676002)(81166006)(15975445007)(5003940100001)(47776003)(66066001)(50226002)(77096005)(48376002)(2906002)(2876002)(86152002)(5001770100001)(50466002)(229853001)(33646002)(36756003)(5004730100002)(86362001)(5008740100001)(50986999)(42186005)(4326007)(92566002)(3846002)(53416004)(189998001)(6116002)(586003); DIR:OUT; SFP:1101; SCL:1; SRVR:BY1PR12MB0438; H:ssuthiku-cz-dev.amd.com; FPR:; SPF:None; MLV:sfv; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BY1PR12MB0438; 23:OiNl6ciycQ46HEpVSnL6vHYwnrR9qR75x3TXJRkTSJrpbycOz+8vqUDGPOd2MT360kepGqopszLfpwSdJNE0TIvQBrCtdV7s5ZBk2V7IS8+Tn2ZxLo4x4NpuiVHt1NNFQG+UIWWmd/QZlEAZ1S9Ovx80DrvJaeRRGMl/oc3r+IagX1QRPoNcu7ghBhjGZIL5PxvCaHWlUjIU8VuovFPKs/qVAlEbB5eGa36vte11kMz6PuErMSB6s25wcCgSNqECq1IzkOMdmEn+C78JJ+G+VAyM+ga9eEGIJBtfMwM0wIH3EhREDve7ehGM0oKZhNrfizSEx3OA93Eht0Ws9UjyKHJcybQ2olQ8FXCpKy8eq6ikkWK/5M20Ql9Ztr/wjkla5LjoRVEGsD8FcmvFzQ3tadJojAnD5b/ohdpWbK5TZMyrPB4yCiW+9fdNmXBdnA+sE+z1Qt4+oNiExBtFxm6LM0AW8oC24B4UQZv6n4zDTwIq9RtX+AT0kdo4XyUnZOWBLWxsJeYYDCFNbaSwvjNTbWI6dr+xBhGKl+IO+k/cISuKjdw6bl5vrkTmydniPsjgPbBp43AMjGiu1rZZUxhazVMSMgehrVVfMk1X/ZKrP9/9vqxL7LSbRLq3jPdMHepUry4kU3S9BGgHeAhRk1qvbQirsbJ41rofAU/sIWyq5Df6rPiQgIGTbJRuqipe2By9gkwQTsDOemX5SNOwFogCYzBuCEjzc6hy/Y48Igtsuirxh0JhkNQlj21/EJNOfMn8Pq1yqt5WoT9AF/RcGH8SANfiEWvs1Mhjl/J8OZKAnhTcfg28QKAzcvoVYep3pJZa8zrJEvyE1Ky242IPK3Z7e0mnYl8F61BY68i+keFpEnOFWkcXtsgRlZaTBIL+GgF506lRuf9zxwP80UJ1b0orBwSBUrgmUvcxueyJ2QhNd+47/Z7ZzPCfqyLSXeaberzg X-Microsoft-Exchange-Diagnostics: 1; BY1PR12MB0438; 5:J4dZflSq0dGTcRGP4nY8PwoK34ZmeMAdZn2xKbDIsjnnyu2eHzGT7bWCfvZSYepj2BCmSMgZoaJGCXiMx3EKyTjng5MAlKg68ERuw/qEQfgv5zYdwUoJtQlyTpkvNSyi+U4adIcuyu1+eoyUeJmj0w==; 24:tZRB1ciIbAuF5bOwKjCrEudfkmBBq1pq1sU/t+VOWtL5q1F2G0ANXhYytXyd8AuYqeOVhihtohcn9QQ3wJBz/y5fvnXTdCuuQLQfToLxuL0=; 7:DgBw9wbnJk718c3fkQjaEgmzqgeSTiBPBCEFKjjX61sLsmt747XCU7/sRj8/BTBW65ppzAk7nvLRtlaOWg4woiVV2ySI47S2wCzVbRNOpH/zIUVz0KC/HoEDV4szbh9HjByo9zeBrO5jDzWXkczCXnvuUxYT+cHWZiobfDNX+C0=; 20:CHO7ru3StwdbhUAaRe5oSKjQQXD7VNHgo61zqLwxMkuXHBebXuI7oY/PfLyVYTNDdBwz9GG1dDlnli00DdwwDk7w81vl5fxpB7wwcuayxp65zDfIsCw1ZlyqlN1zYLcGE/Yp/s9Q/yc0HGid044l8KBsmZ+sF1PXdLKrd5auEP5zlVW8P2smRvjx3FdHGmyJgwjU2Su6F02ACRaF890YK6aq8MOZm8QLJ4ITCAcyLHWpKTp8g9vKSbRX983KnxKy X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 May 2016 00:20:41.3984 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY1PR12MB0438 Cc: Suravee Suthikulpanit Subject: [Xen-devel] [PATCH v2] AMD IOMMU: Introduce support for IVHD block type 11h X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" From: Suravee Suthikulpanit Along with the IVHD block type 10h, newer AMD platforms also come with types 11h, which is a superset of the older one. Having multiple IVHD block types in the same platform allows backward compatibility of newer systems to work with existing drivers. The driver should only parse the highest-level (newest) type of IVHD block that it can support. However, the current driver returns error when encounters with unknown IVHD block type. This causes existing driver to unnecessarily fail IOMMU initialization on new systems. This patch introduces a new logic, which scans through IVRS table looking for the highest-level supporsted IVHD block type. It also adds support for the new IVHD block type 11h. More information about the IVHD type 11h can be found in the AMD I/O Virtualization Technology (IOMMU) Specification rev 2.62. http://support.amd.com/TechDocs/48882_IOMMU.pdf Signed-off-by: Suravee Suthikulpanit --- Changes from V1: * Update get_ivhd_header_size() to use switch statment. * Update logic in get_supported_ivhd_type(). * Move ACPI_FADT_NO_MSI flag check to amd_iommu_init() since it should be checked before any IVRS parsing. * Clean up various styling issues. xen/drivers/passthrough/amd/iommu_acpi.c | 137 ++++++++++++++++++-------- xen/drivers/passthrough/amd/iommu_init.c | 10 +- xen/include/acpi/actbl2.h | 7 +- xen/include/asm-x86/amd-iommu.h | 1 + xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 1 + 5 files changed, 111 insertions(+), 45 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu_acpi.c b/xen/drivers/passthrough/amd/iommu_acpi.c index 79c1f8c..c4eec50 100644 --- a/xen/drivers/passthrough/amd/iommu_acpi.c +++ b/xen/drivers/passthrough/amd/iommu_acpi.c @@ -821,13 +821,33 @@ static u16 __init parse_ivhd_device_special( return dev_length; } +static inline unsigned int +get_ivhd_header_size(const struct acpi_ivrs_hardware *ivhd_block) +{ + int ret = 0; + + switch ( ivhd_block->header.type ) + { + case ACPI_IVRS_TYPE_HARDWARE: + ret = offsetof(struct acpi_ivrs_hardware, efr_image); + break; + case ACPI_IVRS_TYPE_HARDWARE_11H: + ret = sizeof(struct acpi_ivrs_hardware); + break; + default: + break; + } + return ret; +} + static int __init parse_ivhd_block(const struct acpi_ivrs_hardware *ivhd_block) { const union acpi_ivhd_device *ivhd_device; u16 block_length, dev_length; + unsigned int hdr_size = get_ivhd_header_size(ivhd_block) ; struct amd_iommu *iommu; - if ( ivhd_block->header.length < sizeof(*ivhd_block) ) + if ( ivhd_block->header.length < hdr_size ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Block Length!\n"); return -ENODEV; @@ -845,7 +865,7 @@ static int __init parse_ivhd_block(const struct acpi_ivrs_hardware *ivhd_block) } /* parse Device Entries */ - block_length = sizeof(*ivhd_block); + block_length = hdr_size; while ( ivhd_block->header.length >= (block_length + sizeof(struct acpi_ivrs_de_header)) ) { @@ -914,34 +934,6 @@ static int __init parse_ivhd_block(const struct acpi_ivrs_hardware *ivhd_block) return 0; } -static int __init parse_ivrs_block(const struct acpi_ivrs_header *ivrs_block) -{ - const struct acpi_ivrs_hardware *ivhd_block; - const struct acpi_ivrs_memory *ivmd_block; - - switch ( ivrs_block->type ) - { - case ACPI_IVRS_TYPE_HARDWARE: - ivhd_block = container_of(ivrs_block, const struct acpi_ivrs_hardware, - header); - return parse_ivhd_block(ivhd_block); - - case ACPI_IVRS_TYPE_MEMORY_ALL: - case ACPI_IVRS_TYPE_MEMORY_ONE: - case ACPI_IVRS_TYPE_MEMORY_RANGE: - case ACPI_IVRS_TYPE_MEMORY_IOMMU: - ivmd_block = container_of(ivrs_block, const struct acpi_ivrs_memory, - header); - return parse_ivmd_block(ivmd_block); - - default: - AMD_IOMMU_DEBUG("IVRS Error: Invalid Block Type!\n"); - return -ENODEV; - } - - return 0; -} - static void __init dump_acpi_table_header(struct acpi_table_header *table) { int i; @@ -978,6 +970,22 @@ static void __init dump_acpi_table_header(struct acpi_table_header *table) } +#define to_ivhd_block(hdr) \ + container_of(hdr, const struct acpi_ivrs_hardware, header) +#define to_ivmd_block(hdr) \ + container_of(hdr, const struct acpi_ivrs_memory, header) + +#define is_ivhd_block(x) \ + (( x <= IVHD_HIGHEST_SUPPORT_TYPE ) && \ + (( x == ACPI_IVRS_TYPE_HARDWARE ) || \ + ( x == ACPI_IVRS_TYPE_HARDWARE_11H ))) + +#define is_ivmd_block(x) \ + (( x == ACPI_IVRS_TYPE_MEMORY_ALL ) || \ + ( x == ACPI_IVRS_TYPE_MEMORY_ONE ) || \ + ( x == ACPI_IVRS_TYPE_MEMORY_RANGE ) || \ + ( x == ACPI_IVRS_TYPE_MEMORY_IOMMU )) + static int __init parse_ivrs_table(struct acpi_table_header *table) { const struct acpi_ivrs_header *ivrs_block; @@ -1010,7 +1018,10 @@ static int __init parse_ivrs_table(struct acpi_table_header *table) return -ENODEV; } - error = parse_ivrs_block(ivrs_block); + if ( ivrs_block->type == ivhd_type ) + error = parse_ivhd_block(to_ivhd_block(ivrs_block)); + else if ( is_ivmd_block (ivrs_block->type) ) + error = parse_ivmd_block(to_ivmd_block(ivrs_block)); length += ivrs_block->length; } @@ -1083,9 +1094,7 @@ static int __init detect_iommu_acpi(struct acpi_table_header *table) if ( table->length < (length + ivrs_block->length) ) return -ENODEV; if ( ivrs_block->type == ACPI_IVRS_TYPE_HARDWARE && - amd_iommu_detect_one_acpi( - container_of(ivrs_block, const struct acpi_ivrs_hardware, - header)) != 0 ) + amd_iommu_detect_one_acpi(to_ivhd_block(ivrs_block)) != 0 ) return -ENODEV; length += ivrs_block->length; } @@ -1102,15 +1111,16 @@ static int __init get_last_bdf_ivhd( { const union acpi_ivhd_device *ivhd_device; u16 block_length, dev_length; + unsigned int hdr_size = get_ivhd_header_size(ivhd_block) ; int last_bdf = 0; - if ( ivhd_block->header.length < sizeof(*ivhd_block) ) + if ( ivhd_block->header.length < hdr_size ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Block Length!\n"); return -ENODEV; } - block_length = sizeof(*ivhd_block); + block_length = hdr_size; while ( ivhd_block->header.length >= (block_length + sizeof(struct acpi_ivrs_de_header)) ) { @@ -1177,11 +1187,9 @@ static int __init get_last_bdf_acpi(struct acpi_table_header *table) ivrs_block = (struct acpi_ivrs_header *)((u8 *)table + length); if ( table->length < (length + ivrs_block->length) ) return -ENODEV; - if ( ivrs_block->type == ACPI_IVRS_TYPE_HARDWARE ) + if ( ivrs_block->type == ivhd_type ) { - int ret = get_last_bdf_ivhd( - container_of(ivrs_block, const struct acpi_ivrs_hardware, - header)); + int ret = get_last_bdf_ivhd(to_ivhd_block(ivrs_block)); if ( ret < 0 ) return ret; @@ -1207,8 +1215,51 @@ int __init amd_iommu_get_ivrs_dev_entries(void) int __init amd_iommu_update_ivrs_mapping_acpi(void) { - if ( unlikely(acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) ) - return -EPERM; - return acpi_table_parse(ACPI_SIG_IVRS, parse_ivrs_table); } + +static int __init +get_supported_ivhd_type(struct acpi_table_header *table) +{ + unsigned long length = sizeof(struct acpi_table_ivrs); + const struct acpi_ivrs_header *ivrs_block, *blk = NULL; + + while ( table->length > (length + sizeof(*ivrs_block)) ) + { + ivrs_block = (struct acpi_ivrs_header *)((u8 *)table + length); + + if ( table->length < (length + ivrs_block->length) ) + { + AMD_IOMMU_DEBUG("IVRS Error: " + "Table Length Exceeded: %#x -> %#lx\n", + table->length, + (length + ivrs_block->length)); + return -ENODEV; + } + + if ( is_ivhd_block(ivrs_block->type) && + (!blk || blk->type < ivrs_block->type) ) + { + AMD_IOMMU_DEBUG("IVRS Block: Found type %#x flags %#x len %#x id %#x\n", + ivrs_block->type, ivrs_block->flags, + ivrs_block->length, ivrs_block->device_id); + blk = ivrs_block; + } + length += ivrs_block->length; + } + + if ( !blk ) + { + printk(XENLOG_ERR "Cannot find supported IVHD type.\n"); + return -ENODEV; + } + + AMD_IOMMU_DEBUG("Using IVHD type %#x\n", blk->type); + + return blk->type; +} + +int __init amd_iommu_get_supported_ivhd_type(void) +{ + return acpi_table_parse(ACPI_SIG_IVRS, get_supported_ivhd_type); +} diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c index 4536106..1ecbde3 100644 --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -35,6 +35,7 @@ static int __initdata nr_amd_iommus; static struct tasklet amd_iommu_irq_tasklet; unsigned int __read_mostly ivrs_bdf_entries; +int __read_mostly ivhd_type; static struct radix_tree_root ivrs_maps; struct list_head amd_iommu_head; struct table_struct device_table; @@ -1232,8 +1233,15 @@ int __init amd_iommu_init(void) amd_sp5100_erratum28() ) goto error_out; - ivrs_bdf_entries = amd_iommu_get_ivrs_dev_entries(); + /* We implies no IOMMU if ACPI indicates no MSI. */ + if ( unlikely(acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) ) + goto error_out; + ivhd_type = amd_iommu_get_supported_ivhd_type(); + if ( ivhd_type < 0 ) + goto error_out; + + ivrs_bdf_entries = amd_iommu_get_ivrs_dev_entries(); if ( !ivrs_bdf_entries ) goto error_out; diff --git a/xen/include/acpi/actbl2.h b/xen/include/acpi/actbl2.h index 4341a30..a25ed48 100644 --- a/xen/include/acpi/actbl2.h +++ b/xen/include/acpi/actbl2.h @@ -589,12 +589,15 @@ struct acpi_ivrs_header { enum acpi_ivrs_type { ACPI_IVRS_TYPE_HARDWARE = 0x10, + ACPI_IVRS_TYPE_HARDWARE_11H = 0x11, ACPI_IVRS_TYPE_MEMORY_ALL /* _MEMORY1 */ = 0x20, ACPI_IVRS_TYPE_MEMORY_ONE /* _MEMORY2 */ = 0x21, ACPI_IVRS_TYPE_MEMORY_RANGE /* _MEMORY3 */ = 0x22, ACPI_IVRS_TYPE_MEMORY_IOMMU = 0x23 }; +#define IVHD_HIGHEST_SUPPORT_TYPE ACPI_IVRS_TYPE_HARDWARE_11H + /* Masks for Flags field above for IVHD subtable */ #define ACPI_IVHD_TT_ENABLE (1) @@ -622,7 +625,9 @@ struct acpi_ivrs_hardware { u64 base_address; /* IOMMU control registers */ u16 pci_segment_group; u16 info; /* MSI number and unit ID */ - u32 reserved; + u32 iommu_attr; + u64 efr_image; /* Extd feature register */ + u64 reserved; }; /* Masks for Info field above */ diff --git a/xen/include/asm-x86/amd-iommu.h b/xen/include/asm-x86/amd-iommu.h index e9fa9c2..18c9f8e 100644 --- a/xen/include/asm-x86/amd-iommu.h +++ b/xen/include/asm-x86/amd-iommu.h @@ -126,6 +126,7 @@ struct ivrs_mappings { }; extern unsigned int ivrs_bdf_entries; +extern int ivhd_type; struct ivrs_mappings *get_ivrs_mappings(u16 seg); int iterate_ivrs_mappings(int (*)(u16 seg, struct ivrs_mappings *)); diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h index 9c51172..e6065d3 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h @@ -42,6 +42,7 @@ struct acpi_ivrs_hardware; /* amd-iommu-detect functions */ int amd_iommu_get_ivrs_dev_entries(void); +int amd_iommu_get_supported_ivhd_type(void); int amd_iommu_detect_one_acpi(const struct acpi_ivrs_hardware *); int amd_iommu_detect_acpi(void); void get_iommu_features(struct amd_iommu *iommu);