summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2024-11-08 17:34:23 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2024-11-08 17:34:23 +0000
commit5e5560884a20c45ed0f31c208b906dca65cc38c5 (patch)
tree9391475faca61eafa1ab945520cdf241be1055f0 /sys/dev/ic
parentcf358e57108bb4994838c09b466f48e0f82342ac (diff)
Use a mutex to make psp(4) MP safe.
To avoid a race between writing PSP command, sleeping, receiving interrupt, and calling wakeup(9), protect psp(4) driver with a mutex. With that interrupt handler is MP safe and ioctl(2) can release kernel lock. from hshoexer@; OK dlg@
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/psp.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/sys/dev/ic/psp.c b/sys/dev/ic/psp.c
index 1fd1bb89fc7..cce250d111b 100644
--- a/sys/dev/ic/psp.c
+++ b/sys/dev/ic/psp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: psp.c,v 1.11 2024/11/08 12:08:22 bluhm Exp $ */
+/* $OpenBSD: psp.c,v 1.12 2024/11/08 17:34:22 bluhm Exp $ */
/*
* Copyright (c) 2023, 2024 Hans-Joerg Hoexer <hshoexer@genua.de>
@@ -20,12 +20,13 @@
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>
+#include <sys/mutex.h>
#include <sys/pledge.h>
+#include <sys/proc.h>
#include <sys/rwlock.h>
#include <machine/bus.h>
-#include <sys/proc.h>
#include <uvm/uvm.h>
#include <crypto/xform.h>
@@ -56,6 +57,7 @@ struct psp_softc {
caddr_t sc_tmr_kva;
struct rwlock sc_lock;
+ struct mutex psp_lock;
uint32_t sc_flags;
#define PSPF_INITIALIZED 0x1
@@ -90,8 +92,10 @@ psp_sev_intr(void *arg)
struct psp_softc *sc = (struct psp_softc *)csc->sc_psp;
uint32_t status;
+ mtx_enter(&sc->psp_lock);
status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_intsts);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_intsts, status);
+ mtx_leave(&sc->psp_lock);
if (!(status & PSP_CMDRESP_COMPLETE))
return (0);
@@ -137,6 +141,7 @@ psp_attach(struct device *parent, struct device *self, void *aux)
printf(" vers %d,", arg->version);
rw_init(&sc->sc_lock, "psp_lock");
+ mtx_init(&sc->psp_lock, IPL_BIO);
/* create and map SEV command buffer */
sc->sc_cmd_size = size = PAGE_SIZE;
@@ -195,6 +200,8 @@ ccp_wait(struct psp_softc *sc, uint32_t *status, int poll)
uint32_t cmdword;
int count;
+ MUTEX_ASSERT_LOCKED(&sc->psp_lock);
+
if (poll) {
count = 0;
while (count++ < 400) {
@@ -209,7 +216,8 @@ ccp_wait(struct psp_softc *sc, uint32_t *status, int poll)
return (1);
}
- if (tsleep_nsec(sc, PWAIT, "psp", SEC_TO_NSEC(2)) == EWOULDBLOCK)
+ if (msleep_nsec(sc, &sc->psp_lock, PWAIT, "psp", SEC_TO_NSEC(2))
+ == EWOULDBLOCK)
return (1);
cmdword = bus_space_read_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_cmdresp);
@@ -223,6 +231,7 @@ static int
ccp_docmd(struct psp_softc *sc, int cmd, uint64_t paddr)
{
uint32_t plo, phi, cmdword, status;
+ int ret;
plo = ((paddr >> 0) & 0xffffffff);
phi = ((paddr >> 32) & 0xffffffff);
@@ -230,11 +239,14 @@ ccp_docmd(struct psp_softc *sc, int cmd, uint64_t paddr)
if (!cold)
cmdword |= PSP_CMDRESP_IOC;
+ mtx_enter(&sc->psp_lock);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_addrlo, plo);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_addrhi, phi);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_reg_cmdresp, cmdword);
- if (ccp_wait(sc, &status, cold))
+ ret = ccp_wait(sc, &status, cold);
+ mtx_leave(&sc->psp_lock);
+ if (ret)
return (1);
/* Did PSP sent a response code? */
@@ -771,6 +783,8 @@ pspioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
if (sc == NULL)
return (ENXIO);
+ KERNEL_UNLOCK();
+
rw_enter_write(&sc->sc_lock);
switch (cmd) {
@@ -828,6 +842,8 @@ pspioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
rw_exit_write(&sc->sc_lock);
+ KERNEL_LOCK();
+
return (ret);
}