diff -Nru qemu-2.11+dfsg/debian/changelog qemu-2.11+dfsg/debian/changelog --- qemu-2.11+dfsg/debian/changelog 2018-04-09 12:31:08.000000000 +0000 +++ qemu-2.11+dfsg/debian/changelog 2018-04-18 05:29:50.000000000 +0000 @@ -1,3 +1,12 @@ +qemu (1:2.11+dfsg-1ubuntu7) bionic; urgency=medium + + * d/p/ubuntu/lp-1762854-*: fix issue with SCSI-2 devices denying Protection + information (LP: #1762854). + * d/p/ubuntu/lp-1763468-*: fix VSMT handling to fix ppc64el P8/P9 migration + (LP: #1763468). + + -- Christian Ehrhardt Wed, 11 Apr 2018 07:46:18 +0200 + qemu (1:2.11+dfsg-1ubuntu6) bionic; urgency=medium * Remove LP: 1752026 changes to d/p/ubuntu/define-ubuntu-machine-types.patch. diff -Nru qemu-2.11+dfsg/debian/patches/series qemu-2.11+dfsg/debian/patches/series --- qemu-2.11+dfsg/debian/patches/series 2018-04-09 12:36:16.000000000 +0000 +++ qemu-2.11+dfsg/debian/patches/series 2018-04-16 09:04:30.000000000 +0000 @@ -24,3 +24,10 @@ ubuntu/lp-1704312-2-nvdimm-add-a-macro-for-property-label-size.patch ubuntu/lp-1704312-3-nvdimm-add-unarmed-option.patch ubuntu/lp-1762315-slirp-Add-domainname.patch +ubuntu/lp-1762854-scsi-disk-allow-customizing-the-SCSI-version.patch +ubuntu/lp-1762854-hw-scsi-support-SCSI-2-passthrough-without-PI.patch +ubuntu/lp-1763468-1-spapr-Allow-some-cases-where-we-can-t-set-VSMT-mode-.patch +ubuntu/lp-1763468-2-spapr-Adjust-default-VSMT-value-for-better-migration.patch +ubuntu/lp-1763468-3-spapr-set-vsmt-to-MAX-8-smp_threads.patch +ubuntu/lp-1763468-4-spapr-use-spapr-vsmt-to-compute-VCPU-ids.patch +ubuntu/lp-1763468-9-spapr-register-dummy-ICPs-later.patch diff -Nru qemu-2.11+dfsg/debian/patches/ubuntu/lp-1762854-hw-scsi-support-SCSI-2-passthrough-without-PI.patch qemu-2.11+dfsg/debian/patches/ubuntu/lp-1762854-hw-scsi-support-SCSI-2-passthrough-without-PI.patch --- qemu-2.11+dfsg/debian/patches/ubuntu/lp-1762854-hw-scsi-support-SCSI-2-passthrough-without-PI.patch 1970-01-01 00:00:00.000000000 +0000 +++ qemu-2.11+dfsg/debian/patches/ubuntu/lp-1762854-hw-scsi-support-SCSI-2-passthrough-without-PI.patch 2018-04-11 05:49:59.000000000 +0000 @@ -0,0 +1,122 @@ +From 29e560f00e2bc1b5731c8276031aaf192de55d9d Mon Sep 17 00:00:00 2001 +From: Daniel Henrique Barboza +Date: Tue, 27 Mar 2018 18:14:51 -0300 +Subject: [PATCH] hw/scsi: support SCSI-2 passthrough without PI + +QEMU SCSI code makes assumptions about how the PROTECT and BYTCHK +works in the protocol, denying support for PI (Protection +Information) in case the guest OS requests it. However, in SCSI versions 2 +and older, there is no PI concept in the protocol. + +This means that when dealing with such devices: + +- there is no PROTECT bit in byte 5 of the standard INQUIRY response. The +whole byte is marked as "Reserved"; + +- there is no RDPROTECT in byte 2 of READ. We have 'Logical Unit Number' +in this field instead; + +- there is no VRPROTECT in byte 2 of VERIFY. We have 'Logical Unit Number' +in this field instead. This also means that the BYTCHK bit in this case +is not related to PI. + +Since QEMU does not consider these changes, a SCSI passthrough using +a SCSI-2 device will not work. It will mistake these fields with +PI information and return Illegal Request SCSI SENSE thinking +that the driver is asking for PI support. + +This patch fixes it by adding a new attribute called 'scsi_version' +that is read from the standard INQUIRY response of passthrough +devices. This allows for a version verification before applying +conditions related to PI that doesn't apply for older versions. + +Reported-by: Dac Nguyen +Signed-off-by: Daniel Henrique Barboza +Message-Id: <20180327211451.14647-1-danielhb@linux.vnet.ibm.com> +Signed-off-by: Paolo Bonzini + +Forwarded: no (backport) +Author: Christian Ehrhardt +Original-Author: Daniel Henrique Barboza +Origin: upstream, https://github.com/qemu/qemu/commit/29e560f00e2bc1b5731c8276031aaf192de55d9d +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1762854 +Last-Update: 2018-04-11 +--- + hw/scsi/scsi-disk.c | 2 +- + hw/scsi/scsi-generic.c | 47 ++++++++++++++++++++++++++++++++++++----------- + 2 files changed, 37 insertions(+), 12 deletions(-) + +--- a/hw/scsi/scsi-disk.c ++++ b/hw/scsi/scsi-disk.c +@@ -3027,7 +3027,7 @@ static Property scsi_block_properties[] + DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.blk), + DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0), + DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, +- 5), ++ -1), + DEFINE_PROP_END_OF_LIST(), + }; + +--- a/hw/scsi/scsi-generic.c ++++ b/hw/scsi/scsi-generic.c +@@ -194,17 +194,40 @@ static void scsi_read_complete(void * op + r->buf[3] |= 0x80; + } + } +- if (s->type == TYPE_DISK && +- r->req.cmd.buf[0] == INQUIRY && +- r->req.cmd.buf[2] == 0xb0) { +- uint32_t max_transfer = +- blk_get_max_transfer(s->conf.blk) / s->blocksize; +- +- assert(max_transfer); +- stl_be_p(&r->buf[8], max_transfer); +- /* Also take care of the opt xfer len. */ +- stl_be_p(&r->buf[12], +- MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12]))); ++ if (r->req.cmd.buf[0] == INQUIRY) { ++ /* ++ * EVPD set to zero returns the standard INQUIRY data. ++ * ++ * Check if scsi_version is unset (-1) to avoid re-defining it ++ * each time an INQUIRY with standard data is received. ++ * scsi_version is initialized with -1 in scsi_generic_reset ++ * and scsi_disk_reset, making sure that we'll set the ++ * scsi_version after a reset. If the version field of the ++ * INQUIRY response somehow changes after a guest reboot, ++ * we'll be able to keep track of it. ++ * ++ * On SCSI-2 and older, first 3 bits of byte 2 is the ++ * ANSI-approved version, while on later versions the ++ * whole byte 2 contains the version. Check if we're dealing ++ * with a newer version and, in that case, assign the ++ * whole byte. ++ */ ++ if (s->scsi_version == -1 && !(r->req.cmd.buf[1] & 0x01)) { ++ s->scsi_version = r->buf[2] & 0x07; ++ if (s->scsi_version > 2) { ++ s->scsi_version = r->buf[2]; ++ } ++ } ++ if (s->type == TYPE_DISK && r->req.cmd.buf[2] == 0xb0) { ++ uint32_t max_transfer = ++ blk_get_max_transfer(s->conf.blk) / s->blocksize; ++ ++ assert(max_transfer); ++ stl_be_p(&r->buf[8], max_transfer); ++ /* Also take care of the opt xfer len. */ ++ stl_be_p(&r->buf[12], ++ MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12]))); ++ } + } + scsi_req_data(&r->req, len); + scsi_req_unref(&r->req); +@@ -544,6 +567,8 @@ static void scsi_generic_realize(SCSIDev + + DPRINTF("block size %d\n", s->blocksize); + ++ /* Only used by scsi-block, but initialize it nevertheless to be clean. */ ++ s->default_scsi_version = -1; + scsi_generic_read_device_identification(s); + } + diff -Nru qemu-2.11+dfsg/debian/patches/ubuntu/lp-1762854-scsi-disk-allow-customizing-the-SCSI-version.patch qemu-2.11+dfsg/debian/patches/ubuntu/lp-1762854-scsi-disk-allow-customizing-the-SCSI-version.patch --- qemu-2.11+dfsg/debian/patches/ubuntu/lp-1762854-scsi-disk-allow-customizing-the-SCSI-version.patch 1970-01-01 00:00:00.000000000 +0000 +++ qemu-2.11+dfsg/debian/patches/ubuntu/lp-1762854-scsi-disk-allow-customizing-the-SCSI-version.patch 2018-04-11 05:50:38.000000000 +0000 @@ -0,0 +1,151 @@ +From 2343be0d7ee8a6e02c2bf99d0243492085c8d399 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Thu, 5 Apr 2018 18:09:51 +0200 +Subject: [PATCH] scsi-disk: allow customizing the SCSI version + +We would like to have different behavior for passthrough devices +depending on the SCSI version they expose. To prepare for that, +allow the user of emulated devices to specify the desired SCSI +level, and adjust the emulation according to the property value. +The next patch will set the level for scsi-block and scsi-generic +devices. + +Based on a patch by Daniel Henrique Barboza +. + +Signed-off-by: Paolo Bonzini + +Forwarded: no (backport) +Author: Christian Ehrhardt +Original-Author: Paolo Bonzini +Origin: upstream, https://github.com/qemu/qemu/commit/2343be0d7ee8a6e02c2bf99d0243492085c8d399 +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1762854 +Last-Update: 2018-04-11 +--- + hw/scsi/scsi-disk.c | 29 ++++++++++++++++++++++++----- + hw/scsi/scsi-generic.c | 1 + + include/hw/scsi/scsi.h | 2 ++ + 3 files changed, 27 insertions(+), 5 deletions(-) + +--- a/hw/scsi/scsi-disk.c ++++ b/hw/scsi/scsi-disk.c +@@ -808,7 +808,7 @@ static int scsi_disk_emulate_inquiry(SCS + * block characteristics VPD page by default. Not all of SPC-3 + * is actually implemented, but we're good enough. + */ +- outbuf[2] = 5; ++ outbuf[2] = s->qdev.default_scsi_version; + outbuf[3] = 2 | 0x10; /* Format 2, HiSup */ + + if (buflen > 36) { +@@ -2176,7 +2176,11 @@ static int32_t scsi_disk_dma_command(SCS + case READ_12: + case READ_16: + DPRINTF("Read (sector %" PRId64 ", count %u)\n", r->req.cmd.lba, len); +- if (r->req.cmd.buf[1] & 0xe0) { ++ /* Protection information is not supported. For SCSI versions 2 and ++ * older (as determined by snooping the guest's INQUIRY commands), ++ * there is no RD/WR/VRPROTECT, so skip this check in these versions. ++ */ ++ if (s->qdev.scsi_version > 2 && (r->req.cmd.buf[1] & 0xe0)) { + goto illegal_request; + } + if (!check_lba_range(s, r->req.cmd.lba, len)) { +@@ -2207,7 +2211,7 @@ static int32_t scsi_disk_dma_command(SCS + * As far as DMA is concerned, we can treat it the same as a write; + * scsi_block_do_sgio will send VERIFY commands. + */ +- if (r->req.cmd.buf[1] & 0xe0) { ++ if (s->qdev.scsi_version > 2 && (r->req.cmd.buf[1] & 0xe0)) { + goto illegal_request; + } + if (!check_lba_range(s, r->req.cmd.lba, len)) { +@@ -2253,6 +2257,8 @@ static void scsi_disk_reset(DeviceState + /* reset tray statuses */ + s->tray_locked = 0; + s->tray_open = 0; ++ ++ s->qdev.scsi_version = s->qdev.default_scsi_version; + } + + static void scsi_disk_resize_cb(void *opaque) +@@ -2801,6 +2807,8 @@ static bool scsi_block_is_passthrough(SC + static int32_t scsi_block_dma_command(SCSIRequest *req, uint8_t *buf) + { + SCSIBlockReq *r = (SCSIBlockReq *)req; ++ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); ++ + r->cmd = req->cmd.buf[0]; + switch (r->cmd >> 5) { + case 0: +@@ -2826,8 +2834,11 @@ static int32_t scsi_block_dma_command(SC + abort(); + } + +- if (r->cdb1 & 0xe0) { +- /* Protection information is not supported. */ ++ /* Protection information is not supported. For SCSI versions 2 and ++ * older (as determined by snooping the guest's INQUIRY commands), ++ * there is no RD/WR/VRPROTECT, so skip this check in these versions. ++ */ ++ if (s->qdev.scsi_version > 2 && (req->cmd.buf[1] & 0xe0)) { + scsi_check_condition(&r->req, SENSE_CODE(INVALID_FIELD)); + return 0; + } +@@ -2939,6 +2950,8 @@ static Property scsi_hd_properties[] = { + DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, + DEFAULT_MAX_IO_SIZE), + DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0), ++ DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, ++ 5), + DEFINE_BLOCK_CHS_PROPERTIES(SCSIDiskState, qdev.conf), + DEFINE_PROP_END_OF_LIST(), + }; +@@ -2984,6 +2997,8 @@ static Property scsi_cd_properties[] = { + DEFINE_PROP_UINT16("port_index", SCSIDiskState, port_index, 0), + DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, + DEFAULT_MAX_IO_SIZE), ++ DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, ++ 5), + DEFINE_PROP_END_OF_LIST(), + }; + +@@ -3011,6 +3026,8 @@ static Property scsi_block_properties[] + DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), \ + DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.blk), + DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0), ++ DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, ++ 5), + DEFINE_PROP_END_OF_LIST(), + }; + +@@ -3051,6 +3068,8 @@ static Property scsi_disk_properties[] = + DEFAULT_MAX_UNMAP_SIZE), + DEFINE_PROP_UINT64("max_io_size", SCSIDiskState, max_io_size, + DEFAULT_MAX_IO_SIZE), ++ DEFINE_PROP_INT32("scsi_version", SCSIDiskState, qdev.default_scsi_version, ++ 5), + DEFINE_PROP_END_OF_LIST(), + }; + +--- a/hw/scsi/scsi-generic.c ++++ b/hw/scsi/scsi-generic.c +@@ -474,6 +474,7 @@ static void scsi_generic_reset(DeviceSta + { + SCSIDevice *s = SCSI_DEVICE(dev); + ++ s->scsi_version = s->default_scsi_version; + scsi_device_purge_requests(s, SENSE_CODE(RESET)); + } + +--- a/include/hw/scsi/scsi.h ++++ b/include/hw/scsi/scsi.h +@@ -85,6 +85,8 @@ struct SCSIDevice + uint64_t max_lba; + uint64_t wwn; + uint64_t port_wwn; ++ int scsi_version; ++ int default_scsi_version; + }; + + extern const VMStateDescription vmstate_scsi_device; diff -Nru qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-1-spapr-Allow-some-cases-where-we-can-t-set-VSMT-mode-.patch qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-1-spapr-Allow-some-cases-where-we-can-t-set-VSMT-mode-.patch --- qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-1-spapr-Allow-some-cases-where-we-can-t-set-VSMT-mode-.patch 1970-01-01 00:00:00.000000000 +0000 +++ qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-1-spapr-Allow-some-cases-where-we-can-t-set-VSMT-mode-.patch 2018-04-13 06:58:11.000000000 +0000 @@ -0,0 +1,76 @@ +From fefce43c9ddd833a4b97a2b4acaae586efb7c99c Mon Sep 17 00:00:00 2001 +From: David Gibson +Date: Tue, 16 Jan 2018 15:37:37 +1100 +Subject: [PATCH 1/9] spapr: Allow some cases where we can't set VSMT mode in + the kernel + +At present if we require a vsmt mode that's not equal to the kernel's +default, and the kernel doesn't let us change it (e.g. because it's an old +kernel without support) then we always fail. + +But in fact we can cope with the kernel having a different vsmt as long as + a) it's >= the actual number of vthreads/vcore (so that guest threads + that are supposed to be on the same core act like it) + b) it's a submultiple of the requested vsmt mode (so that guest threads + spaced by the vsmt value will act like they're on different cores) + +Allowing this case gives us a bit more freedom to adjust the vsmt behaviour +without breaking existing cases. + +Signed-off-by: David Gibson +Reviewed-by: Laurent Vivier +Tested-by: Greg Kurz +Reviewed-by: Greg Kurz + +Forwarded: no (backport) +Origin: upstream, https://git.qemu.org/?p=qemu.git;a=commit;h=1f20f2e0 +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1763468 +Last-Update: 2018-04-13 +--- + hw/ppc/spapr.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index 3e528fe..f8b3357 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -2314,17 +2314,29 @@ static void spapr_set_vsmt_mode(sPAPRMachineState *spapr, Error **errp) + if (kvm_enabled() && (spapr->vsmt != kvm_smt)) { + ret = kvmppc_set_smt_threads(spapr->vsmt); + if (ret) { ++ /* Looks like KVM isn't able to change VSMT mode */ + error_setg(&local_err, + "Failed to set KVM's VSMT mode to %d (errno %d)", + spapr->vsmt, ret); +- if (!vsmt_user) { +- error_append_hint(&local_err, "On PPC, a VM with %d threads/" +- "core on a host with %d threads/core requires " +- " the use of VSMT mode %d.\n", +- smp_threads, kvm_smt, spapr->vsmt); ++ /* We can live with that if the default one is big enough ++ * for the number of threads, and a submultiple of the one ++ * we want. In this case we'll waste some vcpu ids, but ++ * behaviour will be correct */ ++ if ((kvm_smt >= smp_threads) && ((spapr->vsmt % kvm_smt) == 0)) { ++ warn_report_err(local_err); ++ local_err = NULL; ++ goto out; ++ } else { ++ if (!vsmt_user) { ++ error_append_hint(&local_err, ++ "On PPC, a VM with %d threads/core" ++ " on a host with %d threads/core" ++ " requires the use of VSMT mode %d.\n", ++ smp_threads, kvm_smt, spapr->vsmt); ++ } ++ kvmppc_hint_smt_possible(&local_err); ++ goto out; + } +- kvmppc_hint_smt_possible(&local_err); +- goto out; + } + } + /* else TCG: nothing to do currently */ +-- +2.7.4 + diff -Nru qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-2-spapr-Adjust-default-VSMT-value-for-better-migration.patch qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-2-spapr-Adjust-default-VSMT-value-for-better-migration.patch --- qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-2-spapr-Adjust-default-VSMT-value-for-better-migration.patch 1970-01-01 00:00:00.000000000 +0000 +++ qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-2-spapr-Adjust-default-VSMT-value-for-better-migration.patch 2018-04-13 06:58:50.000000000 +0000 @@ -0,0 +1,107 @@ +From 70d2407b76d794e1ad1bd9676e1c6e5d760dcf2f Mon Sep 17 00:00:00 2001 +From: David Gibson +Date: Mon, 15 Jan 2018 17:51:33 +1100 +Subject: [PATCH 2/9] spapr: Adjust default VSMT value for better migration + compatibility + +fa98fbfc "PC: KVM: Support machine option to set VSMT mode" introduced the +"vsmt" parameter for the pseries machine type, which controls the spacing +of the vcpu ids of thread 0 for each virtual core. This was done to bring +some consistency and stability to how that was done, while still allowing +backwards compatibility for migration and otherwise. + +The default value we used for vsmt was set to the max of the host's +advertised default number of threads and the number of vthreads per vcore +in the guest. This was done to continue running without extra parameters +on older KVM versions which don't allow the VSMT value to be changed. + +Unfortunately, even that smaller than before leakage of host configuration +into guest visible configuration still breaks things. Specifically a guest +with 4 (or less) vthread/vcore will get a different vsmt value when +running on a POWER8 (vsmt==8) and POWER9 (vsmt==4) host. That means the +vcpu ids don't line up so you can't migrate between them, though you should +be able to. + +Long term we really want to make vsmt == smp_threads for sufficiently +new machine types. However, that means that qemu will then require a +sufficiently recent KVM (one which supports changing VSMT) - that's still +not widely enough deployed to be really comfortable to do. + +In the meantime we need some default that will work as often as +possible. This patch changes that default to 8 in all circumstances. +This does change guest visible behaviour (including for existing +machine versions) for many cases - just not the most common/important +case. + +Following is case by case justification for why this is still the least +worst option. Note that any of the old behaviours can still be duplicated +after this patch, it's just that it requires manual intervention by +setting the vsmt property on the command line. + +KVM HV on POWER8 host: + This is the overwhelmingly common case in production setups, and is + unchanged by design. POWER8 hosts will advertise a default VSMT mode + of 8, and > 8 vthreads/vcore isn't permitted + +KVM HV on POWER7 host: + Will break, but POWER7s allowing KVM were never released to the public. + +KVM HV on POWER9 host: + Not yet released to the public, breaking this now will reduce other + breakage later. + +KVM HV on PowerPC 970: + Will theoretically break it, but it was barely supported to begin with + and already required various user visible hacks to work. Also so old + that I just don't care. + +TCG: + This is the nastiest one; it means migration of TCG guests (without + manual vsmt setting) will break. Since TCG is rarely used in production + I think this is worth it for the other benefits. It does also remove + one more barrier to TCG<->KVM migration which could be interesting for + debugging applications. + +KVM PR: + As with TCG, this will break migration of existing configurations, + without adding extra manual vsmt options. As with TCG, it is rare in + production so I think the benefits outweigh breakages. + +Signed-off-by: David Gibson +Reviewed-by: Laurent Vivier +Reviewed-by: Jose Ricardo Ziviani +Reviewed-by: Greg Kurz + +Forwarded: no (backport) +Origin: upstream, https://git.qemu.org/?p=qemu.git;a=commit;h=8904e5a7 +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1763468 +Last-Update: 2018-04-13 +--- + hw/ppc/spapr.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index f8b3357..094dc7c 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -2305,9 +2305,14 @@ static void spapr_set_vsmt_mode(sPAPRMachineState *spapr, Error **errp) + } + /* In this case, spapr->vsmt has been set by the command line */ + } else { +- /* Choose a VSMT mode that may be higher than necessary but is +- * likely to be compatible with hosts that don't have VSMT. */ +- spapr->vsmt = MAX(kvm_smt, smp_threads); ++ /* ++ * Default VSMT value is tricky, because we need it to be as ++ * consistent as possible (for migration), but this requires ++ * changing it for at least some existing cases. We pick 8 as ++ * the value that we'd get with KVM on POWER8, the ++ * overwhelmingly common case in production systems. ++ */ ++ spapr->vsmt = 8; + } + + /* KVM: If necessary, set the SMT mode: */ +-- +2.7.4 + diff -Nru qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-3-spapr-set-vsmt-to-MAX-8-smp_threads.patch qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-3-spapr-set-vsmt-to-MAX-8-smp_threads.patch --- qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-3-spapr-set-vsmt-to-MAX-8-smp_threads.patch 1970-01-01 00:00:00.000000000 +0000 +++ qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-3-spapr-set-vsmt-to-MAX-8-smp_threads.patch 2018-04-13 06:59:07.000000000 +0000 @@ -0,0 +1,40 @@ +From 490cf5e8ad81efa02b448c2e1b75748ddd080380 Mon Sep 17 00:00:00 2001 +From: Laurent Vivier +Date: Fri, 9 Feb 2018 09:18:58 +0100 +Subject: [PATCH 3/9] spapr: set vsmt to MAX(8, smp_threads) + +We ignore silently the value of smp_threads when we set +the default VSMT value, and if smp_threads is greater than VSMT +kernel is going into trouble later. + +Fixes: 8904e5a750 +("spapr: Adjust default VSMT value for better migration compatibility") + +Signed-off-by: Laurent Vivier +Reviewed-by: Greg Kurz +Signed-off-by: David Gibson + +Forwarded: no (backport) +Origin: upstream, https://git.qemu.org/?p=qemu.git;a=commit;h=4ad64cbd +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1763468 +Last-Update: 2018-04-13 +--- + hw/ppc/spapr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index 094dc7c..b4d0d5d 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -2312,7 +2312,7 @@ static void spapr_set_vsmt_mode(sPAPRMachineState *spapr, Error **errp) + * the value that we'd get with KVM on POWER8, the + * overwhelmingly common case in production systems. + */ +- spapr->vsmt = 8; ++ spapr->vsmt = MAX(8, smp_threads); + } + + /* KVM: If necessary, set the SMT mode: */ +-- +2.7.4 + diff -Nru qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-4-spapr-use-spapr-vsmt-to-compute-VCPU-ids.patch qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-4-spapr-use-spapr-vsmt-to-compute-VCPU-ids.patch --- qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-4-spapr-use-spapr-vsmt-to-compute-VCPU-ids.patch 1970-01-01 00:00:00.000000000 +0000 +++ qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-4-spapr-use-spapr-vsmt-to-compute-VCPU-ids.patch 2018-04-13 06:59:33.000000000 +0000 @@ -0,0 +1,248 @@ +From c03ddd27e23e1b2b29afff8d9330eacc3e45a710 Mon Sep 17 00:00:00 2001 +From: Greg Kurz +Date: Wed, 14 Feb 2018 20:40:26 +0100 +Subject: [PATCH 4/9] spapr: use spapr->vsmt to compute VCPU ids + +Since the introduction of VSMT in 2.11, the spacing of VCPU ids +between cores is controllable through a machine property instead +of being only dictated by the SMT mode of the host: + + cpu->vcpu_id = (cc->core_id * spapr->vsmt / smp_threads) + i + +Until recently, the machine code would try to change the SMT mode +of the host to be equal to VSMT or exit. This allowed the rest of +the code to assume that kvmppc_smt_threads() == spapr->vsmt is +always true. + +Recent commit "8904e5a75005 spapr: Adjust default VSMT value for +better migration compatibility" relaxed the rule. If the VSMT +mode cannot be set in KVM for some reasons, but the requested +CPU topology is compatible with the current SMT mode, then we +let the guest run with kvmppc_smt_threads() != spapr->vsmt. + +This breaks quite a few places in the code, in particular when +calculating DRC indexes. + +This is what happens on a POWER host with subcores-per-core=2 (ie, +supports up to SMT4) when passing the following topology: + + -smp threads=4,maxcpus=16 \ + -device host-spapr-cpu-core,core-id=4,id=core1 \ + -device host-spapr-cpu-core,core-id=8,id=core2 + +qemu-system-ppc64: warning: Failed to set KVM's VSMT mode to 8 (errno -22) + +This is expected since KVM is limited to SMT4, but the guest is started +anyway because this topology can run on SMT4 even with a VSMT8 spacing. + +But when we look at the DT, things get nastier: + +cpus { + ... + ibm,drc-indexes = <0x4 0x10000000 0x10000004 0x10000008 0x1000000c>; + +This means that we have the following association: + + CPU core device | DRC | VCPU id +-----------------+------------+--------- + boot core | 0x10000000 | 0 + core1 | 0x10000004 | 4 + core2 | 0x10000008 | 8 + core3 | 0x1000000c | 12 + +But since the spacing of VCPU ids is 8, the DRC for core1 points to a +VCPU that doesn't exist, the DRC for core2 points to the first VCPU of +core1 and and so on... + + ... + + PowerPC,POWER8@0 { + ... + ibm,my-drc-index = <0x10000000>; + ... + }; + + PowerPC,POWER8@8 { + ... + ibm,my-drc-index = <0x10000008>; + ... + }; + + PowerPC,POWER8@10 { + ... + +No ibm,my-drc-index property for this core since 0x10000010 doesn't +exist in ibm,drc-indexes above. + + ... + }; +}; + +... + +interrupt-controller { + ... + ibm,interrupt-server-ranges = <0x0 0x10>; + +With a spacing of 8, the highest VCPU id for the given topology should be: + 16 * 8 / 4 = 32 and not 16 + + ... + linux,phandle = <0x7e7323b8>; + interrupt-controller; +}; + +And CPU hot-plug/unplug is broken: + +(qemu) device_del core1 +pseries-hotplug-cpu: Cannot find CPU (drc index 10000004) to remove + +(qemu) device_del core2 +cpu 4 (hwid 8) Ready to die... +cpu 5 (hwid 9) Ready to die... +cpu 6 (hwid 10) Ready to die... +cpu 7 (hwid 11) Ready to die... + +These are the VCPU ids of core1 actually + +(qemu) device_add host-spapr-cpu-core,core-id=12,id=core3 +(qemu) device_del core3 +pseries-hotplug-cpu: Cannot find CPU (drc index 1000000c) to remove + +This patches all the code in hw/ppc/spapr.c to assume the VSMT +spacing when manipulating VCPU ids. + +Fixes: 8904e5a75005 +Signed-off-by: Greg Kurz + +Signed-off-by: David Gibson + +Forwarded: no (backport) +Origin: upstream, https://git.qemu.org/?p=qemu.git;a=commit;h=72194664 +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1763468 +Last-Update: 2018-04-13 +--- + hw/ppc/spapr.c | 24 ++++++++++-------------- + 1 file changed, 10 insertions(+), 14 deletions(-) + +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -161,9 +161,9 @@ static void pre_2_10_vmstate_unregister_ + (void *)(uintptr_t) i); + } + +-static inline int xics_max_server_number(void) ++static int xics_max_server_number(sPAPRMachineState *spapr) + { +- return DIV_ROUND_UP(max_cpus * kvmppc_smt_threads(), smp_threads); ++ return DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads); + } + + static void xics_system_init(MachineState *machine, int nr_irqs, Error **errp) +@@ -195,7 +195,7 @@ static void xics_system_init(MachineStat + if (smc->pre_2_10_has_unused_icps) { + int i; + +- for (i = 0; i < xics_max_server_number(); i++) { ++ for (i = 0; i < xics_max_server_number(spapr); i++) { + /* Dummy entries get deregistered when real ICPState objects + * are registered during CPU core hotplug. + */ +@@ -338,7 +338,6 @@ static int spapr_fixup_cpu_dt(void *fdt, + int ret = 0, offset, cpus_offset; + CPUState *cs; + char cpu_model[32]; +- int smt = kvmppc_smt_threads(); + uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; + + CPU_FOREACH(cs) { +@@ -347,7 +346,7 @@ static int spapr_fixup_cpu_dt(void *fdt, + int index = spapr_vcpu_id(cpu); + int compat_smt = MIN(smp_threads, ppc_compat_max_threads(cpu)); + +- if ((index % smt) != 0) { ++ if (index % spapr->vsmt != 0) { + continue; + } + +@@ -614,7 +613,6 @@ static void spapr_populate_cpus_dt_node( + CPUState *cs; + int cpus_offset; + char *nodename; +- int smt = kvmppc_smt_threads(); + + cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); + _FDT(cpus_offset); +@@ -632,7 +630,7 @@ static void spapr_populate_cpus_dt_node( + DeviceClass *dc = DEVICE_GET_CLASS(cs); + int offset; + +- if ((index % smt) != 0) { ++ if (index % spapr->vsmt != 0) { + continue; + } + +@@ -1105,7 +1103,7 @@ static void *spapr_build_fdt(sPAPRMachin + _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2)); + + /* /interrupt controller */ +- spapr_dt_xics(xics_max_server_number(), fdt, PHANDLE_XICP); ++ spapr_dt_xics(xics_max_server_number(spapr), fdt, PHANDLE_XICP); + + ret = spapr_populate_memory(spapr, fdt); + if (ret < 0) { +@@ -2198,7 +2196,6 @@ static void spapr_init_cpus(sPAPRMachine + MachineState *machine = MACHINE(spapr); + MachineClass *mc = MACHINE_GET_CLASS(machine); + const char *type = spapr_get_cpu_core_type(machine->cpu_type); +- int smt = kvmppc_smt_threads(); + const CPUArchIdList *possible_cpus; + int boot_cores_nr = smp_cpus / smp_threads; + int i; +@@ -2233,7 +2230,7 @@ static void spapr_init_cpus(sPAPRMachine + + if (mc->has_hotpluggable_cpus) { + spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, +- (core_id / smp_threads) * smt); ++ (core_id / smp_threads) * spapr->vsmt); + } + + if (i < boot_cores_nr) { +@@ -3262,10 +3259,10 @@ static + void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) + { ++ sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); + int index; + sPAPRDRConnector *drc; + CPUCore *cc = CPU_CORE(dev); +- int smt = kvmppc_smt_threads(); + + if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) { + error_setg(errp, "Unable to find CPU core with core-id: %d", +@@ -3277,7 +3274,7 @@ void spapr_core_unplug_request(HotplugHa + return; + } + +- drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index * smt); ++ drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index * spapr->vsmt); + g_assert(drc); + + spapr_drc_detach(drc); +@@ -3296,7 +3293,6 @@ static void spapr_core_plug(HotplugHandl + CPUState *cs = CPU(core->threads); + sPAPRDRConnector *drc; + Error *local_err = NULL; +- int smt = kvmppc_smt_threads(); + CPUArchId *core_slot; + int index; + bool hotplugged = spapr_drc_hotplugged(dev); +@@ -3307,7 +3303,7 @@ static void spapr_core_plug(HotplugHandl + cc->core_id); + return; + } +- drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index * smt); ++ drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index * spapr->vsmt); + + g_assert(drc || !mc->has_hotpluggable_cpus); + diff -Nru qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-9-spapr-register-dummy-ICPs-later.patch qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-9-spapr-register-dummy-ICPs-later.patch --- qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-9-spapr-register-dummy-ICPs-later.patch 1970-01-01 00:00:00.000000000 +0000 +++ qemu-2.11+dfsg/debian/patches/ubuntu/lp-1763468-9-spapr-register-dummy-ICPs-later.patch 2018-04-13 07:01:10.000000000 +0000 @@ -0,0 +1,102 @@ +From 55fc7529a99be73ce09e64ef7c4edab0125fee06 Mon Sep 17 00:00:00 2001 +From: Greg Kurz +Date: Tue, 27 Feb 2018 16:22:58 +0100 +Subject: [PATCH 9/9] spapr: register dummy ICPs later + +Some older machine types create more ICPs than needed. We hence +need to register up to xics_max_server_number() dummy ICPs to +accomodate the migration of these machine types. + +Recent VSMT rework changed xics_max_server_number() to return + + DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads) + +instead of + + DIV_ROUND_UP(max_cpus * kvmppc_smt_threads(), smp_threads); + +The change is okay but it requires spapr->vsmt to be set, which +isn't the case with the current code. This causes the formula to +return zero and we don't create dummy ICPs. This breaks migration +of older guests as reported here: + + https://bugzilla.redhat.com/show_bug.cgi?id=1549087 + +The dummy ICP workaround doesn't really have a dependency on XICS +itself. But it does depend on proper VCPU id numbering and it must +be applied before creating vCPUs (ie, creating real ICPs). So this +patch moves the workaround to spapr_init_cpus(), which already +assumes VSMT to be set. + +Fixes: 72194664c8a1 ("spapr: use spapr->vsmt to compute VCPU ids") +Reported-by: Lukas Doktor +Signed-off-by: Greg Kurz +Signed-off-by: David Gibson + +Forwarded: no (backport) +Origin: upstream, https://git.qemu.org/?p=qemu.git;a=commit;h=72fdd4de +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1763468 +Last-Update: 2018-04-13 +--- + hw/ppc/spapr.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index 979f634..14cd2bf 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -184,7 +184,6 @@ static int xics_max_server_number(sPAPRMachineState *spapr) + static void xics_system_init(MachineState *machine, int nr_irqs, Error **errp) + { + sPAPRMachineState *spapr = SPAPR_MACHINE(machine); +- sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); + + if (kvm_enabled()) { + if (machine_kernel_irqchip_allowed(machine) && +@@ -206,17 +205,6 @@ static void xics_system_init(MachineState *machine, int nr_irqs, Error **errp) + return; + } + } +- +- if (smc->pre_2_10_has_unused_icps) { +- int i; +- +- for (i = 0; i < xics_max_server_number(spapr); i++) { +- /* Dummy entries get deregistered when real ICPState objects +- * are registered during CPU core hotplug. +- */ +- pre_2_10_vmstate_register_dummy_icp(i); +- } +- } + } + + static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, +@@ -2233,6 +2221,7 @@ static void spapr_init_cpus(sPAPRMachineState *spapr) + { + MachineState *machine = MACHINE(spapr); + MachineClass *mc = MACHINE_GET_CLASS(machine); ++ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); + const char *type = spapr_get_cpu_core_type(machine->cpu_type); + const CPUArchIdList *possible_cpus; + int boot_cores_nr = smp_cpus / smp_threads; +@@ -2263,6 +2252,17 @@ static void spapr_init_cpus(sPAPRMachineState *spapr) + boot_cores_nr = possible_cpus->len; + } + ++ if (smc->pre_2_10_has_unused_icps) { ++ int i; ++ ++ for (i = 0; i < xics_max_server_number(spapr); i++) { ++ /* Dummy entries get deregistered when real ICPState objects ++ * are registered during CPU core hotplug. ++ */ ++ pre_2_10_vmstate_register_dummy_icp(i); ++ } ++ } ++ + for (i = 0; i < possible_cpus->len; i++) { + int core_id = i * smp_threads; + +-- +2.7.4 +