From dfd0e4f7f20b1ae8f4bb7478cd5bdad188fe4f76 Mon Sep 17 00:00:00 2001 From: Li Zhang Date: Thu, 25 Apr 2013 16:46:04 +0800 Subject: [PATCH] qemu: Add command line builder and parser for NVRAM. This patch is to add command line builder and parser for NVRAM device, and add test cases. Signed-off-by: Li Zhang --- src/qemu/qemu_capabilities.c | 3 + src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_command.c | 86 ++++++++++++++++++- tests/qemuargv2xmltest.c | 2 + .../qemuxml2argv-pseries-nvram.args | 5 ++ .../qemuxml2argv-pseries-nvram.xml | 23 +++++ tests/qemuxml2argvtest.c | 1 + tests/qemuxml2xmltest.c | 2 + 8 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-nvram.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pseries-nvram.xml diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index ef291c0c3d..1d544776f7 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -220,6 +220,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "machine-usb-opt", "tpm-passthrough", "tpm-tis", + + "nvram", /* 140 */ ); struct _virQEMUCaps { @@ -1347,6 +1349,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "virtio-rng-ccw", QEMU_CAPS_DEVICE_VIRTIO_RNG }, { "rng-random", QEMU_CAPS_OBJECT_RNG_RANDOM }, { "rng-egd", QEMU_CAPS_OBJECT_RNG_EGD }, + { "spapr-nvram", QEMU_CAPS_DEVICE_NVRAM }, }; static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBlk[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 4e76799343..9c2bf57cfa 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -179,6 +179,8 @@ enum virQEMUCapsFlags { QEMU_CAPS_DEVICE_TPM_PASSTHROUGH = 138, /* -tpmdev passthrough */ QEMU_CAPS_DEVICE_TPM_TIS = 139, /* -device tpm_tis */ + QEMU_CAPS_DEVICE_NVRAM = 140, /* -global spapr-nvram.reg=xxxx */ + QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 235468e8fc..37889cdf5f 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -53,6 +53,10 @@ #define VIR_FROM_THIS VIR_FROM_QEMU +#define VIO_ADDR_NET 0x1000ul +#define VIO_ADDR_SCSI 0x2000ul +#define VIO_ADDR_SERIAL 0x30000000ul +#define VIO_ADDR_NVRAM 0x3000ul VIR_ENUM_DECL(virDomainDiskQEMUBus) VIR_ENUM_IMPL(virDomainDiskQEMUBus, VIR_DOMAIN_DISK_BUS_LAST, @@ -1148,7 +1152,7 @@ int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def, STREQ(def->nets[i]->model, "spapr-vlan")) def->nets[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO; if (qemuAssignSpaprVIOAddress(def, &def->nets[i]->info, - 0x1000ul) < 0) + VIO_ADDR_NET) < 0) goto cleanup; } @@ -1163,7 +1167,7 @@ int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def, def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO; if (qemuAssignSpaprVIOAddress(def, &def->controllers[i]->info, - 0x2000ul) < 0) + VIO_ADDR_SCSI) < 0) goto cleanup; } @@ -1173,7 +1177,16 @@ int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def, STREQ(def->os.machine, "pseries")) def->serials[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO; if (qemuAssignSpaprVIOAddress(def, &def->serials[i]->info, - 0x30000000ul) < 0) + VIO_ADDR_SERIAL) < 0) + goto cleanup; + } + + if (def->nvram) { + if (def->os.arch == VIR_ARCH_PPC64 && + STREQ(def->os.machine, "pseries")) + def->nvram->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO; + if (qemuAssignSpaprVIOAddress(def, &def->nvram->info, + VIO_ADDR_NVRAM) < 0) goto cleanup; } @@ -3923,6 +3936,32 @@ error: return NULL; } +static char * +qemuBuildNVRAMDevStr(virDomainNVRAMDefPtr dev) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (dev->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO && + dev->info.addr.spaprvio.has_reg) { + virBufferAsprintf(&buf, "spapr-nvram.reg=0x%llx", + dev->info.addr.spaprvio.reg); + } else { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("nvram address type must be spaprvio")); + goto error; + } + + if (virBufferError(&buf)) { + virReportOOMError(); + goto error; + } + + return virBufferContentAndReset(&buf); + +error: + virBufferFreeAndReset(&buf); + return NULL; +} char * qemuBuildUSBInputDevStr(virDomainInputDefPtr dev, @@ -7805,6 +7844,30 @@ qemuBuildCommandLine(virConnectPtr conn, goto error; } + if (def->nvram) { + if (def->os.arch == VIR_ARCH_PPC64 && + STREQ(def->os.machine, "pseries")) { + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_NVRAM)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("nvram device is not supported by " + "this QEMU binary")); + goto error; + } + + char *optstr; + virCommandAddArg(cmd, "-global"); + optstr = qemuBuildNVRAMDevStr(def->nvram); + if (!optstr) + goto error; + if (optstr) + virCommandAddArg(cmd, optstr); + VIR_FREE(optstr); + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("nvram device is only supported for PPC64")); + goto error; + } + } if (snapshot) virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL); @@ -9916,6 +9979,23 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr qemuCaps, goto error; } + } else if (STREQ(arg, "-global") && + STRPREFIX(progargv[i + 1], "spapr-nvram.reg=")) { + WANT_VALUE(); + + if (VIR_ALLOC(def->nvram) < 0) + goto no_memory; + + def->nvram->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO; + def->nvram->info.addr.spaprvio.has_reg = true; + + val += strlen("spapr-nvram.reg="); + if (virStrToLong_ull(val, NULL, 16, + &def->nvram->info.addr.spaprvio.reg) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse nvram's address '%s'"), val); + goto error; + } } else if (STREQ(arg, "-S")) { /* ignore, always added by libvirt */ } else { diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c index ee6c7a9c38..9f1bb242d8 100644 --- a/tests/qemuargv2xmltest.c +++ b/tests/qemuargv2xmltest.c @@ -244,6 +244,8 @@ mymain(void) DO_TEST("hyperv"); + DO_TEST("pseries-nvram"); + DO_TEST_FULL("restore-v1", 0, "stdio"); DO_TEST_FULL("restore-v2", 0, "stdio"); DO_TEST_FULL("restore-v2", 0, "exec:cat"); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-nvram.args b/tests/qemuxml2argvdata/qemuxml2argv-pseries-nvram.args new file mode 100644 index 0000000000..2215796581 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-nvram.args @@ -0,0 +1,5 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu-system-ppc64 \ +-S -M pseries -m 512 -smp 1 -nographic \ +-monitor unix:/tmp/test-monitor,server,nowait \ +-no-acpi -boot c -usb -net none -serial none -parallel none \ +-global spapr-nvram.reg=0x4000 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pseries-nvram.xml b/tests/qemuxml2argvdata/qemuxml2argv-pseries-nvram.xml new file mode 100644 index 0000000000..bead7e7f9c --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pseries-nvram.xml @@ -0,0 +1,23 @@ + + QEMUGuest1 + 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 + 524288 + 524288 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu-system-ppc64 + + + +
+ + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index b1d62fe181..f40d0026ee 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -916,6 +916,7 @@ mymain(void) QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); DO_TEST_ERROR("pseries-vio-address-clash", QEMU_CAPS_DRIVE, QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); + DO_TEST("pseries-nvram", QEMU_CAPS_DEVICE_NVRAM); DO_TEST("disk-ide-drive-split", QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_IDE_CD); diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 7434190baf..1d10bf2461 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -259,6 +259,8 @@ mymain(void) DO_TEST("virtio-rng-random"); DO_TEST("virtio-rng-egd"); + DO_TEST("pseries-nvram"); + /* These tests generate different XML */ DO_TEST_DIFFERENT("balloon-device-auto"); DO_TEST_DIFFERENT("channel-virtio-auto");