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