diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2011-04-11 05:03:18 -0400 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2011-04-12 03:21:51 -0400 |
commit | d99ddec3eee0be8a43b2c1ff624b9dfaaa26b959 (patch) | |
tree | a87ad31dc20c42346f05bf74f98aa84243bf50a4 | |
parent | 7d0c5cc5be73f7ce26fdcca7b8ec2203f661eb93 (diff) |
x86/amd-iommu: Add extended feature detection
This patch adds detection of the extended features of an
AMD IOMMU. The available features are printed to dmesg on
boot.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
-rw-r--r-- | arch/x86/include/asm/amd_iommu_proto.h | 10 | ||||
-rw-r--r-- | arch/x86/include/asm/amd_iommu_types.h | 17 | ||||
-rw-r--r-- | arch/x86/kernel/amd_iommu_init.c | 24 |
3 files changed, 48 insertions, 3 deletions
diff --git a/arch/x86/include/asm/amd_iommu_proto.h b/arch/x86/include/asm/amd_iommu_proto.h index 1223c0fe03f5..a4ae6c3875eb 100644 --- a/arch/x86/include/asm/amd_iommu_proto.h +++ b/arch/x86/include/asm/amd_iommu_proto.h | |||
@@ -19,7 +19,7 @@ | |||
19 | #ifndef _ASM_X86_AMD_IOMMU_PROTO_H | 19 | #ifndef _ASM_X86_AMD_IOMMU_PROTO_H |
20 | #define _ASM_X86_AMD_IOMMU_PROTO_H | 20 | #define _ASM_X86_AMD_IOMMU_PROTO_H |
21 | 21 | ||
22 | struct amd_iommu; | 22 | #include <asm/amd_iommu_types.h> |
23 | 23 | ||
24 | extern int amd_iommu_init_dma_ops(void); | 24 | extern int amd_iommu_init_dma_ops(void); |
25 | extern int amd_iommu_init_passthrough(void); | 25 | extern int amd_iommu_init_passthrough(void); |
@@ -42,4 +42,12 @@ static inline bool is_rd890_iommu(struct pci_dev *pdev) | |||
42 | (pdev->device == PCI_DEVICE_ID_RD890_IOMMU); | 42 | (pdev->device == PCI_DEVICE_ID_RD890_IOMMU); |
43 | } | 43 | } |
44 | 44 | ||
45 | static inline bool iommu_feature(struct amd_iommu *iommu, u64 f) | ||
46 | { | ||
47 | if (!(iommu->cap & (1 << IOMMU_CAP_EFR))) | ||
48 | return false; | ||
49 | |||
50 | return !!(iommu->features & f); | ||
51 | } | ||
52 | |||
45 | #endif /* _ASM_X86_AMD_IOMMU_PROTO_H */ | 53 | #endif /* _ASM_X86_AMD_IOMMU_PROTO_H */ |
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h index 878ae008eb04..5c24e4652347 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h | |||
@@ -68,12 +68,25 @@ | |||
68 | #define MMIO_CONTROL_OFFSET 0x0018 | 68 | #define MMIO_CONTROL_OFFSET 0x0018 |
69 | #define MMIO_EXCL_BASE_OFFSET 0x0020 | 69 | #define MMIO_EXCL_BASE_OFFSET 0x0020 |
70 | #define MMIO_EXCL_LIMIT_OFFSET 0x0028 | 70 | #define MMIO_EXCL_LIMIT_OFFSET 0x0028 |
71 | #define MMIO_EXT_FEATURES 0x0030 | ||
71 | #define MMIO_CMD_HEAD_OFFSET 0x2000 | 72 | #define MMIO_CMD_HEAD_OFFSET 0x2000 |
72 | #define MMIO_CMD_TAIL_OFFSET 0x2008 | 73 | #define MMIO_CMD_TAIL_OFFSET 0x2008 |
73 | #define MMIO_EVT_HEAD_OFFSET 0x2010 | 74 | #define MMIO_EVT_HEAD_OFFSET 0x2010 |
74 | #define MMIO_EVT_TAIL_OFFSET 0x2018 | 75 | #define MMIO_EVT_TAIL_OFFSET 0x2018 |
75 | #define MMIO_STATUS_OFFSET 0x2020 | 76 | #define MMIO_STATUS_OFFSET 0x2020 |
76 | 77 | ||
78 | |||
79 | /* Extended Feature Bits */ | ||
80 | #define FEATURE_PREFETCH (1ULL<<0) | ||
81 | #define FEATURE_PPR (1ULL<<1) | ||
82 | #define FEATURE_X2APIC (1ULL<<2) | ||
83 | #define FEATURE_NX (1ULL<<3) | ||
84 | #define FEATURE_GT (1ULL<<4) | ||
85 | #define FEATURE_IA (1ULL<<6) | ||
86 | #define FEATURE_GA (1ULL<<7) | ||
87 | #define FEATURE_HE (1ULL<<8) | ||
88 | #define FEATURE_PC (1ULL<<9) | ||
89 | |||
77 | /* MMIO status bits */ | 90 | /* MMIO status bits */ |
78 | #define MMIO_STATUS_COM_WAIT_INT_MASK 0x04 | 91 | #define MMIO_STATUS_COM_WAIT_INT_MASK 0x04 |
79 | 92 | ||
@@ -227,6 +240,7 @@ | |||
227 | /* IOMMU capabilities */ | 240 | /* IOMMU capabilities */ |
228 | #define IOMMU_CAP_IOTLB 24 | 241 | #define IOMMU_CAP_IOTLB 24 |
229 | #define IOMMU_CAP_NPCACHE 26 | 242 | #define IOMMU_CAP_NPCACHE 26 |
243 | #define IOMMU_CAP_EFR 27 | ||
230 | 244 | ||
231 | #define MAX_DOMAIN_ID 65536 | 245 | #define MAX_DOMAIN_ID 65536 |
232 | 246 | ||
@@ -371,6 +385,9 @@ struct amd_iommu { | |||
371 | /* flags read from acpi table */ | 385 | /* flags read from acpi table */ |
372 | u8 acpi_flags; | 386 | u8 acpi_flags; |
373 | 387 | ||
388 | /* Extended features */ | ||
389 | u64 features; | ||
390 | |||
374 | /* | 391 | /* |
375 | * Capability pointer. There could be more than one IOMMU per PCI | 392 | * Capability pointer. There could be more than one IOMMU per PCI |
376 | * device function if there are more than one AMD IOMMU capability | 393 | * device function if there are more than one AMD IOMMU capability |
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 8848dda808e2..047905dc3e14 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c | |||
@@ -299,9 +299,23 @@ static void iommu_feature_disable(struct amd_iommu *iommu, u8 bit) | |||
299 | /* Function to enable the hardware */ | 299 | /* Function to enable the hardware */ |
300 | static void iommu_enable(struct amd_iommu *iommu) | 300 | static void iommu_enable(struct amd_iommu *iommu) |
301 | { | 301 | { |
302 | printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx\n", | 302 | static const char * const feat_str[] = { |
303 | "PreF", "PPR", "X2APIC", "NX", "GT", "[5]", | ||
304 | "IA", "GA", "HE", "PC", NULL | ||
305 | }; | ||
306 | int i; | ||
307 | |||
308 | printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx", | ||
303 | dev_name(&iommu->dev->dev), iommu->cap_ptr); | 309 | dev_name(&iommu->dev->dev), iommu->cap_ptr); |
304 | 310 | ||
311 | if (iommu->cap & (1 << IOMMU_CAP_EFR)) { | ||
312 | printk(KERN_CONT " extended features: "); | ||
313 | for (i = 0; feat_str[i]; ++i) | ||
314 | if (iommu_feature(iommu, (1ULL << i))) | ||
315 | printk(KERN_CONT " %s", feat_str[i]); | ||
316 | } | ||
317 | printk(KERN_CONT "\n"); | ||
318 | |||
305 | iommu_feature_enable(iommu, CONTROL_IOMMU_EN); | 319 | iommu_feature_enable(iommu, CONTROL_IOMMU_EN); |
306 | } | 320 | } |
307 | 321 | ||
@@ -657,7 +671,7 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m) | |||
657 | static void __init init_iommu_from_pci(struct amd_iommu *iommu) | 671 | static void __init init_iommu_from_pci(struct amd_iommu *iommu) |
658 | { | 672 | { |
659 | int cap_ptr = iommu->cap_ptr; | 673 | int cap_ptr = iommu->cap_ptr; |
660 | u32 range, misc; | 674 | u32 range, misc, low, high; |
661 | int i, j; | 675 | int i, j; |
662 | 676 | ||
663 | pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET, | 677 | pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET, |
@@ -673,6 +687,12 @@ static void __init init_iommu_from_pci(struct amd_iommu *iommu) | |||
673 | MMIO_GET_LD(range)); | 687 | MMIO_GET_LD(range)); |
674 | iommu->evt_msi_num = MMIO_MSI_NUM(misc); | 688 | iommu->evt_msi_num = MMIO_MSI_NUM(misc); |
675 | 689 | ||
690 | /* read extended feature bits */ | ||
691 | low = readl(iommu->mmio_base + MMIO_EXT_FEATURES); | ||
692 | high = readl(iommu->mmio_base + MMIO_EXT_FEATURES + 4); | ||
693 | |||
694 | iommu->features = ((u64)high << 32) | low; | ||
695 | |||
676 | if (!is_rd890_iommu(iommu->dev)) | 696 | if (!is_rd890_iommu(iommu->dev)) |
677 | return; | 697 | return; |
678 | 698 | ||