1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#ifndef HW_ARM_SMMU_COMMON_H
20#define HW_ARM_SMMU_COMMON_H
21
22#include "hw/sysbus.h"
23#include "hw/pci/pci.h"
24#include "qom/object.h"
25
26#define SMMU_PCI_BUS_MAX 256
27#define SMMU_PCI_DEVFN_MAX 256
28#define SMMU_PCI_DEVFN(sid) (sid & 0xFF)
29
30#define SMMU_MAX_VA_BITS 48
31
32#define SMMU_MAX_TBU 16
33
34
35
36
37typedef enum {
38 SMMU_PTW_ERR_NONE,
39 SMMU_PTW_ERR_WALK_EABT,
40 SMMU_PTW_ERR_TRANSLATION,
41 SMMU_PTW_ERR_ADDR_SIZE,
42 SMMU_PTW_ERR_ACCESS,
43 SMMU_PTW_ERR_PERMISSION,
44} SMMUPTWEventType;
45
46typedef struct SMMUPTWEventInfo {
47 SMMUPTWEventType type;
48 dma_addr_t addr;
49} SMMUPTWEventInfo;
50
51typedef struct SMMUTransTableInfo {
52 bool disabled;
53 uint64_t ttb;
54 uint8_t tsz;
55 uint8_t granule_sz;
56 bool had;
57} SMMUTransTableInfo;
58
59typedef struct SMMUTLBEntry {
60 IOMMUTLBEntry entry;
61 uint8_t level;
62 uint8_t granule;
63} SMMUTLBEntry;
64
65
66
67
68
69
70typedef struct SMMUTransCfg {
71 int stage;
72 bool aa64;
73 bool disabled;
74 bool bypassed;
75 bool aborted;
76 bool affd;
77 uint64_t ttb;
78 uint8_t s2_sl0;
79 uint8_t oas;
80 uint8_t tbi;
81 uint32_t asid;
82 SMMUTransTableInfo tt[2];
83 uint32_t iotlb_hits;
84 uint32_t iotlb_misses;
85} SMMUTransCfg;
86
87typedef struct SMMUDevice {
88 void *smmu;
89 PCIBus *bus;
90 int devfn;
91 IOMMUMemoryRegion iommu;
92 AddressSpace as;
93 AddressSpace as_downstream;
94 uint32_t cfg_cache_hits;
95 uint32_t cfg_cache_misses;
96 QLIST_ENTRY(SMMUDevice) next;
97} SMMUDevice;
98
99typedef struct SMMUPciBus {
100 PCIBus *bus;
101 SMMUDevice *pbdev[];
102} SMMUPciBus;
103
104typedef struct SMMUIOTLBKey {
105 uint64_t iova;
106 uint16_t asid;
107 uint8_t tg;
108 uint8_t level;
109} SMMUIOTLBKey;
110
111struct SMMUState {
112
113 SysBusDevice dev;
114 const char *mrtypename;
115 MemoryRegion iomem;
116
117 GHashTable *smmu_pcibus_by_busptr;
118 GHashTable *configs;
119 GHashTable *iotlb;
120 SMMUPciBus *smmu_pcibus_by_bus_num[SMMU_PCI_BUS_MAX];
121 PCIBus *pci_bus;
122 QLIST_HEAD(, SMMUDevice) devices_with_notifiers;
123 uint8_t bus_num;
124 PCIBus *primary_bus;
125
126 struct {
127 MemoryRegion *mr;
128 SMMUDevice *sdev;
129 } tbu[SMMU_MAX_TBU];
130};
131
132struct SMMUBaseClass {
133
134 SysBusDeviceClass parent_class;
135
136
137
138 DeviceRealize parent_realize;
139
140};
141
142#define TYPE_ARM_SMMU "arm-smmu"
143OBJECT_DECLARE_TYPE(SMMUState, SMMUBaseClass, ARM_SMMU)
144
145
146SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num);
147
148
149static inline uint16_t smmu_get_sid(SMMUDevice *sdev)
150{
151 return PCI_BUILD_BDF(pci_bus_num(sdev->bus), sdev->devfn);
152}
153
154
155
156
157
158int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
159 SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info);
160
161
162
163
164
165SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova);
166
167
168IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid);
169
170#define SMMU_IOTLB_MAX_SIZE 256
171
172SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg,
173 SMMUTransTableInfo *tt, hwaddr iova);
174void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *entry);
175SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova,
176 uint8_t tg, uint8_t level);
177void smmu_iotlb_inv_all(SMMUState *s);
178void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid);
179void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
180 uint8_t tg, uint64_t num_pages, uint8_t ttl);
181
182
183void smmu_inv_notifiers_all(SMMUState *s);
184
185
186void smmu_inv_notifiers_mr(IOMMUMemoryRegion *mr);
187
188#endif
189