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/qdev-properties.h" 24 #include "system/dma.h" 25 #include "hw/riscv/iommu.h" 26 #include "hw/riscv/riscv-iommu-bits.h" 27 28 typedef enum riscv_iommu_igs_modes riscv_iommu_igs_mode; 29 30 struct RISCVIOMMUState { 31 /*< private >*/ 32 DeviceState parent_obj; 33 34 /*< public >*/ 35 uint32_t version; /* Reported interface version number */ 36 uint32_t pid_bits; /* process identifier width */ 37 uint32_t bus; /* PCI bus mapping for non-root endpoints */ 38 39 uint64_t cap; /* IOMMU supported capabilities */ 40 uint64_t fctl; /* IOMMU enabled features */ 41 uint64_t icvec_avail_vectors; /* Available interrupt vectors in ICVEC */ 42 43 bool enable_off; /* Enable out-of-reset OFF mode (DMA disabled) */ 44 bool enable_msi; /* Enable MSI remapping */ 45 bool enable_ats; /* Enable ATS support */ 46 bool enable_s_stage; /* Enable S/VS-Stage translation */ 47 bool enable_g_stage; /* Enable G-Stage translation */ 48 49 /* IOMMU Internal State */ 50 uint64_t ddtp; /* Validated Device Directory Tree Root Pointer */ 51 52 dma_addr_t cq_addr; /* Command queue base physical address */ 53 dma_addr_t fq_addr; /* Fault/event queue base physical address */ 54 dma_addr_t pq_addr; /* Page request queue base physical address */ 55 56 uint32_t cq_mask; /* Command queue index bit mask */ 57 uint32_t fq_mask; /* Fault/event queue index bit mask */ 58 uint32_t pq_mask; /* Page request queue index bit mask */ 59 60 /* interrupt notifier */ 61 void (*notify)(RISCVIOMMUState *iommu, unsigned vector); 62 63 /* IOMMU target address space */ 64 AddressSpace *target_as; 65 MemoryRegion *target_mr; 66 67 /* MSI / MRIF access trap */ 68 AddressSpace trap_as; 69 MemoryRegion trap_mr; 70 71 GHashTable *ctx_cache; /* Device translation Context Cache */ 72 73 GHashTable *iot_cache; /* IO Translated Address Cache */ 74 unsigned iot_limit; /* IO Translation Cache size limit */ 75 76 /* MMIO Hardware Interface */ 77 MemoryRegion regs_mr; 78 uint8_t *regs_rw; /* register state (user write) */ 79 uint8_t *regs_wc; /* write-1-to-clear mask */ 80 uint8_t *regs_ro; /* read-only mask */ 81 82 QLIST_ENTRY(RISCVIOMMUState) iommus; 83 QLIST_HEAD(, RISCVIOMMUSpace) spaces; 84 85 /* HPM cycle counter */ 86 QEMUTimer *hpm_timer; 87 uint64_t hpmcycle_val; /* Current value of cycle register */ 88 uint64_t hpmcycle_prev; /* Saved value of QEMU_CLOCK_VIRTUAL clock */ 89 uint64_t irq_overflow_left; /* Value beyond INT64_MAX after overflow */ 90 91 /* HPM event counters */ 92 GHashTable *hpm_event_ctr_map; /* Mapping of events to counters */ 93 uint8_t hpm_cntrs; 94 }; 95 96 void riscv_iommu_pci_setup_iommu(RISCVIOMMUState *iommu, PCIBus *bus, 97 Error **errp); 98 void riscv_iommu_set_cap_igs(RISCVIOMMUState *s, riscv_iommu_igs_mode mode); 99 void riscv_iommu_reset(RISCVIOMMUState *s); 100 void riscv_iommu_notify(RISCVIOMMUState *s, int vec_type); 101 102 typedef struct RISCVIOMMUContext RISCVIOMMUContext; 103 /* Device translation context state. */ 104 struct RISCVIOMMUContext { 105 uint64_t devid:24; /* Requester Id, AKA device_id */ 106 uint64_t process_id:20; /* Process ID. PASID for PCIe */ 107 uint64_t tc; /* Translation Control */ 108 uint64_t ta; /* Translation Attributes */ 109 uint64_t satp; /* S-Stage address translation and protection */ 110 uint64_t gatp; /* G-Stage address translation and protection */ 111 uint64_t msi_addr_mask; /* MSI filtering - address mask */ 112 uint64_t msi_addr_pattern; /* MSI filtering - address pattern */ 113 uint64_t msiptp; /* MSI redirection page table pointer */ 114 }; 115 116 /* private helpers */ 117 118 /* Register helper functions */ 119 static inline uint32_t riscv_iommu_reg_mod32(RISCVIOMMUState *s, 120 unsigned idx, uint32_t set, uint32_t clr) 121 { 122 uint32_t val = ldl_le_p(s->regs_rw + idx); 123 stl_le_p(s->regs_rw + idx, (val & ~clr) | set); 124 return val; 125 } 126 127 static inline void riscv_iommu_reg_set32(RISCVIOMMUState *s, unsigned idx, 128 uint32_t set) 129 { 130 stl_le_p(s->regs_rw + idx, set); 131 } 132 133 static inline uint32_t riscv_iommu_reg_get32(RISCVIOMMUState *s, unsigned idx) 134 { 135 return ldl_le_p(s->regs_rw + idx); 136 } 137 138 static inline uint64_t riscv_iommu_reg_mod64(RISCVIOMMUState *s, unsigned idx, 139 uint64_t set, uint64_t clr) 140 { 141 uint64_t val = ldq_le_p(s->regs_rw + idx); 142 stq_le_p(s->regs_rw + idx, (val & ~clr) | set); 143 return val; 144 } 145 146 static inline void riscv_iommu_reg_set64(RISCVIOMMUState *s, unsigned idx, 147 uint64_t set) 148 { 149 stq_le_p(s->regs_rw + idx, set); 150 } 151 152 static inline uint64_t riscv_iommu_reg_get64(RISCVIOMMUState *s, 153 unsigned idx) 154 { 155 return ldq_le_p(s->regs_rw + idx); 156 } 157 #endif 158