sync with OpenBSD -current
This commit is contained in:
parent
d22f2a15f3
commit
f4a22ff4b2
17 changed files with 1316 additions and 178 deletions
|
@ -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
|
||||
|
|
603
sys/dev/ic/ccp.c
603
sys/dev/ic/ccp.c
|
@ -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__ */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue