From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758181AbcDAFn4 (ORCPT ); Fri, 1 Apr 2016 01:43:56 -0400 Received: from mail-bn1on0086.outbound.protection.outlook.com ([157.56.110.86]:5106 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1758075AbcDAFny (ORCPT ); Fri, 1 Apr 2016 01:43:54 -0400 Authentication-Results: spf=none (sender IP is 165.204.84.221) smtp.mailfrom=amd.com; 8bytes.org; dkim=none (message not signed) header.d=none;8bytes.org; dmarc=permerror action=none header.from=amd.com; X-WSS-ID: 0O4XWJT-07-GXI-02 X-M-MSG: From: Wan Zongshun To: Joerg Roedel , CC: Suravee Suthikulpanit , Borislav Petkov , Ray Huang , , , , Wan Zongshun Subject: [PATCH V3 4/9] iommu/amd: Add new map for storing IVHD dev entry type HID Date: Fri, 1 Apr 2016 09:06:00 -0400 Message-ID: <1459515965-2865-5-git-send-email-vincent.wan@amd.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1459515965-2865-1-git-send-email-vincent.wan@amd.com> References: <1459515965-2865-1-git-send-email-vincent.wan@amd.com> MIME-Version: 1.0 Content-Type: text/plain X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:165.204.84.221;IPV:NLI;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(2980300002)(428002)(189002)(199003)(47776003)(106466001)(229853001)(105586002)(50226001)(19580405001)(33646002)(2950100001)(19580395003)(5008740100001)(11100500001)(5001770100001)(101416001)(4326007)(189998001)(36756003)(2906002)(53416004)(92566002)(87936001)(81166005)(5003940100001)(5003600100002)(86362001)(1096002)(586003)(50466002)(77096005)(50986999)(76176999)(1220700001)(48376002);DIR:OUT;SFP:1101;SCL:1;SRVR:CY1PR12MB0716;H:atltwp01.amd.com;FPR:;SPF:None;MLV:sfv;MX:1;A:1;LANG:en; X-MS-Office365-Filtering-Correlation-Id: 39603d9f-d93d-4d60-8370-08d359ee7e44 X-Microsoft-Exchange-Diagnostics: 1;CY1PR12MB0716;2:w+cEM/LXZOLbUWm7qTLy/XLEHWta3Kj4KXaXtBQ8+8JmGWxBSmI01Bhv5E0kRTHCypnNOj44xHcsgcHUeCIYd2jAo9AqwFyKo1o+y2fvhx5Gr4yyO8o2BJUegw3wZEYWz8Q5gr0TY8/5SoyP0Deb/MXi5+tdrGY8TyuOJZgbQxYkKkVxNdqd1aU3U/w5dTGf;3:uYol8IFzBz9CKwZj1Zj9+NqcWu3zDqBmAtnO7VmcDLXpe+yqYv4Mmq3GkAaaLiczvmKVyevzZ7TvMA7rqxVctNPKD8QNNBtVrtLTcehqP33c/uVhW/9tUme5fZh9wd/4zq1fqR5KNPaYfiGKbeZ4wREoORpELrQ6a0hYjtUE3ELUgrQvJiL7csKOo8ybC1JSO7TBx1DlZJodSu7TODVoChxGmxWecw+q3frGrjWymYE= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:CY1PR12MB0716; X-Microsoft-Exchange-Diagnostics: 1;CY1PR12MB0716;25:XfXgfVEuhCodnGXO1klHukQ/XnaPlLlMyjIZnZKuhrLZ2OtXdRETvDZQjsL9LrHUzgOrl8045Y963GBx9S8L3pU20S+Xm+FoUvysYLvyhxBZLXPq7CiblGJfdC3Lc5ylQtG9vZ+WJepts9yAJAhSMflhWaI0M3S6T6X5gF0QYx9pQ/qGT7Ny7//gvU6nTK5COjL6Cwnt+yHxAccMWhy37sjzUQzuevLSNN6lf9Ydoi2+8rmHETZIE37M9C6uwhSx+sBjq5EGKpZn/Yui5WqVtaoY4fjAqxNfxo6gJMqGUfns5nnTG7tIrsM5exT5i31h82jx1/3G2MKYpPuHuoelvQ3zQ8U9ozfurG06v3kjIZLYA9qGAfam4qIeD2n+Rsxh6UnhFOCjKhZOUoODuZd/OtdGApeIQGxHtI32eVYVNLhq07dRVTVeuuoGnbxy4TXg0/GqpJGQ23a1x9PpXr0nhphHXhpqPCPYXM6N8hw39OuU1tFAwFBDAayjIz34Sjv3YrwmOsHanrckET6rmLouLoQACrz48fA1u65GdFWUSVm9+3QU3dkJF2q1eoeICcCIs3okrRMnpFscOL2Y855Vuwzd1PKQFCajuSlnQMl8nAWuyL4vcY782MuN88EQNEY/ X-Microsoft-Exchange-Diagnostics: 1;CY1PR12MB0716;20:iCQffMAJMRVKgQgrSFwtg6stvNh0FYnakWMXJXYEZUeavLgTuCp6MTRAVfdUsyNE7NOQozKDgnKE9cU8lFhLE5Mw3YrTNMgoF2BrL6qL8w5X4ztei+v6/q/HA9aVBdLY1mHePnn2M8+224M5iTQqPp9sW/Xh2jLDsw4nMGdNmscXDysvQ4SKpmhimrQakbqtmdT/qIPt54i1TtmIgtnqpIMv0psr354IXF37VwqzTZgsTo/7qJ5ZvaA08Tj7oCm/q+fPKzJwSRj307Ku0jtL2UGd3zpR3UNWP5ubpAiwDj7snNsYMW5TUclIQtJ8wSay8wBB8zHfgT9PP2e3Sje8bsqqdW0n73vWK4/wB+YcxOraihJUiBF4OYhULo2csl4lmqwLZNO1ictmnh9RAKSSaKZZ5RHfeEuTVuTA5jLbQLpsab8yE9bxlI3++99vXvwjfuCZBb5Kl3azFDDepcd+95H9JcSwTO52GovG3YJoDc8yQzEQBi514PORrKqzgKGX 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)(13018025)(13015025)(13017025)(13023025)(13024025)(10201501046)(3002001);SRVR:CY1PR12MB0716;BCL:0;PCL:0;RULEID:;SRVR:CY1PR12MB0716; X-Microsoft-Exchange-Diagnostics: 1;CY1PR12MB0716;4:JwxgQi5qYpseoFVcs94soTKxvzBmFy1ur7+XEbnmNavx910xgdAUJ+0sMG0DMWYqx1yF44nDCTnd2pRcIsx9ErC1vH56Wlt/8SiHy4E8MNxravoe2RJKcGQIYnbXmha0QHh/ALYBiu2y/hhNU5U4VTWGSe582+ABRTiSL2HdWflj/buTPSxcmGGUG0o+/Wc7qKmhBfR8ADQikfzuYTpIZC7ZpQq79PpBvhMBtueCO/ke/sJlvE+6C40jX1uvHRPI8tqFoLyBRw1WFwaOrSpKNyJ9LzejvyTY5QSC997jSTnchyPbSWUormSK6fCXXhY0zoG1tlE9VAssdLd3sICoGsJ0w0l5iGzUPs4EpW3NDyXGp+uIBAPUEC/yvlq921Iix36+ANTxX4A519h9WP/k0+Pjkk06LPFHPcCAv9gtK5rwB/lFku8LYaOfQlicXrIo8NgsPi+fDljBTrSn2T5rgA== X-Forefront-PRVS: 0899B47777 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;CY1PR12MB0716;23:hJYSGUKRR4oHXRwwtGdOwveZB4whljgdtoRiGJDb7?= =?us-ascii?Q?yPJFcAa+WwwOK6arwyQJeRn7BVwg5QTZjE3iAr/jcs/h59P/6eaKGCPd39l4?= =?us-ascii?Q?w+1Pyx6JCDzT9Lpuwdyyuq0I4DLNAo+gLN+tiAknjGewtvvSxUevJGYUY/Tl?= =?us-ascii?Q?fJNbUzmFIL6mkkvcq3P7RurDtb8UwYCltFBsLH0eRakYmN8dGx0YwFR/P8nA?= =?us-ascii?Q?GDic+fpmjRYtfUlIf5PpBi0I3Of9oxjyVuSB4PdLLITAEXmnnEk55vClsam4?= =?us-ascii?Q?FtwC+FEQfw2/nzGgjTSsgVn2P4lJwRXvYtneMPGV6mCVIKC22kLCvs/HaZ/s?= =?us-ascii?Q?gg1HmTuzbGtvvPfPtSqSd42fGZgy7f1CHoCZjMyH7ZPwz78LL1p/0B7jRbYy?= =?us-ascii?Q?TrJPd/ogU7pfX5vM6HgcY7fKUnLIflwKJrd3Y7599z2p6QNINTRy0z6NvjuC?= =?us-ascii?Q?XkXEbLNRuHk0PJaFz++i4hJO1bmJWa62z3jpbu/HpL9UcLTgrQQF3wWIzM7l?= =?us-ascii?Q?09EyHKwhKlhaB+s+eEo9A9tT3h11zfAMc0UK6j4jAj2UwVdaxUivq4ukFFg2?= =?us-ascii?Q?HGxvkJLQ6B8+DmlnT3qaAhiSYc7eYP+ArImJYtxGdGeckXM5EEAbQ9c0SRMD?= =?us-ascii?Q?nbYRplUZoej78JZcOpLam9DEbldfiLiFGtWJ20YeOdJamXzhOiULwsmb4k6M?= =?us-ascii?Q?nS2r7ehEwh/m7ldGFOK7ZDcWPilBA6hpHjnWLZv5DPv63KYrsX526jLCjR+f?= =?us-ascii?Q?ls9a6HcFH1nUc2n9I9y9DnchAYHiUC1Q4WivESQDzZLoQZkiCa0isKkleo53?= =?us-ascii?Q?D71EiCTZTqGmqggqYq6ySeKPQjtF+8dqGypUYpyCMDn1olf3pX8KRZkwMiMs?= =?us-ascii?Q?ww992SDFYHlgAiOWy0JluP/Fk1NLtsJCpycRgsfVvO3SB5xXxG6Bi69kL6AI?= =?us-ascii?Q?RzO4h3yWYFXEJ1nZUXVfET9Uw7AfNEcD6hvMfKwNmEJynzowNLlo+K/M8PCY?= =?us-ascii?Q?anfo/zudMFPfyfqu36Bc8qF?= X-Microsoft-Exchange-Diagnostics: 1;CY1PR12MB0716;5:rybLKKUkjrQ96M4z3vWPTHGAhzs5i67PnJgq9VqsW8rnNwDc8R6ffDZHAc1KCfvB7tqjclYYuCagap0KUwn7VANRiouZ2/huPoc/9uNceFP0dvarEn6NztSw2yQlSeD42tY+xA29JpqHdQ53KsOGqw==;24:n/1uc5ePtNDdcv3Vb8ckfn8XKZw0EjCzpZbaU4HQ5wMgHqdgpVph3PRjCQGaDq3LN8dWr7hTEuY0LOZG7VB00m0xg1nLdsXhgCpmbSkjpus=;20:8QwD7bbmy19eD8VSTyBhC+GsF5n54/LUGJ+bBYBSrh5bZ0HH3BwA1/0CLKicsoUxj4KCvklagkgQ+5W2lxgCXXiZ9rnK5QRQxB8jGe7U28SQkzokXNMcAE163eomITIXfKtEUg+GLYgnAy05K0WTOjwDRD4veFxv6ZFSloaSqrvg23mqzUbtLplECJvZCdDK8bRSfazdAVj9xYltWKJH/HNXp9j/+JUCy3Xsyd2jYd3J4CA8PBoC+CD4c2yMWzN3 SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 Apr 2016 05:28:43.7066 (UTC) X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.221];Helo=[atltwp01.amd.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR12MB0716 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Wan Zongshun This patch introduces acpihid_map, which is used to store the new IVHD device entry extracted from BIOS IVRS table. It also provides a utility function add_acpi_hid_device(), to add this types of devices to the map. Signed-off-by: Wan Zongshun Signed-off-by: Suravee Suthikulpanit --- drivers/iommu/amd_iommu.c | 1 + drivers/iommu/amd_iommu_init.c | 122 ++++++++++++++++++++++++++++++++++++++++ drivers/iommu/amd_iommu_types.h | 14 +++++ 3 files changed, 137 insertions(+) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 374c129..d8e59a8 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -72,6 +72,7 @@ static DEFINE_SPINLOCK(dev_data_list_lock); LIST_HEAD(ioapic_map); LIST_HEAD(hpet_map); +LIST_HEAD(acpihid_map); /* * Domain for untranslated devices - only allocated diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 8f49612..e7ebfa2 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -60,6 +60,10 @@ #define IVHD_DEV_SPECIAL 0x48 #define IVHD_DEV_ACPI_HID 0xf0 +#define UID_NOT_PRESENT 0 +#define UID_IS_INTEGER 1 +#define UID_IS_CHARACTER 2 + #define IVHD_SPECIAL_IOAPIC 1 #define IVHD_SPECIAL_HPET 2 @@ -116,6 +120,11 @@ struct ivhd_entry { u16 devid; u8 flags; u32 ext; + u32 hidh; + u64 cid; + u8 uidf; + u8 uidl; + u8 uid; } __attribute__((packed)); /* @@ -224,8 +233,12 @@ enum iommu_init_state { #define EARLY_MAP_SIZE 4 static struct devid_map __initdata early_ioapic_map[EARLY_MAP_SIZE]; static struct devid_map __initdata early_hpet_map[EARLY_MAP_SIZE]; +static struct acpihid_map_entry __initdata early_acpihid_map[EARLY_MAP_SIZE]; + static int __initdata early_ioapic_map_size; static int __initdata early_hpet_map_size; +static int __initdata early_acpihid_map_size; + static bool __initdata cmdline_maps; static enum iommu_init_state init_state = IOMMU_START_STATE; @@ -765,6 +778,42 @@ static int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line) return 0; } +static int __init add_acpi_hid_device(u8 *hid, u8 *uid, u16 *devid, + bool cmd_line) +{ + struct acpihid_map_entry *entry; + struct list_head *list = &acpihid_map; + + list_for_each_entry(entry, list, list) { + if (strcmp(entry->hid, hid) || + (*uid && *entry->uid && strcmp(entry->uid, uid)) || + !entry->cmd_line) + continue; + + pr_info("AMD-Vi: Command-line override for hid:%s uid:%s\n", + hid, uid); + *devid = entry->devid; + return 0; + } + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + memcpy(entry->uid, uid, strlen(uid)); + memcpy(entry->hid, hid, strlen(hid)); + entry->devid = *devid; + entry->cmd_line = cmd_line; + entry->root_devid = (entry->devid & (~0x7)); + + pr_info("AMD-Vi:%s, add hid:%s, uid:%s, rdevid:%d\n", + entry->cmd_line ? "cmd" : "ivrs", + entry->hid, entry->uid, entry->root_devid); + + list_add_tail(&entry->list, list); + return 0; +} + static int __init add_early_maps(void) { int i, ret; @@ -787,6 +836,15 @@ static int __init add_early_maps(void) return ret; } + for (i = 0; i < early_acpihid_map_size; ++i) { + ret = add_acpi_hid_device(early_acpihid_map[i].hid, + early_acpihid_map[i].uid, + &early_acpihid_map[i].devid, + early_acpihid_map[i].cmd_line); + if (ret) + return ret; + } + return 0; } @@ -1007,6 +1065,70 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, break; } + case IVHD_DEV_ACPI_HID: { + u16 devid; + u8 hid[ACPIHID_HID_LEN] = {0}; + u8 uid[ACPIHID_UID_LEN] = {0}; + int ret; + + if (h->type != 0x40) { + pr_err(FW_BUG "Invalid IVHD device type %#x\n", + e->type); + break; + } + + memcpy(hid, (u8 *)(&e->ext), ACPIHID_HID_LEN - 1); + hid[ACPIHID_HID_LEN - 1] = '\0'; + + if (!(*hid)) { + pr_err(FW_BUG "Invalid HID.\n"); + break; + } + + switch (e->uidf) { + case UID_NOT_PRESENT: + + if (e->uidl != 0) + pr_warn(FW_BUG "Invalid UID length.\n"); + + break; + case UID_IS_INTEGER: + + sprintf(uid, "%d", e->uid); + + break; + case UID_IS_CHARACTER: + + memcpy(uid, (u8 *)(&e->uid), ACPIHID_UID_LEN - 1); + uid[ACPIHID_UID_LEN - 1] = '\0'; + + break; + default: + break; + } + + DUMP_printk(" DEV_ACPI_HID(%s[%s])\t\tdevid: %02x:%02x.%x\n", + hid, uid, + PCI_BUS_NUM(devid), + PCI_SLOT(devid), + PCI_FUNC(devid)); + + devid = e->devid; + flags = e->flags; + + ret = add_acpi_hid_device(hid, uid, &devid, false); + if (ret) + return ret; + + /* + * add_special_device might update the devid in case a + * command-line override is present. So call + * set_dev_entry_from_acpi after add_special_device. + */ + set_dev_entry_from_acpi(iommu, devid, e->flags, 0); + + break; + } default: break; } diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index 9d32b20..b6b14d2 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -527,6 +527,19 @@ struct amd_iommu { #endif }; +#define ACPIHID_UID_LEN 256 +#define ACPIHID_HID_LEN 9 + +struct acpihid_map_entry { + struct list_head list; + u8 uid[ACPIHID_UID_LEN]; + u8 hid[ACPIHID_HID_LEN]; + u16 devid; + u16 root_devid; + bool cmd_line; + struct iommu_group *group; +}; + struct devid_map { struct list_head list; u8 id; @@ -537,6 +550,7 @@ struct devid_map { /* Map HPET and IOAPIC ids to the devid used by the IOMMU */ extern struct list_head ioapic_map; extern struct list_head hpet_map; +extern struct list_head acpihid_map; /* * List with all IOMMUs in the system. This list is not locked because it is -- 1.9.1 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Wan Zongshun Subject: [PATCH V3 4/9] iommu/amd: Add new map for storing IVHD dev entry type HID Date: Fri, 1 Apr 2016 09:06:00 -0400 Message-ID: <1459515965-2865-5-git-send-email-vincent.wan@amd.com> References: <1459515965-2865-1-git-send-email-vincent.wan@amd.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1459515965-2865-1-git-send-email-vincent.wan-5C7GfCeVMHo@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: iommu-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org Errors-To: iommu-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org To: Joerg Roedel , iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Wan Zongshun , Ray Huang , Borislav Petkov List-Id: iommu@lists.linux-foundation.org From: Wan Zongshun This patch introduces acpihid_map, which is used to store the new IVHD device entry extracted from BIOS IVRS table. It also provides a utility function add_acpi_hid_device(), to add this types of devices to the map. Signed-off-by: Wan Zongshun Signed-off-by: Suravee Suthikulpanit --- drivers/iommu/amd_iommu.c | 1 + drivers/iommu/amd_iommu_init.c | 122 ++++++++++++++++++++++++++++++++++++++++ drivers/iommu/amd_iommu_types.h | 14 +++++ 3 files changed, 137 insertions(+) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 374c129..d8e59a8 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -72,6 +72,7 @@ static DEFINE_SPINLOCK(dev_data_list_lock); LIST_HEAD(ioapic_map); LIST_HEAD(hpet_map); +LIST_HEAD(acpihid_map); /* * Domain for untranslated devices - only allocated diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 8f49612..e7ebfa2 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -60,6 +60,10 @@ #define IVHD_DEV_SPECIAL 0x48 #define IVHD_DEV_ACPI_HID 0xf0 +#define UID_NOT_PRESENT 0 +#define UID_IS_INTEGER 1 +#define UID_IS_CHARACTER 2 + #define IVHD_SPECIAL_IOAPIC 1 #define IVHD_SPECIAL_HPET 2 @@ -116,6 +120,11 @@ struct ivhd_entry { u16 devid; u8 flags; u32 ext; + u32 hidh; + u64 cid; + u8 uidf; + u8 uidl; + u8 uid; } __attribute__((packed)); /* @@ -224,8 +233,12 @@ enum iommu_init_state { #define EARLY_MAP_SIZE 4 static struct devid_map __initdata early_ioapic_map[EARLY_MAP_SIZE]; static struct devid_map __initdata early_hpet_map[EARLY_MAP_SIZE]; +static struct acpihid_map_entry __initdata early_acpihid_map[EARLY_MAP_SIZE]; + static int __initdata early_ioapic_map_size; static int __initdata early_hpet_map_size; +static int __initdata early_acpihid_map_size; + static bool __initdata cmdline_maps; static enum iommu_init_state init_state = IOMMU_START_STATE; @@ -765,6 +778,42 @@ static int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line) return 0; } +static int __init add_acpi_hid_device(u8 *hid, u8 *uid, u16 *devid, + bool cmd_line) +{ + struct acpihid_map_entry *entry; + struct list_head *list = &acpihid_map; + + list_for_each_entry(entry, list, list) { + if (strcmp(entry->hid, hid) || + (*uid && *entry->uid && strcmp(entry->uid, uid)) || + !entry->cmd_line) + continue; + + pr_info("AMD-Vi: Command-line override for hid:%s uid:%s\n", + hid, uid); + *devid = entry->devid; + return 0; + } + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + + memcpy(entry->uid, uid, strlen(uid)); + memcpy(entry->hid, hid, strlen(hid)); + entry->devid = *devid; + entry->cmd_line = cmd_line; + entry->root_devid = (entry->devid & (~0x7)); + + pr_info("AMD-Vi:%s, add hid:%s, uid:%s, rdevid:%d\n", + entry->cmd_line ? "cmd" : "ivrs", + entry->hid, entry->uid, entry->root_devid); + + list_add_tail(&entry->list, list); + return 0; +} + static int __init add_early_maps(void) { int i, ret; @@ -787,6 +836,15 @@ static int __init add_early_maps(void) return ret; } + for (i = 0; i < early_acpihid_map_size; ++i) { + ret = add_acpi_hid_device(early_acpihid_map[i].hid, + early_acpihid_map[i].uid, + &early_acpihid_map[i].devid, + early_acpihid_map[i].cmd_line); + if (ret) + return ret; + } + return 0; } @@ -1007,6 +1065,70 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, break; } + case IVHD_DEV_ACPI_HID: { + u16 devid; + u8 hid[ACPIHID_HID_LEN] = {0}; + u8 uid[ACPIHID_UID_LEN] = {0}; + int ret; + + if (h->type != 0x40) { + pr_err(FW_BUG "Invalid IVHD device type %#x\n", + e->type); + break; + } + + memcpy(hid, (u8 *)(&e->ext), ACPIHID_HID_LEN - 1); + hid[ACPIHID_HID_LEN - 1] = '\0'; + + if (!(*hid)) { + pr_err(FW_BUG "Invalid HID.\n"); + break; + } + + switch (e->uidf) { + case UID_NOT_PRESENT: + + if (e->uidl != 0) + pr_warn(FW_BUG "Invalid UID length.\n"); + + break; + case UID_IS_INTEGER: + + sprintf(uid, "%d", e->uid); + + break; + case UID_IS_CHARACTER: + + memcpy(uid, (u8 *)(&e->uid), ACPIHID_UID_LEN - 1); + uid[ACPIHID_UID_LEN - 1] = '\0'; + + break; + default: + break; + } + + DUMP_printk(" DEV_ACPI_HID(%s[%s])\t\tdevid: %02x:%02x.%x\n", + hid, uid, + PCI_BUS_NUM(devid), + PCI_SLOT(devid), + PCI_FUNC(devid)); + + devid = e->devid; + flags = e->flags; + + ret = add_acpi_hid_device(hid, uid, &devid, false); + if (ret) + return ret; + + /* + * add_special_device might update the devid in case a + * command-line override is present. So call + * set_dev_entry_from_acpi after add_special_device. + */ + set_dev_entry_from_acpi(iommu, devid, e->flags, 0); + + break; + } default: break; } diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index 9d32b20..b6b14d2 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -527,6 +527,19 @@ struct amd_iommu { #endif }; +#define ACPIHID_UID_LEN 256 +#define ACPIHID_HID_LEN 9 + +struct acpihid_map_entry { + struct list_head list; + u8 uid[ACPIHID_UID_LEN]; + u8 hid[ACPIHID_HID_LEN]; + u16 devid; + u16 root_devid; + bool cmd_line; + struct iommu_group *group; +}; + struct devid_map { struct list_head list; u8 id; @@ -537,6 +550,7 @@ struct devid_map { /* Map HPET and IOAPIC ids to the devid used by the IOMMU */ extern struct list_head ioapic_map; extern struct list_head hpet_map; +extern struct list_head acpihid_map; /* * List with all IOMMUs in the system. This list is not locked because it is -- 1.9.1