sync with OpenBSD -current

This commit is contained in:
purplerain 2024-06-13 03:03:45 +00:00
parent d22f2a15f3
commit f4a22ff4b2
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
17 changed files with 1316 additions and 178 deletions

View file

@ -1,4 +1,4 @@
/* $OpenBSD: rktemp.c,v 1.12 2023/03/05 09:57:32 kettenis Exp $ */
/* $OpenBSD: rktemp.c,v 1.13 2024/06/12 09:06:15 kettenis Exp $ */
/*
* Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
*
@ -36,43 +36,38 @@
#define TSADC_USER_CON_INTER_PD_SOC_SHIFT 6
#define TSADC_AUTO_CON 0x0004
#define TSADC_AUTO_CON_TSHUT_POLARITY (1 << 8)
#define TSADC_AUTO_CON_SRC3_EN (1 << 7)
#define TSADC_AUTO_CON_SRC2_EN (1 << 6)
#define TSADC_AUTO_CON_SRC1_EN (1 << 5)
#define TSADC_AUTO_CON_SRC0_EN (1 << 4)
#define TSADC_AUTO_CON_SRC_EN(ch) (1 << ((ch) + 4))
#define TSADC_AUTO_CON_TSADC_Q_SEL (1 << 1)
#define TSADC_AUTO_CON_AUTO_EN (1 << 0)
#define TSADC_INT_EN 0x0008
#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC3 (1 << 11)
#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC2 (1 << 10)
#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC1 (1 << 9)
#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 (1 << 8)
#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC3 (1 << 7)
#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC2 (1 << 6)
#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC1 (1 << 5)
#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 (1 << 4)
#define TSADC_INT_EN_TSHUT_2CRU_EN_SRC(ch) (1 << ((ch) + 8))
#define TSADC_INT_EN_TSHUT_2GPIO_EN_SRC(ch) (1 << ((ch) + 4))
#define TSADC_INT_PD 0x000c
#define TSADC_INT_PD_TSHUT_O_SRC0 (1 << 4)
#define TSADC_INT_PD_TSHUT_O_SRC1 (1 << 5)
#define TSADC_INT_PD_TSHUT_O_SRC2 (1 << 6)
#define TSADC_INT_PD_TSHUT_O_SRC3 (1 << 7)
#define TSADC_DATA0 0x0020
#define TSADC_DATA1 0x0024
#define TSADC_DATA2 0x0028
#define TSADC_DATA3 0x002c
#define TSADC_COMP0_INT 0x0030
#define TSADC_COMP1_INT 0x0034
#define TSADC_COMP2_INT 0x0038
#define TSADC_COMP3_INT 0x003c
#define TSADC_COMP0_SHUT 0x0040
#define TSADC_COMP1_SHUT 0x0044
#define TSADC_COMP2_SHUT 0x0048
#define TSADC_COMP3_SHUT 0x004c
#define TSADC_INT_PD_TSHUT_O_SRC(ch) (1 << ((ch) + 4))
#define TSADC_DATA(ch) (0x0020 + (ch) * 4)
#define TSADC_COMP_INT(ch) (0x0030 + (ch) * 4)
#define TSADC_COMP_SHUT(ch) (0x0040 + (ch) * 4)
#define TSADC_HIGHT_INT_DEBOUNCE 0x0060
#define TSADC_HIGHT_TSHUT_DEBOUNCE 0x0064
#define TSADC_AUTO_PERIOD 0x0068
#define TSADC_AUTO_PERIOD_HT 0x006c
/* RK3588 */
#define TSADC_V3_AUTO_SRC 0x000c
#define TSADC_V3_AUTO_SRC_CH(ch) (1 << (ch))
#define TSADC_V3_GPIO_EN 0x0018
#define TSADC_V3_GPIO_EN_CH(ch) (1 << (ch))
#define TSADC_V3_CRU_EN 0x001c
#define TSADC_V3_CRU_EN_CH(ch) (1 << (ch))
#define TSADC_V3_HLT_INT_PD 0x0024
#define TSADC_V3_HT_INT_STATUS(ch) (1 << (ch))
#define TSADC_V3_DATA(ch) (0x002c + (ch) * 4)
#define TSADC_V3_COMP_SHUT(ch) (0x010c + (ch) * 4)
#define TSADC_V3_HIGHT_INT_DEBOUNCE 0x014c
#define TSADC_V3_HIGHT_TSHUT_DEBOUNCE 0x0150
#define TSADC_V3_AUTO_PERIOD 0x0154
#define TSADC_V3_AUTO_PERIOD_HT 0x0158
/* RK3568 */
#define RK3568_GRF_TSADC_CON 0x0600
#define RK3568_GRF_TSADC_EN (1 << 8)
@ -248,16 +243,36 @@ const struct rktemp_entry rk3568_temps[] = {
const char *const rk3568_names[] = { "CPU", "GPU" };
/* RK3588 conversion table. */
const struct rktemp_entry rk3588_temps[] = {
{ -40000, 215 },
{ 25000, 285 },
{ 85000, 350 },
{ 125000, 395 },
};
const char *const rk3588_names[] = {
"Top",
"CPU (big0)",
"CPU (big1)",
"CPU (little)",
"Center",
"GPU",
"NPU"
};
struct rktemp_softc {
struct device sc_dev;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
int sc_node;
bus_size_t sc_data0;
const struct rktemp_entry *sc_temps;
int sc_ntemps;
struct ksensor sc_sensors[3];
struct ksensor sc_sensors[7];
int sc_nsensors;
struct ksensordev sc_sensordev;
@ -291,7 +306,8 @@ rktemp_match(struct device *parent, void *match, void *aux)
OF_is_compatible(faa->fa_node, "rockchip,rk3308-tsadc") ||
OF_is_compatible(faa->fa_node, "rockchip,rk3328-tsadc") ||
OF_is_compatible(faa->fa_node, "rockchip,rk3399-tsadc") ||
OF_is_compatible(faa->fa_node, "rockchip,rk3568-tsadc"));
OF_is_compatible(faa->fa_node, "rockchip,rk3568-tsadc") ||
OF_is_compatible(faa->fa_node, "rockchip,rk3588-tsadc"));
}
void
@ -301,8 +317,7 @@ rktemp_attach(struct device *parent, struct device *self, void *aux)
struct fdt_attach_args *faa = aux;
const char *const *names;
uint32_t mode, polarity, temp;
uint32_t auto_con, int_en;
uint32_t inter_pd_soc;
uint32_t auto_con, inter_pd_soc;
int auto_period, auto_period_ht;
int i;
@ -354,7 +369,7 @@ rktemp_attach(struct device *parent, struct device *self, void *aux)
inter_pd_soc = 13;
auto_period = 1875; /* 2.5 ms */
auto_period_ht = 1875; /* 2.5 ms */
} else {
} else if (OF_is_compatible(sc->sc_node, "rockchip,rk3568-tsadc")) {
sc->sc_temps = rk3568_temps;
sc->sc_ntemps = nitems(rk3568_temps);
sc->sc_nsensors = 2;
@ -362,6 +377,14 @@ rktemp_attach(struct device *parent, struct device *self, void *aux)
inter_pd_soc = 63; /* 97 us */
auto_period = 1622; /* 2.5 ms */
auto_period_ht = 1622; /* 2.5 ms */
} else {
sc->sc_temps = rk3588_temps;
sc->sc_ntemps = nitems(rk3588_temps);
sc->sc_nsensors = 7;
names = rk3588_names;
inter_pd_soc = 0;
auto_period = 5000; /* 2.5 ms */
auto_period_ht = 5000; /* 2.5 ms */
}
pinctrl_byname(sc->sc_node, "init");
@ -371,57 +394,110 @@ rktemp_attach(struct device *parent, struct device *self, void *aux)
clock_enable(sc->sc_node, "apb_pclk");
/* Reset the TS-ADC controller block. */
reset_assert(sc->sc_node, "tsadc-apb");
reset_assert_all(sc->sc_node);
delay(10);
reset_deassert(sc->sc_node, "tsadc-apb");
reset_deassert_all(sc->sc_node);
mode = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-mode", 1);
polarity = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-polarity", 0);
temp = OF_getpropint(sc->sc_node, "rockchip,hw-tshut-temp", 95000);
HWRITE4(sc, TSADC_USER_CON,
inter_pd_soc << TSADC_USER_CON_INTER_PD_SOC_SHIFT);
HWRITE4(sc, TSADC_AUTO_PERIOD, auto_period);
HWRITE4(sc, TSADC_AUTO_PERIOD_HT, auto_period_ht);
HWRITE4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
HWRITE4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
if (OF_is_compatible(sc->sc_node, "rockchip,rk3588-tsadc")) {
uint32_t gpio_en, cru_en;
if (OF_is_compatible(sc->sc_node, "rockchip,rk3568-tsadc"))
rktemp_rk3568_init(sc);
sc->sc_data0 = TSADC_V3_DATA(0);
HWRITE4(sc, TSADC_V3_AUTO_PERIOD, auto_period);
HWRITE4(sc, TSADC_V3_AUTO_PERIOD_HT, auto_period_ht);
HWRITE4(sc, TSADC_V3_HIGHT_INT_DEBOUNCE, 4);
HWRITE4(sc, TSADC_V3_HIGHT_TSHUT_DEBOUNCE, 4);
auto_con = HREAD4(sc, TSADC_AUTO_CON);
auto_con |= TSADC_AUTO_CON_TSADC_Q_SEL;
if (polarity)
auto_con |= TSADC_AUTO_CON_TSHUT_POLARITY;
HWRITE4(sc, TSADC_AUTO_CON, auto_con);
auto_con = TSADC_AUTO_CON_TSHUT_POLARITY << 16;
if (polarity)
auto_con = TSADC_AUTO_CON_TSHUT_POLARITY;
HWRITE4(sc, TSADC_AUTO_CON, auto_con);
/* Set shutdown limit. */
for (i = 0; i < sc->sc_nsensors; i++) {
HWRITE4(sc, TSADC_COMP0_SHUT + i * 4,
rktemp_calc_code(sc, temp));
auto_con |= (TSADC_AUTO_CON_SRC0_EN << i);
/* Set shutdown limit. */
for (i = 0; i < sc->sc_nsensors; i++) {
HWRITE4(sc, TSADC_V3_COMP_SHUT(i),
rktemp_calc_code(sc, temp));
HWRITE4(sc, TSADC_V3_AUTO_SRC,
TSADC_V3_AUTO_SRC_CH(i) << 16 |
TSADC_V3_AUTO_SRC_CH(i));
}
/* Clear shutdown output status. */
for (i = 0; i < sc->sc_nsensors; i++) {
HWRITE4(sc, TSADC_V3_HLT_INT_PD,
TSADC_V3_HT_INT_STATUS(i));
}
/* Configure mode. */
gpio_en = cru_en = 0;
for (i = 0; i < sc->sc_nsensors; i++) {
gpio_en |= TSADC_V3_GPIO_EN_CH(i) << 16;
cru_en |= TSADC_V3_CRU_EN_CH(i) << 16;
if (mode)
gpio_en |= TSADC_V3_GPIO_EN_CH(i);
else
cru_en |= TSADC_V3_CRU_EN_CH(i);
}
HWRITE4(sc, TSADC_V3_GPIO_EN, gpio_en);
HWRITE4(sc, TSADC_V3_CRU_EN, cru_en);
} else {
uint32_t int_en;
sc->sc_data0 = TSADC_DATA(0);
HWRITE4(sc, TSADC_USER_CON,
inter_pd_soc << TSADC_USER_CON_INTER_PD_SOC_SHIFT);
HWRITE4(sc, TSADC_AUTO_PERIOD, auto_period);
HWRITE4(sc, TSADC_AUTO_PERIOD_HT, auto_period_ht);
HWRITE4(sc, TSADC_HIGHT_INT_DEBOUNCE, 4);
HWRITE4(sc, TSADC_HIGHT_TSHUT_DEBOUNCE, 4);
if (OF_is_compatible(sc->sc_node, "rockchip,rk3568-tsadc"))
rktemp_rk3568_init(sc);
auto_con = HREAD4(sc, TSADC_AUTO_CON);
auto_con |= TSADC_AUTO_CON_TSADC_Q_SEL;
if (polarity)
auto_con |= TSADC_AUTO_CON_TSHUT_POLARITY;
HWRITE4(sc, TSADC_AUTO_CON, auto_con);
/* Set shutdown limit. */
for (i = 0; i < sc->sc_nsensors; i++) {
HWRITE4(sc, TSADC_COMP_SHUT(i),
rktemp_calc_code(sc, temp));
auto_con |= (TSADC_AUTO_CON_SRC_EN(i));
}
HWRITE4(sc, TSADC_AUTO_CON, auto_con);
/* Clear shutdown output status. */
for (i = 0; i < sc->sc_nsensors; i++)
HWRITE4(sc, TSADC_INT_PD, TSADC_INT_PD_TSHUT_O_SRC(i));
/* Configure mode. */
int_en = HREAD4(sc, TSADC_INT_EN);
for (i = 0; i < sc->sc_nsensors; i++) {
if (mode)
int_en |= TSADC_INT_EN_TSHUT_2GPIO_EN_SRC(i);
else
int_en |= TSADC_INT_EN_TSHUT_2CRU_EN_SRC(i);
}
HWRITE4(sc, TSADC_INT_EN, int_en);
}
HWRITE4(sc, TSADC_AUTO_CON, auto_con);
/* Clear shutdown output status. */
for (i = 0; i < sc->sc_nsensors; i++)
HWRITE4(sc, TSADC_INT_PD, (TSADC_INT_PD_TSHUT_O_SRC0 << i));
/* Configure mode. */
int_en = HREAD4(sc, TSADC_INT_EN);
for (i = 0; i < sc->sc_nsensors; i++) {
if (mode)
int_en |= (TSADC_INT_EN_TSHUT_2GPIO_EN_SRC0 << i);
else
int_en |= (TSADC_INT_EN_TSHUT_2CRU_EN_SRC0 << i);
}
HWRITE4(sc, TSADC_INT_EN, int_en);
pinctrl_byname(sc->sc_node, "default");
/* Finally turn on the ADC. */
auto_con |= TSADC_AUTO_CON_AUTO_EN;
HWRITE4(sc, TSADC_AUTO_CON, auto_con);
if (OF_is_compatible(sc->sc_node, "rockchip,rk3588-tsadc")) {
HWRITE4(sc, TSADC_AUTO_CON,
TSADC_AUTO_CON_AUTO_EN << 16 | TSADC_AUTO_CON_AUTO_EN);
} else {
auto_con |= TSADC_AUTO_CON_AUTO_EN;
HWRITE4(sc, TSADC_AUTO_CON, auto_con);
}
/* Register sensors. */
strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
@ -557,7 +633,7 @@ rktemp_refresh_sensors(void *arg)
int i;
for (i = 0; i < sc->sc_nsensors; i++) {
code = HREAD4(sc, TSADC_DATA0 + i * 4);
code = HREAD4(sc, sc->sc_data0 + (i * 4));
temp = rktemp_calc_temp(sc, code);
sc->sc_sensors[i].value = 273150000 + 1000 * temp;
if (rktemp_valid(sc, code))
@ -577,7 +653,7 @@ rktemp_get_temperature(void *cookie, uint32_t *cells)
if (idx >= sc->sc_nsensors)
return THERMAL_SENSOR_MAX;
code = HREAD4(sc, TSADC_DATA0 + idx * 4);
code = HREAD4(sc, sc->sc_data0 + (idx * 4));
if (rktemp_valid(sc, code))
return rktemp_calc_temp(sc, code);
else

View file

@ -1,7 +1,8 @@
/* $OpenBSD: ccp.c,v 1.3 2020/05/29 04:42:25 deraadt Exp $ */
/* $OpenBSD: ccp.c,v 1.4 2024/06/12 12:54:54 bluhm Exp $ */
/*
* Copyright (c) 2018 David Gwynne <dlg@openbsd.org>
* Copyright (c) 2023, 2024 Hans-Joerg Hoexer <hshoexer@genua.de>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -26,6 +27,12 @@
#include <machine/bus.h>
#ifdef __amd64__
#include <sys/proc.h>
#include <uvm/uvm.h>
#include <crypto/xform.h>
#endif
#include <dev/ic/ccpvar.h>
#define CCP_REG_TRNG 0xc
@ -38,13 +45,23 @@ struct cfdriver ccp_cd = {
DV_DULL
};
#ifdef __amd64__
struct ccp_softc *ccp_softc;
int psp_get_pstatus(struct psp_platform_status *);
int psp_init(struct psp_init *);
#endif
void
ccp_attach(struct ccp_softc *sc)
{
timeout_set(&sc->sc_tick, ccp_rng, sc);
ccp_rng(sc);
printf("\n");
if (sc->sc_psp_attached)
printf(", RNG\n");
else
printf(": RNG\n");
}
static void
@ -59,3 +76,585 @@ ccp_rng(void *arg)
timeout_add_msec(&sc->sc_tick, 100);
}
#ifdef __amd64__
int
psp_sev_intr(struct ccp_softc *sc, uint32_t status)
{
if (!(status & PSP_CMDRESP_COMPLETE))
return (0);
wakeup(sc);
return (1);
}
int
psp_attach(struct ccp_softc *sc)
{
struct psp_platform_status pst;
struct psp_init init;
size_t size;
int nsegs;
if (!(sc->sc_capabilities & PSP_CAP_SEV))
return (0);
rw_init(&sc->sc_lock, "ccp_lock");
/* create and map SEV command buffer */
sc->sc_cmd_size = size = PAGE_SIZE;
if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT,
&sc->sc_cmd_map) != 0)
return (0);
if (bus_dmamem_alloc(sc->sc_dmat, size, 0, 0, &sc->sc_cmd_seg, 1,
&nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0)
goto fail_0;
if (bus_dmamem_map(sc->sc_dmat, &sc->sc_cmd_seg, nsegs, size,
&sc->sc_cmd_kva, BUS_DMA_WAITOK) != 0)
goto fail_1;
if (bus_dmamap_load(sc->sc_dmat, sc->sc_cmd_map, sc->sc_cmd_kva,
size, NULL, BUS_DMA_WAITOK) != 0)
goto fail_2;
sc->sc_sev_intr = psp_sev_intr;
ccp_softc = sc;
if (psp_get_pstatus(&pst) || pst.state != 0)
goto fail_3;
printf(", SEV");
/*
* create and map Trusted Memory Region (TMR); size 1 Mbyte,
* needs to be aligend to 1 Mbyte.
*/
sc->sc_tmr_size = size = PSP_TMR_SIZE;
if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT,
&sc->sc_tmr_map) != 0)
goto fail_3;
if (bus_dmamem_alloc(sc->sc_dmat, size, size, 0, &sc->sc_tmr_seg, 1,
&nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0)
goto fail_4;
if (bus_dmamem_map(sc->sc_dmat, &sc->sc_tmr_seg, nsegs, size,
&sc->sc_tmr_kva, BUS_DMA_WAITOK) != 0)
goto fail_5;
if (bus_dmamap_load(sc->sc_dmat, sc->sc_tmr_map, sc->sc_tmr_kva,
size, NULL, BUS_DMA_WAITOK) != 0)
goto fail_6;
memset(&init, 0, sizeof(init));
init.enable_es = 1;
init.tmr_length = PSP_TMR_SIZE;
init.tmr_paddr = sc->sc_tmr_map->dm_segs[0].ds_addr;
if (psp_init(&init))
goto fail_7;
psp_get_pstatus(&pst);
if ((pst.state == 1) && (pst.cfges_build & 0x1))
printf(", SEV-ES");
sc->sc_psp_attached = 1;
return (1);
fail_7:
bus_dmamap_unload(sc->sc_dmat, sc->sc_tmr_map);
fail_6:
bus_dmamem_unmap(sc->sc_dmat, sc->sc_tmr_kva, size);
fail_5:
bus_dmamem_free(sc->sc_dmat, &sc->sc_tmr_seg, 1);
fail_4:
bus_dmamap_destroy(sc->sc_dmat, sc->sc_tmr_map);
fail_3:
bus_dmamap_unload(sc->sc_dmat, sc->sc_cmd_map);
fail_2:
bus_dmamem_unmap(sc->sc_dmat, sc->sc_cmd_kva, size);
fail_1:
bus_dmamem_free(sc->sc_dmat, &sc->sc_cmd_seg, 1);
fail_0:
bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmd_map);
ccp_softc = NULL;
return (0);
}
static int
ccp_wait(struct ccp_softc *sc, uint32_t *status, int poll)
{
uint32_t cmdword;
int count;
if (poll) {
count = 0;
while (count++ < 10) {
cmdword = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
PSP_REG_CMDRESP);
if (cmdword & PSP_CMDRESP_RESPONSE)
goto done;
delay(5000);
}
/* timeout */
return (1);
}
if (tsleep_nsec(sc, PWAIT, "psp", SEC_TO_NSEC(1)) == EWOULDBLOCK)
return (1);
done:
if (status) {
*status = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
PSP_REG_CMDRESP);
}
return (0);
}
static int
ccp_docmd(struct ccp_softc *sc, int cmd, uint64_t paddr)
{
uint32_t plo, phi, cmdword, status;
plo = ((paddr >> 0) & 0xffffffff);
phi = ((paddr >> 32) & 0xffffffff);
cmdword = (cmd & 0x3f) << 16;
if (!cold)
cmdword |= PSP_CMDRESP_IOC;
bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_ADDRLO, plo);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_ADDRHI, phi);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_CMDRESP, cmdword);
if (ccp_wait(sc, &status, cold))
return (1);
/* Did PSP sent a response code? */
if (status & PSP_CMDRESP_RESPONSE) {
if ((status & PSP_STATUS_MASK) != PSP_STATUS_SUCCESS) {
printf("%s: command failed: 0x%x\n", __func__,
(status & PSP_STATUS_MASK));
return (1);
}
}
return (0);
}
int
psp_init(struct psp_init *uinit)
{
struct ccp_softc *sc = ccp_softc;
struct psp_init *init;
int ret;
init = (struct psp_init *)sc->sc_cmd_kva;
bzero(init, sizeof(*init));
init->enable_es = uinit->enable_es;
init->tmr_paddr = uinit->tmr_paddr;
init->tmr_length = uinit->tmr_length;
ret = ccp_docmd(sc, PSP_CMD_INIT, sc->sc_cmd_map->dm_segs[0].ds_addr);
wbinvd_on_all_cpus();
if (ret != 0)
return (EIO);
return (0);
}
int
psp_get_pstatus(struct psp_platform_status *ustatus)
{
struct ccp_softc *sc = ccp_softc;
struct psp_platform_status *status;
int ret;
status = (struct psp_platform_status *)sc->sc_cmd_kva;
bzero(status, sizeof(*status));
ret = ccp_docmd(sc, PSP_CMD_PLATFORMSTATUS,
sc->sc_cmd_map->dm_segs[0].ds_addr);
if (ret != 0)
return (EIO);
bcopy(status, ustatus, sizeof(*ustatus));
return (0);
}
int
psp_df_flush(void)
{
struct ccp_softc *sc = ccp_softc;
int ret;
wbinvd_on_all_cpus();
ret = ccp_docmd(sc, PSP_CMD_DF_FLUSH, 0x0);
if (ret != 0)
return (EIO);
return (0);
}
int
psp_decommission(struct psp_decommission *udecom)
{
struct ccp_softc *sc = ccp_softc;
struct psp_decommission *decom;
int ret;
decom = (struct psp_decommission *)sc->sc_cmd_kva;
bzero(decom, sizeof(*decom));
decom->handle = udecom->handle;
ret = ccp_docmd(sc, PSP_CMD_DECOMMISSION,
sc->sc_cmd_map->dm_segs[0].ds_addr);
if (ret != 0)
return (EIO);
return (0);
}
int
psp_get_gstatus(struct psp_guest_status *ustatus)
{
struct ccp_softc *sc = ccp_softc;
struct psp_guest_status *status;
int ret;
status = (struct psp_guest_status *)sc->sc_cmd_kva;
bzero(status, sizeof(*status));
status->handle = ustatus->handle;
ret = ccp_docmd(sc, PSP_CMD_GUESTSTATUS,
sc->sc_cmd_map->dm_segs[0].ds_addr);
if (ret != 0)
return (EIO);
ustatus->policy = status->policy;
ustatus->asid = status->asid;
ustatus->state = status->state;
return (0);
}
int
psp_launch_start(struct psp_launch_start *ustart)
{
struct ccp_softc *sc = ccp_softc;
struct psp_launch_start *start;
int ret;
start = (struct psp_launch_start *)sc->sc_cmd_kva;
bzero(start, sizeof(*start));
start->handle = ustart->handle;
start->policy = ustart->policy;
ret = ccp_docmd(sc, PSP_CMD_LAUNCH_START,
sc->sc_cmd_map->dm_segs[0].ds_addr);
if (ret != 0)
return (EIO);
/* If requested, return new handle. */
if (ustart->handle == 0)
ustart->handle = start->handle;
return (0);
}
int
psp_launch_update_data(struct psp_launch_update_data *ulud, struct proc *p)
{
struct ccp_softc *sc = ccp_softc;
struct psp_launch_update_data *ludata;
pmap_t pmap;
vaddr_t v, next, end;
size_t size, len, off;
int ret;
/* Ensure AES_XTS_BLOCKSIZE alignment and multiplicity. */
if ((ulud->paddr & (AES_XTS_BLOCKSIZE - 1)) != 0 ||
(ulud->length % AES_XTS_BLOCKSIZE) != 0)
return (EINVAL);
ludata = (struct psp_launch_update_data *)sc->sc_cmd_kva;
bzero(ludata, sizeof(*ludata));
ludata->handle = ulud->handle;
/* Drain caches before we encrypt memory. */
wbinvd_on_all_cpus();
/*
* Launch update one physical page at a time. We could
* optimise this for contiguous pages of physical memory.
*
* vmd(8) provides the guest physical address, thus convert
* to system physical address.
*/
pmap = vm_map_pmap(&p->p_vmspace->vm_map);
size = ulud->length;
end = ulud->paddr + ulud->length;
for (v = ulud->paddr; v < end; v = next) {
off = v & PAGE_MASK;
len = MIN(PAGE_SIZE - off, size);
/* Wire mapping. */
if (uvm_map_pageable(&p->p_vmspace->vm_map, v, v+len, FALSE, 0))
return (EINVAL);
if (!pmap_extract(pmap, v, (paddr_t *)&ludata->paddr))
return (EINVAL);
ludata->length = len;
ret = ccp_docmd(sc, PSP_CMD_LAUNCH_UPDATE_DATA,
sc->sc_cmd_map->dm_segs[0].ds_addr);
if (ret != 0)
return (EIO);
size -= len;
next = v + len;
}
return (0);
}
int
psp_launch_measure(struct psp_launch_measure *ulm)
{
struct psp_launch_measure *lm;
struct ccp_softc *sc = ccp_softc;
int ret;
uint64_t paddr;
if (ulm->measure_len != sizeof(ulm->psp_measure))
return (EINVAL);
lm = (struct psp_launch_measure *)sc->sc_cmd_kva;
bzero(lm, sizeof(*lm));
lm->handle = ulm->handle;
paddr = sc->sc_cmd_map->dm_segs[0].ds_addr;
lm->measure_paddr =
paddr + offsetof(struct psp_launch_measure, psp_measure);
lm->measure_len = sizeof(lm->psp_measure);
ret = ccp_docmd(sc, PSP_CMD_LAUNCH_MEASURE, paddr);
if (ret != 0 || lm->measure_len != ulm->measure_len)
return (EIO);
bcopy(&lm->psp_measure, &ulm->psp_measure, ulm->measure_len);
return (0);
}
int
psp_launch_finish(struct psp_launch_finish *ulf)
{
struct ccp_softc *sc = ccp_softc;
struct psp_launch_finish *lf;
int ret;
lf = (struct psp_launch_finish *)sc->sc_cmd_kva;
bzero(lf, sizeof(*lf));
lf->handle = ulf->handle;
ret = ccp_docmd(sc, PSP_CMD_LAUNCH_FINISH,
sc->sc_cmd_map->dm_segs[0].ds_addr);
if (ret != 0)
return (EIO);
return (0);
}
int
psp_attestation(struct psp_attestation *uat)
{
struct ccp_softc *sc = ccp_softc;
struct psp_attestation *at;
int ret;
uint64_t paddr;
if (uat->attest_len != sizeof(uat->psp_report))
return (EINVAL);
at = (struct psp_attestation *)sc->sc_cmd_kva;
bzero(at, sizeof(*at));
at->handle = uat->handle;
paddr = sc->sc_cmd_map->dm_segs[0].ds_addr;
at->attest_paddr =
paddr + offsetof(struct psp_attestation, psp_report);
bcopy(uat->attest_nonce, at->attest_nonce, sizeof(at->attest_nonce));
at->attest_len = sizeof(at->psp_report);
ret = ccp_docmd(sc, PSP_CMD_ATTESTATION, paddr);
if (ret != 0 || at->attest_len != uat->attest_len)
return (EIO);
bcopy(&at->psp_report, &uat->psp_report, uat->attest_len);
return (0);
}
int
psp_activate(struct psp_activate *uact)
{
struct ccp_softc *sc = ccp_softc;
struct psp_activate *act;
int ret;
act = (struct psp_activate *)sc->sc_cmd_kva;
bzero(act, sizeof(*act));
act->handle = uact->handle;
act->asid = uact->asid;
ret = ccp_docmd(sc, PSP_CMD_ACTIVATE,
sc->sc_cmd_map->dm_segs[0].ds_addr);
if (ret != 0)
return (EIO);
return (0);
}
int
psp_deactivate(struct psp_deactivate *udeact)
{
struct ccp_softc *sc = ccp_softc;
struct psp_deactivate *deact;
int ret;
deact = (struct psp_deactivate *)sc->sc_cmd_kva;
bzero(deact, sizeof(*deact));
deact->handle = udeact->handle;
ret = ccp_docmd(sc, PSP_CMD_DEACTIVATE,
sc->sc_cmd_map->dm_segs[0].ds_addr);
if (ret != 0)
return (EIO);
return (0);
}
int
psp_snp_get_pstatus(struct psp_snp_platform_status *ustatus)
{
struct ccp_softc *sc = ccp_softc;
struct psp_snp_platform_status *status;
int ret;
status = (struct psp_snp_platform_status *)sc->sc_cmd_kva;
bzero(status, sizeof(*status));
ret = ccp_docmd(sc, PSP_CMD_SNP_PLATFORMSTATUS,
sc->sc_cmd_map->dm_segs[0].ds_addr);
if (ret != 0)
return (EIO);
bcopy(status, ustatus, sizeof(*ustatus));
return (0);
}
int
pspopen(dev_t dev, int flag, int mode, struct proc *p)
{
if (ccp_softc == NULL)
return (ENODEV);
return (0);
}
int
pspclose(dev_t dev, int flag, int mode, struct proc *p)
{
return (0);
}
int
pspioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
{
int ret;
rw_enter_write(&ccp_softc->sc_lock);
switch (cmd) {
case PSP_IOC_GET_PSTATUS:
ret = psp_get_pstatus((struct psp_platform_status *)data);
break;
case PSP_IOC_DF_FLUSH:
ret = psp_df_flush();
break;
case PSP_IOC_DECOMMISSION:
ret = psp_decommission((struct psp_decommission *)data);
break;
case PSP_IOC_GET_GSTATUS:
ret = psp_get_gstatus((struct psp_guest_status *)data);
break;
case PSP_IOC_LAUNCH_START:
ret = psp_launch_start((struct psp_launch_start *)data);
break;
case PSP_IOC_LAUNCH_UPDATE_DATA:
ret = psp_launch_update_data(
(struct psp_launch_update_data *)data, p);
break;
case PSP_IOC_LAUNCH_MEASURE:
ret = psp_launch_measure((struct psp_launch_measure *)data);
break;
case PSP_IOC_LAUNCH_FINISH:
ret = psp_launch_finish((struct psp_launch_finish *)data);
break;
case PSP_IOC_ATTESTATION:
ret = psp_attestation((struct psp_attestation *)data);
break;
case PSP_IOC_ACTIVATE:
ret = psp_activate((struct psp_activate *)data);
break;
case PSP_IOC_DEACTIVATE:
ret = psp_deactivate((struct psp_deactivate *)data);
break;
case PSP_IOC_SNP_GET_PSTATUS:
ret =
psp_snp_get_pstatus((struct psp_snp_platform_status *)data);
break;
default:
printf("%s: unkown ioctl code 0x%lx\n", __func__, cmd);
ret = ENOTTY;
}
rw_exit_write(&ccp_softc->sc_lock);
return (ret);
}
#endif /* __amd64__ */

View file

@ -1,7 +1,8 @@
/* $OpenBSD: ccpvar.h,v 1.1 2018/04/20 04:37:21 dlg Exp $ */
/* $OpenBSD: ccpvar.h,v 1.2 2024/06/12 12:54:54 bluhm Exp $ */
/*
* Copyright (c) 2018 David Gwynne <dlg@openbsd.org>
* Copyright (c) 2023, 2024 Hans-Joerg Hoexer <hshoexer@genua.de>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -24,6 +25,266 @@ struct ccp_softc {
bus_space_handle_t sc_ioh;
struct timeout sc_tick;
bus_size_t sc_size;
int sc_psp_attached;
#ifdef __amd64__
bus_dma_tag_t sc_dmat;
uint32_t sc_capabilities;
int (*sc_sev_intr)(struct ccp_softc *, uint32_t);
void * sc_ih;
bus_dmamap_t sc_cmd_map;
bus_dma_segment_t sc_cmd_seg;
size_t sc_cmd_size;
caddr_t sc_cmd_kva;
bus_dmamap_t sc_tmr_map;
bus_dma_segment_t sc_tmr_seg;
size_t sc_tmr_size;
caddr_t sc_tmr_kva;
struct rwlock sc_lock;
#endif
};
#ifdef __amd64__
#include <sys/ioctl.h>
#include <sys/rwlock.h>
/* AMD 17h */
#define PSP_REG_INTEN 0x10690
#define PSP_REG_INTSTS 0x10694
#define PSP_REG_CMDRESP 0x10980
#define PSP_REG_ADDRLO 0x109e0
#define PSP_REG_ADDRHI 0x109e4
#define PSP_REG_CAPABILITIES 0x109fc
#define PSP_PSTATE_UNINIT 0x0
#define PSP_PSTATE_INIT 0x1
#define PSP_PSTATE_WORKING 0x2
#define PSP_GSTATE_UNINIT 0x0
#define PSP_GSTATE_LUPDATE 0x1
#define PSP_GSTATE_LSECRET 0x2
#define PSP_GSTATE_RUNNING 0x3
#define PSP_GSTATE_SUPDATE 0x4
#define PSP_GSTATE_RUPDATE 0x5
#define PSP_GSTATE_SENT 0x6
#define PSP_CAP_SEV (1 << 0)
#define PSP_CAP_TEE (1 << 1)
#define PSP_CAP_DBC_THRU_EXT (1 << 2)
#define PSP_CAP_SECURITY_REPORTING (1 << 7)
#define PSP_CAP_SECURITY_FUSED_PART (1 << 8)
#define PSP_CAP_SECURITY_DEBUG_LOCK_ON (1 << 10)
#define PSP_CAP_SECURITY_TSME_STATUS (1 << 13)
#define PSP_CAP_SECURITY_ANTI_ROLLBACK_STATUS (1 << 15)
#define PSP_CAP_SECURITY_RPMC_PRODUCTION_ENABLED (1 << 16)
#define PSP_CAP_SECURITY_RPMC_SPIROM_AVAILABLE (1 << 17)
#define PSP_CAP_SECURITY_HSP_TPM_AVAILABLE (1 << 18)
#define PSP_CAP_SECURITY_ROM_ARMOR_ENFORCED (1 << 19)
#define PSP_CAP_BITS "\20\001SEV\002TEE\003DBC_THRU_EXT\010REPORTING\011FUSED_PART\013DEBUG_LOCK_ON\016TSME_STATUS\020ANTI_ROLLBACK_STATUS\021RPMC_PRODUCTION_ENABLED\022RPMC_SPIROM_AVAILABLE\023HSP_TPM_AVAILABLE\024ROM_ARMOR_ENFORCED"
#define PSP_CMDRESP_IOC (1 << 0)
#define PSP_CMDRESP_COMPLETE (1 << 1)
#define PSP_CMDRESP_RESPONSE (1 << 31)
#define PSP_STATUS_MASK 0xffff
#define PSP_STATUS_SUCCESS 0x0000
#define PSP_STATUS_INVALID_PLATFORM_STATE 0x0001
#define PSP_TMR_SIZE (1024*1024) /* 1 Mb */
#define PSP_SUCCESS 0x0000
#define PSP_INVALID_ADDRESS 0x0009
/* Selection of PSP commands of the SEV API Version 0.24 */
#define PSP_CMD_INIT 0x1
#define PSP_CMD_PLATFORMSTATUS 0x4
#define PSP_CMD_DF_FLUSH 0xa
#define PSP_CMD_DECOMMISSION 0x20
#define PSP_CMD_ACTIVATE 0x21
#define PSP_CMD_DEACTIVATE 0x22
#define PSP_CMD_GUESTSTATUS 0x23
#define PSP_CMD_LAUNCH_START 0x30
#define PSP_CMD_LAUNCH_UPDATE_DATA 0x31
#define PSP_CMD_LAUNCH_MEASURE 0x33
#define PSP_CMD_LAUNCH_FINISH 0x35
#define PSP_CMD_ATTESTATION 0x36
struct psp_platform_status {
/* Output parameters from PSP_CMD_PLATFORMSTATUS */
uint8_t api_major;
uint8_t api_minor;
uint8_t state;
uint8_t owner;
uint32_t cfges_build;
uint32_t guest_count;
} __packed;
struct psp_guest_status {
/* Input parameter for PSP_CMD_GUESTSTATUS */
uint32_t handle;
/* Output parameters from PSP_CMD_GUESTSTATUS */
uint32_t policy;
uint32_t asid;
uint8_t state;
} __packed;
struct psp_launch_start {
/* Input/Output parameter for PSP_CMD_LAUNCH_START */
uint32_t handle;
/* Input parameters for PSP_CMD_LAUNCH_START */
uint32_t policy;
/* The following input parameters are not used yet */
uint64_t dh_cert_paddr;
uint32_t dh_cert_len;
uint32_t reserved;
uint64_t session_paddr;
uint32_t session_len;
} __packed;
struct psp_launch_update_data {
/* Input parameters for PSP_CMD_LAUNCH_UPDATE_DATA */
uint32_t handle;
uint32_t reserved;
uint64_t paddr;
uint32_t length;
} __packed;
struct psp_measure {
/* Output buffer for PSP_CMD_LAUNCH_MEASURE */
uint8_t measure[32];
uint8_t measure_nonce[16];
} __packed;
struct psp_launch_measure {
/* Input parameters for PSP_CMD_LAUNCH_MEASURE */
uint32_t handle;
uint32_t reserved;
uint64_t measure_paddr;
/* Input/output parameter for PSP_CMD_LAUNCH_MEASURE */
uint32_t measure_len;
uint32_t padding;
/* Output buffer from PSP_CMD_LAUNCH_MEASURE */
struct psp_measure psp_measure; /* 64bit aligned */
#define measure psp_measure.measure
#define measure_nonce psp_measure.measure_nonce
} __packed;
struct psp_launch_finish {
/* Input parameter for PSP_CMD_LAUNCH_FINISH */
uint32_t handle;
} __packed;
struct psp_report {
/* Output buffer for PSP_CMD_ATTESTATION */
uint8_t report_nonce[16];
uint8_t report_launch_digest[32];
uint32_t report_policy;
uint32_t report_sig_usage;
uint32_t report_sig_algo;
uint32_t reserved2;
uint8_t report_sig1[144];
} __packed;
struct psp_attestation {
/* Input parameters for PSP_CMD_ATTESTATION */
uint32_t handle;
uint32_t reserved;
uint64_t attest_paddr;
uint8_t attest_nonce[16];
/* Input/output parameter from PSP_CMD_ATTESTATION */
uint32_t attest_len;
uint32_t padding;
/* Output parameter from PSP_CMD_ATTESTATION */
struct psp_report psp_report; /* 64bit aligned */
#define report_nonce psp_report.report_nonce
#define report_launch_digest psp_report.report_launch_digest
#define report_policy psp_report.report_policy
#define report_sig_usage psp_report.report_sig_usage;
#define report_report_sig_alg psp_report.report_sig_algo;
#define report_report_sig1 psp_report.report_sig1;
} __packed;
struct psp_activate {
/* Input parameters for PSP_CMD_ACTIVATE */
uint32_t handle;
uint32_t asid;
} __packed;
struct psp_deactivate {
/* Input parameter for PSP_CMD_DEACTIVATE */
uint32_t handle;
} __packed;
struct psp_decommission {
/* Input parameter for PSP_CMD_DECOMMISSION */
uint32_t handle;
} __packed;
struct psp_init {
/* Output parameters from PSP_CMD_INIT */
uint32_t enable_es;
uint32_t reserved;
uint64_t tmr_paddr;
uint32_t tmr_length;
} __packed;
/* Selection of PSP commands of the SEV-SNP ABI Version 1.55 */
#define PSP_CMD_SNP_PLATFORMSTATUS 0x81
struct psp_snp_platform_status {
uint8_t api_major;
uint8_t api_minor;
uint8_t state;
uint8_t is_rmp_init;
uint32_t build;
uint32_t features;
uint32_t guest_count;
uint64_t current_tcb;
uint64_t reported_tcb;
} __packed;
#define PSP_IOC_GET_PSTATUS _IOR('P', 0, struct psp_platform_status)
#define PSP_IOC_DF_FLUSH _IO('P', 1)
#define PSP_IOC_DECOMMISSION _IOW('P', 2, struct psp_decommission)
#define PSP_IOC_GET_GSTATUS _IOWR('P', 3, struct psp_guest_status)
#define PSP_IOC_LAUNCH_START _IOWR('P', 4, struct psp_launch_start)
#define PSP_IOC_LAUNCH_UPDATE_DATA \
_IOW('P', 5, struct psp_launch_update_data)
#define PSP_IOC_LAUNCH_MEASURE _IOWR('P', 6, struct psp_launch_measure)
#define PSP_IOC_LAUNCH_FINISH _IOW('P', 7, struct psp_launch_finish)
#define PSP_IOC_ATTESTATION _IOWR('P', 8, struct psp_attestation)
#define PSP_IOC_ACTIVATE _IOW('P', 9, struct psp_activate)
#define PSP_IOC_DEACTIVATE _IOW('P', 10, struct psp_deactivate)
#define PSP_IOC_SNP_GET_PSTATUS _IOR('P', 11, struct psp_snp_platform_status)
#endif /* __amd64__ */
#ifdef _KERNEL
void ccp_attach(struct ccp_softc *);
#ifdef __amd64__
int psp_attach(struct ccp_softc *);
int pspclose(dev_t, int, int, struct proc *);
int pspopen(dev_t, int, int, struct proc *);
int pspioctl(dev_t, u_long, caddr_t, int, struct proc *);
#endif
#endif /* _KERNEL */

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ccp_pci.c,v 1.9 2024/05/24 06:02:53 jsg Exp $ */
/* $OpenBSD: ccp_pci.c,v 1.10 2024/06/12 12:54:54 bluhm Exp $ */
/*
* Copyright (c) 2018 David Gwynne <dlg@openbsd.org>
@ -33,6 +33,11 @@
int ccp_pci_match(struct device *, void *, void *);
void ccp_pci_attach(struct device *, struct device *, void *);
#ifdef __amd64__
void psp_pci_attach(struct device *, struct device *, void *);
int psp_pci_intr(void *);
#endif
const struct cfattach ccp_pci_ca = {
sizeof(struct ccp_softc),
ccp_pci_match,
@ -69,10 +74,67 @@ ccp_pci_attach(struct device *parent, struct device *self, void *aux)
}
if (pci_mapreg_map(pa, CCP_PCI_BAR, memtype, 0,
&sc->sc_iot, &sc->sc_ioh, NULL, NULL, 0) != 0) {
&sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_size, 0) != 0) {
printf(": cannot map registers\n");
return;
}
#ifdef __amd64__
psp_pci_attach(parent, self, aux);
#endif
ccp_attach(sc);
}
#ifdef __amd64__
void
psp_pci_attach(struct device *parent, struct device *self, void *aux)
{
struct ccp_softc *sc = (struct ccp_softc *)self;
struct pci_attach_args *pa = aux;
pci_intr_handle_t ih;
const char *intrstr = NULL;
sc->sc_dmat = pa->pa_dmat;
sc->sc_capabilities = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
PSP_REG_CAPABILITIES);
/* clear and disable interrupts */
bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTEN, 0);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTSTS, -1);
if (pci_intr_map_msix(pa, 0, &ih) != 0 &&
pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) {
printf(": couldn't map interrupt\n");
bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
return;
}
intrstr = pci_intr_string(pa->pa_pc, ih);
sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, psp_pci_intr,
sc, sc->sc_dev.dv_xname);
if (sc->sc_ih != NULL)
printf(": %s", intrstr);
if (psp_attach(sc)) {
/* enable interrupts */
bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTEN, -1);
}
}
int
psp_pci_intr(void *arg)
{
struct ccp_softc *sc = arg;
uint32_t status;
status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTSTS);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, PSP_REG_INTSTS, status);
if (sc->sc_sev_intr)
return (sc->sc_sev_intr(sc, status));
return (1);
}
#endif /* __amd64__ */