1 /* 2 * QEMU emulation of an RISC-V IOMMU 3 * 4 * Copyright (C) 2022-2023 Rivos Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2 or later, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #ifndef HW_RISCV_IOMMU_STATE_H 20 #define HW_RISCV_IOMMU_STATE_H 21 22 #include "qom/object.h" 23 #include "hw/riscv/iommu.h" 24 #include "hw/riscv/riscv-iommu-bits.h" 25 26 typedef enum riscv_iommu_igs_modes riscv_iommu_igs_mode; 27 28 struct RISCVIOMMUState { 29 /*< private >*/ 30 DeviceState parent_obj; 31 32 /*< public >*/ 33 uint32_t version; /* Reported interface version number */ 34 uint32_t pid_bits; /* process identifier width */ 35 uint32_t bus; /* PCI bus mapping for non-root endpoints */ 36 37 uint64_t cap; /* IOMMU supported capabilities */ 38 uint64_t fctl; /* IOMMU enabled features */ 39 uint64_t icvec_avail_vectors; /* Available interrupt vectors in ICVEC */ 40 41 bool enable_off; /* Enable out-of-reset OFF mode (DMA disabled) */ 42 bool enable_msi; /* Enable MSI remapping */ 43 bool enable_ats; /* Enable ATS support */ 44 bool enable_s_stage; /* Enable S/VS-Stage translation */ 45 bool enable_g_stage; /* Enable G-Stage translation */ 46 47 /* IOMMU Internal State */ 48 uint64_t ddtp; /* Validated Device Directory Tree Root Pointer */ 49 50 dma_addr_t cq_addr; /* Command queue base physical address */ 51 dma_addr_t fq_addr; /* Fault/event queue base physical address */ 52 dma_addr_t pq_addr; /* Page request queue base physical address */ 53 54 uint32_t cq_mask; /* Command queue index bit mask */ 55 uint32_t fq_mask; /* Fault/event queue index bit mask */ 56 uint32_t pq_mask; /* Page request queue index bit mask */ 57 58 /* interrupt notifier */ 59 void (*notify)(RISCVIOMMUState *iommu, unsigned vector); 60 61 /* IOMMU State Machine */ 62 QemuThread core_proc; /* Background processing thread */ 63 QemuCond core_cond; /* Background processing wake up signal */ 64 unsigned core_exec; /* Processing thread execution actions */ 65 66 /* IOMMU target address space */ 67 AddressSpace *target_as; 68 MemoryRegion *target_mr; 69 70 /* MSI / MRIF access trap */ 71 AddressSpace trap_as; 72 MemoryRegion trap_mr; 73 74 GHashTable *ctx_cache; /* Device translation Context Cache */ 75 76 GHashTable *iot_cache; /* IO Translated Address Cache */ 77 unsigned iot_limit; /* IO Translation Cache size limit */ 78 79 /* MMIO Hardware Interface */ 80 MemoryRegion regs_mr; 81 uint8_t *regs_rw; /* register state (user write) */ 82 uint8_t *regs_wc; /* write-1-to-clear mask */ 83 uint8_t *regs_ro; /* read-only mask */ 84 85 QLIST_ENTRY(RISCVIOMMUState) iommus; 86 QLIST_HEAD(, RISCVIOMMUSpace) spaces; 87 }; 88 89 void riscv_iommu_pci_setup_iommu(RISCVIOMMUState *iommu, PCIBus *bus, 90 Error **errp); 91 void riscv_iommu_set_cap_igs(RISCVIOMMUState *s, riscv_iommu_igs_mode mode); 92 void riscv_iommu_reset(RISCVIOMMUState *s); 93 94 /* private helpers */ 95 96 /* Register helper functions */ 97 static inline uint32_t riscv_iommu_reg_mod32(RISCVIOMMUState *s, 98 unsigned idx, uint32_t set, uint32_t clr) 99 { 100 uint32_t val = ldl_le_p(s->regs_rw + idx); 101 stl_le_p(s->regs_rw + idx, (val & ~clr) | set); 102 return val; 103 } 104 105 static inline void riscv_iommu_reg_set32(RISCVIOMMUState *s, unsigned idx, 106 uint32_t set) 107 { 108 stl_le_p(s->regs_rw + idx, set); 109 } 110 111 static inline uint32_t riscv_iommu_reg_get32(RISCVIOMMUState *s, unsigned idx) 112 { 113 return ldl_le_p(s->regs_rw + idx); 114 } 115 116 static inline uint64_t riscv_iommu_reg_mod64(RISCVIOMMUState *s, unsigned idx, 117 uint64_t set, uint64_t clr) 118 { 119 uint64_t val = ldq_le_p(s->regs_rw + idx); 120 stq_le_p(s->regs_rw + idx, (val & ~clr) | set); 121 return val; 122 } 123 124 static inline void riscv_iommu_reg_set64(RISCVIOMMUState *s, unsigned idx, 125 uint64_t set) 126 { 127 stq_le_p(s->regs_rw + idx, set); 128 } 129 130 static inline uint64_t riscv_iommu_reg_get64(RISCVIOMMUState *s, 131 unsigned idx) 132 { 133 return ldq_le_p(s->regs_rw + idx); 134 } 135 #endif 136