<pre>
...
<devices>
+ <panic model='hyperv'/>
<panic model='isa'>
<address type='isa' iobase='0x505'/>
</panic>
<optional>
<ref name="nvram"/>
</optional>
- <optional>
+ <zeroOrMore>
<ref name="panic"/>
- </optional>
+ </zeroOrMore>
</interleave>
</element>
</define>
virDomainTPMDefFree(def->tpm);
- virDomainPanicDefFree(def->panic);
+ for (i = 0; i < def->npanics; i++)
+ virDomainPanicDefFree(def->panics[i]);
+ VIR_FREE(def->panics);
VIR_FREE(def->idmap.uidmap);
VIR_FREE(def->idmap.gidmap);
if (cb(def, &device, &def->tpm->info, opaque) < 0)
return -1;
}
- if (def->panic) {
- device.type = VIR_DOMAIN_DEVICE_PANIC;
- device.data.panic = def->panic;
- if (cb(def, &device, &def->panic->info, opaque) < 0)
+ device.type = VIR_DOMAIN_DEVICE_PANIC;
+ for (i = 0; i < def->npanics; i++) {
+ device.data.panic = def->panics[i];
+ if (cb(def, &device, &def->panics[i]->info, opaque) < 0)
return -1;
}
VIR_FREE(nodes);
/* analysis of the panic devices */
- def->panic = NULL;
if ((n = virXPathNodeSet("./devices/panic", ctxt, &nodes)) < 0)
goto error;
- if (n > 1) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("only a single panic device is supported"));
+ if (n && VIR_ALLOC_N(def->panics, n) < 0)
goto error;
- }
- if (n > 0) {
+ for (i = 0; i < n; i++) {
virDomainPanicDefPtr panic =
- virDomainPanicDefParseXML(nodes[0]);
+ virDomainPanicDefParseXML(nodes[i]);
if (!panic)
goto error;
- def->panic = panic;
- VIR_FREE(nodes);
+ def->panics[def->npanics++] = panic;
}
+ VIR_FREE(nodes);
/* analysis of the shmem devices */
if ((n = virXPathNodeSet("./devices/shmem", ctxt, &nodes)) < 0)
virDomainPanicDefCheckABIStability(virDomainPanicDefPtr src,
virDomainPanicDefPtr dst)
{
- if (!src && !dst)
- return true;
-
- if (!src || !dst) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("Target domain panic device count '%d' "
- "does not match source count '%d'"),
- src ? 1 : 0, dst ? 1 : 0);
- return false;
- }
-
if (src->model != dst->model) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Target panic model '%s' does not match source '%s'"),
if (!virDomainRNGDefCheckABIStability(src->rngs[i], dst->rngs[i]))
goto error;
- if (!virDomainPanicDefCheckABIStability(src->panic, dst->panic))
+ if (src->npanics != dst->npanics) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target domain panic device count %zu "
+ "does not match source %zu"), dst->npanics, src->npanics);
goto error;
+ }
+
+ for (i = 0; i < src->npanics; i++) {
+ if (!virDomainPanicDefCheckABIStability(src->panics[i], dst->panics[i]))
+ goto error;
+ }
if (src->nshmems != dst->nshmems) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
if (def->nvram)
virDomainNVRAMDefFormat(buf, def->nvram, flags);
- if (def->panic &&
- virDomainPanicDefFormat(buf, def->panic) < 0)
- goto error;
+ for (n = 0; n < def->npanics; n++)
+ if (virDomainPanicDefFormat(buf, def->panics[n]) < 0)
+ goto error;
for (n = 0; n < def->nshmems; n++)
if (virDomainShmemDefFormat(buf, def->shmems[n], flags) < 0)
size_t nmems;
virDomainMemoryDefPtr *mems;
+ size_t npanics;
+ virDomainPanicDefPtr *panics;
+
/* Only 1 */
virDomainWatchdogDefPtr watchdog;
virDomainMemballoonDefPtr memballoon;
virCPUDefPtr cpu;
virSysinfoDefPtr sysinfo;
virDomainRedirFilterDefPtr redirfilter;
- virDomainPanicDefPtr panic;
void *namespaceData;
virDomainXMLNamespace ns;
}
}
- if (def->panic &&
- def->panic->model == VIR_DOMAIN_PANIC_MODEL_HYPERV) {
- if (!have_cpu) {
- virBufferAdd(&buf, default_model, -1);
- have_cpu = true;
- }
+ for (i = 0; i < def->npanics; i++) {
+ if (def->panics[i]->model == VIR_DOMAIN_PANIC_MODEL_HYPERV) {
+ if (!have_cpu) {
+ virBufferAdd(&buf, default_model, -1);
+ have_cpu = true;
+ }
- virBufferAddLit(&buf, ",hv_crash");
+ virBufferAddLit(&buf, ",hv_crash");
+ break;
+ }
}
if (def->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
goto error;
}
- if (def->panic) {
- switch ((virDomainPanicModel) def->panic->model) {
+ for (i = 0; i < def->npanics; i++) {
+ switch ((virDomainPanicModel) def->panics[i]->model) {
case VIR_DOMAIN_PANIC_MODEL_HYPERV:
/* Panic with model 'hyperv' is not a device, it should
* be configured in cpu commandline. The address
"panic device of model 'hyperv'"));
goto error;
}
- if (def->panic->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+ if (def->panics[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("setting the panic device address is not "
"supported for model 'hyperv'"));
"of model 'pseries'"));
goto error;
}
- if (def->panic->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
+ if (def->panics[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("setting the panic device address is not "
"supported for model 'pseries'"));
goto error;
}
- switch (def->panic->info.type) {
+ switch (def->panics[i]->info.type) {
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA:
virCommandAddArg(cmd, "-device");
virCommandAddArgFormat(cmd, "pvpanic,ioport=%d",
- def->panic->info.addr.isa.iobase);
+ def->panics[i]->info.addr.isa.iobase);
break;
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
goto cleanup;
}
} else if (STREQ(tokens[i], "hv_crash")) {
- virDomainPanicDefPtr panic;
- if (VIR_ALLOC(panic) < 0)
- goto cleanup;
-
- panic->model = VIR_DOMAIN_PANIC_MODEL_HYPERV;
- dom->panic = panic;
+ size_t j;
+ for (j = 0; j < dom->npanics; j++) {
+ if (dom->panics[j]->model == VIR_DOMAIN_PANIC_MODEL_HYPERV)
+ break;
+ }
+
+ if (j == dom->npanics) {
+ virDomainPanicDefPtr panic;
+ if (VIR_ALLOC(panic) < 0 ||
+ VIR_APPEND_ELEMENT_COPY(dom->panics,
+ dom->npanics, panic) < 0) {
+ VIR_FREE(panic);
+ goto cleanup;
+ }
+ panic->model = VIR_DOMAIN_PANIC_MODEL_HYPERV;
+ }
} else if (STRPREFIX(tokens[i], "hv_")) {
const char *token = tokens[i] + 3; /* "hv_" */
const char *feature, *value;
VIR_DOMAIN_INPUT_BUS_USB) < 0)
goto cleanup;
- if (addPanicDevice && !def->panic) {
- virDomainPanicDefPtr panic;
- if (VIR_ALLOC(panic) < 0)
- goto cleanup;
+ if (addPanicDevice) {
+ size_t j;
+ for (j = 0; j < def->npanics; j++) {
+ if (def->panics[j]->model == VIR_DOMAIN_PANIC_MODEL_DEFAULT ||
+ def->panics[j]->model == VIR_DOMAIN_PANIC_MODEL_PSERIES)
+ break;
+ }
- def->panic = panic;
+ if (j == def->npanics) {
+ virDomainPanicDefPtr panic;
+ if (VIR_ALLOC(panic) < 0 ||
+ VIR_APPEND_ELEMENT_COPY(def->panics,
+ def->npanics, panic) < 0) {
+ VIR_FREE(panic);
+ goto cleanup;
+ }
+ }
}
ret = 0;
--- /dev/null
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu \
+-name QEMUGuest1 \
+-S \
+-M pc \
+-cpu qemu32,hv_crash \
+-m 214 \
+-smp 6 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-nographic \
+-nodefconfig \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-boot n \
+-usb \
+-device pvpanic,ioport=1285
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>6</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='network'/>
+ </os>
+ <features>
+ <acpi/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <controller type='usb' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <memballoon model='none'/>
+ <panic model='hyperv'/>
+ <panic model='isa'>
+ <address type='isa' iobase='0x505'/>
+ </panic>
+ </devices>
+</domain>
DO_TEST("panic", QEMU_CAPS_DEVICE_PANIC,
QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
+ DO_TEST("panic-double", QEMU_CAPS_DEVICE_PANIC,
+ QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
DO_TEST("panic-no-address", QEMU_CAPS_DEVICE_PANIC,
QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
DO_TEST_DIFFERENT("panic");
DO_TEST("panic-isa");
DO_TEST("panic-pseries");
+ DO_TEST("panic-double");
DO_TEST("panic-no-address");
DO_TEST_DIFFERENT("disk-backing-chains");