]>
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" | |
24 | ||
25 | #define SMMU_PCI_BUS_MAX 256 | |
26 | #define SMMU_PCI_DEVFN_MAX 256 | |
27 | ||
28 | #define SMMU_MAX_VA_BITS 48 | |
29 | ||
30 | /* | |
31 | * Page table walk error types | |
32 | */ | |
33 | typedef enum { | |
34 | SMMU_PTW_ERR_NONE, | |
35 | SMMU_PTW_ERR_WALK_EABT, /* Translation walk external abort */ | |
36 | SMMU_PTW_ERR_TRANSLATION, /* Translation fault */ | |
37 | SMMU_PTW_ERR_ADDR_SIZE, /* Address Size fault */ | |
38 | SMMU_PTW_ERR_ACCESS, /* Access fault */ | |
39 | SMMU_PTW_ERR_PERMISSION, /* Permission fault */ | |
40 | } SMMUPTWEventType; | |
41 | ||
42 | typedef struct SMMUPTWEventInfo { | |
43 | SMMUPTWEventType type; | |
44 | dma_addr_t addr; /* fetched address that induced an abort, if any */ | |
45 | } SMMUPTWEventInfo; | |
46 | ||
47 | typedef struct SMMUTransTableInfo { | |
48 | bool disabled; /* is the translation table disabled? */ | |
49 | uint64_t ttb; /* TT base address */ | |
50 | uint8_t tsz; /* input range, ie. 2^(64 -tsz)*/ | |
51 | uint8_t granule_sz; /* granule page shift */ | |
52 | } SMMUTransTableInfo; | |
53 | ||
54 | /* | |
55 | * Generic structure populated by derived SMMU devices | |
56 | * after decoding the configuration information and used as | |
57 | * input to the page table walk | |
58 | */ | |
59 | typedef struct SMMUTransCfg { | |
60 | int stage; /* translation stage */ | |
61 | bool aa64; /* arch64 or aarch32 translation table */ | |
62 | bool disabled; /* smmu is disabled */ | |
63 | bool bypassed; /* translation is bypassed */ | |
64 | bool aborted; /* translation is aborted */ | |
65 | uint64_t ttb; /* TT base address */ | |
66 | uint8_t oas; /* output address width */ | |
67 | uint8_t tbi; /* Top Byte Ignore */ | |
68 | uint16_t asid; | |
69 | SMMUTransTableInfo tt[2]; | |
cc27ed81 EA |
70 | uint32_t iotlb_hits; /* counts IOTLB hits for this asid */ |
71 | uint32_t iotlb_misses; /* counts IOTLB misses for this asid */ | |
527773ee EA |
72 | } SMMUTransCfg; |
73 | ||
74 | typedef struct SMMUDevice { | |
75 | void *smmu; | |
76 | PCIBus *bus; | |
77 | int devfn; | |
78 | IOMMUMemoryRegion iommu; | |
79 | AddressSpace as; | |
32cfd7f3 EA |
80 | uint32_t cfg_cache_hits; |
81 | uint32_t cfg_cache_misses; | |
527773ee EA |
82 | } SMMUDevice; |
83 | ||
84 | typedef struct SMMUNotifierNode { | |
85 | SMMUDevice *sdev; | |
86 | QLIST_ENTRY(SMMUNotifierNode) next; | |
87 | } SMMUNotifierNode; | |
88 | ||
89 | typedef struct SMMUPciBus { | |
90 | PCIBus *bus; | |
91 | SMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */ | |
92 | } SMMUPciBus; | |
93 | ||
cc27ed81 EA |
94 | typedef struct SMMUIOTLBKey { |
95 | uint64_t iova; | |
96 | uint16_t asid; | |
97 | } SMMUIOTLBKey; | |
98 | ||
527773ee EA |
99 | typedef struct SMMUState { |
100 | /* <private> */ | |
101 | SysBusDevice dev; | |
102 | const char *mrtypename; | |
103 | MemoryRegion iomem; | |
104 | ||
105 | GHashTable *smmu_pcibus_by_busptr; | |
106 | GHashTable *configs; /* cache for configuration data */ | |
107 | GHashTable *iotlb; | |
108 | SMMUPciBus *smmu_pcibus_by_bus_num[SMMU_PCI_BUS_MAX]; | |
109 | PCIBus *pci_bus; | |
110 | QLIST_HEAD(, SMMUNotifierNode) notifiers_list; | |
111 | uint8_t bus_num; | |
112 | PCIBus *primary_bus; | |
113 | } SMMUState; | |
114 | ||
115 | typedef struct { | |
116 | /* <private> */ | |
117 | SysBusDeviceClass parent_class; | |
118 | ||
119 | /*< public >*/ | |
120 | ||
121 | DeviceRealize parent_realize; | |
122 | ||
123 | } SMMUBaseClass; | |
124 | ||
125 | #define TYPE_ARM_SMMU "arm-smmu" | |
126 | #define ARM_SMMU(obj) OBJECT_CHECK(SMMUState, (obj), TYPE_ARM_SMMU) | |
127 | #define ARM_SMMU_CLASS(klass) \ | |
128 | OBJECT_CLASS_CHECK(SMMUBaseClass, (klass), TYPE_ARM_SMMU) | |
129 | #define ARM_SMMU_GET_CLASS(obj) \ | |
130 | OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_ARM_SMMU) | |
131 | ||
cac994ef EA |
132 | /* Return the SMMUPciBus handle associated to a PCI bus number */ |
133 | SMMUPciBus *smmu_find_smmu_pcibus(SMMUState *s, uint8_t bus_num); | |
134 | ||
135 | /* Return the stream ID of an SMMU device */ | |
136 | static inline uint16_t smmu_get_sid(SMMUDevice *sdev) | |
137 | { | |
138 | return PCI_BUILD_BDF(pci_bus_num(sdev->bus), sdev->devfn); | |
139 | } | |
93641948 EA |
140 | |
141 | /** | |
142 | * smmu_ptw - Perform the page table walk for a given iova / access flags | |
143 | * pair, according to @cfg translation config | |
144 | */ | |
145 | int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm, | |
146 | IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info); | |
147 | ||
148 | /** | |
149 | * select_tt - compute which translation table shall be used according to | |
150 | * the input iova and translation config and return the TT specific info | |
151 | */ | |
152 | SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova); | |
153 | ||
32cfd7f3 EA |
154 | /* Return the iommu mr associated to @sid, or NULL if none */ |
155 | IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid); | |
156 | ||
cc27ed81 EA |
157 | #define SMMU_IOTLB_MAX_SIZE 256 |
158 | ||
159 | void smmu_iotlb_inv_all(SMMUState *s); | |
160 | void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid); | |
161 | void smmu_iotlb_inv_iova(SMMUState *s, uint16_t asid, dma_addr_t iova); | |
162 | ||
832e4222 EA |
163 | /* Unmap the range of all the notifiers registered to any IOMMU mr */ |
164 | void smmu_inv_notifiers_all(SMMUState *s); | |
165 | ||
166 | /* Unmap the range of all the notifiers registered to @mr */ | |
167 | void smmu_inv_notifiers_mr(IOMMUMemoryRegion *mr); | |
168 | ||
527773ee | 169 | #endif /* HW_ARM_SMMU_COMMON */ |