1 /* Copyright 2013-2016 IBM Corp.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 * implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <skiboot.h>
18 #include <pci.h>
19 #include <pci-virt.h>
20
pci_virt_cfg_read_raw(struct pci_virt_device * pvd,uint32_t space,uint32_t offset,uint32_t size,uint32_t * data)21 void pci_virt_cfg_read_raw(struct pci_virt_device *pvd,
22 uint32_t space, uint32_t offset,
23 uint32_t size, uint32_t *data)
24 {
25 uint32_t i;
26
27 if (space >= PCI_VIRT_CFG_MAX || !pvd->config[space])
28 return;
29
30 for (*data = 0, i = 0; i < size; i++)
31 *data |= ((uint32_t)(pvd->config[space][offset + i]) << (i * 8));
32 }
33
pci_virt_cfg_write_raw(struct pci_virt_device * pvd,uint32_t space,uint32_t offset,uint32_t size,uint32_t data)34 void pci_virt_cfg_write_raw(struct pci_virt_device *pvd,
35 uint32_t space, uint32_t offset,
36 uint32_t size, uint32_t data)
37 {
38 int i;
39
40 if (space >= PCI_VIRT_CFG_MAX || !pvd->config[space])
41 return;
42
43 for (i = 0; i < size; i++) {
44 pvd->config[space][offset + i] = data;
45 data = (data >> 8);
46 }
47 }
48
pci_virt_find_filter(struct pci_virt_device * pvd,uint32_t start,uint32_t len)49 static struct pci_cfg_reg_filter *pci_virt_find_filter(
50 struct pci_virt_device *pvd,
51 uint32_t start, uint32_t len)
52 {
53 struct pci_cfg_reg_filter *pcrf;
54
55 if (!pvd || !len || start >= pvd->cfg_size)
56 return NULL;
57
58 /* Return filter if there is overlapped region. We don't
59 * require strict matching for more flexibility. It also
60 * means the associated handler should validate the register
61 * offset and length.
62 */
63 list_for_each(&pvd->pcrf, pcrf, link) {
64 if (start < (pcrf->start + pcrf->len) &&
65 (start + len) > pcrf->start)
66 return pcrf;
67 }
68
69 return NULL;
70 }
71
pci_virt_add_filter(struct pci_virt_device * pvd,uint32_t start,uint32_t len,uint32_t flags,pci_cfg_reg_func func,void * data)72 struct pci_cfg_reg_filter *pci_virt_add_filter(struct pci_virt_device *pvd,
73 uint32_t start,
74 uint32_t len,
75 uint32_t flags,
76 pci_cfg_reg_func func,
77 void *data)
78 {
79 struct pci_cfg_reg_filter *pcrf;
80
81 if (!pvd || !len || (start + len) >= pvd->cfg_size)
82 return NULL;
83 if (!(flags & PCI_REG_FLAG_MASK))
84 return NULL;
85
86 pcrf = pci_virt_find_filter(pvd, start, len);
87 if (pcrf) {
88 prlog(PR_ERR, "%s: Filter [%x, %x] overlapped with [%x, %x]\n",
89 __func__, start, len, pcrf->start, pcrf->len);
90 return NULL;
91 }
92
93 pcrf = zalloc(sizeof(*pcrf));
94 if (!pcrf) {
95 prlog(PR_ERR, "%s: Out of memory!\n", __func__);
96 return NULL;
97 }
98
99 pcrf->start = start;
100 pcrf->len = len;
101 pcrf->flags = flags;
102 pcrf->func = func;
103 pcrf->data = data;
104 list_add_tail(&pvd->pcrf, &pcrf->link);
105
106 return pcrf;
107 }
108
pci_virt_find_device(struct phb * phb,uint32_t bdfn)109 struct pci_virt_device *pci_virt_find_device(struct phb *phb,
110 uint32_t bdfn)
111 {
112 struct pci_virt_device *pvd;
113
114 list_for_each(&phb->virt_devices, pvd, node) {
115 if (pvd->bdfn == bdfn)
116 return pvd;
117 }
118
119 return NULL;
120 }
121
pci_virt_cfg_valid(struct pci_virt_device * pvd,uint32_t offset,uint32_t size)122 static inline bool pci_virt_cfg_valid(struct pci_virt_device *pvd,
123 uint32_t offset, uint32_t size)
124 {
125 if ((offset + size) > pvd->cfg_size)
126 return false;
127
128 if (!size || (size > 4))
129 return false;
130
131 if ((size & (size - 1)) || (offset & (size - 1)))
132 return false;
133
134 return true;
135 }
136
pci_virt_cfg_read(struct phb * phb,uint32_t bdfn,uint32_t offset,uint32_t size,uint32_t * data)137 int64_t pci_virt_cfg_read(struct phb *phb, uint32_t bdfn,
138 uint32_t offset, uint32_t size,
139 uint32_t *data)
140 {
141 struct pci_virt_device *pvd;
142 struct pci_cfg_reg_filter *pcrf;
143 int64_t ret = OPAL_SUCCESS;
144
145 *data = 0xffffffff;
146
147 /* Search for PCI virtual device */
148 pvd = pci_virt_find_device(phb, bdfn);
149 if (!pvd)
150 return OPAL_PARAMETER;
151
152 /* Check if config address is valid or not */
153 if (!pci_virt_cfg_valid(pvd, offset, size))
154 return OPAL_PARAMETER;
155
156 /* The value is fetched from the normal config space when the
157 * trap handler returns OPAL_PARTIAL. Otherwise, the trap handler
158 * should provide the return value.
159 */
160 pcrf = pci_virt_find_filter(pvd, offset, size);
161 if (!pcrf || !pcrf->func || !(pcrf->flags & PCI_REG_FLAG_READ))
162 goto out;
163
164 ret = pcrf->func(pvd, pcrf, offset, size, data, false);
165 if (ret != OPAL_PARTIAL)
166 return ret;
167 out:
168 pci_virt_cfg_read_raw(pvd, PCI_VIRT_CFG_NORMAL, offset, size, data);
169 return OPAL_SUCCESS;
170 }
171
pci_virt_cfg_write(struct phb * phb,uint32_t bdfn,uint32_t offset,uint32_t size,uint32_t data)172 int64_t pci_virt_cfg_write(struct phb *phb, uint32_t bdfn,
173 uint32_t offset, uint32_t size,
174 uint32_t data)
175 {
176 struct pci_virt_device *pvd;
177 struct pci_cfg_reg_filter *pcrf;
178 uint32_t val, v, r, c, i;
179 int64_t ret = OPAL_SUCCESS;
180
181 /* Search for PCI virtual device */
182 pvd = pci_virt_find_device(phb, bdfn);
183 if (!pvd)
184 return OPAL_PARAMETER;
185
186 /* Check if config address is valid or not */
187 if (!pci_virt_cfg_valid(pvd, offset, size))
188 return OPAL_PARAMETER;
189
190 /* The value is written to the config space if the trap handler
191 * returns OPAL_PARTIAL. Otherwise, the value to be written is
192 * dropped.
193 */
194 pcrf = pci_virt_find_filter(pvd, offset, size);
195 if (!pcrf || !pcrf->func || !(pcrf->flags & PCI_REG_FLAG_WRITE))
196 goto out;
197
198 ret = pcrf->func(pvd, pcrf, offset, size, &data, true);
199 if (ret != OPAL_PARTIAL)
200 return ret;
201 out:
202 val = data;
203 for (i = 0; i < size; i++) {
204 PCI_VIRT_CFG_NORMAL_RD(pvd, offset + i, 1, &v);
205 PCI_VIRT_CFG_RDONLY_RD(pvd, offset + i, 1, &r);
206 PCI_VIRT_CFG_W1CLR_RD(pvd, offset + i, 1, &c);
207
208 /* Drop read-only bits */
209 val &= ~(r << (i * 8));
210 val |= (r & v) << (i * 8);
211
212 /* Drop W1C bits */
213 val &= ~(val & ((c & v) << (i * 8)));
214 }
215
216 PCI_VIRT_CFG_NORMAL_WR(pvd, offset, size, val);
217 return OPAL_SUCCESS;
218 }
219
pci_virt_add_device(struct phb * phb,uint32_t bdfn,uint32_t cfg_size,void * data)220 struct pci_virt_device *pci_virt_add_device(struct phb *phb, uint32_t bdfn,
221 uint32_t cfg_size, void *data)
222 {
223 struct pci_virt_device *pvd;
224 uint8_t *cfg;
225 uint32_t i;
226
227 /* The standard config header size is 64 bytes */
228 if (!phb || (bdfn & 0xffff0000) || (cfg_size < 64))
229 return NULL;
230
231 /* Check if the bdfn is available */
232 pvd = pci_virt_find_device(phb, bdfn);
233 if (pvd) {
234 prlog(PR_ERR, "%s: bdfn 0x%x was reserved\n",
235 __func__, bdfn);
236 return NULL;
237 }
238
239 /* Populate the PCI virtual device */
240 pvd = zalloc(sizeof(*pvd));
241 if (!pvd) {
242 prlog(PR_ERR, "%s: Cannot alloate PCI virtual device (0x%x)\n",
243 __func__, bdfn);
244 return NULL;
245 }
246
247 cfg = zalloc(cfg_size * PCI_VIRT_CFG_MAX);
248 if (!cfg) {
249 prlog(PR_ERR, "%s: Cannot allocate config space (0x%x)\n",
250 __func__, bdfn);
251 free(pvd);
252 return NULL;
253 }
254
255 for (i = 0; i < PCI_VIRT_CFG_MAX; i++, cfg += cfg_size)
256 pvd->config[i] = cfg;
257
258 pvd->bdfn = bdfn;
259 pvd->cfg_size = cfg_size;
260 pvd->data = data;
261 list_head_init(&pvd->pcrf);
262 list_add_tail(&phb->virt_devices, &pvd->node);
263
264 return pvd;
265 }
266