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} SMMUDevice;
84
85typedef struct SMMUNotifierNode {
86 SMMUDevice *sdev;
87 QLIST_ENTRY(SMMUNotifierNode) next;
88} SMMUNotifierNode;
89
90typedef struct SMMUPciBus {
91 PCIBus *bus;
92 SMMUDevice *pbdev[0];
93} SMMUPciBus;
94
95typedef struct SMMUIOTLBKey {
96 uint64_t iova;
97 uint16_t asid;
98} SMMUIOTLBKey;
99
100typedef struct SMMUState {
101
102 SysBusDevice dev;
103 const char *mrtypename;
104 MemoryRegion iomem;
105
106 GHashTable *smmu_pcibus_by_busptr;
107 GHashTable *configs;
108 GHashTable *iotlb;
109 SMMUPciBus *smmu_pcibus_by_bus_num[SMMU_PCI_BUS_MAX];
110 PCIBus *pci_bus;
111 QLIST_HEAD(, SMMUNotifierNode) notifiers_list;
112 uint8_t bus_num;
113 PCIBus *primary_bus;
114} SMMUState;
115
116typedef struct {
117
118 SysBusDeviceClass parent_class;
119
120
121
122 DeviceRealize parent_realize;
123
124} SMMUBaseClass;
125
126#define TYPE_ARM_SMMU "arm-smmu"
127#define ARM_SMMU(obj) OBJECT_CHECK(SMMUState, (obj), TYPE_ARM_SMMU)
128#define ARM_SMMU_CLASS(klass) \
129 OBJECT_CLASS_CHECK(SMMUBaseClass, (klass), TYPE_ARM_SMMU)
130#define ARM_SMMU_GET_CLASS(obj) \
131 OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_ARM_SMMU)
132
133
134SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num);
135
136
137static inline uint16_t smmu_get_sid(SMMUDevice *sdev)
138{
139 return PCI_BUILD_BDF(pci_bus_num(sdev->bus), sdev->devfn);
140}
141
142
143
144
145
146int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm,
147 IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info);
148
149
150
151
152
153SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova);
154
155
156IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid);
157
158#define SMMU_IOTLB_MAX_SIZE 256
159
160void smmu_iotlb_inv_all(SMMUState *s);
161void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid);
162void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova);
163
164
165void smmu_inv_notifiers_all(SMMUState *s);
166
167
168void smmu_inv_notifiers_mr(IOMMUMemoryRegion *mr);
169
170#endif
171