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