bhyve: add cmdline option for TPM emulation

At the moment, only a TPM passthru is supported. The cmdline looks like:

-l tpm,passthru,/dev/tpm0

Reviewed by:		markj
MFC after:		1 week
Sponsored by:		Beckhoff Automation GmbH & Co. KG
Differential Revision:	https://reviews.freebsd.org/D32961
This commit is contained in:
Corvin Köhne 2021-10-07 16:20:37 +02:00
parent d1d7a27370
commit 67c26eb2a5
No known key found for this signature in database
GPG key ID: D854DA56315E026A
6 changed files with 101 additions and 1 deletions

View file

@ -215,6 +215,8 @@ The only supported devices are the TTY-class devices
.Cm com1 , com2 , com3 ,
and
.Cm com4 ,
the TPM module
.Cm tpm ,
the boot ROM device
.Cm bootrom ,
the
@ -538,6 +540,23 @@ process.
Use the host TTY device for serial port I/O.
.El
.Pp
TPM device backends:
.Bl -tag -width 10n
.It Ar type Ns \&, Ns Ar path Ns Op Cm \&, Ns Ar tpm-device-options
Emulate a TPM device.
.El
.Pp
The
.Ar tpm-device-options
are:
.Bl -tag -width 10n
.It Cm version= Ns Ar version
Version of the TPM device according to the TCG specification.
Defaults to
.Cm 2.0
.El
.El
.Pp
Boot ROM device backends:
.Bl -tag -width 10n
.It Ar romfile Ns Op Cm \&, Ns Ar varfile
@ -623,6 +642,26 @@ The host device must have been reserved at boot-time using the
loader variable as described in
.Xr vmm 4 .
.Pp
TPM devices:
.Bl -tag -width 10n
.It Ns Ar type
Specifies the type of the TPM device.
.Pp
Supported types:
.Bl -tag -width 10n
.It Cm passthru
.El
.It Cm version= Ns Ar version
The
.Ar version
of the emulated TPM device according to the TCG specification.
.Pp
Supported versions:
.Bl -tag -width 10n
.It Cm 2.0
.El
.El
.Pp
Virtio console device backends:
.Bl -bullet
.Sm off

View file

@ -139,6 +139,15 @@ Specify the keyboard layout name with the file name in
This value only works when loaded with UEFI mode for VNC, and
used a VNC client that don't support QEMU Extended Key Event
Message (e.g. TightVNC).
.It Va tpm.path Ta string Ta Ta
Path to the host TPM device.
This is typically /dev/tpm0.
.It Va tpm.type Ta string Ta Ta
Type of the TPM device passed to the guest.
Currently, only "passthru" is supported.
.It Va tpm.version Ta string Ta 2.0 Ta
Version of the TPM device according to the TCG specification.
Currently, only version 2.0 is supported.
.It Va rtc.use_localtime Ta bool Ta true Ta
The real time clock uses the local time of the host.
If this is set to false, the real time clock uses UTC.

View file

@ -103,6 +103,7 @@
#ifdef BHYVE_SNAPSHOT
#include "snapshot.h"
#endif
#include "tpm_device.h"
#include "xmsr.h"
#include "spinup_ap.h"
#include "rtc.h"
@ -1474,6 +1475,10 @@ main(int argc, char *argv[])
perror("device emulation initialization error");
exit(4);
}
if (init_tpm(ctx) != 0) {
fprintf(stderr, "Failed to init TPM device");
exit(4);
}
/*
* Initialize after PCI, to allow a bootrom file to reserve the high

View file

@ -49,6 +49,7 @@
#include "pci_lpc.h"
#include "pci_passthru.h"
#include "pctestdev.h"
#include "tpm_device.h"
#include "uart_emul.h"
#define IO_ICU1 0x20
@ -93,7 +94,7 @@ lpc_device_parse(const char *opts)
{
int unit, error;
char *str, *cpy, *lpcdev, *node_name;
const char *romfile, *varfile;
const char *romfile, *varfile, *tpm_type, *tpm_path;
error = -1;
str = cpy = strdup(opts);
@ -124,6 +125,27 @@ lpc_device_parse(const char *opts)
error = 0;
goto done;
}
if (strcasecmp(lpcdev, "tpm") == 0) {
nvlist_t *nvl = create_config_node("tpm");
tpm_type = strsep(&str, ",");
if (tpm_type == NULL) {
errx(4, "invalid tpm type \"%s\"", opts);
}
set_config_value_node(nvl, "type", tpm_type);
tpm_path = strsep(&str, ",");
if (tpm_path == NULL) {
errx(4, "invalid tpm path \"%s\"", opts);
}
set_config_value_node(nvl, "path", tpm_path);
pci_parse_legacy_config(find_config_node("tpm"), str);
set_config_value_node_if_unset(nvl, "version", "2.0");
error = 0;
goto done;
}
for (unit = 0; unit < LPC_UART_NUM; unit++) {
if (strcasecmp(lpcdev, lpc_uart_names[unit]) == 0) {
asprintf(&node_name, "lpc.%s.path",
@ -157,6 +179,7 @@ lpc_print_supported_devices(void)
printf("bootrom\n");
for (i = 0; i < LPC_UART_NUM; i++)
printf("%s\n", lpc_uart_names[i]);
printf("tpm\n");
printf("%s\n", pctestdev_getname());
}

View file

@ -232,3 +232,25 @@ tpm_device_create(struct tpm_device **const new_dev, struct vmctx *const vm_ctx,
return (error);
}
static struct tpm_device *lpc_tpm;
int
init_tpm(struct vmctx *ctx)
{
nvlist_t *nvl;
int error;
nvl = find_config_node("tpm");
if (nvl == NULL)
return (0);
error = tpm_device_create(&lpc_tpm, ctx, nvl);
if (error) {
warnx("%s: unable to create a TPM device (%d)",
__func__, error);
return (error);
}
return (0);
}

View file

@ -16,3 +16,5 @@ struct tpm_device;
int tpm_device_create(struct tpm_device **new_dev, struct vmctx *vm_ctx,
nvlist_t *nvl);
void tpm_device_destroy(struct tpm_device *dev);
int init_tpm(struct vmctx *ctx);