diff options
author | Wei Wang <wei.wang2@amd.com> | 2012-01-12 13:49:34 +0100 |
---|---|---|
committer | Wei Wang <wei.wang2@amd.com> | 2012-01-12 13:49:34 +0100 |
commit | 262bb227a4f27d0d18dfd2151798a884967db9b6 (patch) | |
tree | f748842e3b55c4de49186367b239d0cf14479272 | |
parent | 7ec332ba83b835e802e186c860aceccbaf3fd1c6 (diff) | |
download | xen-262bb227a4f27d0d18dfd2151798a884967db9b6.tar.gz xen-262bb227a4f27d0d18dfd2151798a884967db9b6.tar.bz2 xen-262bb227a4f27d0d18dfd2151798a884967db9b6.zip |
amd iommu: Introduces new helper functions to simplify bitwise operations
Signed-off-by: Wei Wang <wei.wang2@amd.com>
Committed-by: Jan Beulich <jbeulich@suse.com>
-rw-r--r-- | xen/drivers/passthrough/amd/iommu_cmd.c | 12 | ||||
-rw-r--r-- | xen/drivers/passthrough/amd/iommu_init.c | 50 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/svm/amd-iommu-defs.h | 33 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 67 |
4 files changed, 110 insertions, 52 deletions
diff --git a/xen/drivers/passthrough/amd/iommu_cmd.c b/xen/drivers/passthrough/amd/iommu_cmd.c index 9b2fd6c586..d146a7e698 100644 --- a/xen/drivers/passthrough/amd/iommu_cmd.c +++ b/xen/drivers/passthrough/amd/iommu_cmd.c @@ -33,10 +33,8 @@ static int queue_iommu_command(struct amd_iommu *iommu, u32 cmd[]) if ( ++tail == iommu->cmd_buffer.entries ) tail = 0; - head = get_field_from_reg_u32(readl(iommu->mmio_base + - IOMMU_CMD_BUFFER_HEAD_OFFSET), - IOMMU_CMD_BUFFER_HEAD_MASK, - IOMMU_CMD_BUFFER_HEAD_SHIFT); + head = iommu_get_rb_pointer(readl(iommu->mmio_base + + IOMMU_CMD_BUFFER_HEAD_OFFSET)); if ( head != tail ) { cmd_buffer = (u32 *)(iommu->cmd_buffer.buffer + @@ -55,11 +53,9 @@ static int queue_iommu_command(struct amd_iommu *iommu, u32 cmd[]) static void commit_iommu_command_buffer(struct amd_iommu *iommu) { - u32 tail; + u32 tail = 0; - set_field_in_reg_u32(iommu->cmd_buffer.tail, 0, - IOMMU_CMD_BUFFER_TAIL_MASK, - IOMMU_CMD_BUFFER_TAIL_SHIFT, &tail); + iommu_set_rb_pointer(&tail, iommu->cmd_buffer.tail); writel(tail, iommu->mmio_base+IOMMU_CMD_BUFFER_TAIL_OFFSET); } diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c index d0fb075223..2626b8963b 100644 --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -106,21 +106,21 @@ static void register_iommu_dev_table_in_mmio_space(struct amd_iommu *iommu) u64 addr_64, addr_lo, addr_hi; u32 entry; + ASSERT( iommu->dev_table.buffer ); + addr_64 = (u64)virt_to_maddr(iommu->dev_table.buffer); addr_lo = addr_64 & DMA_32BIT_MASK; addr_hi = addr_64 >> 32; - set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0, - IOMMU_DEV_TABLE_BASE_LOW_MASK, - IOMMU_DEV_TABLE_BASE_LOW_SHIFT, &entry); + entry = 0; + iommu_set_addr_lo_to_reg(&entry, addr_lo >> PAGE_SHIFT); set_field_in_reg_u32((iommu->dev_table.alloc_size / PAGE_SIZE) - 1, entry, IOMMU_DEV_TABLE_SIZE_MASK, IOMMU_DEV_TABLE_SIZE_SHIFT, &entry); writel(entry, iommu->mmio_base + IOMMU_DEV_TABLE_BASE_LOW_OFFSET); - set_field_in_reg_u32((u32)addr_hi, 0, - IOMMU_DEV_TABLE_BASE_HIGH_MASK, - IOMMU_DEV_TABLE_BASE_HIGH_SHIFT, &entry); + entry = 0; + iommu_set_addr_hi_to_reg(&entry, addr_hi); writel(entry, iommu->mmio_base + IOMMU_DEV_TABLE_BASE_HIGH_OFFSET); } @@ -130,21 +130,21 @@ static void register_iommu_cmd_buffer_in_mmio_space(struct amd_iommu *iommu) u32 power_of2_entries; u32 entry; + ASSERT( iommu->cmd_buffer.buffer ); + addr_64 = (u64)virt_to_maddr(iommu->cmd_buffer.buffer); addr_lo = addr_64 & DMA_32BIT_MASK; addr_hi = addr_64 >> 32; - set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0, - IOMMU_CMD_BUFFER_BASE_LOW_MASK, - IOMMU_CMD_BUFFER_BASE_LOW_SHIFT, &entry); + entry = 0; + iommu_set_addr_lo_to_reg(&entry, addr_lo >> PAGE_SHIFT); writel(entry, iommu->mmio_base + IOMMU_CMD_BUFFER_BASE_LOW_OFFSET); power_of2_entries = get_order_from_bytes(iommu->cmd_buffer.alloc_size) + IOMMU_CMD_BUFFER_POWER_OF2_ENTRIES_PER_PAGE; - set_field_in_reg_u32((u32)addr_hi, 0, - IOMMU_CMD_BUFFER_BASE_HIGH_MASK, - IOMMU_CMD_BUFFER_BASE_HIGH_SHIFT, &entry); + entry = 0; + iommu_set_addr_hi_to_reg(&entry, addr_hi); set_field_in_reg_u32(power_of2_entries, entry, IOMMU_CMD_BUFFER_LENGTH_MASK, IOMMU_CMD_BUFFER_LENGTH_SHIFT, &entry); @@ -157,21 +157,21 @@ static void register_iommu_event_log_in_mmio_space(struct amd_iommu *iommu) u32 power_of2_entries; u32 entry; + ASSERT( iommu->event_log.buffer ); + addr_64 = (u64)virt_to_maddr(iommu->event_log.buffer); addr_lo = addr_64 & DMA_32BIT_MASK; addr_hi = addr_64 >> 32; - set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0, - IOMMU_EVENT_LOG_BASE_LOW_MASK, - IOMMU_EVENT_LOG_BASE_LOW_SHIFT, &entry); + entry = 0; + iommu_set_addr_lo_to_reg(&entry, addr_lo >> PAGE_SHIFT); writel(entry, iommu->mmio_base + IOMMU_EVENT_LOG_BASE_LOW_OFFSET); power_of2_entries = get_order_from_bytes(iommu->event_log.alloc_size) + IOMMU_EVENT_LOG_POWER_OF2_ENTRIES_PER_PAGE; - set_field_in_reg_u32((u32)addr_hi, 0, - IOMMU_EVENT_LOG_BASE_HIGH_MASK, - IOMMU_EVENT_LOG_BASE_HIGH_SHIFT, &entry); + entry = 0; + iommu_set_addr_hi_to_reg(&entry, addr_hi); set_field_in_reg_u32(power_of2_entries, entry, IOMMU_EVENT_LOG_LENGTH_MASK, IOMMU_EVENT_LOG_LENGTH_SHIFT, &entry); @@ -234,14 +234,12 @@ static void register_iommu_exclusion_range(struct amd_iommu *iommu) addr_lo = iommu->exclusion_base & DMA_32BIT_MASK; addr_hi = iommu->exclusion_base >> 32; - set_field_in_reg_u32((u32)addr_hi, 0, - IOMMU_EXCLUSION_BASE_HIGH_MASK, - IOMMU_EXCLUSION_BASE_HIGH_SHIFT, &entry); + entry = 0; + iommu_set_addr_hi_to_reg(&entry, addr_hi); writel(entry, iommu->mmio_base+IOMMU_EXCLUSION_BASE_HIGH_OFFSET); - set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0, - IOMMU_EXCLUSION_BASE_LOW_MASK, - IOMMU_EXCLUSION_BASE_LOW_SHIFT, &entry); + entry = 0; + iommu_set_addr_lo_to_reg(&entry, addr_lo >> PAGE_SHIFT); set_field_in_reg_u32(iommu->exclusion_allow_all, entry, IOMMU_EXCLUSION_ALLOW_ALL_MASK, @@ -490,9 +488,7 @@ static void parse_event_log_entry(struct amd_iommu *iommu, u32 entry[]) if ( code == IOMMU_EVENT_IO_PAGE_FAULT ) { - device_id = get_field_from_reg_u32(entry[0], - IOMMU_EVENT_DEVICE_ID_MASK, - IOMMU_EVENT_DEVICE_ID_SHIFT); + device_id = iommu_get_devid_from_event(entry[0]); domain_id = get_field_from_reg_u32(entry[1], IOMMU_EVENT_DOMAIN_ID_MASK, IOMMU_EVENT_DOMAIN_ID_SHIFT); diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h index a9325cb724..03c682c6f5 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h @@ -82,10 +82,6 @@ /* Device Table */ #define IOMMU_DEV_TABLE_BASE_LOW_OFFSET 0x00 #define IOMMU_DEV_TABLE_BASE_HIGH_OFFSET 0x04 -#define IOMMU_DEV_TABLE_BASE_LOW_MASK 0xFFFFF000 -#define IOMMU_DEV_TABLE_BASE_LOW_SHIFT 12 -#define IOMMU_DEV_TABLE_BASE_HIGH_MASK 0x000FFFFF -#define IOMMU_DEV_TABLE_BASE_HIGH_SHIFT 0 #define IOMMU_DEV_TABLE_SIZE_MASK 0x000001FF #define IOMMU_DEV_TABLE_SIZE_SHIFT 0 @@ -164,22 +160,13 @@ #define IOMMU_DEV_TABLE_INT_CONTROL_MASK 0x30000000 #define IOMMU_DEV_TABLE_INT_CONTROL_SHIFT 28 - /* Command Buffer */ #define IOMMU_CMD_BUFFER_BASE_LOW_OFFSET 0x08 #define IOMMU_CMD_BUFFER_BASE_HIGH_OFFSET 0x0C #define IOMMU_CMD_BUFFER_HEAD_OFFSET 0x2000 #define IOMMU_CMD_BUFFER_TAIL_OFFSET 0x2008 -#define IOMMU_CMD_BUFFER_BASE_LOW_MASK 0xFFFFF000 -#define IOMMU_CMD_BUFFER_BASE_LOW_SHIFT 12 -#define IOMMU_CMD_BUFFER_BASE_HIGH_MASK 0x000FFFFF -#define IOMMU_CMD_BUFFER_BASE_HIGH_SHIFT 0 #define IOMMU_CMD_BUFFER_LENGTH_MASK 0x0F000000 #define IOMMU_CMD_BUFFER_LENGTH_SHIFT 24 -#define IOMMU_CMD_BUFFER_HEAD_MASK 0x0007FFF0 -#define IOMMU_CMD_BUFFER_HEAD_SHIFT 4 -#define IOMMU_CMD_BUFFER_TAIL_MASK 0x0007FFF0 -#define IOMMU_CMD_BUFFER_TAIL_SHIFT 4 #define IOMMU_CMD_BUFFER_ENTRY_SIZE 16 #define IOMMU_CMD_BUFFER_POWER_OF2_ENTRIES_PER_PAGE 8 @@ -251,10 +238,6 @@ #define IOMMU_EVENT_LOG_BASE_HIGH_OFFSET 0x14 #define IOMMU_EVENT_LOG_HEAD_OFFSET 0x2010 #define IOMMU_EVENT_LOG_TAIL_OFFSET 0x2018 -#define IOMMU_EVENT_LOG_BASE_LOW_MASK 0xFFFFF000 -#define IOMMU_EVENT_LOG_BASE_LOW_SHIFT 12 -#define IOMMU_EVENT_LOG_BASE_HIGH_MASK 0x000FFFFF -#define IOMMU_EVENT_LOG_BASE_HIGH_SHIFT 0 #define IOMMU_EVENT_LOG_LENGTH_MASK 0x0F000000 #define IOMMU_EVENT_LOG_LENGTH_SHIFT 24 #define IOMMU_EVENT_LOG_HEAD_MASK 0x0007FFF0 @@ -440,4 +423,20 @@ #define INV_IOMMU_ALL_PAGES_ADDRESS ((1ULL << 63) - 1) +#define IOMMU_RING_BUFFER_PTR_MASK 0x0007FFF0 +#define IOMMU_RING_BUFFER_PTR_SHIFT 4 + +#define IOMMU_CMD_DEVICE_ID_MASK 0x0000FFFF +#define IOMMU_CMD_DEVICE_ID_SHIFT 0 + +#define IOMMU_CMD_ADDR_LOW_MASK 0xFFFFF000 +#define IOMMU_CMD_ADDR_LOW_SHIFT 12 +#define IOMMU_CMD_ADDR_HIGH_MASK 0xFFFFFFFF +#define IOMMU_CMD_ADDR_HIGH_SHIFT 0 + +#define IOMMU_REG_BASE_ADDR_LOW_MASK 0xFFFFF000 +#define IOMMU_REG_BASE_ADDR_LOW_SHIFT 12 +#define IOMMU_REG_BASE_ADDR_HIGH_MASK 0x000FFFFF +#define IOMMU_REG_BASE_ADDR_HIGH_SHIFT 0 + #endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */ 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 4648640b13..f3b9376e2b 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h @@ -192,4 +192,71 @@ static inline int iommu_has_feature(struct amd_iommu *iommu, uint32_t bit) return !!(iommu->features & (1U << bit)); } +/* access tail or head pointer of ring buffer */ +static inline uint32_t iommu_get_rb_pointer(uint32_t reg) +{ + return get_field_from_reg_u32(reg, IOMMU_RING_BUFFER_PTR_MASK, + IOMMU_RING_BUFFER_PTR_SHIFT); +} + +static inline void iommu_set_rb_pointer(uint32_t *reg, uint32_t val) +{ + set_field_in_reg_u32(val, *reg, IOMMU_RING_BUFFER_PTR_MASK, + IOMMU_RING_BUFFER_PTR_SHIFT, reg); +} + +/* access device id field from iommu cmd */ +static inline uint16_t iommu_get_devid_from_cmd(uint32_t cmd) +{ + return get_field_from_reg_u32(cmd, IOMMU_CMD_DEVICE_ID_MASK, + IOMMU_CMD_DEVICE_ID_SHIFT); +} + +static inline void iommu_set_devid_to_cmd(uint32_t *cmd, uint16_t id) +{ + set_field_in_reg_u32(id, *cmd, IOMMU_CMD_DEVICE_ID_MASK, + IOMMU_CMD_DEVICE_ID_SHIFT, cmd); +} + +/* access address field from iommu cmd */ +static inline uint32_t iommu_get_addr_lo_from_cmd(uint32_t cmd) +{ + return get_field_from_reg_u32(cmd, IOMMU_CMD_ADDR_LOW_MASK, + IOMMU_CMD_ADDR_LOW_SHIFT); +} + +static inline uint32_t iommu_get_addr_hi_from_cmd(uint32_t cmd) +{ + return get_field_from_reg_u32(cmd, IOMMU_CMD_ADDR_LOW_MASK, + IOMMU_CMD_ADDR_HIGH_SHIFT); +} + +/* access address field from event log entry */ +#define iommu_get_devid_from_event iommu_get_devid_from_cmd + +/* access iommu base addresses field from mmio regs */ +static inline void iommu_set_addr_lo_to_reg(uint32_t *reg, uint32_t addr) +{ + set_field_in_reg_u32(addr, *reg, IOMMU_REG_BASE_ADDR_LOW_MASK, + IOMMU_REG_BASE_ADDR_LOW_SHIFT, reg); +} + +static inline void iommu_set_addr_hi_to_reg(uint32_t *reg, uint32_t addr) +{ + set_field_in_reg_u32(addr, *reg, IOMMU_REG_BASE_ADDR_HIGH_MASK, + IOMMU_REG_BASE_ADDR_HIGH_SHIFT, reg); +} + +static inline uint32_t iommu_get_addr_lo_from_reg(uint32_t reg) +{ + return get_field_from_reg_u32(reg, IOMMU_REG_BASE_ADDR_LOW_MASK, + IOMMU_REG_BASE_ADDR_LOW_SHIFT); +} + +static inline uint32_t iommu_get_addr_hi_from_reg(uint32_t reg) +{ + return get_field_from_reg_u32(reg, IOMMU_REG_BASE_ADDR_HIGH_MASK, + IOMMU_REG_BASE_ADDR_HIGH_SHIFT); +} + #endif /* _ASM_X86_64_AMD_IOMMU_PROTO_H */ |