diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2008-09-05 08:29:07 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-09-19 06:59:11 -0400 |
commit | 335503e57b6b8de04cec5d27eb2c3d09ff98905b (patch) | |
tree | a2f33f3a2a668e832273aa0b18608ef51e90a742 | |
parent | 6d4f343f84993eb0d5864c0823dc9babd171a33a (diff) |
AMD IOMMU: add event buffer allocation
This patch adds the allocation of a event buffer for each AMD IOMMU in
the system. The hardware will log events like device page faults or
other errors to this buffer once this is enabled.
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/kernel/amd_iommu_init.c | 29 | ||||
-rw-r--r-- | include/asm-x86/amd_iommu_types.h | 9 |
2 files changed, 38 insertions, 0 deletions
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index f2fa8dc81beb..41ce8d5d626e 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c | |||
@@ -417,6 +417,30 @@ static void __init free_command_buffer(struct amd_iommu *iommu) | |||
417 | free_pages((unsigned long)iommu->cmd_buf, get_order(CMD_BUFFER_SIZE)); | 417 | free_pages((unsigned long)iommu->cmd_buf, get_order(CMD_BUFFER_SIZE)); |
418 | } | 418 | } |
419 | 419 | ||
420 | /* allocates the memory where the IOMMU will log its events to */ | ||
421 | static u8 * __init alloc_event_buffer(struct amd_iommu *iommu) | ||
422 | { | ||
423 | u64 entry; | ||
424 | iommu->evt_buf = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, | ||
425 | get_order(EVT_BUFFER_SIZE)); | ||
426 | |||
427 | if (iommu->evt_buf == NULL) | ||
428 | return NULL; | ||
429 | |||
430 | entry = (u64)virt_to_phys(iommu->evt_buf) | EVT_LEN_MASK; | ||
431 | memcpy_toio(iommu->mmio_base + MMIO_EVT_BUF_OFFSET, | ||
432 | &entry, sizeof(entry)); | ||
433 | |||
434 | iommu->evt_buf_size = EVT_BUFFER_SIZE; | ||
435 | |||
436 | return iommu->evt_buf; | ||
437 | } | ||
438 | |||
439 | static void __init free_event_buffer(struct amd_iommu *iommu) | ||
440 | { | ||
441 | free_pages((unsigned long)iommu->evt_buf, get_order(EVT_BUFFER_SIZE)); | ||
442 | } | ||
443 | |||
420 | /* sets a specific bit in the device table entry. */ | 444 | /* sets a specific bit in the device table entry. */ |
421 | static void set_dev_entry_bit(u16 devid, u8 bit) | 445 | static void set_dev_entry_bit(u16 devid, u8 bit) |
422 | { | 446 | { |
@@ -622,6 +646,7 @@ static int __init init_iommu_devices(struct amd_iommu *iommu) | |||
622 | static void __init free_iommu_one(struct amd_iommu *iommu) | 646 | static void __init free_iommu_one(struct amd_iommu *iommu) |
623 | { | 647 | { |
624 | free_command_buffer(iommu); | 648 | free_command_buffer(iommu); |
649 | free_event_buffer(iommu); | ||
625 | iommu_unmap_mmio_space(iommu); | 650 | iommu_unmap_mmio_space(iommu); |
626 | } | 651 | } |
627 | 652 | ||
@@ -661,6 +686,10 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) | |||
661 | if (!iommu->cmd_buf) | 686 | if (!iommu->cmd_buf) |
662 | return -ENOMEM; | 687 | return -ENOMEM; |
663 | 688 | ||
689 | iommu->evt_buf = alloc_event_buffer(iommu); | ||
690 | if (!iommu->evt_buf) | ||
691 | return -ENOMEM; | ||
692 | |||
664 | init_iommu_from_pci(iommu); | 693 | init_iommu_from_pci(iommu); |
665 | init_iommu_from_acpi(iommu, h); | 694 | init_iommu_from_acpi(iommu, h); |
666 | init_iommu_devices(iommu); | 695 | init_iommu_devices(iommu); |
diff --git a/include/asm-x86/amd_iommu_types.h b/include/asm-x86/amd_iommu_types.h index dcc472445ffd..8b8cd0c60b3c 100644 --- a/include/asm-x86/amd_iommu_types.h +++ b/include/asm-x86/amd_iommu_types.h | |||
@@ -116,6 +116,10 @@ | |||
116 | #define MMIO_CMD_SIZE_SHIFT 56 | 116 | #define MMIO_CMD_SIZE_SHIFT 56 |
117 | #define MMIO_CMD_SIZE_512 (0x9ULL << MMIO_CMD_SIZE_SHIFT) | 117 | #define MMIO_CMD_SIZE_512 (0x9ULL << MMIO_CMD_SIZE_SHIFT) |
118 | 118 | ||
119 | /* constants for event buffer handling */ | ||
120 | #define EVT_BUFFER_SIZE 8192 /* 512 entries */ | ||
121 | #define EVT_LEN_MASK (0x9ULL << 56) | ||
122 | |||
119 | #define PAGE_MODE_1_LEVEL 0x01 | 123 | #define PAGE_MODE_1_LEVEL 0x01 |
120 | #define PAGE_MODE_2_LEVEL 0x02 | 124 | #define PAGE_MODE_2_LEVEL 0x02 |
121 | #define PAGE_MODE_3_LEVEL 0x03 | 125 | #define PAGE_MODE_3_LEVEL 0x03 |
@@ -243,6 +247,11 @@ struct amd_iommu { | |||
243 | /* size of command buffer */ | 247 | /* size of command buffer */ |
244 | u32 cmd_buf_size; | 248 | u32 cmd_buf_size; |
245 | 249 | ||
250 | /* event buffer virtual address */ | ||
251 | u8 *evt_buf; | ||
252 | /* size of event buffer */ | ||
253 | u32 evt_buf_size; | ||
254 | |||
246 | /* if one, we need to send a completion wait command */ | 255 | /* if one, we need to send a completion wait command */ |
247 | int need_sync; | 256 | int need_sync; |
248 | 257 | ||