xref: /minix/minix/drivers/iommu/amddev/amddev.c (revision 83133719)
1 /*
2 amddev.c
3 
4 Driver for the AMD Device Exclusion Vector (DEV)
5 */
6 
7 #include <minix/driver.h>
8 #include <minix/config.h>
9 #include <minix/type.h>
10 
11 #include <errno.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <machine/vm.h>
17 #include <machine/vmparam.h>
18 #include <signal.h>
19 #include <minix/com.h>
20 #include <minix/const.h>
21 #include <minix/ipc.h>
22 #include <minix/syslib.h>
23 #include <minix/sysutil.h>
24 #include <minix/endpoint.h>
25 #include <machine/pci.h>
26 
27 /* Offsets from capability pointer */
28 #define DEV_OP		4	/* Selects control/status register to access */
29 #define		DEV_OP_FUNC_SHIFT	8	/* Function part in OP reg. */
30 #define DEV_DATA	8	/* Read/write to access reg. selected */
31 
32 /* Functions */
33 #define DEVF_BASE_LO	0
34 #define DEVF_BASE_HI	1
35 #define DEVF_MAP		2
36 #define DEVF_CAP		3
37 #define		DEVF_CAP_MAPS_MASK	0x00ff0000
38 #define		DEVF_CAP_MAPS_SHIFT	16
39 #define		DEVF_CAP_DOMS_MASK	0x0000ff00
40 #define		DEVF_CAP_DOMS_SHIFT	8
41 #define		DEVF_CAP_REV_MASK	0x000000ff
42 #define		DEVF_CAP_REV_SHIFT	0
43 #define DEVF_CR		4
44 #define DEVF_ERR_STATUS	5
45 #define DEVF_ERR_ADDR_LO	6
46 #define DEVF_ERR_ADDR_HI	7
47 
48 static int dev_devind;
49 static u8_t dev_capptr;
50 static u8_t *table;
51 
52 static int find_dev(int *devindp, u8_t *capaddrp);
53 static u32_t read_reg(int function, int index);
54 static void write_reg(int function, int index, u32_t value);
55 static void init_domain(int index);
56 static void init_map(unsigned int ix);
57 static int do_add4pci(const message *m);
58 static void add_range(phys_bytes busaddr, phys_bytes size);
59 #if 0
60 static void del_range(phys_bytes busaddr, phys_bytes size);
61 static void sef_cb_signal_handler(int signo);
62 #endif
63 static void report_exceptions(void);
64 
65 /* SEF functions and variables. */
66 static void sef_local_startup(void);
67 static int sef_cb_init_fresh(int type, sef_init_info_t *info);
68 
69 int main(void)
70 {
71 	int r;
72 	message m;
73 	int ipc_status;
74 
75 	/* SEF local startup. */
76 	sef_local_startup();
77 
78 	for(;;)
79 	{
80 		report_exceptions();
81 
82 		r= driver_receive(ANY, &m, &ipc_status);
83 		if (r != OK)
84 			panic("driver_receive failed: %d", r);
85 		if (m.m_type == IOMMU_MAP) {
86 			r= do_add4pci(&m);
87 			m.m_type= r;
88 			ipc_send(m.m_source, &m);
89 			continue;
90 		}
91 		printf("amddev: got message from %d\n", m.m_source);
92 	}
93 }
94 
95 /*===========================================================================*
96  *			       sef_local_startup			     *
97  *===========================================================================*/
98 static void sef_local_startup()
99 {
100   /* Register init callbacks. */
101   sef_setcb_init_fresh(sef_cb_init_fresh);
102   sef_setcb_init_lu(sef_cb_init_fresh);
103   sef_setcb_init_restart(sef_cb_init_fresh);
104 
105   /* Register live update callbacks. */
106   sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
107   sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
108 
109 #if 0
110   /* Register signal callbacks. */
111   sef_setcb_signal_handler(sef_cb_signal_handler);
112 #endif
113 
114   /* Let SEF perform startup. */
115   sef_startup();
116 }
117 
118 /*===========================================================================*
119  *		            sef_cb_init_fresh                                *
120  *===========================================================================*/
121 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
122 {
123 /* Initialize the amddev driver. */
124 	int r, n_maps, n_domains, revision;
125 	u16_t flags;
126 	u32_t bits;
127 
128 	printf("amddev: starting\n");
129 
130 	r= find_dev(&dev_devind, &dev_capptr);
131 	if (!r)
132 		return r;
133 	flags= pci_attr_r16(dev_devind, dev_capptr+CAP_SD_INFO);
134 	printf("amddev`init: flags = 0x%x\n", flags);
135 
136 	bits= read_reg(DEVF_CAP, 0);
137 	n_maps= ((bits & DEVF_CAP_MAPS_MASK) >> DEVF_CAP_MAPS_SHIFT);
138 	n_domains= ((bits & DEVF_CAP_DOMS_MASK) >> DEVF_CAP_DOMS_SHIFT);
139 	revision= ((bits & DEVF_CAP_REV_MASK) >> DEVF_CAP_REV_SHIFT);
140 	printf("amddev`init: DEVF_CAP = 0x%x (%d maps, %d domains, rev 0x%x)\n",
141 		bits, n_maps, n_domains, revision);
142 
143 	printf("status = 0x%x, addr-lo = 0x%x, addr-hi = 0x%x\n",
144 		read_reg(DEVF_ERR_STATUS, 0),
145 		read_reg(DEVF_ERR_ADDR_LO, 0),
146 		read_reg(DEVF_ERR_ADDR_HI, 0));
147 
148 	init_domain(0);
149 	init_map(0);
150 #if 0
151 	init_domain(1);
152 #endif
153 
154 	write_reg(DEVF_CR, 0, 0x10 | 0x8 | 0x4 | 1);
155 
156 	printf("after write: DEVF_CR: 0x%x\n", read_reg(DEVF_CR, 0));
157 
158 	return(OK);
159 }
160 
161 
162 #if 0
163 /*===========================================================================*
164  *		           sef_cb_signal_handler                             *
165  *===========================================================================*/
166 static void sef_cb_signal_handler(int signo)
167 {
168 	int r;
169 	endpoint_t proc_e;
170 	phys_bytes base, size;
171 
172 	/* Only check for termination signal, ignore anything else. */
173 	if (signo != SIGTERM) return;
174 
175 	for (;;)
176 	{
177 		r= vm_getdma(&proc_e, &base, &size);
178 		if (r == -1)
179 		{
180 			if (errno != -EAGAIN)
181 			{
182 				printf(
183 				"amddev: vm_getdma failed: %d\n",
184 					errno);
185 			}
186 			break;
187 		}
188 
189 		printf(
190 		"amddev: deleting 0x%lx@0x%lx for proc %d\n",
191 			size, base, proc_e);
192 		del_range(base, size);
193 		r= vm_deldma(proc_e, base, size);
194 		if (r == -1)
195 		{
196 			printf("amddev: vm_deldma failed: %d\n",
197 				errno);
198 			break;
199 		}
200 	}
201 }
202 #endif
203 
204 /* Returns 0 if no device found, or 1 if a device is found. */
205 static int find_dev(devindp, capaddrp)
206 int *devindp;
207 u8_t *capaddrp;
208 {
209 	int r, devind, first;
210 	u8_t capptr, type, next, subtype;
211 	u16_t vid, did, status;
212 
213 	pci_init();
214 
215 	first= 1;
216 	for(;;)
217 	{
218 		if (first)
219 		{
220 			first= 0;
221 			r= pci_first_dev(&devind, &vid, &did);
222 			if (!r)
223 			{
224 				printf("amddev`find_dev: no first dev\n");
225 				return 0;
226 			}
227 		}
228 		else
229 		{
230 			r= pci_next_dev(&devind, &vid, &did);
231 			if (!r)
232 			{
233 				printf("amddev`find_dev: no next dev\n");
234 				return 0;
235 			}
236 		}
237 
238 		printf("amddev`find_dev: got devind %d, vid 0x%x, did 0x%x\n",
239 			devind, vid, did);
240 
241 		/* Check capabilities bit in the device status register */
242 		status= pci_attr_r16(devind, PCI_SR);
243 		if (!(status & PSR_CAPPTR))
244 			continue;
245 
246 		capptr= (pci_attr_r8(devind, PCI_CAPPTR) & PCI_CP_MASK);
247 		while (capptr != 0)
248 		{
249 			type = pci_attr_r8(devind, capptr+CAP_TYPE);
250 			next= (pci_attr_r8(devind, capptr+CAP_NEXT) &
251 				PCI_CP_MASK);
252 			if (type == CAP_T_SECURE_DEV)
253 			{
254 				printf(
255 				"amddev`find_dev: found secure device\n");
256 				subtype= (pci_attr_r8(devind, capptr+
257 					CAP_SD_INFO) & CAP_SD_SUBTYPE_MASK);
258 				if (subtype == CAP_T_SD_DEV)
259 				{
260 					printf("amddev`find_dev: AMD DEV\n");
261 					pci_reserve(devind);
262 					*devindp= devind;
263 					*capaddrp= capptr;
264 					return 1;
265 				}
266 			}
267 			capptr= next;
268 		}
269 	}
270 	return 0;
271 }
272 
273 static u32_t read_reg(int function, int index)
274 {
275 	pci_attr_w32(dev_devind, dev_capptr + DEV_OP, ((function <<
276 		DEV_OP_FUNC_SHIFT) | index));
277 	return pci_attr_r32(dev_devind, dev_capptr + DEV_DATA);
278 }
279 
280 static void write_reg(int function, int index, u32_t value)
281 {
282 	pci_attr_w32(dev_devind, dev_capptr + DEV_OP, ((function <<
283 		DEV_OP_FUNC_SHIFT) | index));
284 	pci_attr_w32(dev_devind, dev_capptr + DEV_DATA, value);
285 }
286 
287 static void init_domain(int index)
288 {
289 	size_t size, memsize;
290 	phys_bytes busaddr;
291 
292 	size= 0x100000 / 8;
293 	table= alloc_contig(size, AC_ALIGN4K, &busaddr);
294 	if (table == NULL)
295 		panic("malloc failed");
296 	if (index == 0)
297 	{
298 		memset(table, 0, size);
299 		memsize= 0x37000 / 8;
300 		printf("memsize = 0x%x / 8\n", memsize*8);
301 		memset(table, 0xff, memsize);
302 	}
303 	else
304 	{
305 		memset(table, 0xff, size);
306 		memset(table, 0x00, size);
307 	}
308 
309 printf("init_domain: busaddr = 0x%lx\n", busaddr);
310 
311 	write_reg(DEVF_BASE_HI, index, 0);
312 	write_reg(DEVF_BASE_LO, index, busaddr | 3);
313 
314 	printf("after write: DEVF_BASE_LO: 0x%x\n",
315 		read_reg(DEVF_BASE_LO, index));
316 }
317 
318 static void init_map(unsigned int ix)
319 {
320 	u32_t v, dom, busno, unit0, unit1;
321 
322 	dom= 1;
323 	busno= 7;
324 	unit1= 9;
325 	unit0= 9;
326 	v= (dom << 26) | (dom << 20) | (busno << 12) |
327 		(0 << 11) | (unit1 << 6) |
328 		(0 << 5) | (unit0 << 0);
329 	write_reg(DEVF_MAP, ix, v);
330 
331 	printf("after write: DEVF_MAP: 0x%x\n", read_reg(DEVF_MAP, ix));
332 }
333 
334 #if 0
335 static int do_add(message *m)
336 {
337 	int r;
338 	endpoint_t proc;
339 	vir_bytes start;
340 	size_t size;
341 	phys_bytes busaddr;
342 
343 	proc= m->m_source;
344 	start= m->m2_l1;
345 	size= m->m2_l2;
346 
347 #if 0
348 	printf("amddev`do_add: got request for 0x%x@0x%x from %d\n",
349 		size, start, proc);
350 #endif
351 
352 	if (start % PAGE_SIZE)
353 	{
354 		printf("amddev`do_add: bad start 0x%x from proc %d\n",
355 			start, proc);
356 		return EINVAL;
357 	}
358 	if (size % PAGE_SIZE)
359 	{
360 		printf("amddev`do_add: bad size 0x%x from proc %d\n",
361 			size, proc);
362 		return EINVAL;
363 	}
364 	r= sys_umap_remote(proc, SELF, VM_D, (vir_bytes)start, size, &busaddr);
365 	if (r != OK)
366 	{
367 		printf("amddev`do_add: umap failed for 0x%x@0x%x, proc %d\n",
368 			size, start, proc);
369 		return r;
370 	}
371 	add_range(busaddr, size);
372 
373 }
374 #endif
375 
376 
377 
378 static int do_add4pci(const message *m)
379 {
380 	int r, pci_bus, pci_dev, pci_func;
381 	endpoint_t proc;
382 	vir_bytes start;
383 	size_t size;
384 	phys_bytes busaddr;
385 
386 	proc= m->m_source;
387 	start= m->m2_l1;
388 	size= m->m2_l2;
389 	pci_bus= m->m1_i1;
390 	pci_dev= m->m1_i2;
391 	pci_func= m->m1_i3;
392 
393 	printf(
394 "amddev`do_add4pci: got request for 0x%x@0x%lx from %d for pci dev %u.%u.%u\n",
395 		size, start, proc, pci_bus, pci_dev, pci_func);
396 
397 	if (start % PAGE_SIZE)
398 	{
399 		printf("amddev`do_add4pci: bad start 0x%lx from proc %d\n",
400 			start, proc);
401 		return EINVAL;
402 	}
403 	if (size % PAGE_SIZE)
404 	{
405 		printf("amddev`do_add4pci: bad size 0x%x from proc %d\n",
406 			size, proc);
407 		return EINVAL;
408 	}
409 
410 	printf("amddev`do_add4pci: should check with PCI\n");
411 
412 	r= sys_umap_remote(proc, SELF, VM_D, (vir_bytes)start, size, &busaddr);
413 	if (r != OK)
414 	{
415 		printf(
416 		"amddev`do_add4pci: umap failed for 0x%x@0x%lx, proc %d: %d\n",
417 			size, start, proc, r);
418 		return r;
419 	}
420 
421 #if 0
422 	r= vm_adddma(proc, start, size);
423 	if (r != 0)
424 	{
425 		r= -errno;
426 		printf("amddev`do_add4pci: vm_adddma failed for 0x%x@0x%lx, "
427 			"proc %d: %d\n", size, start, proc, r);
428 		return r;
429 	}
430 #endif
431 
432 	add_range(busaddr, size);
433 
434 	return OK;
435 }
436 
437 
438 static void add_range(phys_bytes busaddr, phys_bytes size)
439 {
440 	phys_bytes o;
441 
442 #if 0
443 	printf("add_range: mapping 0x%x@0x%x\n", size, busaddr);
444 #endif
445 
446 	for (o= 0; o<size; o += PAGE_SIZE)
447 	{
448 		u32_t bit= (busaddr+o)/PAGE_SIZE;
449 		table[bit/8] &= ~(1U << (bit % 8));
450 	}
451 }
452 
453 #if 0
454 static void del_range(phys_bytes busaddr, phys_bytes size)
455 {
456 	phys_bytes o;
457 
458 #if 0
459 	printf("del_range: mapping 0x%x@0x%x\n", size, busaddr);
460 #endif
461 
462 	for (o= 0; o<size; o += PAGE_SIZE)
463 	{
464 		u32_t bit= (busaddr+o)/PAGE_SIZE;
465 		table[bit/8] |= (1 << (bit % 8));
466 	}
467 }
468 #endif
469 
470 static void report_exceptions(void)
471 {
472 	u32_t status;
473 
474 	status= read_reg(DEVF_ERR_STATUS, 0);
475 	if (!(status & 0x80000000))
476 		return;
477 	printf("amddev: status = 0x%x, addr-lo = 0x%x, addr-hi = 0x%x\n",
478 		status, read_reg(DEVF_ERR_ADDR_LO, 0),
479 			read_reg(DEVF_ERR_ADDR_HI, 0));
480 	write_reg(DEVF_ERR_STATUS, 0, 0);
481 }
482