]>
Commit | Line | Data |
---|---|---|
527773ee EA |
1 | /* |
2 | * ARM SMMU Support | |
3 | * | |
4 | * Copyright (C) 2015-2016 Broadcom Corporation | |
5 | * Copyright (c) 2017 Red Hat, Inc. | |
6 | * Written by Prem Mallappa, Eric Auger | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License version 2 as | |
10 | * published by the Free Software Foundation. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
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" | |
db1015e9 | 24 | #include "qom/object.h" |
527773ee EA |
25 | |
26 | #define SMMU_PCI_BUS_MAX 256 | |
27 | #define SMMU_PCI_DEVFN_MAX 256 | |
b78aae9b | 28 | #define SMMU_PCI_DEVFN(sid) (sid & 0xFF) |
527773ee EA |
29 | |
30 | #define SMMU_MAX_VA_BITS 48 | |
31 | ||
32 | /* | |
33 | * Page table walk error types | |
34 | */ | |
35 | typedef enum { | |
36 | SMMU_PTW_ERR_NONE, | |
37 | SMMU_PTW_ERR_WALK_EABT, /* Translation walk external abort */ | |
38 | SMMU_PTW_ERR_TRANSLATION, /* Translation fault */ | |
39 | SMMU_PTW_ERR_ADDR_SIZE, /* Address Size fault */ | |
40 | SMMU_PTW_ERR_ACCESS, /* Access fault */ | |
41 | SMMU_PTW_ERR_PERMISSION, /* Permission fault */ | |
42 | } SMMUPTWEventType; | |
43 | ||
44 | typedef struct SMMUPTWEventInfo { | |
45 | SMMUPTWEventType type; | |
46 | dma_addr_t addr; /* fetched address that induced an abort, if any */ | |
47 | } SMMUPTWEventInfo; | |
48 | ||
49 | typedef struct SMMUTransTableInfo { | |
50 | bool disabled; /* is the translation table disabled? */ | |
51 | uint64_t ttb; /* TT base address */ | |
52 | uint8_t tsz; /* input range, ie. 2^(64 -tsz)*/ | |
53 | uint8_t granule_sz; /* granule page shift */ | |
e7c3b9d9 | 54 | bool had; /* hierarchical attribute disable */ |
527773ee EA |
55 | } SMMUTransTableInfo; |
56 | ||
a7550158 EA |
57 | typedef struct SMMUTLBEntry { |
58 | IOMMUTLBEntry entry; | |
59 | uint8_t level; | |
60 | uint8_t granule; | |
61 | } SMMUTLBEntry; | |
62 | ||
527773ee EA |
63 | /* |
64 | * Generic structure populated by derived SMMU devices | |
65 | * after decoding the configuration information and used as | |
66 | * input to the page table walk | |
67 | */ | |
68 | typedef struct SMMUTransCfg { | |
69 | int stage; /* translation stage */ | |
70 | bool aa64; /* arch64 or aarch32 translation table */ | |
71 | bool disabled; /* smmu is disabled */ | |
72 | bool bypassed; /* translation is bypassed */ | |
73 | bool aborted; /* translation is aborted */ | |
ced71694 | 74 | bool record_faults; /* record fault events */ |
527773ee EA |
75 | uint64_t ttb; /* TT base address */ |
76 | uint8_t oas; /* output address width */ | |
77 | uint8_t tbi; /* Top Byte Ignore */ | |
78 | uint16_t asid; | |
79 | SMMUTransTableInfo tt[2]; | |
cc27ed81 EA |
80 | uint32_t iotlb_hits; /* counts IOTLB hits for this asid */ |
81 | uint32_t iotlb_misses; /* counts IOTLB misses for this asid */ | |
527773ee EA |
82 | } SMMUTransCfg; |
83 | ||
84 | typedef struct SMMUDevice { | |
85 | void *smmu; | |
86 | PCIBus *bus; | |
87 | int devfn; | |
88 | IOMMUMemoryRegion iommu; | |
89 | AddressSpace as; | |
32cfd7f3 EA |
90 | uint32_t cfg_cache_hits; |
91 | uint32_t cfg_cache_misses; | |
c6370441 | 92 | QLIST_ENTRY(SMMUDevice) next; |
527773ee EA |
93 | } SMMUDevice; |
94 | ||
527773ee EA |
95 | typedef struct SMMUPciBus { |
96 | PCIBus *bus; | |
f7795e40 | 97 | SMMUDevice *pbdev[]; /* Parent array is sparse, so dynamically alloc */ |
527773ee EA |
98 | } SMMUPciBus; |
99 | ||
cc27ed81 EA |
100 | typedef struct SMMUIOTLBKey { |
101 | uint64_t iova; | |
102 | uint16_t asid; | |
9e54dee7 EA |
103 | uint8_t tg; |
104 | uint8_t level; | |
cc27ed81 EA |
105 | } SMMUIOTLBKey; |
106 | ||
db1015e9 | 107 | struct SMMUState { |
527773ee EA |
108 | /* <private> */ |
109 | SysBusDevice dev; | |
110 | const char *mrtypename; | |
111 | MemoryRegion iomem; | |
112 | ||
113 | GHashTable *smmu_pcibus_by_busptr; | |
114 | GHashTable *configs; /* cache for configuration data */ | |
115 | GHashTable *iotlb; | |
116 | SMMUPciBus *smmu_pcibus_by_bus_num[SMMU_PCI_BUS_MAX]; | |
117 | PCIBus *pci_bus; | |
c6370441 | 118 | QLIST_HEAD(, SMMUDevice) devices_with_notifiers; |
527773ee EA |
119 | uint8_t bus_num; |
120 | PCIBus *primary_bus; | |
db1015e9 | 121 | }; |
527773ee | 122 | |
db1015e9 | 123 | struct SMMUBaseClass { |
527773ee EA |
124 | /* <private> */ |
125 | SysBusDeviceClass parent_class; | |
126 | ||
127 | /*< public >*/ | |
128 | ||
129 | DeviceRealize parent_realize; | |
130 | ||
db1015e9 | 131 | }; |
527773ee EA |
132 | |
133 | #define TYPE_ARM_SMMU "arm-smmu" | |
a489d195 | 134 | OBJECT_DECLARE_TYPE(SMMUState, SMMUBaseClass, ARM_SMMU) |
527773ee | 135 | |
cac994ef EA |
136 | /* Return the SMMUPciBus handle associated to a PCI bus number */ |
137 | SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num); | |
138 | ||
139 | /* Return the stream ID of an SMMU device */ | |
140 | static inline uint16_t smmu_get_sid(SMMUDevice *sdev) | |
141 | { | |
142 | return PCI_BUILD_BDF(pci_bus_num(sdev->bus), sdev->devfn); | |
143 | } | |
93641948 EA |
144 | |
145 | /** | |
146 | * smmu_ptw - Perform the page table walk for a given iova / access flags | |
147 | * pair, according to @cfg translation config | |
148 | */ | |
149 | int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm, | |
a7550158 | 150 | SMMUTLBEntry *tlbe, SMMUPTWEventInfo *info); |
93641948 EA |
151 | |
152 | /** | |
153 | * select_tt - compute which translation table shall be used according to | |
154 | * the input iova and translation config and return the TT specific info | |
155 | */ | |
156 | SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova); | |
157 | ||
32cfd7f3 EA |
158 | /* Return the iommu mr associated to @sid, or NULL if none */ |
159 | IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid); | |
160 | ||
cc27ed81 EA |
161 | #define SMMU_IOTLB_MAX_SIZE 256 |
162 | ||
9e54dee7 EA |
163 | SMMUTLBEntry *smmu_iotlb_lookup(SMMUState *bs, SMMUTransCfg *cfg, |
164 | SMMUTransTableInfo *tt, hwaddr iova); | |
a7550158 | 165 | void smmu_iotlb_insert(SMMUState *bs, SMMUTransCfg *cfg, SMMUTLBEntry *entry); |
9e54dee7 EA |
166 | SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova, |
167 | uint8_t tg, uint8_t level); | |
cc27ed81 EA |
168 | void smmu_iotlb_inv_all(SMMUState *s); |
169 | void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid); | |
d5291561 EA |
170 | void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova, |
171 | uint8_t tg, uint64_t num_pages, uint8_t ttl); | |
cc27ed81 | 172 | |
832e4222 EA |
173 | /* Unmap the range of all the notifiers registered to any IOMMU mr */ |
174 | void smmu_inv_notifiers_all(SMMUState *s); | |
175 | ||
6834c3f4 | 176 | #endif /* HW_ARM_SMMU_COMMON_H */ |