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