diff --git a/devicemodel/Makefile b/devicemodel/Makefile index 3cfae455d..18dfab3d2 100644 --- a/devicemodel/Makefile +++ b/devicemodel/Makefile @@ -132,6 +132,7 @@ SRCS += hw/pci/uart.c SRCS += hw/pci/gvt.c SRCS += hw/pci/npk.c SRCS += hw/pci/ivshmem.c +SRCS += hw/mmio/core.c # core #SRCS += core/bootrom.c diff --git a/devicemodel/core/main.c b/devicemodel/core/main.c index 5b3972c4c..d13f45991 100644 --- a/devicemodel/core/main.c +++ b/devicemodel/core/main.c @@ -62,6 +62,7 @@ #include "pm.h" #include "atomic.h" #include "tpm.h" +#include "mmio_dev.h" #include "virtio.h" #include "pm_vuart.h" #include "log.h" @@ -87,6 +88,7 @@ char *mac_seed; bool stdio_in_use; bool lapic_pt; bool is_rtvm; +bool pt_tpm2; bool is_winvm; bool skip_pci_mem64bar_workaround = false; @@ -138,6 +140,7 @@ usage(int code) " %*s [-l lpc] [-m mem] [-r ramdisk_image_path]\n" " %*s [-s pci] [-U uuid] [--vsbl vsbl_file_name] [--ovmf ovmf_file_path]\n" " %*s [--part_info part_info_name] [--enable_trusty] [--intr_monitor param_setting]\n" + " %*s [--acpidev_pt HID] [--mmiodev_pt MMIO_Regions]\n" " %*s [--vtpm2 sock_path] [--virtio_poll interval] [--mac_seed seed_string]\n" " %*s [--vmcfg sub_options] [--dump vm_idx] [--debugexit] \n" " %*s [--logger-setting param_setting] [--pm_notify_channel]\n" @@ -171,6 +174,8 @@ usage(int code) " --intr_monitor: enable interrupt storm monitor\n" " its params: threshold/s,probe-period(s),delay_time(ms),delay_duration(ms)\n" " --virtio_poll: enable virtio poll mode with poll interval with ns\n" + " --acpidev_pt: acpi device ID args: HID in ACPI Table\n" + " --mmiodev_pt: MMIO resources args: physical MMIO regions\n" " --vtpm2: Virtual TPM2 args: sock_path=$PATH_OF_SWTPM_SOCKET\n" " --lapic_pt: enable local apic passthrough\n" " --rtvm: indicate that the guest is rtvm\n" @@ -179,7 +184,8 @@ usage(int code) " --pm_by_vuart:pty,/run/acrn/vuart_vmname or tty,/dev/ttySn\n" " --windows: support Oracle virtio-blk, virtio-net and virtio-input devices\n" " for windows guest with secure boot\n", - progname, (int)strnlen(progname, PATH_MAX), "", (int)strnlen(progname, PATH_MAX), "", + progname, (int)strnlen(progname, PATH_MAX), "", + (int)strnlen(progname, PATH_MAX), "", (int)strnlen(progname, PATH_MAX), "", (int)strnlen(progname, PATH_MAX), "", (int)strnlen(progname, PATH_MAX), "", (int)strnlen(progname, PATH_MAX), "", (int)strnlen(progname, PATH_MAX), "", (int)strnlen(progname, PATH_MAX), "", (int)strnlen(progname, PATH_MAX), ""); @@ -478,15 +484,22 @@ vm_init_vdevs(struct vmctx *ctx) if (ret < 0) goto monitor_fail; + ret = init_mmio_devs(ctx); + if (ret < 0) + goto mmio_dev_fail; + ret = init_pci(ctx); if (ret < 0) goto pci_fail; + /* FIXME: if we plan to support pass through a TPM device and emulate another b TPM device */ init_vtpm2(ctx); return 0; pci_fail: + deinit_mmio_devs(ctx); +mmio_dev_fail: monitor_close(); monitor_fail: if (debugexit_enabled) @@ -515,6 +528,7 @@ vm_deinit_vdevs(struct vmctx *ctx) acrn_writeback_ovmf_nvstorage(ctx); deinit_pci(ctx); + deinit_mmio_devs(ctx); monitor_close(); if (debugexit_enabled) @@ -730,6 +744,8 @@ enum { CMD_OPT_VMCFG, CMD_OPT_DUMP, CMD_OPT_INTR_MONITOR, + CMD_OPT_ACPIDEV_PT, + CMD_OPT_MMIODEV_PT, CMD_OPT_VTPM2, CMD_OPT_LAPIC_PT, CMD_OPT_RTVM, @@ -769,6 +785,8 @@ static struct option long_options[] = { {"mac_seed", required_argument, 0, CMD_OPT_MAC_SEED}, {"debugexit", no_argument, 0, CMD_OPT_DEBUGEXIT}, {"intr_monitor", required_argument, 0, CMD_OPT_INTR_MONITOR}, + {"apcidev_pt", required_argument, 0, CMD_OPT_ACPIDEV_PT}, + {"mmiodev_pt", required_argument, 0, CMD_OPT_MMIODEV_PT}, {"vtpm2", required_argument, 0, CMD_OPT_VTPM2}, {"lapic_pt", no_argument, 0, CMD_OPT_LAPIC_PT}, {"rtvm", no_argument, 0, CMD_OPT_RTVM}, @@ -915,8 +933,16 @@ main(int argc, char *argv[]) case CMD_OPT_RTVM: is_rtvm = true; break; + case CMD_OPT_ACPIDEV_PT: + if (parse_pt_acpidev(optarg) != 0) + errx(EX_USAGE, "invalid pt acpi dev param %s", optarg); + break; + case CMD_OPT_MMIODEV_PT: + if (parse_pt_mmiodev(optarg) != 0) + errx(EX_USAGE, "invalid pt mmio dev param %s", optarg); + break; case CMD_OPT_VTPM2: - if (acrn_parse_vtpm2(optarg) != 0) + if (pt_tpm2 || acrn_parse_vtpm2(optarg) != 0) errx(EX_USAGE, "invalid vtpm2 param %s", optarg); break; case CMD_OPT_INTR_MONITOR: diff --git a/devicemodel/hw/mmio/core.c b/devicemodel/hw/mmio/core.c new file mode 100644 index 000000000..dd5b49146 --- /dev/null +++ b/devicemodel/hw/mmio/core.c @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2020 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dm.h" +#include "vmmapi.h" +#include "acpi.h" +#include "inout.h" +#include "mem.h" +#include "log.h" + + +struct mmio_dev { + char name[16]; +}; + +#define MAX_MMIO_DEV_NUM 2 + +static struct mmio_dev mmio_devs[MAX_MMIO_DEV_NUM]; + +struct mmio_dev_ops { + char *name; + uint64_t base_gpa; + uint64_t base_hpa; + uint64_t size; + int (*init)(struct vmctx *, struct acrn_mmiodev *); + void (*deinit)(struct vmctx *, struct acrn_mmiodev *); +}; + + +SET_DECLARE(mmio_dev_ops_set, struct mmio_dev_ops); +#define DEFINE_MMIO_DEV(x) DATA_SET(mmio_dev_ops_set, x) + +struct mmio_dev_ops pt_mmiodev; + +int parse_pt_acpidev(char *opt) +{ + int err = -EINVAL; + if (strncmp(opt, "MSFT0101", 8) == 0) { + strncpy(mmio_devs[0].name, "MSFT0101", 8); + pt_tpm2 = true; + err = 0; + } + + return err; +} + +int parse_pt_mmiodev(char *opt) +{ + + int err = -EINVAL; + uint64_t base_hpa, size; + char *cp; + + if((!dm_strtoul(opt, &cp, 16, &base_hpa) && *cp == ',') && + (!dm_strtoul(cp + 1, &cp, 16, &size))) { + printf("%s pt mmiodev base: 0x%lx, size: 0x%lx\n", __func__, base_hpa, size); + strncpy(mmio_devs[1].name, pt_mmiodev.name, 8); + pt_mmiodev.base_hpa = base_hpa; + pt_mmiodev.size = size; + } else { + printf("%s, %s invalid, please check!\n", __func__, opt); + } + + return err; +} + +static struct mmio_dev_ops *mmio_dev_finddev(char *name) +{ + struct mmio_dev_ops **mdpp, *mdp; + + SET_FOREACH(mdpp, mmio_dev_ops_set) { + mdp = *mdpp; + if (!strcmp(mdp->name, name)) + return mdp; + } + + return NULL; +} + +int init_mmio_dev(struct vmctx *ctx, struct mmio_dev_ops *ops) +{ + struct acrn_mmiodev mmiodev = { + .base_gpa = ops->base_gpa, + .base_hpa = ops->base_hpa, + .size = ops->size, + }; + + return ops->init(ctx, &mmiodev); +} + +void deinit_mmio_dev(struct vmctx *ctx, struct mmio_dev_ops *ops) +{ + struct acrn_mmiodev mmiodev = { + .base_gpa = ops->base_gpa, + .base_hpa = ops->base_hpa, + .size = ops->size, + }; + + ops->deinit(ctx, &mmiodev); +} + +int init_mmio_devs(struct vmctx *ctx) +{ + int i, err = 0; + struct mmio_dev_ops *ops; + + for (i = 0; i < MAX_MMIO_DEV_NUM; i++) { + ops = mmio_dev_finddev(mmio_devs[i].name); + if (ops != NULL) + err = init_mmio_dev(ctx, ops); + + if (err != 0) + goto init_mmio_devs_fail; + } + + return 0; + +init_mmio_devs_fail: + for (; i>=0; i--) { + ops = mmio_dev_finddev(mmio_devs[i].name); + if (ops != NULL) + deinit_mmio_dev(ctx, ops); + } + + return err; +} + +void deinit_mmio_devs(struct vmctx *ctx) +{ + int i; + struct mmio_dev_ops *ops; + + for (i = 0; i < MAX_MMIO_DEV_NUM; i++) { + ops = mmio_dev_finddev(mmio_devs[i].name); + if (ops != NULL) + deinit_mmio_dev(ctx, ops); + + } +} + +static int init_pt_mmiodev(struct vmctx *ctx, struct acrn_mmiodev *dev) +{ + return vm_assign_mmiodev(ctx, dev); +} + +static void deinit_pt_mmiodev(struct vmctx *ctx, struct acrn_mmiodev *dev) +{ + vm_deassign_mmiodev(ctx, dev); +} + +struct mmio_dev_ops tpm2 = { + .name = "MSFT0101", + /* ToDo: we may allocate the gpa MMIO resource in a reserved MMIO region + * rether than hard-coded here. + */ + .base_gpa = 0xFED40000UL, + .base_hpa = 0xFED40000UL, + .size = 0x00005000UL, + .init = init_pt_mmiodev, + .deinit = deinit_pt_mmiodev, +}; +DEFINE_MMIO_DEV(tpm2); + +struct mmio_dev_ops pt_mmiodev = { + .name = "MMIODEV", + /* ToDo: we may allocate the gpa MMIO resource in a reserved MMIO region + * rether than hard-coded here. + */ + .base_gpa = 0xF0000000UL, + .init = init_pt_mmiodev, + .deinit = deinit_pt_mmiodev, +}; +DEFINE_MMIO_DEV(pt_mmiodev); diff --git a/devicemodel/hw/platform/acpi/acpi.c b/devicemodel/hw/platform/acpi/acpi.c index 891f16321..0c25ff555 100644 --- a/devicemodel/hw/platform/acpi/acpi.c +++ b/devicemodel/hw/platform/acpi/acpi.c @@ -182,7 +182,7 @@ basl_fwrite_rsdt(FILE *fp, struct vmctx *ctx) EFPRINTF(fp, "[0004]\t\tACPI Table Address %u : %08X\n", num++, basl_acpi_base + NHLT_OFFSET); - if (ctx->tpm_dev) + if (ctx->tpm_dev || pt_tpm2) EFPRINTF(fp, "[0004]\t\tACPI Table Address %u : %08X\n", num++, basl_acpi_base + TPM2_OFFSET); @@ -224,7 +224,7 @@ basl_fwrite_xsdt(FILE *fp, struct vmctx *ctx) EFPRINTF(fp, "[0004]\t\tACPI Table Address %u : 00000000%08X\n", num++, basl_acpi_base + NHLT_OFFSET); - if (ctx->tpm_dev) + if (ctx->tpm_dev || pt_tpm2) EFPRINTF(fp, "[0004]\t\tACPI Table Address %u : 00000000%08X\n", num++, basl_acpi_base + TPM2_OFFSET); @@ -859,7 +859,7 @@ basl_fwrite_dsdt(FILE *fp, struct vmctx *ctx) pm_write_dsdt(ctx, basl_ncpu); - if (ctx->tpm_dev) + if (ctx->tpm_dev || pt_tpm2) tpm2_crb_fwrite_dsdt(); dsdt_line("}"); @@ -1124,7 +1124,7 @@ acpi_build(struct vmctx *ctx, int ncpu) */ while (!err && (i < ARRAY_SIZE(basl_ftables))) { if ((basl_ftables[i].offset == TPM2_OFFSET) && - (ctx->tpm_dev != NULL)) { + (ctx->tpm_dev != NULL || pt_tpm2)) { basl_ftables[i].valid = true; } diff --git a/devicemodel/include/dm.h b/devicemodel/include/dm.h index 575172f02..063bd79ba 100644 --- a/devicemodel/include/dm.h +++ b/devicemodel/include/dm.h @@ -48,6 +48,7 @@ extern bool stdio_in_use; extern char *mac_seed; extern bool lapic_pt; extern bool is_rtvm; +extern bool pt_tpm2; extern bool is_winvm; int vmexit_task_switch(struct vmctx *ctx, struct vhm_request *vhm_req, diff --git a/devicemodel/include/mmio_dev.h b/devicemodel/include/mmio_dev.h new file mode 100644 index 000000000..a3be281aa --- /dev/null +++ b/devicemodel/include/mmio_dev.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2020 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#ifndef _MMIO_DEV_H_ +#define _MMIO_DEV_H_ + +int parse_pt_acpidev(char *arg); +int parse_pt_mmiodev(char *arg); + +int init_mmio_devs(struct vmctx *ctx); +int deinit_mmio_devs(struct vmctx *ctx); + +#endif /* _MMIO_DEV_H_ */ diff --git a/devicemodel/include/tpm.h b/devicemodel/include/tpm.h index 2ae8af7b8..3770306a1 100644 --- a/devicemodel/include/tpm.h +++ b/devicemodel/include/tpm.h @@ -9,7 +9,7 @@ #define _TPM_H_ #define TPM_CRB_MMIO_ADDR 0xFED40000UL -#define TPM_CRB_MMIO_SIZE 0x1000U +#define TPM_CRB_MMIO_SIZE 0x5000U /* TPM CRB registers */ enum {