xref: /openbsd/sys/dev/ic/psp.c (revision 0b9f4c66)
1 /*	$OpenBSD: psp.c,v 1.1 2024/09/03 00:23:05 jsg Exp $ */
2 
3 /*
4  * Copyright (c) 2023, 2024 Hans-Joerg Hoexer <hshoexer@genua.de>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/device.h>
22 #include <sys/timeout.h>
23 #include <sys/pledge.h>
24 
25 #include <machine/bus.h>
26 
27 #include <sys/proc.h>
28 #include <uvm/uvm.h>
29 #include <crypto/xform.h>
30 
31 #include <dev/ic/ccpvar.h>
32 #include <dev/ic/pspvar.h>
33 
34 struct ccp_softc *ccp_softc;
35 
36 int	psp_get_pstatus(struct psp_platform_status *);
37 int	psp_init(struct psp_init *);
38 
39 int
40 psp_sev_intr(struct ccp_softc *sc, uint32_t status)
41 {
42 	if (!(status & PSP_CMDRESP_COMPLETE))
43 		return (0);
44 
45 	wakeup(sc);
46 
47 	return (1);
48 }
49 
50 int
51 psp_attach(struct ccp_softc *sc)
52 {
53 	struct psp_platform_status	pst;
54 	struct psp_init			init;
55 	size_t				size;
56 	int				nsegs;
57 
58 	if (!(sc->sc_capabilities & PSP_CAP_SEV))
59 		return (0);
60 
61 	rw_init(&sc->sc_lock, "ccp_lock");
62 
63 	/* create and map SEV command buffer */
64 	sc->sc_cmd_size = size = PAGE_SIZE;
65 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
66 	    BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT,
67 	    &sc->sc_cmd_map) != 0)
68 		return (0);
69 
70 	if (bus_dmamem_alloc(sc->sc_dmat, size, 0, 0, &sc->sc_cmd_seg, 1,
71 	    &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0)
72 		goto fail_0;
73 
74 	if (bus_dmamem_map(sc->sc_dmat, &sc->sc_cmd_seg, nsegs, size,
75 	    &sc->sc_cmd_kva, BUS_DMA_WAITOK) != 0)
76 		goto fail_1;
77 
78 	if (bus_dmamap_load(sc->sc_dmat, sc->sc_cmd_map, sc->sc_cmd_kva,
79 	    size, NULL, BUS_DMA_WAITOK) != 0)
80 		goto fail_2;
81 
82 	sc->sc_sev_intr = psp_sev_intr;
83 	ccp_softc = sc;
84 
85 	if (psp_get_pstatus(&pst) || pst.state != 0)
86 		goto fail_3;
87 
88 	/*
89          * create and map Trusted Memory Region (TMR); size 1 Mbyte,
90          * needs to be aligned to 1 Mbyte.
91 	 */
92 	sc->sc_tmr_size = size = PSP_TMR_SIZE;
93 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
94 	    BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT,
95 	    &sc->sc_tmr_map) != 0)
96 		goto fail_3;
97 
98 	if (bus_dmamem_alloc(sc->sc_dmat, size, size, 0, &sc->sc_tmr_seg, 1,
99 	    &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0)
100 		goto fail_4;
101 
102 	if (bus_dmamem_map(sc->sc_dmat, &sc->sc_tmr_seg, nsegs, size,
103 	    &sc->sc_tmr_kva, BUS_DMA_WAITOK) != 0)
104 		goto fail_5;
105 
106 	if (bus_dmamap_load(sc->sc_dmat, sc->sc_tmr_map, sc->sc_tmr_kva,
107 	    size, NULL, BUS_DMA_WAITOK) != 0)
108 		goto fail_6;
109 
110 	memset(&init, 0, sizeof(init));
111 	init.enable_es = 1;
112 	init.tmr_length = PSP_TMR_SIZE;
113 	init.tmr_paddr = sc->sc_tmr_map->dm_segs[0].ds_addr;
114 	if (psp_init(&init))
115 		goto fail_7;
116 
117 	printf(", SEV");
118 
119 	psp_get_pstatus(&pst);
120 	if ((pst.state == 1) && (pst.cfges_build & 0x1))
121 		printf(", SEV-ES");
122 
123 	sc->sc_psp_attached = 1;
124 
125 	return (1);
126 
127 fail_7:
128 	bus_dmamap_unload(sc->sc_dmat, sc->sc_tmr_map);
129 fail_6:
130 	bus_dmamem_unmap(sc->sc_dmat, sc->sc_tmr_kva, size);
131 fail_5:
132 	bus_dmamem_free(sc->sc_dmat, &sc->sc_tmr_seg, 1);
133 fail_4:
134 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_tmr_map);
135 fail_3:
136 	bus_dmamap_unload(sc->sc_dmat, sc->sc_cmd_map);
137 fail_2:
138 	bus_dmamem_unmap(sc->sc_dmat, sc->sc_cmd_kva, size);
139 fail_1:
140 	bus_dmamem_free(sc->sc_dmat, &sc->sc_cmd_seg, 1);
141 fail_0:
142 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmd_map);
143 
144 	ccp_softc = NULL;
145 	sc->sc_psp_attached = -1;
146 
147 	return (0);
148 }
149 
150 static int
151 ccp_wait(struct ccp_softc *sc, uint32_t *status, int poll)
152 {
153 	uint32_t	cmdword;
154 	int		count;
155 
156 	if (poll) {
157 		count = 0;
158 		while (count++ < 10) {
159 			cmdword = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
160 			    PSP_REG_CMDRESP);
161 			if (cmdword & PSP_CMDRESP_RESPONSE)
162 				goto done;
163 			delay(5000);
164 		}
165 
166 		/* timeout */
167 		return (1);
168 	}
169 
170 	if (tsleep_nsec(sc, PWAIT, "psp", SEC_TO_NSEC(1)) == EWOULDBLOCK)
171 		return (1);
172 
173 done:
174 	if (status) {
175 		*status = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
176 		    PSP_REG_CMDRESP);
177 	}
178 
179 	return (0);
180 }
181 
182 static int
183 ccp_docmd(struct ccp_softc *sc, int cmd, uint64_t paddr)
184 {
185 	uint32_t	plo, phi, cmdword, status;
186 
187 	plo = ((paddr >> 0) & 0xffffffff);
188 	phi = ((paddr >> 32) & 0xffffffff);
189 	cmdword = (cmd & 0x3ff) << 16;
190 	if (!cold)
191 		cmdword |= PSP_CMDRESP_IOC;
192 
193 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_ADDRLO, plo);
194 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_ADDRHI, phi);
195 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_CMDRESP, cmdword);
196 
197 	if (ccp_wait(sc, &status, cold))
198 		return (1);
199 
200 	/* Did PSP sent a response code? */
201 	if (status & PSP_CMDRESP_RESPONSE) {
202 		if ((status & PSP_STATUS_MASK) != PSP_STATUS_SUCCESS)
203 			return (1);
204 	}
205 
206 	return (0);
207 }
208 
209 int
210 psp_init(struct psp_init *uinit)
211 {
212 	struct ccp_softc	*sc = ccp_softc;
213 	struct psp_init		*init;
214 	int			 ret;
215 
216 	init = (struct psp_init *)sc->sc_cmd_kva;
217 	bzero(init, sizeof(*init));
218 
219 	init->enable_es = uinit->enable_es;
220 	init->tmr_paddr = uinit->tmr_paddr;
221 	init->tmr_length = uinit->tmr_length;
222 
223 	ret = ccp_docmd(sc, PSP_CMD_INIT, sc->sc_cmd_map->dm_segs[0].ds_addr);
224 	if (ret != 0)
225 		return (EIO);
226 
227 	wbinvd_on_all_cpus();
228 
229 	return (0);
230 }
231 
232 int
233 psp_get_pstatus(struct psp_platform_status *ustatus)
234 {
235 	struct ccp_softc	*sc = ccp_softc;
236 	struct psp_platform_status *status;
237 	int			 ret;
238 
239 	status = (struct psp_platform_status *)sc->sc_cmd_kva;
240 	bzero(status, sizeof(*status));
241 
242 	ret = ccp_docmd(sc, PSP_CMD_PLATFORMSTATUS,
243 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
244 
245 	if (ret != 0)
246 		return (EIO);
247 
248 	bcopy(status, ustatus, sizeof(*ustatus));
249 
250 	return (0);
251 }
252 
253 int
254 psp_df_flush(void)
255 {
256 	struct ccp_softc	*sc = ccp_softc;
257 	int			 ret;
258 
259 	wbinvd_on_all_cpus();
260 
261 	ret = ccp_docmd(sc, PSP_CMD_DF_FLUSH, 0x0);
262 
263 	if (ret != 0)
264 		return (EIO);
265 
266 	return (0);
267 }
268 
269 int
270 psp_decommission(struct psp_decommission *udecom)
271 {
272 	struct ccp_softc	*sc = ccp_softc;
273 	struct psp_decommission	*decom;
274 	int			 ret;
275 
276 	decom = (struct psp_decommission *)sc->sc_cmd_kva;
277 	bzero(decom, sizeof(*decom));
278 
279 	decom->handle = udecom->handle;
280 
281 	ret = ccp_docmd(sc, PSP_CMD_DECOMMISSION,
282 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
283 
284 	if (ret != 0)
285 		return (EIO);
286 
287 	return (0);
288 }
289 
290 int
291 psp_get_gstatus(struct psp_guest_status *ustatus)
292 {
293 	struct ccp_softc	*sc = ccp_softc;
294 	struct psp_guest_status	*status;
295 	int			 ret;
296 
297 	status = (struct psp_guest_status *)sc->sc_cmd_kva;
298 	bzero(status, sizeof(*status));
299 
300 	status->handle = ustatus->handle;
301 
302 	ret = ccp_docmd(sc, PSP_CMD_GUESTSTATUS,
303 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
304 
305 	if (ret != 0)
306 		return (EIO);
307 
308 	ustatus->policy = status->policy;
309 	ustatus->asid = status->asid;
310 	ustatus->state = status->state;
311 
312 	return (0);
313 }
314 
315 int
316 psp_launch_start(struct psp_launch_start *ustart)
317 {
318 	struct ccp_softc	*sc = ccp_softc;
319 	struct psp_launch_start	*start;
320 	int			 ret;
321 
322 	start = (struct psp_launch_start *)sc->sc_cmd_kva;
323 	bzero(start, sizeof(*start));
324 
325 	start->handle = ustart->handle;
326 	start->policy = ustart->policy;
327 
328 	ret = ccp_docmd(sc, PSP_CMD_LAUNCH_START,
329 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
330 
331 	if (ret != 0)
332 		return (EIO);
333 
334 	/* If requested, return new handle. */
335 	if (ustart->handle == 0)
336 		ustart->handle = start->handle;
337 
338 	return (0);
339 }
340 
341 int
342 psp_launch_update_data(struct psp_launch_update_data *ulud, struct proc *p)
343 {
344 	struct ccp_softc		*sc = ccp_softc;
345 	struct psp_launch_update_data	*ludata;
346 	pmap_t				 pmap;
347 	vaddr_t				 v, next, end;
348 	size_t				 size, len, off;
349 	int				 ret;
350 
351 	/* Ensure AES_XTS_BLOCKSIZE alignment and multiplicity. */
352 	if ((ulud->paddr & (AES_XTS_BLOCKSIZE - 1)) != 0 ||
353 	    (ulud->length % AES_XTS_BLOCKSIZE) != 0)
354 		return (EINVAL);
355 
356 	ludata = (struct psp_launch_update_data *)sc->sc_cmd_kva;
357 	bzero(ludata, sizeof(*ludata));
358 
359 	ludata->handle = ulud->handle;
360 
361 	/* Drain caches before we encrypt memory. */
362 	wbinvd_on_all_cpus();
363 
364 	/*
365 	 * Launch update one physical page at a time.  We could
366 	 * optimise this for contiguous pages of physical memory.
367 	 *
368 	 * vmd(8) provides the guest physical address, thus convert
369 	 * to system physical address.
370 	 */
371 	pmap = vm_map_pmap(&p->p_vmspace->vm_map);
372 	size = ulud->length;
373 	end = ulud->paddr + ulud->length;
374 	for (v = ulud->paddr; v < end; v = next) {
375 		off = v & PAGE_MASK;
376 
377 		len = MIN(PAGE_SIZE - off, size);
378 
379 		/* Wire mapping. */
380 		if (uvm_map_pageable(&p->p_vmspace->vm_map, v, v+len, FALSE, 0))
381 			return (EINVAL);
382 		if (!pmap_extract(pmap, v, (paddr_t *)&ludata->paddr))
383 			return (EINVAL);
384 		ludata->length = len;
385 
386 		ret = ccp_docmd(sc, PSP_CMD_LAUNCH_UPDATE_DATA,
387 		    sc->sc_cmd_map->dm_segs[0].ds_addr);
388 
389 		if (ret != 0)
390 			return (EIO);
391 
392 		size -= len;
393 		next = v + len;
394 	}
395 
396 	return (0);
397 }
398 
399 int
400 psp_launch_measure(struct psp_launch_measure *ulm)
401 {
402 	struct psp_launch_measure *lm;
403 	struct ccp_softc	*sc = ccp_softc;
404 	int			 ret;
405 	uint64_t		 paddr;
406 
407 	if (ulm->measure_len != sizeof(ulm->psp_measure))
408 		return (EINVAL);
409 
410 	lm = (struct psp_launch_measure *)sc->sc_cmd_kva;
411 	bzero(lm, sizeof(*lm));
412 
413 	lm->handle = ulm->handle;
414 	paddr = sc->sc_cmd_map->dm_segs[0].ds_addr;
415 	lm->measure_paddr =
416 	    paddr + offsetof(struct psp_launch_measure, psp_measure);
417 	lm->measure_len = sizeof(lm->psp_measure);
418 
419 	ret = ccp_docmd(sc, PSP_CMD_LAUNCH_MEASURE, paddr);
420 
421 	if (ret != 0 || lm->measure_len != ulm->measure_len)
422 		return (EIO);
423 
424 	bcopy(&lm->psp_measure, &ulm->psp_measure, ulm->measure_len);
425 
426 	return (0);
427 }
428 
429 int
430 psp_launch_finish(struct psp_launch_finish *ulf)
431 {
432 	struct ccp_softc	*sc = ccp_softc;
433 	struct psp_launch_finish *lf;
434 	int			 ret;
435 
436 	lf = (struct psp_launch_finish *)sc->sc_cmd_kva;
437 	bzero(lf, sizeof(*lf));
438 
439 	lf->handle = ulf->handle;
440 
441 	ret = ccp_docmd(sc, PSP_CMD_LAUNCH_FINISH,
442 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
443 
444 	if (ret != 0)
445 		return (EIO);
446 
447 	return (0);
448 }
449 
450 int
451 psp_attestation(struct psp_attestation *uat)
452 {
453 	struct ccp_softc	*sc = ccp_softc;
454 	struct psp_attestation	*at;
455 	int			 ret;
456 	uint64_t		 paddr;
457 
458 	if (uat->attest_len != sizeof(uat->psp_report))
459 		return (EINVAL);
460 
461 	at = (struct psp_attestation *)sc->sc_cmd_kva;
462 	bzero(at, sizeof(*at));
463 
464 	at->handle = uat->handle;
465 	paddr = sc->sc_cmd_map->dm_segs[0].ds_addr;
466 	at->attest_paddr =
467 	    paddr + offsetof(struct psp_attestation, psp_report);
468 	bcopy(uat->attest_nonce, at->attest_nonce, sizeof(at->attest_nonce));
469 	at->attest_len = sizeof(at->psp_report);
470 
471 	ret = ccp_docmd(sc, PSP_CMD_ATTESTATION, paddr);
472 
473 	if (ret != 0 || at->attest_len != uat->attest_len)
474 		return (EIO);
475 
476 	bcopy(&at->psp_report, &uat->psp_report, uat->attest_len);
477 
478 	return (0);
479 }
480 
481 int
482 psp_activate(struct psp_activate *uact)
483 {
484 	struct ccp_softc	*sc = ccp_softc;
485 	struct psp_activate	*act;
486 	int			 ret;
487 
488 	act = (struct psp_activate *)sc->sc_cmd_kva;
489 	bzero(act, sizeof(*act));
490 
491 	act->handle = uact->handle;
492 	act->asid = uact->asid;
493 
494 	ret = ccp_docmd(sc, PSP_CMD_ACTIVATE,
495 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
496 
497 	if (ret != 0)
498 		return (EIO);
499 
500 	return (0);
501 }
502 
503 int
504 psp_deactivate(struct psp_deactivate *udeact)
505 {
506 	struct ccp_softc	*sc = ccp_softc;
507 	struct psp_deactivate	*deact;
508 	int			 ret;
509 
510 	deact = (struct psp_deactivate *)sc->sc_cmd_kva;
511 	bzero(deact, sizeof(*deact));
512 
513 	deact->handle = udeact->handle;
514 
515 	ret = ccp_docmd(sc, PSP_CMD_DEACTIVATE,
516 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
517 
518 	if (ret != 0)
519 		return (EIO);
520 
521 	return (0);
522 }
523 
524 int
525 psp_guest_shutdown(struct psp_guest_shutdown *ugshutdown)
526 {
527 	struct psp_deactivate	deact;
528 	struct psp_decommission	decom;
529 	int			ret;
530 
531 	bzero(&deact, sizeof(deact));
532 	deact.handle = ugshutdown->handle;
533 	if ((ret = psp_deactivate(&deact)) != 0)
534 		return (ret);
535 
536 	if ((ret = psp_df_flush()) != 0)
537 		return (ret);
538 
539 	bzero(&decom, sizeof(decom));
540 	decom.handle = ugshutdown->handle;
541 	if ((ret = psp_decommission(&decom)) != 0)
542 		return (ret);
543 
544 	return (0);
545 }
546 
547 int
548 psp_snp_get_pstatus(struct psp_snp_platform_status *ustatus)
549 {
550 	struct ccp_softc	*sc = ccp_softc;
551 	struct psp_snp_platform_status *status;
552 	int			 ret;
553 
554 	status = (struct psp_snp_platform_status *)sc->sc_cmd_kva;
555 	bzero(status, sizeof(*status));
556 
557 	ret = ccp_docmd(sc, PSP_CMD_SNP_PLATFORMSTATUS,
558 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
559 
560 	if (ret != 0)
561 		return (EIO);
562 
563 	bcopy(status, ustatus, sizeof(*ustatus));
564 
565 	return (0);
566 }
567 
568 int
569 pspopen(dev_t dev, int flag, int mode, struct proc *p)
570 {
571 	if (ccp_softc == NULL)
572 		return (ENODEV);
573 
574 	return (0);
575 }
576 
577 int
578 pspclose(dev_t dev, int flag, int mode, struct proc *p)
579 {
580 	return (0);
581 }
582 
583 int
584 pspioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
585 {
586 	int	ret;
587 
588 	rw_enter_write(&ccp_softc->sc_lock);
589 
590 	switch (cmd) {
591 	case PSP_IOC_GET_PSTATUS:
592 		ret = psp_get_pstatus((struct psp_platform_status *)data);
593 		break;
594 	case PSP_IOC_DF_FLUSH:
595 		ret = psp_df_flush();
596 		break;
597 	case PSP_IOC_DECOMMISSION:
598 		ret = psp_decommission((struct psp_decommission *)data);
599 		break;
600 	case PSP_IOC_GET_GSTATUS:
601 		ret = psp_get_gstatus((struct psp_guest_status *)data);
602 		break;
603 	case PSP_IOC_LAUNCH_START:
604 		ret = psp_launch_start((struct psp_launch_start *)data);
605 		break;
606 	case PSP_IOC_LAUNCH_UPDATE_DATA:
607 		ret = psp_launch_update_data(
608 		    (struct psp_launch_update_data *)data, p);
609 		break;
610 	case PSP_IOC_LAUNCH_MEASURE:
611 		ret = psp_launch_measure((struct psp_launch_measure *)data);
612 		break;
613 	case PSP_IOC_LAUNCH_FINISH:
614 		ret = psp_launch_finish((struct psp_launch_finish *)data);
615 		break;
616 	case PSP_IOC_ATTESTATION:
617 		ret = psp_attestation((struct psp_attestation *)data);
618 		break;
619 	case PSP_IOC_ACTIVATE:
620 		ret = psp_activate((struct psp_activate *)data);
621 		break;
622 	case PSP_IOC_DEACTIVATE:
623 		ret = psp_deactivate((struct psp_deactivate *)data);
624 		break;
625 	case PSP_IOC_GUEST_SHUTDOWN:
626 		ret = psp_guest_shutdown((struct psp_guest_shutdown *)data);
627 		break;
628 	case PSP_IOC_SNP_GET_PSTATUS:
629 		ret =
630 		    psp_snp_get_pstatus((struct psp_snp_platform_status *)data);
631 		break;
632 	default:
633 		ret = ENOTTY;
634 		break;
635 	}
636 
637 	rw_exit_write(&ccp_softc->sc_lock);
638 
639 	return (ret);
640 }
641 
642 int
643 pledge_ioctl_psp(struct proc *p, long com)
644 {
645 	switch (com) {
646 	case PSP_IOC_GET_PSTATUS:
647 	case PSP_IOC_DF_FLUSH:
648 	case PSP_IOC_GET_GSTATUS:
649 	case PSP_IOC_LAUNCH_START:
650 	case PSP_IOC_LAUNCH_UPDATE_DATA:
651 	case PSP_IOC_LAUNCH_MEASURE:
652 	case PSP_IOC_LAUNCH_FINISH:
653 	case PSP_IOC_ACTIVATE:
654 	case PSP_IOC_GUEST_SHUTDOWN:
655 		return (0);
656 	default:
657 		return (pledge_fail(p, EPERM, PLEDGE_VMM));
658 	}
659 }
660