diff options
| -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 | ||
