xref: /openbsd/sys/dev/ic/psp.c (revision 305d28e7)
1 /*	$OpenBSD: psp.c,v 1.11 2024/11/08 12:08:22 bluhm 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/malloc.h>
23 #include <sys/pledge.h>
24 #include <sys/rwlock.h>
25 
26 #include <machine/bus.h>
27 
28 #include <sys/proc.h>
29 #include <uvm/uvm.h>
30 #include <crypto/xform.h>
31 
32 #include <dev/ic/ccpvar.h>
33 #include <dev/ic/pspvar.h>
34 
35 struct psp_softc {
36 	struct device		sc_dev;
37 	bus_space_tag_t		sc_iot;
38 	bus_space_handle_t	sc_ioh;
39 
40 	bus_dma_tag_t		sc_dmat;
41 
42 	bus_size_t		sc_reg_inten;
43 	bus_size_t		sc_reg_intsts;
44 	bus_size_t		sc_reg_cmdresp;
45 	bus_size_t		sc_reg_addrlo;
46 	bus_size_t		sc_reg_addrhi;
47 
48 	bus_dmamap_t		sc_cmd_map;
49 	bus_dma_segment_t	sc_cmd_seg;
50 	size_t			sc_cmd_size;
51 	caddr_t			sc_cmd_kva;
52 
53 	bus_dmamap_t		sc_tmr_map;
54 	bus_dma_segment_t	sc_tmr_seg;
55 	size_t			sc_tmr_size;
56 	caddr_t			sc_tmr_kva;
57 
58 	struct rwlock		sc_lock;
59 
60 	uint32_t		sc_flags;
61 #define PSPF_INITIALIZED	0x1
62 #define PSPF_UCODELOADED	0x2
63 #define PSPF_NOUCODE		0x4
64 
65 	u_char			*sc_ucodebuf;
66 	size_t			sc_ucodelen;
67 };
68 
69 int	psp_get_pstatus(struct psp_softc *, struct psp_platform_status *);
70 int	psp_init(struct psp_softc *, struct psp_init *);
71 int	psp_reinit(struct psp_softc *);
72 int	psp_match(struct device *, void *, void *);
73 void	psp_attach(struct device *, struct device *, void *);
74 void	psp_load_ucode(struct psp_softc *);
75 
76 struct cfdriver psp_cd = {
77 	NULL, "psp", DV_DULL
78 };
79 
80 const struct cfattach psp_ca = {
81 	sizeof(struct psp_softc),
82 	psp_match,
83 	psp_attach
84 };
85 
86 int
87 psp_sev_intr(void *arg)
88 {
89 	struct ccp_softc *csc = arg;
90 	struct psp_softc *sc = (struct psp_softc *)csc->sc_psp;
91 	uint32_t status;
92 
93 	status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_intsts);
94 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_intsts, status);
95 
96 	if (!(status & PSP_CMDRESP_COMPLETE))
97 		return (0);
98 
99 	wakeup(sc);
100 
101 	return (1);
102 }
103 
104 int
105 psp_match(struct device *parent, void *match, void *aux)
106 {
107 	return (1);
108 }
109 
110 void
111 psp_attach(struct device *parent, struct device *self, void *aux)
112 {
113 	struct psp_softc		*sc = (struct psp_softc *)self;
114 	struct psp_attach_args		*arg = aux;
115 	struct psp_platform_status	pst;
116 	size_t				size;
117 	int				nsegs;
118 
119 	printf(":");
120 	sc->sc_iot = arg->iot;
121 	sc->sc_ioh = arg->ioh;
122 	sc->sc_dmat = arg->dmat;
123 	if (arg->version == 1) {
124 		sc->sc_reg_inten = PSPV1_REG_INTEN;
125 		sc->sc_reg_intsts = PSPV1_REG_INTSTS;
126 		sc->sc_reg_cmdresp = PSPV1_REG_CMDRESP;
127 		sc->sc_reg_addrlo = PSPV1_REG_ADDRLO;
128 		sc->sc_reg_addrhi = PSPV1_REG_ADDRHI;
129 	} else {
130 		sc->sc_reg_inten = PSP_REG_INTEN;
131 		sc->sc_reg_intsts = PSP_REG_INTSTS;
132 		sc->sc_reg_cmdresp = PSP_REG_CMDRESP;
133 		sc->sc_reg_addrlo = PSP_REG_ADDRLO;
134 		sc->sc_reg_addrhi = PSP_REG_ADDRHI;
135 	}
136 	if (arg->version)
137 		printf(" vers %d,", arg->version);
138 
139 	rw_init(&sc->sc_lock, "psp_lock");
140 
141 	/* create and map SEV command buffer */
142 	sc->sc_cmd_size = size = PAGE_SIZE;
143 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
144 	    BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT,
145 	    &sc->sc_cmd_map) != 0)
146 		return;
147 
148 	if (bus_dmamem_alloc(sc->sc_dmat, size, 0, 0, &sc->sc_cmd_seg, 1,
149 	    &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0)
150 		goto fail_0;
151 
152 	if (bus_dmamem_map(sc->sc_dmat, &sc->sc_cmd_seg, nsegs, size,
153 	    &sc->sc_cmd_kva, BUS_DMA_WAITOK) != 0)
154 		goto fail_1;
155 
156 	if (bus_dmamap_load(sc->sc_dmat, sc->sc_cmd_map, sc->sc_cmd_kva,
157 	    size, NULL, BUS_DMA_WAITOK) != 0)
158 		goto fail_2;
159 
160 	if (psp_get_pstatus(sc, &pst)) {
161 		printf(" platform status");
162 		goto fail_3;
163 	}
164 	if (pst.state != PSP_PSTATE_UNINIT) {
165 		printf(" uninitialized state");
166 		goto fail_3;
167 	}
168 	printf(" api %u.%u, build %u, SEV, SEV-ES",
169 	    pst.api_major, pst.api_minor, pst.cfges_build >> 24);
170 
171 	/* enable interrupts */
172 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_inten, -1);
173 
174 	printf("\n");
175 
176 	return;
177 
178 fail_3:
179 	bus_dmamap_unload(sc->sc_dmat, sc->sc_cmd_map);
180 fail_2:
181 	bus_dmamem_unmap(sc->sc_dmat, sc->sc_cmd_kva, size);
182 fail_1:
183 	bus_dmamem_free(sc->sc_dmat, &sc->sc_cmd_seg, 1);
184 fail_0:
185 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmd_map);
186 
187 	printf(" failed\n");
188 
189 	return;
190 }
191 
192 static int
193 ccp_wait(struct psp_softc *sc, uint32_t *status, int poll)
194 {
195 	uint32_t	cmdword;
196 	int		count;
197 
198 	if (poll) {
199 		count = 0;
200 		while (count++ < 400) {
201 			cmdword = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
202 			    sc->sc_reg_cmdresp);
203 			if (cmdword & PSP_CMDRESP_RESPONSE)
204 				goto done;
205 			delay(5000);
206 		}
207 
208 		/* timeout */
209 		return (1);
210 	}
211 
212 	if (tsleep_nsec(sc, PWAIT, "psp", SEC_TO_NSEC(2)) == EWOULDBLOCK)
213 		return (1);
214 
215 	cmdword = bus_space_read_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_cmdresp);
216 done:
217 	if (status != NULL)
218 		*status = cmdword;
219 	return (0);
220 }
221 
222 static int
223 ccp_docmd(struct psp_softc *sc, int cmd, uint64_t paddr)
224 {
225 	uint32_t	plo, phi, cmdword, status;
226 
227 	plo = ((paddr >> 0) & 0xffffffff);
228 	phi = ((paddr >> 32) & 0xffffffff);
229 	cmdword = (cmd & 0x3ff) << 16;
230 	if (!cold)
231 		cmdword |= PSP_CMDRESP_IOC;
232 
233 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_addrlo, plo);
234 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_addrhi, phi);
235 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_cmdresp, cmdword);
236 
237 	if (ccp_wait(sc, &status, cold))
238 		return (1);
239 
240 	/* Did PSP sent a response code? */
241 	if (status & PSP_CMDRESP_RESPONSE) {
242 		if ((status & PSP_STATUS_MASK) != PSP_STATUS_SUCCESS)
243 			return (1);
244 	}
245 
246 	return (0);
247 }
248 
249 int
250 psp_init(struct psp_softc *sc, struct psp_init *uinit)
251 {
252 	struct psp_init		*init;
253 	int			 ret;
254 
255 	init = (struct psp_init *)sc->sc_cmd_kva;
256 	bzero(init, sizeof(*init));
257 
258 	init->enable_es = uinit->enable_es;
259 	init->tmr_paddr = uinit->tmr_paddr;
260 	init->tmr_length = uinit->tmr_length;
261 
262 	ret = ccp_docmd(sc, PSP_CMD_INIT, sc->sc_cmd_map->dm_segs[0].ds_addr);
263 	if (ret != 0)
264 		return (EIO);
265 
266 	wbinvd_on_all_cpus_acked();
267 
268 	sc->sc_flags |= PSPF_INITIALIZED;
269 
270 	return (0);
271 }
272 
273 int
274 psp_reinit(struct psp_softc *sc)
275 {
276 	struct psp_init	init;
277 	size_t		size;
278 	int		nsegs;
279 
280 	if (sc->sc_flags & PSPF_INITIALIZED) {
281 		printf("%s: invalid flags 0x%x\n", __func__, sc->sc_flags);
282 		return (EINVAL);
283 	}
284 
285 	if (sc->sc_tmr_map != NULL)
286 		return (EINVAL);
287 
288 	/*
289 	 * create and map Trusted Memory Region (TMR); size 1 Mbyte,
290 	 * needs to be aligend to 1 Mbyte.
291 	 */
292 	sc->sc_tmr_size = size = PSP_TMR_SIZE;
293 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
294 	    BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT,
295 	    &sc->sc_tmr_map) != 0)
296 		return (ENOMEM);
297 
298 	if (bus_dmamem_alloc(sc->sc_dmat, size, size, 0, &sc->sc_tmr_seg, 1,
299 	    &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0)
300 		goto fail_0;
301 
302 	if (bus_dmamem_map(sc->sc_dmat, &sc->sc_tmr_seg, nsegs, size,
303 	    &sc->sc_tmr_kva, BUS_DMA_WAITOK) != 0)
304 		goto fail_1;
305 
306 	if (bus_dmamap_load(sc->sc_dmat, sc->sc_tmr_map, sc->sc_tmr_kva,
307 	    size, NULL, BUS_DMA_WAITOK) != 0)
308 		goto fail_2;
309 
310 	memset(&init, 0, sizeof(init));
311 	init.enable_es = 1;
312 	init.tmr_length = PSP_TMR_SIZE;
313 	init.tmr_paddr = sc->sc_tmr_map->dm_segs[0].ds_addr;
314 	if (psp_init(sc, &init))
315 		goto fail_3;
316 
317 	return (0);
318 
319 fail_3:
320 	bus_dmamap_unload(sc->sc_dmat, sc->sc_tmr_map);
321 fail_2:
322 	bus_dmamem_unmap(sc->sc_dmat, sc->sc_tmr_kva, size);
323 fail_1:
324 	bus_dmamem_free(sc->sc_dmat, &sc->sc_tmr_seg, 1);
325 fail_0:
326 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_tmr_map);
327 
328 	return (ENOMEM);
329 }
330 
331 int
332 psp_shutdown(struct psp_softc *sc)
333 {
334 	int ret;
335 
336 	if (sc->sc_tmr_map == NULL)
337 		return (EINVAL);
338 
339 	ret = ccp_docmd(sc, PSP_CMD_SHUTDOWN, 0x0);
340 
341 	if (ret != 0)
342 		return (EIO);
343 
344 	/* wbinvd right after SHUTDOWN */
345 	wbinvd_on_all_cpus_acked();
346 
347 	/* release TMR */
348 	bus_dmamap_unload(sc->sc_dmat, sc->sc_tmr_map);
349 	bus_dmamem_unmap(sc->sc_dmat, sc->sc_tmr_kva, sc->sc_tmr_size);
350 	bus_dmamem_free(sc->sc_dmat, &sc->sc_tmr_seg, 1);
351 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_tmr_map);
352 	sc->sc_tmr_map = NULL;
353 
354 	/* reset flags */
355 	sc->sc_flags = 0;
356 
357 	return (0);
358 }
359 
360 int
361 psp_get_pstatus(struct psp_softc *sc, struct psp_platform_status *ustatus)
362 {
363 	struct psp_platform_status *status;
364 	int			 ret;
365 
366 	status = (struct psp_platform_status *)sc->sc_cmd_kva;
367 	bzero(status, sizeof(*status));
368 
369 	ret = ccp_docmd(sc, PSP_CMD_PLATFORMSTATUS,
370 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
371 
372 	if (ret != 0)
373 		return (EIO);
374 
375 	bcopy(status, ustatus, sizeof(*ustatus));
376 
377 	return (0);
378 }
379 
380 int
381 psp_df_flush(struct psp_softc *sc)
382 {
383 	int			 ret;
384 
385 	wbinvd_on_all_cpus_acked();
386 
387 	ret = ccp_docmd(sc, PSP_CMD_DF_FLUSH, 0x0);
388 
389 	if (ret != 0)
390 		return (EIO);
391 
392 	return (0);
393 }
394 
395 int
396 psp_decommission(struct psp_softc *sc, struct psp_decommission *udecom)
397 {
398 	struct psp_decommission	*decom;
399 	int			 ret;
400 
401 	decom = (struct psp_decommission *)sc->sc_cmd_kva;
402 	bzero(decom, sizeof(*decom));
403 
404 	decom->handle = udecom->handle;
405 
406 	ret = ccp_docmd(sc, PSP_CMD_DECOMMISSION,
407 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
408 
409 	if (ret != 0)
410 		return (EIO);
411 
412 	return (0);
413 }
414 
415 int
416 psp_get_gstatus(struct psp_softc *sc, struct psp_guest_status *ustatus)
417 {
418 	struct psp_guest_status	*status;
419 	int			 ret;
420 
421 	status = (struct psp_guest_status *)sc->sc_cmd_kva;
422 	bzero(status, sizeof(*status));
423 
424 	status->handle = ustatus->handle;
425 
426 	ret = ccp_docmd(sc, PSP_CMD_GUESTSTATUS,
427 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
428 
429 	if (ret != 0)
430 		return (EIO);
431 
432 	ustatus->policy = status->policy;
433 	ustatus->asid = status->asid;
434 	ustatus->state = status->state;
435 
436 	return (0);
437 }
438 
439 int
440 psp_launch_start(struct psp_softc *sc, struct psp_launch_start *ustart)
441 {
442 	struct psp_launch_start	*start;
443 	int			 ret;
444 
445 	start = (struct psp_launch_start *)sc->sc_cmd_kva;
446 	bzero(start, sizeof(*start));
447 
448 	start->handle = ustart->handle;
449 	start->policy = ustart->policy;
450 
451 	ret = ccp_docmd(sc, PSP_CMD_LAUNCH_START,
452 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
453 
454 	if (ret != 0)
455 		return (EIO);
456 
457 	/* If requested, return new handle. */
458 	if (ustart->handle == 0)
459 		ustart->handle = start->handle;
460 
461 	return (0);
462 }
463 
464 int
465 psp_launch_update_data(struct psp_softc *sc,
466     struct psp_launch_update_data *ulud, struct proc *p)
467 {
468 	struct psp_launch_update_data	*ludata;
469 	pmap_t				 pmap;
470 	vaddr_t				 v, next, end;
471 	size_t				 size, len, off;
472 	int				 ret;
473 
474 	/* Ensure AES_XTS_BLOCKSIZE alignment and multiplicity. */
475 	if ((ulud->paddr & (AES_XTS_BLOCKSIZE - 1)) != 0 ||
476 	    (ulud->length % AES_XTS_BLOCKSIZE) != 0)
477 		return (EINVAL);
478 
479 	ludata = (struct psp_launch_update_data *)sc->sc_cmd_kva;
480 	bzero(ludata, sizeof(*ludata));
481 
482 	ludata->handle = ulud->handle;
483 
484 	/* Drain caches before we encrypt memory. */
485 	wbinvd_on_all_cpus_acked();
486 
487 	/*
488 	 * Launch update one physical page at a time.  We could
489 	 * optimise this for contiguous pages of physical memory.
490 	 *
491 	 * vmd(8) provides the guest physical address, thus convert
492 	 * to system physical address.
493 	 */
494 	pmap = vm_map_pmap(&p->p_vmspace->vm_map);
495 	size = ulud->length;
496 	end = ulud->paddr + ulud->length;
497 	for (v = ulud->paddr; v < end; v = next) {
498 		off = v & PAGE_MASK;
499 
500 		len = MIN(PAGE_SIZE - off, size);
501 
502 		/* Wire mapping. */
503 		if (uvm_map_pageable(&p->p_vmspace->vm_map, v, v+len, FALSE, 0))
504 			return (EINVAL);
505 		if (!pmap_extract(pmap, v, (paddr_t *)&ludata->paddr))
506 			return (EINVAL);
507 		ludata->length = len;
508 
509 		ret = ccp_docmd(sc, PSP_CMD_LAUNCH_UPDATE_DATA,
510 		    sc->sc_cmd_map->dm_segs[0].ds_addr);
511 
512 		if (ret != 0)
513 			return (EIO);
514 
515 		size -= len;
516 		next = v + len;
517 	}
518 
519 	return (0);
520 }
521 
522 int
523 psp_launch_measure(struct psp_softc *sc, struct psp_launch_measure *ulm)
524 {
525 	struct psp_launch_measure *lm;
526 	int			 ret;
527 	uint64_t		 paddr;
528 
529 	if (ulm->measure_len != sizeof(ulm->psp_measure))
530 		return (EINVAL);
531 
532 	lm = (struct psp_launch_measure *)sc->sc_cmd_kva;
533 	bzero(lm, sizeof(*lm));
534 
535 	lm->handle = ulm->handle;
536 	paddr = sc->sc_cmd_map->dm_segs[0].ds_addr;
537 	lm->measure_paddr =
538 	    paddr + offsetof(struct psp_launch_measure, psp_measure);
539 	lm->measure_len = sizeof(lm->psp_measure);
540 
541 	ret = ccp_docmd(sc, PSP_CMD_LAUNCH_MEASURE, paddr);
542 
543 	if (ret != 0 || lm->measure_len != ulm->measure_len)
544 		return (EIO);
545 
546 	bcopy(&lm->psp_measure, &ulm->psp_measure, ulm->measure_len);
547 
548 	return (0);
549 }
550 
551 int
552 psp_launch_finish(struct psp_softc *sc, struct psp_launch_finish *ulf)
553 {
554 	struct psp_launch_finish *lf;
555 	int			 ret;
556 
557 	lf = (struct psp_launch_finish *)sc->sc_cmd_kva;
558 	bzero(lf, sizeof(*lf));
559 
560 	lf->handle = ulf->handle;
561 
562 	ret = ccp_docmd(sc, PSP_CMD_LAUNCH_FINISH,
563 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
564 
565 	if (ret != 0)
566 		return (EIO);
567 
568 	return (0);
569 }
570 
571 int
572 psp_attestation(struct psp_softc *sc, struct psp_attestation *uat)
573 {
574 	struct psp_attestation	*at;
575 	int			 ret;
576 	uint64_t		 paddr;
577 
578 	if (uat->attest_len != sizeof(uat->psp_report))
579 		return (EINVAL);
580 
581 	at = (struct psp_attestation *)sc->sc_cmd_kva;
582 	bzero(at, sizeof(*at));
583 
584 	at->handle = uat->handle;
585 	paddr = sc->sc_cmd_map->dm_segs[0].ds_addr;
586 	at->attest_paddr =
587 	    paddr + offsetof(struct psp_attestation, psp_report);
588 	bcopy(uat->attest_nonce, at->attest_nonce, sizeof(at->attest_nonce));
589 	at->attest_len = sizeof(at->psp_report);
590 
591 	ret = ccp_docmd(sc, PSP_CMD_ATTESTATION, paddr);
592 
593 	if (ret != 0 || at->attest_len != uat->attest_len)
594 		return (EIO);
595 
596 	bcopy(&at->psp_report, &uat->psp_report, uat->attest_len);
597 
598 	return (0);
599 }
600 
601 int
602 psp_activate(struct psp_softc *sc, struct psp_activate *uact)
603 {
604 	struct psp_activate	*act;
605 	int			 ret;
606 
607 	act = (struct psp_activate *)sc->sc_cmd_kva;
608 	bzero(act, sizeof(*act));
609 
610 	act->handle = uact->handle;
611 	act->asid = uact->asid;
612 
613 	ret = ccp_docmd(sc, PSP_CMD_ACTIVATE,
614 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
615 
616 	if (ret != 0)
617 		return (EIO);
618 
619 	return (0);
620 }
621 
622 int
623 psp_deactivate(struct psp_softc *sc, struct psp_deactivate *udeact)
624 {
625 	struct psp_deactivate	*deact;
626 	int			 ret;
627 
628 	deact = (struct psp_deactivate *)sc->sc_cmd_kva;
629 	bzero(deact, sizeof(*deact));
630 
631 	deact->handle = udeact->handle;
632 
633 	ret = ccp_docmd(sc, PSP_CMD_DEACTIVATE,
634 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
635 
636 	if (ret != 0)
637 		return (EIO);
638 
639 	return (0);
640 }
641 
642 int
643 psp_downloadfirmware(struct psp_softc *sc, struct psp_downloadfirmware *udlfw)
644 {
645 	struct psp_downloadfirmware *dlfw;
646 	bus_dmamap_t		 map;
647 	bus_dma_segment_t	 seg;
648 	caddr_t			 kva;
649 	int			 nsegs;
650 	int			 ret;
651 
652 	dlfw = (struct psp_downloadfirmware *)sc->sc_cmd_kva;
653 	bzero(dlfw, sizeof(*dlfw));
654 
655 	ret = ENOMEM;
656 	if (bus_dmamap_create(sc->sc_dmat, udlfw->fw_len, 1, udlfw->fw_len, 0,
657 	    BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, &map) != 0)
658 		return (ret);
659 	if (bus_dmamem_alloc(sc->sc_dmat, udlfw->fw_len, 0, 0, &seg, 1,
660 	    &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0 || nsegs != 1)
661 		goto fail_0;
662 	if (bus_dmamem_map(sc->sc_dmat, &seg, nsegs, udlfw->fw_len, &kva,
663 	    BUS_DMA_WAITOK) != 0)
664 		goto fail_1;
665 	if (bus_dmamap_load(sc->sc_dmat, map, kva, udlfw->fw_len, NULL,
666 	    BUS_DMA_WAITOK) != 0)
667 		goto fail_2;
668 
669 	bcopy((void *)udlfw->fw_paddr, kva, udlfw->fw_len);
670 
671 	dlfw->fw_paddr = map->dm_segs[0].ds_addr;
672 	dlfw->fw_len = map->dm_segs[0].ds_len;
673 
674 	ret = ccp_docmd(sc, PSP_CMD_DOWNLOADFIRMWARE,
675 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
676 
677 	if (ret != 0)
678 		ret = EIO;
679 
680 	bus_dmamap_unload(sc->sc_dmat, map);
681 fail_2:
682 	bus_dmamem_unmap(sc->sc_dmat, kva, udlfw->fw_len);
683 fail_1:
684 	bus_dmamem_free(sc->sc_dmat, &seg, 1);
685 fail_0:
686 	bus_dmamap_destroy(sc->sc_dmat, map);
687 
688 	return (ret);
689 }
690 
691 int
692 psp_guest_shutdown(struct psp_softc *sc, struct psp_guest_shutdown *ugshutdown)
693 {
694 	struct psp_deactivate	deact;
695 	struct psp_decommission	decom;
696 	int			ret;
697 
698 	bzero(&deact, sizeof(deact));
699 	deact.handle = ugshutdown->handle;
700 	if ((ret = psp_deactivate(sc, &deact)) != 0)
701 		return (ret);
702 
703 	if ((ret = psp_df_flush(sc)) != 0)
704 		return (ret);
705 
706 	bzero(&decom, sizeof(decom));
707 	decom.handle = ugshutdown->handle;
708 	if ((ret = psp_decommission(sc, &decom)) != 0)
709 		return (ret);
710 
711 	return (0);
712 }
713 
714 int
715 psp_snp_get_pstatus(struct psp_softc *sc,
716     struct psp_snp_platform_status *ustatus)
717 {
718 	struct psp_snp_platform_status *status;
719 	int			 ret;
720 
721 	status = (struct psp_snp_platform_status *)sc->sc_cmd_kva;
722 	bzero(status, sizeof(*status));
723 
724 	ret = ccp_docmd(sc, PSP_CMD_SNP_PLATFORMSTATUS,
725 	    sc->sc_cmd_map->dm_segs[0].ds_addr);
726 
727 	if (ret != 0)
728 		return (EIO);
729 
730 	bcopy(status, ustatus, sizeof(*ustatus));
731 
732 	return (0);
733 }
734 
735 int
736 pspopen(dev_t dev, int flag, int mode, struct proc *p)
737 {
738 	struct psp_softc *sc;
739 
740 	sc = (struct psp_softc *)device_lookup(&psp_cd, minor(dev));
741 	if (sc == NULL)
742 		return (ENXIO);
743 
744 	psp_load_ucode(sc);
745 
746 	if (!(sc->sc_flags & PSPF_INITIALIZED))
747 		return (psp_reinit(sc));
748 
749 	return (0);
750 }
751 
752 int
753 pspclose(dev_t dev, int flag, int mode, struct proc *p)
754 {
755 	struct psp_softc *sc;
756 
757 	sc = (struct psp_softc *)device_lookup(&psp_cd, minor(dev));
758 	if (sc == NULL)
759 		return (ENXIO);
760 
761 	return (0);
762 }
763 
764 int
765 pspioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
766 {
767 	struct psp_softc *sc;
768 	int ret;
769 
770 	sc = (struct psp_softc *)device_lookup(&psp_cd, minor(dev));
771 	if (sc == NULL)
772 		return (ENXIO);
773 
774 	rw_enter_write(&sc->sc_lock);
775 
776 	switch (cmd) {
777 	case PSP_IOC_INIT:
778 		ret = psp_reinit(sc);
779 		break;
780 	case PSP_IOC_SHUTDOWN:
781 		ret = psp_shutdown(sc);
782 		break;
783 	case PSP_IOC_GET_PSTATUS:
784 		ret = psp_get_pstatus(sc, (struct psp_platform_status *)data);
785 		break;
786 	case PSP_IOC_DF_FLUSH:
787 		ret = psp_df_flush(sc);
788 		break;
789 	case PSP_IOC_DECOMMISSION:
790 		ret = psp_decommission(sc, (struct psp_decommission *)data);
791 		break;
792 	case PSP_IOC_GET_GSTATUS:
793 		ret = psp_get_gstatus(sc, (struct psp_guest_status *)data);
794 		break;
795 	case PSP_IOC_LAUNCH_START:
796 		ret = psp_launch_start(sc, (struct psp_launch_start *)data);
797 		break;
798 	case PSP_IOC_LAUNCH_UPDATE_DATA:
799 		ret = psp_launch_update_data(sc,
800 		    (struct psp_launch_update_data *)data, p);
801 		break;
802 	case PSP_IOC_LAUNCH_MEASURE:
803 		ret = psp_launch_measure(sc, (struct psp_launch_measure *)data);
804 		break;
805 	case PSP_IOC_LAUNCH_FINISH:
806 		ret = psp_launch_finish(sc, (struct psp_launch_finish *)data);
807 		break;
808 	case PSP_IOC_ATTESTATION:
809 		ret = psp_attestation(sc, (struct psp_attestation *)data);
810 		break;
811 	case PSP_IOC_ACTIVATE:
812 		ret = psp_activate(sc, (struct psp_activate *)data);
813 		break;
814 	case PSP_IOC_DEACTIVATE:
815 		ret = psp_deactivate(sc, (struct psp_deactivate *)data);
816 		break;
817 	case PSP_IOC_GUEST_SHUTDOWN:
818 		ret = psp_guest_shutdown(sc, (struct psp_guest_shutdown *)data);
819 		break;
820 	case PSP_IOC_SNP_GET_PSTATUS:
821 		ret = psp_snp_get_pstatus(sc,
822 		    (struct psp_snp_platform_status *)data);
823 		break;
824 	default:
825 		ret = ENOTTY;
826 		break;
827 	}
828 
829 	rw_exit_write(&sc->sc_lock);
830 
831 	return (ret);
832 }
833 
834 int
835 pledge_ioctl_psp(struct proc *p, long com)
836 {
837 	switch (com) {
838 	case PSP_IOC_GET_PSTATUS:
839 	case PSP_IOC_DF_FLUSH:
840 	case PSP_IOC_GET_GSTATUS:
841 	case PSP_IOC_LAUNCH_START:
842 	case PSP_IOC_LAUNCH_UPDATE_DATA:
843 	case PSP_IOC_LAUNCH_MEASURE:
844 	case PSP_IOC_LAUNCH_FINISH:
845 	case PSP_IOC_ACTIVATE:
846 	case PSP_IOC_GUEST_SHUTDOWN:
847 		return (0);
848 	default:
849 		return (pledge_fail(p, EPERM, PLEDGE_VMM));
850 	}
851 }
852 
853 int
854 pspprint(void *aux, const char *pnp)
855 {
856 	return QUIET;
857 }
858 
859 int
860 pspsubmatch(struct device *parent, void *match, void *aux)
861 {
862 	struct psp_attach_args *arg = aux;
863 	struct cfdata *cf = match;
864 
865 	if (!(arg->capabilities & PSP_CAP_SEV))
866 		return (0);
867 	return ((*cf->cf_attach->ca_match)(parent, cf, aux));
868 }
869 
870 struct ucode {
871 	uint8_t		 family;
872 	uint8_t		 model;
873 	const char	*uname;
874 } const psp_ucode_table[] = {
875 	{ 0x17, 0x0, "amdsev/amd_sev_fam17h_model0xh.sbin" },
876 	{ 0x17, 0x3, "amdsev/amd_sev_fam17h_model3xh.sbin" },
877 	{ 0x19, 0x0, "amdsev/amd_sev_fam19h_model0xh.sbin" },
878 	{ 0x19, 0x1, "amdsev/amd_sev_fam19h_model1xh.sbin" },
879 	{ 0, 0, NULL }
880 };
881 
882 void
883 psp_load_ucode(struct psp_softc *sc)
884 {
885 	struct psp_downloadfirmware dlfw;
886 	struct cpu_info		*ci = &cpu_info_primary;
887 	const struct ucode	*uc;
888 	uint8_t			 family, model;
889 	int			 error;
890 
891 	if ((sc->sc_flags & PSPF_UCODELOADED) ||
892 	    (sc->sc_flags & PSPF_NOUCODE) ||
893 	    (sc->sc_flags & PSPF_INITIALIZED))
894 		return;
895 
896 	family = ci->ci_family;
897 	model = (ci->ci_model & 0xf0) >> 4;
898 
899 	for (uc = psp_ucode_table; uc->uname; uc++) {
900 		if ((uc->family == family) && (uc->model == model))
901 			break;
902 	}
903 
904 	if (uc->uname == NULL) {
905 		printf("%s: no firmware found, CPU family 0x%x model 0x%x\n",
906 		    sc->sc_dev.dv_xname, family, model);
907 		sc->sc_flags |= PSPF_NOUCODE;
908 		return;
909 	}
910 
911 	error = loadfirmware(uc->uname, &sc->sc_ucodebuf, &sc->sc_ucodelen);
912 	if (error) {
913 		if (error != ENOENT) {
914 			printf("%s: error %d, could not read firmware %s\n",
915 			    sc->sc_dev.dv_xname, error, uc->uname);
916 		}
917 		sc->sc_flags |= PSPF_NOUCODE;
918 		return;
919 	}
920 
921 	bzero(&dlfw, sizeof(dlfw));
922 	dlfw.fw_len = sc->sc_ucodelen;
923 	dlfw.fw_paddr = (uint64_t)sc->sc_ucodebuf;
924 
925 	if (psp_downloadfirmware(sc, &dlfw) < 0)
926 		goto out;
927 
928 	sc->sc_flags |= PSPF_UCODELOADED;
929 out:
930 	if (sc->sc_ucodebuf) {
931 		free(sc->sc_ucodebuf, M_DEVBUF, sc->sc_ucodelen);
932 		sc->sc_ucodebuf = NULL;
933 		sc->sc_ucodelen = 0;
934 	}
935 }
936