mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
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>
This commit is contained in:
1 parent
7ec332ba83
commit
262bb227a4
4 files changed
+110
-52
No files matched your search
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||