|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 4/4] libxl: Add emulated TPM support on ARM
From: Stefano Stabellini <stefano.stabellini@xxxxxxx>
QEMU's ARM "xenpvh" machine runs as an IOREQ server and, when given a
"tpm-base-addr" machine property, instantiates a TPM TIS sysbus device
at that address connected to the "tpm0" TPM backend. Hook the existing
tpm_* configuration up to it so ARM guests can use an swtpm-backed TPM.
Reserve GUEST_TPM_BASE/GUEST_TPM_SIZE in the ARM guest memory map and
add a "tcg,tpm-tis-mmio" node to the guest device tree when a TPM
version is configured. The xenpvh machine has no CRB device, so TIS is
the default and only interface allowed for both TPM 1.2 and 2.0.
Add libxl__arch_pv_pvh_machinearg() returning the QEMU -machine argument
for a PV/PVH guest. x86 returns plain "xenpv", while ARM uses "xenpvh"
and appends tpm-base-addr when a TPM is configured. uint64_t tpm_base
in ARM's libxl__arch_pvh_machinearg() is to allow PRIx64 to print the
value. Otherwise the ull argument mismatches PRIx64's %lx format.
libxl__arch_pv_pvh_machinearg() also handles PV guests. This keeps the
extra_pv handling identical between PV and PVH guests.
Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxx>
[ Merge ARM parts with new libxl_dm implementation. ]
Signed-off-by: Jason Andryuk <jason.andryuk@xxxxxxx>
---
docs/man/xl.cfg.5.pod.in | 14 ++++++++---
tools/include/libxl.h | 5 ++--
tools/libs/light/libxl_arch.h | 6 +++++
tools/libs/light/libxl_arm.c | 47 +++++++++++++++++++++++++++++++++++
tools/libs/light/libxl_dm.c | 14 ++++++++++-
tools/libs/light/libxl_x86.c | 6 +++++
xen/include/public/arch-arm.h | 4 +++
7 files changed, 89 insertions(+), 7 deletions(-)
diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
index c12d2dc4db..e5952d7e27 100644
--- a/docs/man/xl.cfg.5.pod.in
+++ b/docs/man/xl.cfg.5.pod.in
@@ -823,11 +823,16 @@ value is optional if this is a guest domain.
=item B<tpm_version=NUMBER>
-Provides an emulated TPM to a QEMU-based HVM guest, backed by B<swtpm(8)>.
-The TPM version to emulate is either B<1> for TPM 1.2 or B<2> for TPM 2.0.
+Provides an emulated TPM to a QEMU-based HVM guest, or to an Arm guest,
+backed by B<swtpm(8)>. The TPM version to emulate is either B<1> for
+TPM 1.2 or B<2> for TPM 2.0.
When this option is not specified, no TPM is provided and the other
B<tpm_*> options are ignored.
+On Arm, QEMU's B<xenpvh> machine is started as an IOREQ server to emulate
+a TPM TIS interface, and the guest device tree gains a
+C<tcg,tpm-tis-mmio> node describing it.
+
One of B<tpm_statefile> or B<tpm_statedir> is required, but not both.
=item B<tpm_statefile="PATH">
@@ -844,8 +849,9 @@ Path to a directory in which B<swtpm> stores the persistent
TPM state.
The TPM interface presented to the guest. B<tis> is the TPM Interface
Specification (FIFO) interface and B<crb> is the Command Response Buffer
-interface. B<tpm_version=1> only supports B<tis>, while B<tpm_version=2>
-supports either and defaults to B<crb>.
+interface. On x86, B<tpm_version=1> only supports B<tis>, while
+B<tpm_version=2> supports either and defaults to B<crb>. On Arm, only
+B<tis> is supported, for both TPM versions.
=item B<tpm_swtpm_override="PATH">
diff --git a/tools/include/libxl.h b/tools/include/libxl.h
index 8b431b708d..8d19cf41bc 100644
--- a/tools/include/libxl.h
+++ b/tools/include/libxl.h
@@ -1568,8 +1568,9 @@ void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, const
libxl_mac *src);
*
* If this is defined the tpm member of struct domain_build_info is
* available. When its version is non-zero, libxl starts swtpm to
- * provide an emulated TPM to a QEMU-based HVM guest. Its interface
- * member selects the TPM interface (TIS or CRB) presented to the guest.
+ * provide an emulated TPM to a QEMU-based HVM guest, or to an Arm guest
+ * via QEMU's xenpvh machine. Its interface member selects the TPM
+ * interface (TIS or CRB) presented to the guest.
*/
#define LIBXL_HAVE_TPM
diff --git a/tools/libs/light/libxl_arch.h b/tools/libs/light/libxl_arch.h
index c8ef52ddbe..b3355d1e82 100644
--- a/tools/libs/light/libxl_arch.h
+++ b/tools/libs/light/libxl_arch.h
@@ -97,6 +97,12 @@ _hidden
int libxl__arch_hvm_unmap_gsi(libxl__gc *gc, uint32_t sbdf, uint32_t domid);
_hidden
bool libxl__arch_local_domain_has_pirq_notion(libxl__gc *gc);
+
+/* QEMU -machine argument for a PVH guest. */
+_hidden
+char *libxl__arch_pv_pvh_machinearg(libxl__gc *gc,
+ const libxl_domain_build_info *b_info);
+
#if defined(__i386__) || defined(__x86_64__)
#define LAPIC_BASE_ADDRESS 0xfee00000
diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c
index 47b662ea5c..6325b19766 100644
--- a/tools/libs/light/libxl_arm.c
+++ b/tools/libs/light/libxl_arm.c
@@ -978,6 +978,29 @@ static int make_xen_iommu_node(libxl__gc *gc, void *fdt)
return 0;
}
+static int make_tpm_node(libxl__gc *gc, void *fdt)
+{
+ int res;
+ const uint64_t base = GUEST_TPM_BASE;
+ const char *name = GCSPRINTF("tpm@%"PRIx64, base);
+
+ res = fdt_begin_node(fdt, name);
+ if (res) return res;
+
+ res = fdt_property_compat(gc, fdt, 1, "tcg,tpm-tis-mmio");
+ if (res) return res;
+
+ res = fdt_property_regs(gc, fdt, GUEST_ROOT_ADDRESS_CELLS,
+ GUEST_ROOT_SIZE_CELLS, 1,
+ base, GUEST_TPM_SIZE);
+ if (res) return res;
+
+ res = fdt_end_node(fdt);
+ if (res) return res;
+
+ return 0;
+}
+
/* The caller is responsible to complete / close the fdt node */
static int make_virtio_mmio_node_common(libxl__gc *gc, void *fdt, uint64_t
base,
uint32_t irq, uint32_t backend_domid,
@@ -1450,6 +1473,9 @@ next_resize:
if (iommu_needed)
FDT( make_xen_iommu_node(gc, fdt) );
+ if (info->tpm.version)
+ FDT( make_tpm_node(gc, fdt) );
+
if (pfdt)
FDT( copy_partial_fdt(gc, fdt, pfdt) );
@@ -1860,6 +1886,16 @@ int libxl__arch_domain_build_info_setdefault(libxl__gc
*gc,
return ERROR_FAIL;
}
+ /* The xenpvh machine only provides a TIS TPM interface. */
+ if (b_info->tpm.version) {
+ if (b_info->tpm.interface == LIBXL_TPM_INTERFACE_DEFAULT)
+ b_info->tpm.interface = LIBXL_TPM_INTERFACE_TIS;
+ if (b_info->tpm.interface != LIBXL_TPM_INTERFACE_TIS) {
+ LOG(ERROR, "Only the tis TPM interface is supported on Arm.");
+ return ERROR_INVAL;
+ }
+ }
+
/* Sanitise SVE parameter */
if (b_info->arch_arm.sve_vl) {
unsigned int max_sve_vl =
@@ -1949,6 +1985,17 @@ bool libxl__arch_local_domain_has_pirq_notion(libxl__gc
*gc)
return true;
}
+char *libxl__arch_pv_pvh_machinearg(libxl__gc *gc,
+ const libxl_domain_build_info *b_info)
+{
+ uint64_t tpm_base = GUEST_TPM_BASE;
+
+ if (b_info->tpm.version)
+ return GCSPRINTF("xenpvh,tpm-base-addr=0x%"PRIx64, tpm_base);
+
+ return libxl__strdup(gc, "xenpvh");
+}
+
/*
* Local variables:
* mode: C
diff --git a/tools/libs/light/libxl_dm.c b/tools/libs/light/libxl_dm.c
index 843b8e29eb..ebdd05586e 100644
--- a/tools/libs/light/libxl_dm.c
+++ b/tools/libs/light/libxl_dm.c
@@ -18,6 +18,7 @@
#include "libxl_osdeps.h" /* must come before any other headers */
#include "libxl_internal.h"
+#include "libxl_arch.h"
#include <xen/hvm/e820.h>
#include <sys/types.h>
@@ -1573,7 +1574,12 @@ static int libxl__build_device_model_args_new(libxl__gc
*gc,
switch (b_info->type) {
case LIBXL_DOMAIN_TYPE_PVH:
case LIBXL_DOMAIN_TYPE_PV:
- flexarray_append(dm_args, "xenpv");
+ machinearg = libxl__arch_pv_pvh_machinearg(gc, b_info);
+ flexarray_append(dm_args, machinearg);
+
+ if (b_info->tpm.version)
+ libxl__dm_add_tpm_args(gc, dm_args, guest_domid);
+
for (i = 0; b_info->extra_pv && b_info->extra_pv[i] != NULL; i++)
flexarray_append(dm_args, b_info->extra_pv[i]);
break;
@@ -3892,6 +3898,12 @@ int libxl__need_xenpv_qemu(libxl__gc *gc,
libxl_domain_config *d_config)
goto out;
}
+ /* QEMU provides the emulated TPM, e.g. via the ARM xenpvh machine. */
+ if (d_config->b_info.tpm.version) {
+ ret = 1;
+ goto out;
+ }
+
for (idx = 0;; idx++) {
dt = device_type_tbl[idx];
if (!dt)
diff --git a/tools/libs/light/libxl_x86.c b/tools/libs/light/libxl_x86.c
index 3182cfc9df..a6e9ad777e 100644
--- a/tools/libs/light/libxl_x86.c
+++ b/tools/libs/light/libxl_x86.c
@@ -937,6 +937,12 @@ bool libxl__arch_local_domain_has_pirq_notion(libxl__gc
*gc)
return false;
}
+char *libxl__arch_pv_pvh_machinearg(libxl__gc *gc,
+ const libxl_domain_build_info *b_info)
+{
+ return libxl__strdup(gc, "xenpv");
+}
+
int libxl__arch_hvm_map_gsi(libxl__gc *gc, uint32_t sbdf, uint32_t domid)
{
int pirq = -1, gsi, r;
diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
index 5d15f572c7..efb45eb33c 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -452,6 +452,10 @@ typedef uint64_t xen_callback_t;
#define GUEST_VPCI_ECAM_BASE xen_mk_ullong(0x10000000)
#define GUEST_VPCI_ECAM_SIZE xen_mk_ullong(0x10000000)
+/* Emulated TPM (TIS over MMIO) */
+#define GUEST_TPM_BASE xen_mk_ullong(0x0c000000)
+#define GUEST_TPM_SIZE xen_mk_ullong(0x00005000)
+
/* ACPI tables physical address */
#define GUEST_ACPI_BASE xen_mk_ullong(0x20000000)
#define GUEST_ACPI_SIZE xen_mk_ullong(0x02000000)
--
2.34.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |