Skip to content

Commit 856c0cf

Browse files
tjeznachjoergroedel
authored andcommitted
iommu/riscv: Command and fault queue support
Introduce device command submission and fault reporting queues, as described in Chapter 3.1 and 3.2 of the RISC-V IOMMU Architecture Specification. Command and fault queues are instantiated in contiguous system memory local to IOMMU device domain, or mapped from fixed I/O space provided by the hardware implementation. Detection of the location and maximum allowed size of the queue utilize WARL properties of queue base control register. Driver implementation will try to allocate up to 128KB of system memory, while respecting hardware supported maximum queue size. Interrupts allocation is based on interrupt vectors availability and distributed to all queues in simple round-robin fashion. For hardware Implementation with fixed event type to interrupt vector assignment IVEC WARL property is used to discover such mappings. Address translation, command and queue fault handling in this change is limited to simple fault reporting without taking any action. Reviewed-by: Lu Baolu <[email protected]> Reviewed-by: Zong Li <[email protected]> Signed-off-by: Tomasz Jeznach <[email protected]> Acked-by: Palmer Dabbelt <[email protected]> Link: https://lore.kernel.org/r/c4735fb6829053eff37ce1bcca4906192afd743c.1729059707.git.tjeznach@rivosinc.com Signed-off-by: Joerg Roedel <[email protected]>
1 parent 1bac10c commit 856c0cf

File tree

3 files changed

+613
-2
lines changed

3 files changed

+613
-2
lines changed

drivers/iommu/riscv/iommu-bits.h

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,4 +706,79 @@ struct riscv_iommu_msipte {
706706
#define RISCV_IOMMU_MSIPTE_MRIF_NPPN RISCV_IOMMU_PPN_FIELD
707707
#define RISCV_IOMMU_MSIPTE_MRIF_NID_MSB BIT_ULL(60)
708708

709+
/* Helper functions: command structure builders. */
710+
711+
static inline void riscv_iommu_cmd_inval_vma(struct riscv_iommu_command *cmd)
712+
{
713+
cmd->dword0 = FIELD_PREP(RISCV_IOMMU_CMD_OPCODE, RISCV_IOMMU_CMD_IOTINVAL_OPCODE) |
714+
FIELD_PREP(RISCV_IOMMU_CMD_FUNC, RISCV_IOMMU_CMD_IOTINVAL_FUNC_VMA);
715+
cmd->dword1 = 0;
716+
}
717+
718+
static inline void riscv_iommu_cmd_inval_set_addr(struct riscv_iommu_command *cmd,
719+
u64 addr)
720+
{
721+
cmd->dword1 = FIELD_PREP(RISCV_IOMMU_CMD_IOTINVAL_ADDR, phys_to_pfn(addr));
722+
cmd->dword0 |= RISCV_IOMMU_CMD_IOTINVAL_AV;
723+
}
724+
725+
static inline void riscv_iommu_cmd_inval_set_pscid(struct riscv_iommu_command *cmd,
726+
int pscid)
727+
{
728+
cmd->dword0 |= FIELD_PREP(RISCV_IOMMU_CMD_IOTINVAL_PSCID, pscid) |
729+
RISCV_IOMMU_CMD_IOTINVAL_PSCV;
730+
}
731+
732+
static inline void riscv_iommu_cmd_inval_set_gscid(struct riscv_iommu_command *cmd,
733+
int gscid)
734+
{
735+
cmd->dword0 |= FIELD_PREP(RISCV_IOMMU_CMD_IOTINVAL_GSCID, gscid) |
736+
RISCV_IOMMU_CMD_IOTINVAL_GV;
737+
}
738+
739+
static inline void riscv_iommu_cmd_iofence(struct riscv_iommu_command *cmd)
740+
{
741+
cmd->dword0 = FIELD_PREP(RISCV_IOMMU_CMD_OPCODE, RISCV_IOMMU_CMD_IOFENCE_OPCODE) |
742+
FIELD_PREP(RISCV_IOMMU_CMD_FUNC, RISCV_IOMMU_CMD_IOFENCE_FUNC_C) |
743+
RISCV_IOMMU_CMD_IOFENCE_PR | RISCV_IOMMU_CMD_IOFENCE_PW;
744+
cmd->dword1 = 0;
745+
}
746+
747+
static inline void riscv_iommu_cmd_iofence_set_av(struct riscv_iommu_command *cmd,
748+
u64 addr, u32 data)
749+
{
750+
cmd->dword0 = FIELD_PREP(RISCV_IOMMU_CMD_OPCODE, RISCV_IOMMU_CMD_IOFENCE_OPCODE) |
751+
FIELD_PREP(RISCV_IOMMU_CMD_FUNC, RISCV_IOMMU_CMD_IOFENCE_FUNC_C) |
752+
FIELD_PREP(RISCV_IOMMU_CMD_IOFENCE_DATA, data) |
753+
RISCV_IOMMU_CMD_IOFENCE_AV;
754+
cmd->dword1 = addr >> 2;
755+
}
756+
757+
static inline void riscv_iommu_cmd_iodir_inval_ddt(struct riscv_iommu_command *cmd)
758+
{
759+
cmd->dword0 = FIELD_PREP(RISCV_IOMMU_CMD_OPCODE, RISCV_IOMMU_CMD_IODIR_OPCODE) |
760+
FIELD_PREP(RISCV_IOMMU_CMD_FUNC, RISCV_IOMMU_CMD_IODIR_FUNC_INVAL_DDT);
761+
cmd->dword1 = 0;
762+
}
763+
764+
static inline void riscv_iommu_cmd_iodir_inval_pdt(struct riscv_iommu_command *cmd)
765+
{
766+
cmd->dword0 = FIELD_PREP(RISCV_IOMMU_CMD_OPCODE, RISCV_IOMMU_CMD_IODIR_OPCODE) |
767+
FIELD_PREP(RISCV_IOMMU_CMD_FUNC, RISCV_IOMMU_CMD_IODIR_FUNC_INVAL_PDT);
768+
cmd->dword1 = 0;
769+
}
770+
771+
static inline void riscv_iommu_cmd_iodir_set_did(struct riscv_iommu_command *cmd,
772+
unsigned int devid)
773+
{
774+
cmd->dword0 |= FIELD_PREP(RISCV_IOMMU_CMD_IODIR_DID, devid) |
775+
RISCV_IOMMU_CMD_IODIR_DV;
776+
}
777+
778+
static inline void riscv_iommu_cmd_iodir_set_pid(struct riscv_iommu_command *cmd,
779+
unsigned int pasid)
780+
{
781+
cmd->dword0 |= FIELD_PREP(RISCV_IOMMU_CMD_IODIR_PID, pasid);
782+
}
783+
709784
#endif /* _RISCV_IOMMU_BITS_H_ */

0 commit comments

Comments
 (0)