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