Package init

This commit is contained in:
overweight 2019-09-30 11:15:46 -04:00
commit 9a683b2a29
54 changed files with 6275 additions and 0 deletions

View File

@ -0,0 +1,2 @@
SUBSYSTEM=="virtio-ports", ATTR{name}=="org.qemu.guest_agent.0", \
TAG+="systemd" ENV{SYSTEMD_WANTS}="qemu-guest-agent.service"

View File

@ -0,0 +1,135 @@
From b341b4c1b514d1ca41b39bdf4d4bc4b0267350a3 Mon Sep 17 00:00:00 2001
From: Ying Fang <fangying1@huawei.com>
Date: Mon, 29 Jul 2019 15:47:27 +0800
Subject: [PATCH] ARM64: record vtimer tick when cpu is stopped
The vtimer kick still increases even if the vcpu is stopped when VM has
save/restore or suspend/resume operation. This will cause guest watchdog
soft-lockup if the VM has lots of memory in use.
Signed-off-by: Hao Hong <honghao5@huawei.com>
Signed-off-by: Haibin Wang <wanghaibin.wang@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
cpus.c | 59 ++++++++++++++++++++++++++++++++++++++++++++
target/arm/cpu.h | 2 ++
target/arm/machine.c | 1 +
3 files changed, 62 insertions(+)
diff --git a/cpus.c b/cpus.c
index e83f72b4..94c3b8ca 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1063,6 +1063,28 @@ void cpu_synchronize_all_pre_loadvm(void)
}
}
+#ifdef __aarch64__
+static void get_vcpu_timer_tick(CPUState *cs)
+{
+ CPUARMState *env = &ARM_CPU(cs)->env;
+ int err;
+ struct kvm_one_reg reg;
+ uint64_t timer_tick;
+
+ reg.id = KVM_REG_ARM_TIMER_CNT;
+ reg.addr = (uintptr_t) &timer_tick;
+
+ err = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+ if (err < 0) {
+ error_report("get vcpu tick failed, ret = %d", err);
+ env->vtimer = 0;
+ return;
+ }
+ env->vtimer = timer_tick;
+ return;
+}
+#endif
+
static int do_vm_stop(RunState state, bool send_stop)
{
int ret = 0;
@@ -1070,6 +1092,11 @@ static int do_vm_stop(RunState state, bool send_stop)
if (runstate_is_running()) {
cpu_disable_ticks();
pause_all_vcpus();
+#ifdef __aarch64__
+ if (first_cpu) {
+ get_vcpu_timer_tick(first_cpu);
+ }
+#endif
runstate_set(state);
vm_state_notify(0, state);
if (send_stop) {
@@ -1909,11 +1936,43 @@ void cpu_resume(CPUState *cpu)
qemu_cpu_kick(cpu);
}
+#ifdef __aarch64__
+static void set_vcpu_timer_tick(CPUState *cs)
+{
+ CPUARMState *env = &ARM_CPU(cs)->env;
+
+ if (env->vtimer == 0) {
+ error_report("Do not set vcpu tick.");
+ return;
+ }
+
+ int err;
+ struct kvm_one_reg reg;
+ uint64_t timer_tick = env->vtimer;
+ env->vtimer = 0;
+
+ reg.id = KVM_REG_ARM_TIMER_CNT;
+ reg.addr = (uintptr_t) &timer_tick;
+
+ err = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+ if (err < 0) {
+ error_report("Set vcpu tick failed, ret = %d", err);
+ return;
+ }
+ return;
+}
+#endif
+
void resume_all_vcpus(void)
{
CPUState *cpu;
qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
+#ifdef __aarch64__
+ if (first_cpu) {
+ set_vcpu_timer_tick(first_cpu);
+ }
+#endif
CPU_FOREACH(cpu) {
cpu_resume(cpu);
}
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index d4d28369..e107e395 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -270,6 +270,8 @@ typedef struct CPUARMState {
uint64_t elr_el[4]; /* AArch64 exception link regs */
uint64_t sp_el[4]; /* AArch64 banked stack pointers */
+ uint64_t vtimer; /* Timer tick when vcpu stop */
+
/* System control coprocessor (cp15) */
struct {
uint32_t c0_cpuid;
diff --git a/target/arm/machine.c b/target/arm/machine.c
index b2925496..d64a0057 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -792,6 +792,7 @@ const VMStateDescription vmstate_arm_cpu = {
VMSTATE_UINT32(env.exception.syndrome, ARMCPU),
VMSTATE_UINT32(env.exception.fsr, ARMCPU),
VMSTATE_UINT64(env.exception.vaddress, ARMCPU),
+ VMSTATE_UINT64(env.vtimer, ARMCPU),
VMSTATE_TIMER_PTR(gt_timer[GTIMER_PHYS], ARMCPU),
VMSTATE_TIMER_PTR(gt_timer[GTIMER_VIRT], ARMCPU),
{
--
2.19.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,107 @@
From 1bffe1ae7a7b707c3a14ea2ccd00d3609d3ce4d8 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 17 Apr 2019 17:15:25 +0200
Subject: [PATCH] block: Fix AioContext switch for bs->drv == NULL
Even for block nodes with bs->drv == NULL, we can't just ignore a
bdrv_set_aio_context() call. Leaving the node in its old context can
mean that it's still in an iothread context in bdrv_close_all() during
shutdown, resulting in an attempted unlock of the AioContext lock which
we don't hold.
This is an example stack trace of a related crash:
#0 0x00007ffff59da57f in raise () at /lib64/libc.so.6
#1 0x00007ffff59c4895 in abort () at /lib64/libc.so.6
#2 0x0000555555b97b1e in error_exit (err=<optimized out>, msg=msg@entry=0x555555d386d0 <__func__.19059> "qemu_mutex_unlock_impl") at util/qemu-thread-posix.c:36
#3 0x0000555555b97f7f in qemu_mutex_unlock_impl (mutex=mutex@entry=0x5555568002f0, file=file@entry=0x555555d378df "util/async.c", line=line@entry=507) at util/qemu-thread-posix.c:97
#4 0x0000555555b92f55 in aio_context_release (ctx=ctx@entry=0x555556800290) at util/async.c:507
#5 0x0000555555b05cf8 in bdrv_prwv_co (child=child@entry=0x7fffc80012f0, offset=offset@entry=131072, qiov=qiov@entry=0x7fffffffd4f0, is_write=is_write@entry=true, flags=flags@entry=0)
at block/io.c:833
#6 0x0000555555b060a9 in bdrv_pwritev (qiov=0x7fffffffd4f0, offset=131072, child=0x7fffc80012f0) at block/io.c:990
#7 0x0000555555b060a9 in bdrv_pwrite (child=0x7fffc80012f0, offset=131072, buf=<optimized out>, bytes=<optimized out>) at block/io.c:990
#8 0x0000555555ae172b in qcow2_cache_entry_flush (bs=bs@entry=0x555556810680, c=c@entry=0x5555568cc740, i=i@entry=0) at block/qcow2-cache.c:51
#9 0x0000555555ae18dd in qcow2_cache_write (bs=bs@entry=0x555556810680, c=0x5555568cc740) at block/qcow2-cache.c:248
#10 0x0000555555ae15de in qcow2_cache_flush (bs=0x555556810680, c=<optimized out>) at block/qcow2-cache.c:259
#11 0x0000555555ae16b1 in qcow2_cache_flush_dependency (c=0x5555568a1700, c=0x5555568a1700, bs=0x555556810680) at block/qcow2-cache.c:194
#12 0x0000555555ae16b1 in qcow2_cache_entry_flush (bs=bs@entry=0x555556810680, c=c@entry=0x5555568a1700, i=i@entry=0) at block/qcow2-cache.c:194
#13 0x0000555555ae18dd in qcow2_cache_write (bs=bs@entry=0x555556810680, c=0x5555568a1700) at block/qcow2-cache.c:248
#14 0x0000555555ae15de in qcow2_cache_flush (bs=bs@entry=0x555556810680, c=<optimized out>) at block/qcow2-cache.c:259
#15 0x0000555555ad242c in qcow2_inactivate (bs=bs@entry=0x555556810680) at block/qcow2.c:2124
#16 0x0000555555ad2590 in qcow2_close (bs=0x555556810680) at block/qcow2.c:2153
#17 0x0000555555ab0c62 in bdrv_close (bs=0x555556810680) at block.c:3358
#18 0x0000555555ab0c62 in bdrv_delete (bs=0x555556810680) at block.c:3542
#19 0x0000555555ab0c62 in bdrv_unref (bs=0x555556810680) at block.c:4598
#20 0x0000555555af4d72 in blk_remove_bs (blk=blk@entry=0x5555568103d0) at block/block-backend.c:785
#21 0x0000555555af4dbb in blk_remove_all_bs () at block/block-backend.c:483
#22 0x0000555555aae02f in bdrv_close_all () at block.c:3412
#23 0x00005555557f9796 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4776
The reproducer I used is a qcow2 image on gluster volume, where the
virtual disk size (4 GB) is larger than the gluster volume size (64M),
so we can easily trigger an ENOSPC. This backend is assigned to a
virtio-blk device using an iothread, and then from the guest a
'dd if=/dev/zero of=/dev/vda bs=1G count=1' causes the VM to stop
because of an I/O error. qemu_gluster_co_flush_to_disk() sets
bs->drv = NULL on error, so when virtio-blk stops the dataplane, the
block nodes stay in the iothread AioContext. A 'quit' monitor command
issued from this paused state crashes the process.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1631227
Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
(cherry-picked from commit 1bffe1ae7a7b707c3a14ea2ccd00d3609d3ce4d8)
---
block.c | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/block.c b/block.c
index 16615bc876..9ae5c0ed2f 100644
--- a/block.c
+++ b/block.c
@@ -5672,10 +5672,6 @@ void bdrv_detach_aio_context(BlockDriverState *bs)
BdrvAioNotifier *baf, *baf_tmp;
BdrvChild *child;
- if (!bs->drv) {
- return;
- }
-
assert(!bs->walking_aio_notifiers);
bs->walking_aio_notifiers = true;
QLIST_FOREACH_SAFE(baf, &bs->aio_notifiers, list, baf_tmp) {
@@ -5690,7 +5686,7 @@ void bdrv_detach_aio_context(BlockDriverState *bs)
*/
bs->walking_aio_notifiers = false;
- if (bs->drv->bdrv_detach_aio_context) {
+ if (bs->drv && bs->drv->bdrv_detach_aio_context) {
bs->drv->bdrv_detach_aio_context(bs);
}
QLIST_FOREACH(child, &bs->children, next) {
@@ -5709,10 +5705,6 @@ void bdrv_attach_aio_context(BlockDriverState *bs,
BdrvAioNotifier *ban, *ban_tmp;
BdrvChild *child;
- if (!bs->drv) {
- return;
- }
-
if (bs->quiesce_counter) {
aio_disable_external(new_context);
}
@@ -5722,7 +5714,7 @@ void bdrv_attach_aio_context(BlockDriverState *bs,
QLIST_FOREACH(child, &bs->children, next) {
bdrv_attach_aio_context(child->bs, new_context);
}
- if (bs->drv->bdrv_attach_aio_context) {
+ if (bs->drv && bs->drv->bdrv_attach_aio_context) {
bs->drv->bdrv_attach_aio_context(bs, new_context);
}
--
2.19.1

View File

@ -0,0 +1,87 @@
From 9c3db310ff0b7473272ae8dce5e04e2f8a825390 Mon Sep 17 00:00:00 2001
From: Max Reitz <mreitz@redhat.com>
Date: Wed, 15 May 2019 06:15:40 +0200
Subject: [PATCH] block/file-posix: Unaligned O_DIRECT block-status
Currently, qemu crashes whenever someone queries the block status of an
unaligned image tail of an O_DIRECT image:
$ echo > foo
$ qemu-img map --image-opts driver=file,filename=foo,cache.direct=on
Offset Length Mapped to File
qemu-img: block/io.c:2093: bdrv_co_block_status: Assertion `*pnum &&
QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset'
failed.
This is because bdrv_co_block_status() checks that the result returned
by the driver's implementation is aligned to the request_alignment, but
file-posix can fail to do so, which is actually mentioned in a comment
there: "[...] possibly including a partial sector at EOF".
Fix this by rounding up those partial sectors.
There are two possible alternative fixes:
(1) We could refuse to open unaligned image files with O_DIRECT
altogether. That sounds reasonable until you realize that qcow2
does necessarily not fill up its metadata clusters, and that nobody
runs qemu-img create with O_DIRECT. Therefore, unpreallocated qcow2
files usually have an unaligned image tail.
(2) bdrv_co_block_status() could ignore unaligned tails. It actually
throws away everything past the EOF already, so that sounds
reasonable.
Unfortunately, the block layer knows file lengths only with a
granularity of BDRV_SECTOR_SIZE, so bdrv_co_block_status() usually
would have to guess whether its file length information is inexact
or whether the driver is broken.
Fixing what raw_co_block_status() returns is the safest thing to do.
There seems to be no other block driver that sets request_alignment and
does not make sure that it always returns aligned values.
Cc: qemu-stable@nongnu.org
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry-picked from commit 9c3db310ff0b7473272ae8dce5e04e2f8a825390)
---
block/file-posix.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/block/file-posix.c b/block/file-posix.c
index e09e15bbf8..d018429672 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -2488,6 +2488,8 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
off_t data = 0, hole = 0;
int ret;
+ assert(QEMU_IS_ALIGNED(offset | bytes, bs->bl.request_alignment));
+
ret = fd_open(bs);
if (ret < 0) {
return ret;
@@ -2513,6 +2515,20 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs,
/* On a data extent, compute bytes to the end of the extent,
* possibly including a partial sector at EOF. */
*pnum = MIN(bytes, hole - offset);
+
+ /*
+ * We are not allowed to return partial sectors, though, so
+ * round up if necessary.
+ */
+ if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) {
+ int64_t file_length = raw_getlength(bs);
+ if (file_length > 0) {
+ /* Ignore errors, this is just a safeguard */
+ assert(hole == file_length);
+ }
+ *pnum = ROUND_UP(*pnum, bs->bl.request_alignment);
+ }
+
ret = BDRV_BLOCK_DATA;
} else {
/* On a hole, compute bytes to the beginning of the next extent. */
--
2.19.1

1
bridge.conf Normal file
View File

@ -0,0 +1 @@
allow virbr0

View File

@ -0,0 +1,58 @@
From 4304d1de2c790ac75ed2f5984c4a3a2760c08fff Mon Sep 17 00:00:00 2001
From: Xu Yandong <xuyandong2@huawei.com>
Date: Mon, 23 Sep 2019 14:35:25 +0800
Subject: [PATCH] cpu: add Cortex-A72 processor kvm target support
The ARM Cortex-A72 is ARMv8-A micro-architecture,
add kvm target to ARM Cortex-A72 processor definition.
Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
target/arm/cpu64.c | 2 +-
target/arm/kvm-consts.h | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index e408f50d..afbfd1ec 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -212,6 +212,7 @@ static void aarch64_a72_initfn(Object *obj)
ARMCPU *cpu = ARM_CPU(obj);
cpu->dtb_compatible = "arm,cortex-a72";
+ cpu->kvm_target = QEMU_KVM_ARM_TARGET_GENERIC_V8;
set_feature(&cpu->env, ARM_FEATURE_V8);
set_feature(&cpu->env, ARM_FEATURE_VFP4);
set_feature(&cpu->env, ARM_FEATURE_NEON);
@@ -276,7 +277,6 @@ static void aarch64_kunpeng_t82_initfn(Object *obj)
cpu->id_aa64dfr0 = 0x110305408;
cpu->isar.id_aa64isar0 = 0x10211120;
cpu->isar.id_aa64mmfr0 = 0x101125;
- cpu->kvm_target = KVM_ARM_TARGET_GENERIC_V8;
}
static void cpu_max_get_sve_vq(Object *obj, Visitor *v, const char *name,
diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h
index aad28258..b7dac596 100644
--- a/target/arm/kvm-consts.h
+++ b/target/arm/kvm-consts.h
@@ -130,6 +130,8 @@ MISMATCH_CHECK(QEMU_PSCI_RET_DISABLED, PSCI_RET_DISABLED);
#define QEMU_KVM_ARM_TARGET_CORTEX_A57 2
#define QEMU_KVM_ARM_TARGET_XGENE_POTENZA 3
#define QEMU_KVM_ARM_TARGET_CORTEX_A53 4
+/* Generic ARM v8 target */
+#define QEMU_KVM_ARM_TARGET_GENERIC_V8 5
/* There's no kernel define for this: sentinel value which
* matches no KVM target value for either 64 or 32 bit
@@ -142,6 +144,7 @@ MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_FOUNDATION_V8, KVM_ARM_TARGET_FOUNDATION_V8);
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A57, KVM_ARM_TARGET_CORTEX_A57);
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_XGENE_POTENZA, KVM_ARM_TARGET_XGENE_POTENZA);
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A53, KVM_ARM_TARGET_CORTEX_A53);
+MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_GENERIC_V8, KVM_ARM_TARGET_GENERIC_V8);
#else
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A15, KVM_ARM_TARGET_CORTEX_A15);
MISMATCH_CHECK(QEMU_KVM_ARM_TARGET_CORTEX_A7, KVM_ARM_TARGET_CORTEX_A7);
--
2.23.0

View File

@ -0,0 +1,65 @@
From 70063948181062161a341a8738a53708d8ed0a0b Mon Sep 17 00:00:00 2001
From: Xu Yandong <xuyandong2@huawei.com>
Date: Wed, 28 Aug 2019 01:36:21 -0400
Subject: [PATCH] cpu: add Kunpeng-T82 cpu support
Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
---
hw/arm/virt.c | 1 +
target/arm/cpu64.c | 21 +++++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index f89757df..11468b72 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -179,6 +179,7 @@ static const char *valid_cpus[] = {
ARM_CPU_TYPE_NAME("cortex-a53"),
ARM_CPU_TYPE_NAME("cortex-a57"),
ARM_CPU_TYPE_NAME("cortex-a72"),
+ ARM_CPU_TYPE_NAME("Kunpeng-T82"),
ARM_CPU_TYPE_NAME("host"),
ARM_CPU_TYPE_NAME("max"),
};
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 228906f2..5581d5e1 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -258,6 +258,26 @@ static void aarch64_a72_initfn(Object *obj)
define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo);
}
+static void aarch64_kunpeng_t82_initfn(Object *obj)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+
+ /*
+ * Hisilicon Kunpeng-T82 CPU is based on cortex-a72,
+ * so first initialize cpu data as cortex-a72 CPU,
+ * and then update the special registers.
+ */
+ aarch64_a72_initfn(obj);
+
+ cpu->midr = 0x480fd010;
+ cpu->ctr = 0x84448004;
+ cpu->isar.id_aa64pfr0 = 0x11001111;
+ cpu->id_aa64dfr0 = 0x110305408;
+ cpu->isar.id_aa64isar0 = 0x10211120;
+ cpu->isar.id_aa64mmfr0 = 0x101125;
+ cpu->kvm_target = KVM_ARM_TARGET_GENERIC_V8;
+}
+
static void cpu_max_get_sve_vq(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
@@ -388,6 +408,7 @@ static const ARMCPUInfo aarch64_cpus[] = {
{ .name = "cortex-a57", .initfn = aarch64_a57_initfn },
{ .name = "cortex-a53", .initfn = aarch64_a53_initfn },
{ .name = "cortex-a72", .initfn = aarch64_a72_initfn },
+ { .name = "Kunpeng-T82", .initfn = aarch64_kunpeng_t82_initfn },
{ .name = "max", .initfn = aarch64_max_initfn },
{ .name = NULL }
};
--
2.19.1

View File

@ -0,0 +1,72 @@
From ba1ca232cfa2ca273c610beda40bee2143f11964 Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Tue, 3 Sep 2019 16:27:39 +0800
Subject: [PATCH] cpu: parse +/- feature to avoid failure
---
target/arm/cpu64.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 0d492877..6ce87ce0 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -30,6 +30,7 @@
#include "sysemu/kvm.h"
#include "kvm_arm.h"
#include "qapi/visitor.h"
+#include "hw/qdev-properties.h"
static inline void set_feature(CPUARMState *env, int feature)
{
@@ -455,10 +456,47 @@ static gchar *aarch64_gdb_arch_name(CPUState *cs)
return g_strdup("aarch64");
}
+/* Parse "+feature,-feature,feature=foo" CPU feature string
+ */
+static void arm_cpu_parse_featurestr(const char *typename, char *features,
+ Error **errp)
+{
+ char *featurestr;
+ char *val;
+ static bool cpu_globals_initialized;
+
+ if (cpu_globals_initialized) {
+ return;
+ }
+ cpu_globals_initialized = true;
+
+ featurestr = features ? strtok(features, ",") : NULL;
+ while (featurestr) {
+ val = strchr(featurestr, '=');
+ if (val) {
+ GlobalProperty *prop = g_new0(typeof(*prop), 1);
+ *val = 0;
+ val++;
+ prop->driver = typename;
+ prop->property = g_strdup(featurestr);
+ prop->value = g_strdup(val);
+ qdev_prop_register_global(prop);
+ } else if (featurestr[0] == '+' || featurestr[0] == '-') {
+ warn_report("Ignore %s feature\n", featurestr);
+ } else {
+ error_setg(errp, "Expected key=value format, found %s.",
+ featurestr);
+ return;
+ }
+ featurestr = strtok(NULL, ",");
+ }
+}
+
static void aarch64_cpu_class_init(ObjectClass *oc, void *data)
{
CPUClass *cc = CPU_CLASS(oc);
+ cc->parse_features = arm_cpu_parse_featurestr;
cc->cpu_exec_interrupt = arm_cpu_exec_interrupt;
cc->gdb_read_register = aarch64_cpu_gdb_read_register;
cc->gdb_write_register = aarch64_cpu_gdb_write_register;
--
2.19.1

View File

@ -0,0 +1,37 @@
From 754da86714d550c3f995f11a2587395081362e0a Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Wed, 17 Apr 2019 12:11:00 -0500
Subject: [PATCH] cutils: Fix size_to_str() on 32-bit platforms
When extracting a human-readable size formatter, we changed 'uint64_t
div' pre-patch to 'unsigned long div' post-patch. Which breaks on
32-bit platforms, resulting in 'inf' instead of intended values larger
than 999GB.
Fixes: 22951aaa
CC: qemu-stable@nongnu.org
Reported-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry-picked from commit 754da86714d550c3f995f11a2587395081362e0a)
---
util/cutils.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/util/cutils.c b/util/cutils.c
index e098debdc0..d682c90901 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -825,7 +825,7 @@ const char *qemu_ether_ntoa(const MACAddr *mac)
char *size_to_str(uint64_t val)
{
static const char *suffixes[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" };
- unsigned long div;
+ uint64_t div;
int i;
/*
--
2.19.1

View File

@ -0,0 +1,35 @@
From 901ac0dee4b17890db815d143a8efeeac5d105f7 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Wed, 21 Aug 2019 10:53:19 +0200
Subject: [PATCH 1/5] ehci: fix queue->dev null ptr dereference
In case we don't have a device for an active queue, just skip
processing the queue (same we do for inactive queues) and log
a guest bug.
Reported-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Tested-by: Guenter Roeck <linux@roeck-us.net>
Message-id: 20190821085319.13711-1-kraxel@redhat.com
(cherry-picked from commit 1be344b7ad25d572dadeee46d80f0103354352b2)
---
hw/usb/hcd-ehci.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 62dab05..5f089f3 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1834,6 +1834,9 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
ehci_set_state(q->ehci, q->async, EST_EXECUTING);
break;
}
+ } else if (q->dev == NULL) {
+ ehci_trace_guest_bug(q->ehci, "no device attached to queue");
+ ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
} else {
p = ehci_alloc_packet(q);
p->qtdaddr = q->qtdaddr;
--
1.8.3.1

View File

@ -0,0 +1,124 @@
From 56deb8f0db72858985ba077cb0f678f2dbc13bba Mon Sep 17 00:00:00 2001
From: Greg Kurz <groug@kaod.org>
Date: Mon, 5 Aug 2019 15:56:58 +0800
Subject: [PATCH] hw: Nuke hw_compat_4_0_1 and pc_compat_4_0_1
Commit c87759ce876a fixed a regression affecting pc-q35 machines by
introducing a new pc-q35-4.0.1 machine version to be used instead
of pc-q35-4.0. The only purpose was to revert the default behaviour
of not using split irqchip, but the change also introduced the usual
hw_compat and pc_compat bits, and wired them for pc-q35 only.
This raises questions when it comes to add new compat properties for
4.0* machine versions of any architecture. Where to add them ? In
4.0, 4.0.1 or both ? Error prone. Another possibility would be to teach
all other architectures about 4.0.1. This solution isn't satisfying,
especially since this is a pc-q35 specific issue.
It turns out that the split irqchip default is handled in the machine
option function and doesn't involve compat lists at all.
Drop all the 4.0.1 compat lists and use the 4.0 ones instead in the 4.0.1
machine option function.
Move the compat props that were added to the 4.0.1 since c87759ce876a to
4.0.
Even if only hw_compat_4_0_1 had an impact on other architectures,
drop pc_compat_4_0_1 as well for consistency.
Fixes: c87759ce876a "q35: Revert to kernel irqchip"
Suggested-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <156051774276.244890.8660277280145466396.stgit@bahia.lan>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from commit 8e8cbed09ad9d577955691b4c061b61b602406d1)
---
hw/core/machine.c | 3 ---
hw/i386/pc.c | 3 ---
hw/i386/pc_q35.c | 9 +++++++--
include/hw/boards.h | 3 ---
include/hw/i386/pc.h | 3 ---
5 files changed, 7 insertions(+), 14 deletions(-)
diff --git a/hw/core/machine.c b/hw/core/machine.c
index e41e6698..5d046a43 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -24,9 +24,6 @@
#include "hw/pci/pci.h"
#include "hw/mem/nvdimm.h"
-GlobalProperty hw_compat_4_0_1[] = {};
-const size_t hw_compat_4_0_1_len = G_N_ELEMENTS(hw_compat_4_0_1);
-
GlobalProperty hw_compat_4_0[] = {};
const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index b5311e7e..d98b737b 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -115,9 +115,6 @@ struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
/* Physical Address of PVH entry point read from kernel ELF NOTE */
static size_t pvh_start_addr;
-GlobalProperty pc_compat_4_0_1[] = {};
-const size_t pc_compat_4_0_1_len = G_N_ELEMENTS(pc_compat_4_0_1);
-
GlobalProperty pc_compat_4_0[] = {};
const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index dcddc646..e3498a45 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -378,8 +378,13 @@ static void pc_q35_4_0_1_machine_options(MachineClass *m)
{
pc_q35_4_1_machine_options(m);
m->alias = NULL;
- compat_props_add(m->compat_props, hw_compat_4_0_1, hw_compat_4_0_1_len);
- compat_props_add(m->compat_props, pc_compat_4_0_1, pc_compat_4_0_1_len);
+ /*
+ * This is the default machine for the 4.0-stable branch. It is basically
+ * a 4.0 that doesn't use split irqchip by default. It MUST hence apply the
+ * 4.0 compat props.
+ */
+ compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len);
+ compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
}
DEFINE_Q35_MACHINE(v4_0_1, "pc-q35-4.0.1", NULL,
diff --git a/include/hw/boards.h b/include/hw/boards.h
index ad3950d3..fe1885cb 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -293,9 +293,6 @@ struct MachineState {
} \
type_init(machine_initfn##_register_types)
-extern GlobalProperty hw_compat_4_0_1[];
-extern const size_t hw_compat_4_0_1_len;
-
extern GlobalProperty hw_compat_4_0[];
extern const size_t hw_compat_4_0_len;
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 5d563624..43df7230 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -293,9 +293,6 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
int e820_get_num_entries(void);
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
-extern GlobalProperty pc_compat_4_0_1[];
-extern const size_t pc_compat_4_0_1_len;
-
extern GlobalProperty pc_compat_4_0[];
extern const size_t pc_compat_4_0_len;
--
2.19.1

View File

@ -0,0 +1,232 @@
From 9bf2650bc3aab126b85c034bf86e27d564f9a1aa Mon Sep 17 00:00:00 2001
From: Cornelia Huck <cohuck@redhat.com>
Date: Thu, 11 Apr 2019 12:20:25 +0200
Subject: [PATCH] hw: add compat machines for 4.1
Add 4.1 machine types for arm/i440fx/q35/s390x/spapr.
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20190411102025.22559-1-cohuck@redhat.com>
Acked-by: Greg Kurz <groug@kaod.org>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
(cherry-picked from commit 9bf2650bc3aab126b85c034bf86e27d564f9a1aa)
---
hw/arm/virt.c | 9 ++++++++-
hw/core/machine.c | 3 +++
hw/i386/pc.c | 3 +++
hw/i386/pc_piix.c | 14 +++++++++++++-
hw/i386/pc_q35.c | 13 ++++++++++++-
hw/ppc/spapr.c | 15 +++++++++++++--
hw/s390x/s390-virtio-ccw.c | 14 +++++++++++++-
include/hw/boards.h | 3 +++
include/hw/i386/pc.h | 3 +++
9 files changed, 71 insertions(+), 6 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index ce2664a30b..16ba67f7a7 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1978,10 +1978,17 @@ static void machvirt_machine_init(void)
}
type_init(machvirt_machine_init);
+static void virt_machine_4_1_options(MachineClass *mc)
+{
+}
+DEFINE_VIRT_MACHINE_AS_LATEST(4, 1)
+
static void virt_machine_4_0_options(MachineClass *mc)
{
+ virt_machine_4_1_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
}
-DEFINE_VIRT_MACHINE_AS_LATEST(4, 0)
+DEFINE_VIRT_MACHINE(4, 0)
static void virt_machine_3_1_options(MachineClass *mc)
{
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 743fef2898..5d046a43e3 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -24,6 +24,9 @@
#include "hw/pci/pci.h"
#include "hw/mem/nvdimm.h"
+GlobalProperty hw_compat_4_0[] = {};
+const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);
+
GlobalProperty hw_compat_3_1[] = {
{ "pcie-root-port", "x-speed", "2_5" },
{ "pcie-root-port", "x-width", "1" },
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index f2c15bf1f2..d98b737b8f 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -115,6 +115,9 @@ struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
/* Physical Address of PVH entry point read from kernel ELF NOTE */
static size_t pvh_start_addr;
+GlobalProperty pc_compat_4_0[] = {};
+const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0);
+
GlobalProperty pc_compat_3_1[] = {
{ "intel-iommu", "dma-drain", "off" },
{ "Opteron_G3" "-" TYPE_X86_CPU, "rdtscp", "off" },
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 8ad8e885c6..2a7700b564 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -428,13 +428,25 @@ static void pc_i440fx_machine_options(MachineClass *m)
machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE);
}
-static void pc_i440fx_4_0_machine_options(MachineClass *m)
+static void pc_i440fx_4_1_machine_options(MachineClass *m)
{
pc_i440fx_machine_options(m);
m->alias = "pc";
m->is_default = 1;
}
+DEFINE_I440FX_MACHINE(v4_1, "pc-i440fx-4.1", NULL,
+ pc_i440fx_4_1_machine_options);
+
+static void pc_i440fx_4_0_machine_options(MachineClass *m)
+{
+ pc_i440fx_4_1_machine_options(m);
+ m->alias = NULL;
+ m->is_default = 0;
+ compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len);
+ compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
+}
+
DEFINE_I440FX_MACHINE(v4_0, "pc-i440fx-4.0", NULL,
pc_i440fx_4_0_machine_options);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 372c6b73be..37dd350511 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -365,12 +365,23 @@ static void pc_q35_machine_options(MachineClass *m)
m->max_cpus = 288;
}
-static void pc_q35_4_0_machine_options(MachineClass *m)
+static void pc_q35_4_1_machine_options(MachineClass *m)
{
pc_q35_machine_options(m);
m->alias = "q35";
}
+DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL,
+ pc_q35_4_1_machine_options);
+
+static void pc_q35_4_0_machine_options(MachineClass *m)
+{
+ pc_q35_4_1_machine_options(m);
+ m->alias = NULL;
+ compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len);
+ compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
+}
+
DEFINE_Q35_MACHINE(v4_0, "pc-q35-4.0", NULL,
pc_q35_4_0_machine_options);
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index b52b82d298..8438741ec2 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4344,15 +4344,26 @@ static const TypeInfo spapr_machine_info = {
} \
type_init(spapr_machine_register_##suffix)
+/*
+ * pseries-4.1
+ */
+static void spapr_machine_4_1_class_options(MachineClass *mc)
+{
+ /* Defaults for the latest behaviour inherited from the base class */
+}
+
+DEFINE_SPAPR_MACHINE(4_1, "4.1", true);
+
/*
* pseries-4.0
*/
static void spapr_machine_4_0_class_options(MachineClass *mc)
{
- /* Defaults for the latest behaviour inherited from the base class */
+ spapr_machine_4_1_class_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
}
-DEFINE_SPAPR_MACHINE(4_0, "4.0", true);
+DEFINE_SPAPR_MACHINE(4_0, "4.0", false);
/*
* pseries-3.1
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index d11069b860..02470e78c7 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -646,14 +646,26 @@ bool css_migration_enabled(void)
} \
type_init(ccw_machine_register_##suffix)
+static void ccw_machine_4_1_instance_options(MachineState *machine)
+{
+}
+
+static void ccw_machine_4_1_class_options(MachineClass *mc)
+{
+}
+DEFINE_CCW_MACHINE(4_1, "4.1", true);
+
static void ccw_machine_4_0_instance_options(MachineState *machine)
{
+ ccw_machine_4_1_instance_options(machine);
}
static void ccw_machine_4_0_class_options(MachineClass *mc)
{
+ ccw_machine_4_1_class_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
}
-DEFINE_CCW_MACHINE(4_0, "4.0", true);
+DEFINE_CCW_MACHINE(4_0, "4.0", false);
static void ccw_machine_3_1_instance_options(MachineState *machine)
{
diff --git a/include/hw/boards.h b/include/hw/boards.h
index e231860666..fe1885cbff 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -293,6 +293,9 @@ struct MachineState {
} \
type_init(machine_initfn##_register_types)
+extern GlobalProperty hw_compat_4_0[];
+extern const size_t hw_compat_4_0_len;
+
extern GlobalProperty hw_compat_3_1[];
extern const size_t hw_compat_3_1_len;
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index ca65ef18af..43df7230a2 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -293,6 +293,9 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
int e820_get_num_entries(void);
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
+extern GlobalProperty pc_compat_4_0[];
+extern const size_t pc_compat_4_0_len;
+
extern GlobalProperty pc_compat_3_1[];
extern const size_t pc_compat_3_1_len;
--
2.19.1

View File

@ -0,0 +1,606 @@
From 773b25c55c7428b64d21b23a6b08fc629a665ca5 Mon Sep 17 00:00:00 2001
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
Date: Mon, 29 Jul 2019 09:54:43 +0800
Subject: [PATCH] hw/arm: expose host CPU frequency info to guest
On ARM64, CPU frequency is fetched by ACPI CPPC, so we add virtual
CPPC registers and ACPI _CPC objects.
The default frequency is set to the nominal frequency of Hi1616, which
will not support CPPC in future. On Hi1620 we are fetching the value
from Host CPPC sys file.
All performance data are set to the same value for we don't support
guest initiating performance scaling.
We don't emulate performance counters and simply return 1 for all
counter readings, and guest Linux should fall back to use the desired
performance value as the current performance.
Signed-off-by: Heyi Guo <guoheyi@huawei.com>
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
---
default-configs/aarch64-softmmu.mak | 1 +
hw/acpi/Makefile.objs | 1 +
hw/acpi/aml-build.c | 22 +++
hw/acpi/cpufreq.c | 278 ++++++++++++++++++++++++++++
hw/arm/virt-acpi-build.c | 78 +++++++-
hw/arm/virt.c | 13 ++
hw/char/Kconfig | 4 +
include/hw/acpi/acpi-defs.h | 38 ++++
include/hw/acpi/aml-build.h | 3 +
include/hw/arm/virt.h | 1 +
10 files changed, 437 insertions(+), 2 deletions(-)
create mode 100644 hw/acpi/cpufreq.c
diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
index 4ea9add0..37399c14 100644
--- a/default-configs/aarch64-softmmu.mak
+++ b/default-configs/aarch64-softmmu.mak
@@ -10,3 +10,4 @@ CONFIG_XLNX_ZYNQMP=y
CONFIG_XLNX_ZYNQMP_ARM=y
CONFIG_XLNX_VERSAL=y
CONFIG_ARM_SMMUV3=y
+CONFIG_CPUFREQ=y
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index 2d46e378..60979db9 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -12,6 +12,7 @@ common-obj-y += acpi_interface.o
common-obj-y += bios-linker-loader.o
common-obj-y += aml-build.o
common-obj-$(CONFIG_TPM) += tpm.o
+common-obj-$(CONFIG_CPUFREQ) += cpufreq.o
common-obj-$(CONFIG_IPMI) += ipmi.o
common-obj-$(call lnot,$(CONFIG_IPMI)) += ipmi-stub.o
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 555c24f2..73f97751 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1369,6 +1369,28 @@ Aml *aml_sleep(uint64_t msec)
return var;
}
+/* ACPI 5.0b: 6.4.3.7 Generic Register Descriptor */
+Aml *aml_generic_register(AmlRegionSpace rs, uint8_t reg_width,
+ uint8_t reg_offset, AmlAccessType type, uint64_t addr)
+{
+ int i;
+ Aml *var = aml_alloc();
+ build_append_byte(var->buf, 0x82); /* Generic Register Descriptor */
+ build_append_byte(var->buf, 0x0C); /* Length, bits[7:0] value = 0x0C */
+ build_append_byte(var->buf, 0); /* Length, bits[15:8] value = 0 */
+ build_append_byte(var->buf, rs); /* Address Space ID */
+ build_append_byte(var->buf, reg_width); /* Register Bit Width */
+ build_append_byte(var->buf, reg_offset); /* Register Bit Offset */
+ build_append_byte(var->buf, type); /* Access Size */
+
+ /* Register address */
+ for (i = 0; i < 8; i++) {
+ build_append_byte(var->buf, extract64(addr, i * 8, 8));
+ }
+
+ return var;
+}
+
static uint8_t Hex2Byte(const char *src)
{
int hi, lo;
diff --git a/hw/acpi/cpufreq.c b/hw/acpi/cpufreq.c
new file mode 100644
index 00000000..c123a22b
--- /dev/null
+++ b/hw/acpi/cpufreq.c
@@ -0,0 +1,278 @@
+/*
+ * ACPI CPPC register device
+ *
+ * Support for showing CPU frequency in guest OS.
+ *
+ * Copyright (c) 2019 HUAWEI TECHNOLOGIES CO.,LTD.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "chardev/char.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "qemu/option.h"
+#include "sysemu/sysemu.h"
+#include "hw/acpi/acpi-defs.h"
+#include "qemu/cutils.h"
+#include "qemu/error-report.h"
+
+#define TYPE_CPUFREQ "cpufreq"
+#define CPUFREQ(obj) OBJECT_CHECK(CpuhzState, (obj), TYPE_CPUFREQ)
+#define NOMINAL_FREQ_FILE "/sys/devices/system/cpu/cpu0/acpi_cppc/nominal_freq"
+#define CPU_MAX_FREQ_FILE "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"
+#define HZ_MAX_LENGTH 1024
+#define MAX_SUPPORT_SPACE 0x10000
+
+/*
+ * Since Hi1616 will not support CPPC, we simply use its nominal frequency as
+ * the default.
+ */
+#define DEFAULT_HZ 2400
+
+
+int cppc_regs_offset[CPPC_REG_COUNT] = {
+ [HIGHEST_PERF] = 0,
+ [NOMINAL_PERF] = 4,
+ [LOW_NON_LINEAR_PERF] = 8,
+ [LOWEST_PERF] = 12,
+ [GUARANTEED_PERF] = 16,
+ [DESIRED_PERF] = 20,
+ [MIN_PERF] = -1,
+ [MAX_PERF] = -1,
+ [PERF_REDUC_TOLERANCE] = -1,
+ [TIME_WINDOW] = -1,
+ [CTR_WRAP_TIME] = -1,
+ [REFERENCE_CTR] = 24,
+ [DELIVERED_CTR] = 32,
+ [PERF_LIMITED] = 40,
+ [ENABLE] = -1,
+ [AUTO_SEL_ENABLE] = -1,
+ [AUTO_ACT_WINDOW] = -1,
+ [ENERGY_PERF] = -1,
+ [REFERENCE_PERF] = -1,
+ [LOWEST_FREQ] = 44,
+ [NOMINAL_FREQ] = 48,
+};
+
+typedef struct CpuhzState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ uint32_t HighestPerformance;
+ uint32_t NominalPerformance;
+ uint32_t LowestNonlinearPerformance;
+ uint32_t LowestPerformance;
+ uint32_t GuaranteedPerformance;
+ uint32_t DesiredPerformance;
+ uint64_t ReferencePerformanceCounter;
+ uint64_t DeliveredPerformanceCounter;
+ uint32_t PerformanceLimited;
+ uint32_t LowestFreq;
+ uint32_t NominalFreq;
+ uint32_t reg_size;
+} CpuhzState;
+
+
+static uint64_t cpufreq_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+ CpuhzState *s = (CpuhzState *)opaque;
+ uint64_t r;
+ uint64_t n;
+
+ if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) {
+ warn_report("cpufreq_read: offset 0x%lx out of range", offset);
+ return 0;
+ }
+
+ n = offset % CPPC_REG_PER_CPU_STRIDE;
+ switch (n) {
+ case 0:
+ r = s->HighestPerformance;
+ break;
+ case 4:
+ r = s->NominalPerformance;
+ break;
+ case 8:
+ r = s->LowestNonlinearPerformance;
+ break;
+ case 12:
+ r = s->LowestPerformance;
+ break;
+ case 16:
+ r = s->GuaranteedPerformance;
+ break;
+ case 20:
+ r = s->DesiredPerformance;
+ break;
+ /*
+ * We don't have real counters and it is hard to emulate, so always set the
+ * counter value to 1 to rely on Linux to use the DesiredPerformance value
+ * directly.
+ */
+ case 24:
+ r = s->ReferencePerformanceCounter;
+ break;
+ /*
+ * Guest may still access the register by 32bit; add the process to
+ * eliminate unnecessary warnings
+ */
+ case 28:
+ r = s->ReferencePerformanceCounter >> 32;
+ break;
+ case 32:
+ r = s->DeliveredPerformanceCounter;
+ break;
+ case 36:
+ r = s->DeliveredPerformanceCounter >> 32;
+ break;
+
+ case 40:
+ r = s->PerformanceLimited;
+ break;
+ case 44:
+ r = s->LowestFreq;
+ break;
+ case 48:
+ r = s->NominalFreq;
+ break;
+ default:
+ error_printf("cpufreq_read: Bad offset 0x%lx\n", offset);
+ r = 0;
+ break;
+ }
+ return r;
+}
+
+
+static void cpufreq_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ uint64_t n;
+
+ if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) {
+ error_printf("cpufreq_write: offset 0x%lx out of range", offset);
+ return;
+ }
+
+ n = offset % CPPC_REG_PER_CPU_STRIDE;
+
+ switch (n) {
+ case 20:
+ break;
+ default:
+ error_printf("cpufreq_write: Bad offset 0x%lx\n", offset);
+ }
+}
+
+static uint32_t CPPC_Read(const char *hostpath)
+{
+ int fd;
+ char buffer[HZ_MAX_LENGTH] = { 0 };
+ uint64_t hz;
+ int len;
+ const char *endptr = NULL;
+ int ret;
+
+ fd = qemu_open(hostpath, O_RDONLY);
+ if (fd < 0) {
+ return 0;
+ }
+
+ len = read(fd, buffer, HZ_MAX_LENGTH);
+ qemu_close(fd);
+ if (len <= 0) {
+ return 0;
+ }
+ ret = qemu_strtoul(buffer, &endptr, 0, &hz);
+ if (ret < 0) {
+ return 0;
+ }
+ return (uint32_t)hz;
+}
+
+static const MemoryRegionOps cpufreq_ops = {
+ .read = cpufreq_read,
+ .write = cpufreq_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void hz_init(CpuhzState *s)
+{
+ uint32_t hz;
+
+ hz = CPPC_Read(NOMINAL_FREQ_FILE);
+ if (hz == 0) {
+ hz = CPPC_Read(CPU_MAX_FREQ_FILE);
+ if (hz == 0) {
+ hz = DEFAULT_HZ;
+ } else {
+ /* Value in CpuMaxFrequency is in KHz unit; convert to MHz */
+ hz = hz / 1000;
+ }
+ }
+
+ s->HighestPerformance = hz;
+ s->NominalPerformance = hz;
+ s->LowestNonlinearPerformance = hz;
+ s->LowestPerformance = hz;
+ s->GuaranteedPerformance = hz;
+ s->DesiredPerformance = hz;
+ s->ReferencePerformanceCounter = 1;
+ s->DeliveredPerformanceCounter = 1;
+ s->PerformanceLimited = 0;
+ s->LowestFreq = hz;
+ s->NominalFreq = hz;
+}
+
+static void cpufreq_init(Object *obj)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ CpuhzState *s = CPUFREQ(obj);
+
+ s->reg_size = smp_cpus * CPPC_REG_PER_CPU_STRIDE;
+ if (s->reg_size > MAX_SUPPORT_SPACE) {
+ error_report("Required space 0x%x excesses the max support 0x%x",
+ s->reg_size, MAX_SUPPORT_SPACE);
+ goto err_end;
+ }
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &cpufreq_ops, s, "cpufreq",
+ s->reg_size);
+ sysbus_init_mmio(sbd, &s->iomem);
+ hz_init(s);
+ return;
+
+err_end:
+ /* Set desired perf register offset to -1 to indicate no support for CPPC */
+ cppc_regs_offset[DESIRED_PERF] = -1;
+}
+
+static const TypeInfo cpufreq_arm_info = {
+ .name = TYPE_CPUFREQ,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(CpuhzState),
+ .instance_init = cpufreq_init,
+};
+
+static void cpufreq_register_types(void)
+{
+ type_register_static(&cpufreq_arm_info);
+}
+
+type_init(cpufreq_register_types)
+
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index bf9c0bc2..33a8e2e3 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -45,11 +45,73 @@
#include "hw/arm/virt.h"
#include "sysemu/numa.h"
#include "kvm_arm.h"
+#include "hw/acpi/acpi-defs.h"
#define ARM_SPI_BASE 32
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
-static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
+static void acpi_dsdt_add_psd(Aml *dev, int cpus)
+{
+ Aml *pkg;
+ Aml *sub;
+
+ sub = aml_package(5);
+ aml_append(sub, aml_int(5));
+ aml_append(sub, aml_int(0));
+ /* Assume all vCPUs belong to the same domain */
+ aml_append(sub, aml_int(0));
+ /* SW_ANY: OSPM coordinate, initiate on any processor */
+ aml_append(sub, aml_int(0xFD));
+ aml_append(sub, aml_int(cpus));
+
+ pkg = aml_package(1);
+ aml_append(pkg, sub);
+
+ aml_append(dev, aml_name_decl("_PSD", pkg));
+}
+
+static void acpi_dsdt_add_cppc(Aml *dev, uint64_t cpu_base, int *regs_offset)
+{
+ Aml *cpc;
+ int i;
+
+ /* Use version 3 of CPPC table from ACPI 6.3 */
+ cpc = aml_package(23);
+ aml_append(cpc, aml_int(23));
+ aml_append(cpc, aml_int(3));
+
+ for (i = 0; i < CPPC_REG_COUNT; i++) {
+ Aml *res;
+ uint8_t reg_width;
+ uint8_t acc_type;
+ uint64_t addr;
+
+ if (regs_offset[i] == -1) {
+ reg_width = 0;
+ acc_type = AML_ANY_ACC;
+ addr = 0;
+ } else {
+ addr = cpu_base + regs_offset[i];
+ if (i == REFERENCE_CTR || i == DELIVERED_CTR) {
+ reg_width = 64;
+ acc_type = AML_QWORD_ACC;
+ } else {
+ reg_width = 32;
+ acc_type = AML_DWORD_ACC;
+ }
+ }
+
+ res = aml_resource_template();
+ aml_append(res, aml_generic_register(AML_SYSTEM_MEMORY, reg_width, 0,
+ acc_type, addr));
+ aml_append(cpc, res);
+ }
+
+ aml_append(dev, aml_name_decl("_CPC", cpc));
+}
+
+static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus,
+ const MemMapEntry *cppc_memmap)
{
uint16_t i;
@@ -57,6 +119,18 @@ static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
Aml *dev = aml_device("C%.03X", i);
aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007")));
aml_append(dev, aml_name_decl("_UID", aml_int(i)));
+
+ /*
+ * Append _CPC and _PSD to support CPU frequence show
+ * Check CPPC available by DESIRED_PERF register
+ */
+ if (cppc_regs_offset[DESIRED_PERF] != -1) {
+ acpi_dsdt_add_cppc(dev,
+ cppc_memmap->base + i * CPPC_REG_PER_CPU_STRIDE,
+ cppc_regs_offset);
+ acpi_dsdt_add_psd(dev, smp_cpus);
+ }
+
aml_append(scope, dev);
}
}
@@ -740,7 +814,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
* the RTC ACPI device at all when using UEFI.
*/
scope = aml_scope("\\_SB");
- acpi_dsdt_add_cpus(scope, vms->smp_cpus);
+ acpi_dsdt_add_cpus(scope, vms->smp_cpus, &memmap[VIRT_CPUFREQ]);
acpi_dsdt_add_uart(scope, &memmap[VIRT_UART],
(irqmap[VIRT_UART] + ARM_SPI_BASE));
acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index ce2664a3..ec6f00ab 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -132,6 +132,7 @@ static const MemMapEntry base_memmap[] = {
[VIRT_SECURE_UART] = { 0x09040000, 0x00001000 },
[VIRT_SMMU] = { 0x09050000, 0x00020000 },
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
+ [VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 },
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
[VIRT_SECURE_MEM] = { 0x0e000000, 0x01000000 },
@@ -725,6 +726,16 @@ static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart,
g_free(nodename);
}
+static void create_cpufreq(const VirtMachineState *vms, MemoryRegion *mem)
+{
+ hwaddr base = vms->memmap[VIRT_CPUFREQ].base;
+ DeviceState *dev = qdev_create(NULL, "cpufreq");
+ SysBusDevice *s = SYS_BUS_DEVICE(dev);
+
+ qdev_init_nofail(dev);
+ memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0));
+}
+
static void create_rtc(const VirtMachineState *vms, qemu_irq *pic)
{
char *nodename;
@@ -1618,6 +1629,8 @@ static void machvirt_init(MachineState *machine)
create_uart(vms, pic, VIRT_UART, sysmem, serial_hd(0));
+ create_cpufreq(vms, sysmem);
+
if (vms->secure) {
create_secure_ram(vms, secure_sysmem);
create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
diff --git a/hw/char/Kconfig b/hw/char/Kconfig
index 6360c9ff..8cc3ae2a 100644
--- a/hw/char/Kconfig
+++ b/hw/char/Kconfig
@@ -40,3 +40,7 @@ config SCLPCONSOLE
config TERMINAL3270
bool
+
+config CPUFREQ
+ bool
+ default y
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index f9aa4bd3..b4899a32 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -652,4 +652,42 @@ struct AcpiIortRC {
} QEMU_PACKED;
typedef struct AcpiIortRC AcpiIortRC;
+/*
+ * CPPC register definition from kernel header
+ * include/acpi/cppc_acpi.h
+ * The last element is newly added for easy use
+ */
+enum cppc_regs {
+ HIGHEST_PERF,
+ NOMINAL_PERF,
+ LOW_NON_LINEAR_PERF,
+ LOWEST_PERF,
+ GUARANTEED_PERF,
+ DESIRED_PERF,
+ MIN_PERF,
+ MAX_PERF,
+ PERF_REDUC_TOLERANCE,
+ TIME_WINDOW,
+ CTR_WRAP_TIME,
+ REFERENCE_CTR,
+ DELIVERED_CTR,
+ PERF_LIMITED,
+ ENABLE,
+ AUTO_SEL_ENABLE,
+ AUTO_ACT_WINDOW,
+ ENERGY_PERF,
+ REFERENCE_PERF,
+ LOWEST_FREQ,
+ NOMINAL_FREQ,
+ CPPC_REG_COUNT,
+};
+
+#define CPPC_REG_PER_CPU_STRIDE 0x40
+
+/*
+ * Offset for each CPPC register; -1 for unavailable
+ * The whole register space is unavailable if desired perf offset is -1.
+ */
+extern int cppc_regs_offset[CPPC_REG_COUNT];
+
#endif
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 1a563ad7..375335ab 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -347,6 +347,9 @@ Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz,
uint8_t channel);
Aml *aml_sleep(uint64_t msec);
+Aml *aml_generic_register(AmlRegionSpace rs, uint8_t reg_width,
+ uint8_t reg_offset, AmlAccessType type,
+ uint64_t addr);
/* Block AML object primitives */
Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 507517c6..8465f9bd 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -66,6 +66,7 @@ enum {
VIRT_GIC_REDIST,
VIRT_SMMU,
VIRT_UART,
+ VIRT_CPUFREQ,
VIRT_MMIO,
VIRT_RTC,
VIRT_FW_CFG,
--
2.19.1

View File

@ -0,0 +1,224 @@
From 123b4eb3cb7b9b4e3e0705a9b5f974b37d3b8431 Mon Sep 17 00:00:00 2001
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
Date: Mon, 5 Aug 2019 15:04:31 +0800
Subject: [PATCH] hw/arm/virt: Introduce cpu topology support
Add topology support for guest vcpu by cpu-map in dtb when the guest is booted
with dtb, and by pptt table when the guest is booted with acpi.
Signed-off-by: Honghao <honghao5@huawei.com>
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
(picked-from https://patchwork.ozlabs.org/cover/939301/ which is pushed by
Andrew Jones <drjones@redhat.com>)
---
device_tree.c | 32 +++++++++++++++++++++++
hw/acpi/aml-build.c | 50 ++++++++++++++++++++++++++++++++++++
hw/arm/virt-acpi-build.c | 4 +++
hw/arm/virt.c | 29 +++++++++++++++++++++
include/hw/acpi/aml-build.h | 2 ++
include/sysemu/device_tree.h | 1 +
6 files changed, 118 insertions(+)
diff --git a/device_tree.c b/device_tree.c
index f8b46b3c..03906a14 100644
--- a/device_tree.c
+++ b/device_tree.c
@@ -524,6 +524,38 @@ int qemu_fdt_add_subnode(void *fdt, const char *name)
return retval;
}
+/**
+ * qemu_fdt_add_path
+ * @fdt: Flattened Device Tree
+ * @path: Flattened Device Tree node path
+ *
+ * qemu_fdt_add_path works like qemu_fdt_add_subnode, except it
+ * also recursively adds any missing parent nodes.
+ */
+int qemu_fdt_add_path(void *fdt, const char *path)
+{
+ char *parent;
+ int offset;
+
+ offset = fdt_path_offset(fdt, path);
+ if (offset < 0 && offset != -FDT_ERR_NOTFOUND) {
+ error_report("%s Couldn't find node %s: %s", __func__, path,
+ fdt_strerror(offset));
+ exit(1);
+ }
+
+ if (offset != -FDT_ERR_NOTFOUND) {
+ return offset;
+ }
+
+ parent = g_strdup(path);
+ strrchr(parent, '/')[0] = '\0';
+ qemu_fdt_add_path(fdt, parent);
+ g_free(parent);
+
+ return qemu_fdt_add_subnode(fdt, path);
+}
+
void qemu_fdt_dumpdtb(void *fdt, int size)
{
const char *dumpdtb = qemu_opt_get(qemu_get_machine_opts(), "dumpdtb");
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 73f97751..9d39ad10 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -25,6 +25,7 @@
#include "qemu/bswap.h"
#include "qemu/bitops.h"
#include "sysemu/numa.h"
+#include "sysemu/cpus.h"
static GArray *build_alloc_array(void)
{
@@ -51,6 +52,55 @@ static void build_append_array(GArray *array, GArray *val)
g_array_append_vals(array, val->data, val->len);
}
+/*
+ * ACPI 6.2 Processor Properties Topology Table (PPTT)
+ */
+static void build_cpu_hierarchy(GArray *tbl, uint32_t flags,
+ uint32_t parent, uint32_t id)
+{
+ build_append_byte(tbl, 0); /* Type 0 - processor */
+ build_append_byte(tbl, 20); /* Length, no private resources */
+ build_append_int_noprefix(tbl, 0, 2); /* Reserved */
+ build_append_int_noprefix(tbl, flags, 4);
+ build_append_int_noprefix(tbl, parent, 4);
+ build_append_int_noprefix(tbl, id, 4);
+ build_append_int_noprefix(tbl, 0, 4); /* Num private resources */
+}
+
+void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus)
+{
+ int pptt_start = table_data->len;
+ int uid = 0, cpus = 0, socket;
+
+ acpi_data_push(table_data, sizeof(AcpiTableHeader));
+
+ for (socket = 0; cpus < possible_cpus; socket++) {
+ uint32_t socket_offset = table_data->len - pptt_start;
+ int core;
+
+ build_cpu_hierarchy(table_data, 1, 0, socket);
+
+ for (core = 0; core < smp_cores; core++) {
+ uint32_t core_offset = table_data->len - pptt_start;
+ int thread;
+
+ if (smp_threads > 1) {
+ build_cpu_hierarchy(table_data, 0, socket_offset, core);
+ for (thread = 0; thread < smp_threads; thread++) {
+ build_cpu_hierarchy(table_data, 2, core_offset, uid++);
+ }
+ } else {
+ build_cpu_hierarchy(table_data, 2, socket_offset, uid++);
+ }
+ }
+ cpus += smp_cores * smp_threads;
+ }
+
+ build_header(linker, table_data,
+ (void *)(table_data->data + pptt_start), "PPTT",
+ table_data->len - pptt_start, 1, NULL, NULL);
+}
+
#define ACPI_NAMESEG_LEN 4
static void
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 33a8e2e3..18653e6d 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -870,6 +870,10 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
acpi_add_table(table_offsets, tables_blob);
build_fadt_rev5(tables_blob, tables->linker, vms, dsdt);
+ acpi_add_table(table_offsets, tables_blob);
+
+ build_pptt(tables_blob, tables->linker, vms->smp_cpus);
+
acpi_add_table(table_offsets, tables_blob);
build_madt(tables_blob, tables->linker, vms);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 57a78b16..16700a2e 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -42,6 +42,7 @@
#include "net/net.h"
#include "sysemu/device_tree.h"
#include "sysemu/numa.h"
+#include "sysemu/cpus.h"
#include "sysemu/sysemu.h"
#include "sysemu/kvm.h"
#include "hw/loader.h"
@@ -364,8 +365,36 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
ms->possible_cpus->cpus[cs->cpu_index].props.node_id);
}
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle",
+ qemu_fdt_alloc_phandle(vms->fdt));
+
g_free(nodename);
}
+
+ /* Add vcpu topology by fdt node cpu-map. */
+ qemu_fdt_add_subnode(vms->fdt, "/cpus/cpu-map");
+
+ for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) {
+ char *cpu_path = g_strdup_printf("/cpus/cpu@%d", cpu);
+ char *map_path;
+
+ if (smp_threads > 1) {
+ map_path = g_strdup_printf(
+ "/cpus/cpu-map/%s%d/%s%d/%s%d",
+ "cluster", cpu / (smp_cores * smp_threads),
+ "core", (cpu / smp_threads) % smp_cores,
+ "thread", cpu % smp_threads);
+ } else {
+ map_path = g_strdup_printf(
+ "/cpus/cpu-map/%s%d/%s%d",
+ "cluster", cpu / smp_cores,
+ "core", cpu % smp_cores);
+ }
+ qemu_fdt_add_path(vms->fdt, map_path);
+ qemu_fdt_setprop_phandle(vms->fdt, map_path, "cpu", cpu_path);
+ g_free(map_path);
+ g_free(cpu_path);
+ }
}
static void fdt_add_its_gic_node(VirtMachineState *vms)
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 375335ab..bfb0b100 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -417,6 +417,8 @@ build_append_gas_from_struct(GArray *table, const struct AcpiGenericAddress *s)
void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
uint64_t len, int node, MemoryAffinityFlags flags);
+void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus);
+
void build_slit(GArray *table_data, BIOSLinker *linker);
void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h
index c16fd69b..d62fc873 100644
--- a/include/sysemu/device_tree.h
+++ b/include/sysemu/device_tree.h
@@ -101,6 +101,7 @@ uint32_t qemu_fdt_get_phandle(void *fdt, const char *path);
uint32_t qemu_fdt_alloc_phandle(void *fdt);
int qemu_fdt_nop_node(void *fdt, const char *node_path);
int qemu_fdt_add_subnode(void *fdt, const char *name);
+int qemu_fdt_add_path(void *fdt, const char *path);
#define qemu_fdt_setprop_cells(fdt, node_path, property, ...) \
do { \
--
2.19.1

View File

@ -0,0 +1,318 @@
From 8db6d888e3eb131900111506b93f6101413df5b4 Mon Sep 17 00:00:00 2001
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
Date: Mon, 5 Aug 2019 15:30:05 +0800
Subject: [PATCH] hw/arm64: add vcpu cache info support
Support VCPU Cache info by dtb and PPTT table, including L1, L2 and L3 Cache.
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Honghao <honghao5@huawei.com>
---
hw/acpi/aml-build.c | 124 ++++++++++++++++++++++++++++++++++++
hw/arm/virt.c | 76 +++++++++++++++++++++-
include/hw/acpi/aml-build.h | 46 +++++++++++++
3 files changed, 245 insertions(+), 1 deletion(-)
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 9d39ad10..99209c0a 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -55,6 +55,129 @@ static void build_append_array(GArray *array, GArray *val)
/*
* ACPI 6.2 Processor Properties Topology Table (PPTT)
*/
+#ifdef __aarch64__
+static void build_cache_head(GArray *tbl, uint32_t next_level)
+{
+ build_append_byte(tbl, 1);
+ build_append_byte(tbl, 24);
+ build_append_int_noprefix(tbl, 0, 2);
+ build_append_int_noprefix(tbl, 127, 4);
+ build_append_int_noprefix(tbl, next_level, 4);
+}
+
+static void build_cache_tail(GArray *tbl, uint32_t cache_type)
+{
+ switch (cache_type) {
+ case ARM_L1D_CACHE: /* L1 dcache info*/
+ build_append_int_noprefix(tbl, ARM_L1DCACHE_SIZE, 4);
+ build_append_int_noprefix(tbl, ARM_L1DCACHE_SET, 4);
+ build_append_byte(tbl, ARM_L1DCACHE_ASSOCIATIVITY);
+ build_append_byte(tbl, ARM_L1DCACHE_ATTRIBUTES);
+ build_append_int_noprefix(tbl, ARM_L1DCACHE_LINE_SIZE, 2);
+ break;
+ case ARM_L1I_CACHE: /* L1 icache info*/
+ build_append_int_noprefix(tbl, ARM_L1ICACHE_SIZE, 4);
+ build_append_int_noprefix(tbl, ARM_L1ICACHE_SET, 4);
+ build_append_byte(tbl, ARM_L1ICACHE_ASSOCIATIVITY);
+ build_append_byte(tbl, ARM_L1ICACHE_ATTRIBUTES);
+ build_append_int_noprefix(tbl, ARM_L1ICACHE_LINE_SIZE, 2);
+ break;
+ case ARM_L2_CACHE: /* L2 cache info*/
+ build_append_int_noprefix(tbl, ARM_L2CACHE_SIZE, 4);
+ build_append_int_noprefix(tbl, ARM_L2CACHE_SET, 4);
+ build_append_byte(tbl, ARM_L2CACHE_ASSOCIATIVITY);
+ build_append_byte(tbl, ARM_L2CACHE_ATTRIBUTES);
+ build_append_int_noprefix(tbl, ARM_L2CACHE_LINE_SIZE, 2);
+ break;
+ case ARM_L3_CACHE: /* L3 cache info*/
+ build_append_int_noprefix(tbl, ARM_L3CACHE_SIZE, 4);
+ build_append_int_noprefix(tbl, ARM_L3CACHE_SET, 4);
+ build_append_byte(tbl, ARM_L3CACHE_ASSOCIATIVITY);
+ build_append_byte(tbl, ARM_L3CACHE_ATTRIBUTES);
+ build_append_int_noprefix(tbl, ARM_L3CACHE_LINE_SIZE, 2);
+ break;
+ default:
+ build_append_int_noprefix(tbl, 0, 4);
+ build_append_int_noprefix(tbl, 0, 4);
+ build_append_byte(tbl, 0);
+ build_append_byte(tbl, 0);
+ build_append_int_noprefix(tbl, 0, 2);
+ break;
+ }
+}
+
+static void build_cache_hierarchy(GArray *tbl,
+ uint32_t next_level, uint32_t cache_type)
+{
+ build_cache_head(tbl, next_level);
+ build_cache_tail(tbl, cache_type);
+}
+
+static void build_arm_socket_hierarchy(GArray *tbl,
+ uint32_t offset, uint32_t id)
+{
+ build_append_byte(tbl, 0); /* Type 0 - processor */
+ build_append_byte(tbl, 24); /* Length, add private resources */
+ build_append_int_noprefix(tbl, 0, 2); /* Reserved */
+ build_append_int_noprefix(tbl, 1, 4); /* Processor boundary and id invalid*/
+ build_append_int_noprefix(tbl, 0, 4);
+ build_append_int_noprefix(tbl, id, 4);
+ build_append_int_noprefix(tbl, 1, 4); /* Num private resources */
+ build_append_int_noprefix(tbl, offset, 4);
+}
+
+static void build_arm_cpu_hierarchy(GArray *tbl,
+ struct offset_status *offset, uint32_t id)
+{
+ if (!offset) {
+ return;
+ }
+ build_append_byte(tbl, 0); /* Type 0 - processor */
+ build_append_byte(tbl, 32); /* Length, add private resources */
+ build_append_int_noprefix(tbl, 0, 2); /* Reserved */
+ build_append_int_noprefix(tbl, 2, 4); /* Valid id*/
+ build_append_int_noprefix(tbl, offset->parent, 4);
+ build_append_int_noprefix(tbl, id, 4);
+ build_append_int_noprefix(tbl, 3, 4); /* Num private resources */
+ build_append_int_noprefix(tbl, offset->l1d_offset, 4);
+ build_append_int_noprefix(tbl, offset->l1i_offset, 4);
+ build_append_int_noprefix(tbl, offset->l2_offset, 4);
+}
+
+void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus)
+{
+ int pptt_start = table_data->len;
+ int uid = 0, cpus = 0, socket;
+ struct offset_status offset;
+
+ acpi_data_push(table_data, sizeof(AcpiTableHeader));
+
+ for (socket = 0; cpus < possible_cpus; socket++) {
+ int core;
+ uint32_t l3_offset = table_data->len - pptt_start;
+ build_cache_hierarchy(table_data, 0, ARM_L3_CACHE);
+
+ offset.parent = table_data->len - pptt_start;
+ build_arm_socket_hierarchy(table_data, l3_offset, socket);
+
+ for (core = 0; core < smp_cores; core++) {
+ offset.l2_offset = table_data->len - pptt_start;
+ build_cache_hierarchy(table_data, 0, ARM_L2_CACHE);
+ offset.l1d_offset = table_data->len - pptt_start;
+ build_cache_hierarchy(table_data, offset.l2_offset, ARM_L1D_CACHE);
+ offset.l1i_offset = table_data->len - pptt_start;
+ build_cache_hierarchy(table_data, offset.l2_offset, ARM_L1I_CACHE);
+ build_arm_cpu_hierarchy(table_data, &offset, uid++);
+ cpus++;
+ }
+ }
+
+ build_header(linker, table_data,
+ (void *)(table_data->data + pptt_start), "PPTT",
+ table_data->len - pptt_start, 1, NULL, NULL);
+}
+
+#else
static void build_cpu_hierarchy(GArray *tbl, uint32_t flags,
uint32_t parent, uint32_t id)
{
@@ -100,6 +223,7 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus)
(void *)(table_data->data + pptt_start), "PPTT",
table_data->len - pptt_start, 1, NULL, NULL);
}
+#endif
#define ACPI_NAMESEG_LEN 4
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 16700a2e..96f56e2e 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -304,6 +304,77 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL2_IRQ, irqflags);
}
+static void fdt_add_l3cache_nodes(const VirtMachineState *vms)
+{
+ int i;
+ unsigned int sockets = vms->smp_cpus / smp_cores;
+
+ /* If current is not equal to max */
+ if (vms->smp_cpus % smp_cores)
+ sockets++;
+
+ for (i = 0; i < sockets; i++) {
+ char *nodename = g_strdup_printf("/cpus/l3-cache%d", i);
+ qemu_fdt_add_subnode(vms->fdt, nodename);
+ qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cache");
+ qemu_fdt_setprop_string(vms->fdt, nodename, "cache-unified", "true");
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "cache-level", 3);
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "cache-size", 0x2000000);
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "cache-line-size", 128);
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "cache-sets", 2048);
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle",
+ qemu_fdt_alloc_phandle(vms->fdt));
+ g_free(nodename);
+ }
+}
+
+
+static void fdt_add_l2cache_nodes(const VirtMachineState *vms)
+{
+ int i, j;
+ signed int sockets = vms->smp_cpus / smp_cores;
+
+ /* If current is not equal to max */
+ if (vms->smp_cpus % smp_cores)
+ sockets++;
+
+ for (i = 0; i < sockets; i++) {
+ char *next_path = g_strdup_printf("/cpus/l3-cache%d", i);
+ for (j = 0; j < smp_cores; j++) {
+ char *nodename = g_strdup_printf("/cpus/l2-cache%d",
+ i * smp_cores + j);
+ qemu_fdt_add_subnode(vms->fdt, nodename);
+ qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cache");
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "cache-size", 0x80000);
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "cache-line-size", 64);
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "cache-sets", 1024);
+ qemu_fdt_setprop_phandle(vms->fdt, nodename,
+ "next-level-cache", next_path);
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle",
+ qemu_fdt_alloc_phandle(vms->fdt));
+ g_free(nodename);
+ }
+ g_free(next_path);
+ }
+}
+
+static void fdt_add_l1cache_prop(const VirtMachineState *vms,
+ char *nodename, int cpu)
+{
+ char *cachename = g_strdup_printf("/cpus/l2-cache%d", cpu);
+
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "d-cache-size", 0x10000);
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "d-cache-line-size", 64);
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "d-cache-sets", 256);
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "i-cache-size", 0x10000);
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "i-cache-line-size", 64);
+ qemu_fdt_setprop_cell(vms->fdt, nodename, "i-cache-sets", 256);
+ qemu_fdt_setprop_phandle(vms->fdt, nodename,
+ "next-level-cache", cachename);
+ g_free(cachename);
+}
+
+
static void fdt_add_cpu_nodes(const VirtMachineState *vms)
{
int cpu;
@@ -336,6 +407,9 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#address-cells", addr_cells);
qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#size-cells", 0x0);
+ fdt_add_l3cache_nodes(vms);
+ fdt_add_l2cache_nodes(vms);
+
for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) {
char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
@@ -364,7 +438,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms)
qemu_fdt_setprop_cell(vms->fdt, nodename, "numa-node-id",
ms->possible_cpus->cpus[cs->cpu_index].props.node_id);
}
-
+ fdt_add_l1cache_prop(vms, nodename, cpu);
qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle",
qemu_fdt_alloc_phandle(vms->fdt));
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index bfb0b100..0be3453a 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -223,6 +223,52 @@ struct AcpiBuildTables {
BIOSLinker *linker;
} AcpiBuildTables;
+#ifdef __aarch64__
+/* Definitions of the hardcoded cache info*/
+
+typedef enum {
+ ARM_L1D_CACHE,
+ ARM_L1I_CACHE,
+ ARM_L2_CACHE,
+ ARM_L3_CACHE
+} ArmCacheType;
+
+/* L1 data cache: */
+#define ARM_L1DCACHE_SIZE 65536
+#define ARM_L1DCACHE_SET 256
+#define ARM_L1DCACHE_ASSOCIATIVITY 4
+#define ARM_L1DCACHE_ATTRIBUTES 2
+#define ARM_L1DCACHE_LINE_SIZE 64
+
+/* L1 instruction cache: */
+#define ARM_L1ICACHE_SIZE 65536
+#define ARM_L1ICACHE_SET 256
+#define ARM_L1ICACHE_ASSOCIATIVITY 4
+#define ARM_L1ICACHE_ATTRIBUTES 4
+#define ARM_L1ICACHE_LINE_SIZE 64
+
+/* Level 2 unified cache: */
+#define ARM_L2CACHE_SIZE 524288
+#define ARM_L2CACHE_SET 1024
+#define ARM_L2CACHE_ASSOCIATIVITY 8
+#define ARM_L2CACHE_ATTRIBUTES 10
+#define ARM_L2CACHE_LINE_SIZE 64
+
+/* Level 3 unified cache: */
+#define ARM_L3CACHE_SIZE 33554432
+#define ARM_L3CACHE_SET 2048
+#define ARM_L3CACHE_ASSOCIATIVITY 15
+#define ARM_L3CACHE_ATTRIBUTES 10
+#define ARM_L3CACHE_LINE_SIZE 128
+
+struct offset_status {
+ uint32_t parent;
+ uint32_t l2_offset;
+ uint32_t l1d_offset;
+ uint32_t l1i_offset;
+};
+
+#endif
/**
* init_aml_allocator:
*
--
2.23.0

View File

@ -0,0 +1,54 @@
From 21e2acd583126db94f6d881005cd58e835160582 Mon Sep 17 00:00:00 2001
From: Evgeny Yakovlev <wrfsh@yandex-team.ru>
Date: Thu, 18 Jul 2019 19:14:23 +0300
Subject: [PATCH] i386/acpi: fix gint overflow in crs_range_compare
When very large regions (32GB sized in our case, PCI pass-through of GPUs)
are compared substraction result does not fit into gint.
As a result crs_replace_with_free_ranges does not get sorted ranges and
incorrectly computes PCI64 free space regions. Which then makes linux
guest complain about device and PCI64 hole intersection and device
becomes unusable.
Fix that by returning exactly fitting ranges.
Also fix indentation of an entire crs_replace_with_free_ranges to make
checkpatch happy.
Cc: qemu-stable@nongnu.org
Signed-off-by: Evgeny Yakovlev <wrfsh@yandex-team.ru>
Message-Id: <1563466463-26012-1-git-send-email-wrfsh@yandex-team.ru>
Signed-off-by: Evgeny Yakovlev <wrfsh@yandex-team.ru>
(cherry-picked from commit 21e2acd583126db94f6d881005cd58e835160582)
---
hw/i386/acpi-build.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index d281ffa89e..e7b756b51b 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -755,10 +755,16 @@ static void crs_range_set_free(CrsRangeSet *range_set)
static gint crs_range_compare(gconstpointer a, gconstpointer b)
{
- CrsRangeEntry *entry_a = *(CrsRangeEntry **)a;
- CrsRangeEntry *entry_b = *(CrsRangeEntry **)b;
+ CrsRangeEntry *entry_a = *(CrsRangeEntry **)a;
+ CrsRangeEntry *entry_b = *(CrsRangeEntry **)b;
- return (int64_t)entry_a->base - (int64_t)entry_b->base;
+ if (entry_a->base < entry_b->base) {
+ return -1;
+ } else if (entry_a->base > entry_b->base) {
+ return 1;
+ } else {
+ return 0;
+ }
}
/*
--
2.19.1

View File

@ -0,0 +1,40 @@
From ee4b0c8686f781987879508d7c6dd605b5435bac Mon Sep 17 00:00:00 2001
From: Evgeny Yakovlev <wrfsh@yandex-team.ru>
Date: Fri, 19 Jul 2019 11:54:29 +0300
Subject: [PATCH] i386/acpi: show PCI Express bus on pxb-pcie expanders
Show PCIe host bridge PNP id with PCI host bridge as a compatible id
when expanding a pcie bus.
Cc: qemu-stable@nongnu.org
Signed-off-by: Evgeny Yakovlev <wrfsh@yandex-team.ru>
Message-Id: <1563526469-15588-1-git-send-email-wrfsh@yandex-team.ru>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry-picked from commit ee4b0c8686f781987879508d7c6dd605b5435bac)
---
hw/i386/acpi-build.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index e7b756b51b..f3fdfefcd5 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1914,10 +1914,13 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
scope = aml_scope("\\_SB");
dev = aml_device("PC%.02X", bus_num);
aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
- aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
if (pci_bus_is_express(bus)) {
+ aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08")));
+ aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
aml_append(dev, build_q35_osc_method());
+ } else {
+ aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
}
if (numa_node != NUMA_NODE_UNASSIGNED) {
--
2.19.1

View File

@ -0,0 +1,46 @@
From be1927c97e564346cbd409cb17fe611df74b84e5 Mon Sep 17 00:00:00 2001
From: Jan Kiszka <jan.kiszka@siemens.com>
Date: Sun, 2 Jun 2019 13:42:13 +0200
Subject: [PATCH] ioapic: kvm: Skip route updates for masked pins
Masked entries will not generate interrupt messages, thus do no need to
be routed by KVM. This is a cosmetic cleanup, just avoiding warnings of
the kind
qemu-system-x86_64: vtd_irte_get: detected non-present IRTE (index=0, high=0xff00, low=0x100)
if the masked entry happens to reference a non-present IRTE.
Cc: qemu-stable@nongnu.org
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Message-Id: <a84b7e03-f9a8-b577-be27-4d93d1caa1c9@siemens.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
(cherry-picked from commit be1927c97e564346cbd409cb17fe611df74b84e5)
---
hw/intc/ioapic.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c
index c408749876..e99c37cceb 100644
--- a/hw/intc/ioapic.c
+++ b/hw/intc/ioapic.c
@@ -197,9 +197,11 @@ static void ioapic_update_kvm_routes(IOAPICCommonState *s)
MSIMessage msg;
struct ioapic_entry_info info;
ioapic_entry_parse(s->ioredtbl[i], &info);
- msg.address = info.addr;
- msg.data = info.data;
- kvm_irqchip_update_msi_route(kvm_state, i, msg, NULL);
+ if (!info.masked) {
+ msg.address = info.addr;
+ msg.data = info.data;
+ kvm_irqchip_update_msi_route(kvm_state, i, msg, NULL);
+ }
}
kvm_irqchip_commit_routes(kvm_state);
}
--
2.19.1

View File

@ -0,0 +1,40 @@
From 5fff13f245cddd3bc260dfe6ebe1b1f05b72116f Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Tue, 14 May 2019 06:24:43 +0200
Subject: [PATCH] kbd-state: fix autorepeat handling
When allowing multiple down-events in a row (key autorepeat) we can't
use change_bit() any more to update the state, because autorepeat events
don't change the key state. We have to explicitly use set_bit() and
clear_bit() instead.
Cc: qemu-stable@nongnu.org
Fixes: 35921860156e kbd-state: don't block auto-repeat events
Buglink: https://bugs.launchpad.net/qemu/+bug/1828272
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 20190514042443.10735-1-kraxel@redhat.com
(cherry-picked from commit 5fff13f245cddd3bc260dfe6ebe1b1f05b72116f)
---
ui/kbd-state.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/ui/kbd-state.c b/ui/kbd-state.c
index f3ab2d7a66..1668d17dda 100644
--- a/ui/kbd-state.c
+++ b/ui/kbd-state.c
@@ -59,7 +59,11 @@ void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down)
}
/* update key and modifier state */
- change_bit(qcode, kbd->keys);
+ if (down) {
+ set_bit(qcode, kbd->keys);
+ } else {
+ clear_bit(qcode, kbd->keys);
+ }
switch (qcode) {
case Q_KEY_CODE_SHIFT:
case Q_KEY_CODE_SHIFT_R:
--
2.19.1

View File

@ -0,0 +1,35 @@
From 2e56fbc87f6ec3cd56c37b01d313abd502b80d61 Mon Sep 17 00:00:00 2001
From: Peter Lieven <pl@kamp.de>
Date: Thu, 4 Apr 2019 14:10:15 +0200
Subject: [PATCH] megasas: fix mapped frame size
the current value of 1024 bytes (16 * MFI_FRAME_SIZE) we map is not enough to hold
the maximum number of scatter gather elements we advertise. We actually need a
maximum of 2048 bytes. This is 128 max sg elements * 16 bytes (sizeof (union mfi_sgl)).
Cc: qemu-stable@nongnu.org
Signed-off-by: Peter Lieven <pl@kamp.de>
Message-Id: <20190404121015.28634-1-pl@kamp.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from commit 2e56fbc87f6ec3cd56c37b01d313abd502b80d61)
---
hw/scsi/megasas.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index a56317e026..5ad762de23 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -477,7 +477,7 @@ static MegasasCmd *megasas_enqueue_frame(MegasasState *s,
{
PCIDevice *pcid = PCI_DEVICE(s);
MegasasCmd *cmd = NULL;
- int frame_size = MFI_FRAME_SIZE * 16;
+ int frame_size = MEGASAS_MAX_SGE * sizeof(union mfi_sgl);
hwaddr frame_size_p = frame_size;
unsigned long index;
--
2.19.1

View File

@ -0,0 +1,85 @@
From b9f43f0cca03586a31b53e47ade72e77db01cb4c Mon Sep 17 00:00:00 2001
From: King Wang <king.wang@huawei.com>
Date: Fri, 12 Jul 2019 14:52:41 +0800
Subject: [PATCH 2/5] memory: unref the memory region in simplify flatview
The memory region reference is increased when insert a range
into flatview range array, then decreased by destroy flatview.
If some flat range merged by flatview_simplify, the memory region
reference can not be decreased by destroy flatview any more.
In this case, start virtual machine by the command line:
qemu-system-x86_64
-name guest=ubuntu,debug-threads=on
-machine pc,accel=kvm,usb=off,dump-guest-core=off
-cpu host
-m 16384
-realtime mlock=off
-smp 8,sockets=2,cores=4,threads=1
-object memory-backend-file,id=ram-node0,prealloc=yes,mem-path=/dev/hugepages,share=yes,size=8589934592
-numa node,nodeid=0,cpus=0-3,memdev=ram-node0
-object memory-backend-file,id=ram-node1,prealloc=yes,mem-path=/dev/hugepages,share=yes,size=8589934592
-numa node,nodeid=1,cpus=4-7,memdev=ram-node1
-no-user-config
-nodefaults
-rtc base=utc
-no-shutdown
-boot strict=on
-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2
-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x2
-device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x3
-drive file=ubuntu.qcow2,format=qcow2,if=none,id=drive-virtio-disk0,cache=none,aio=native
-device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1
-chardev pty,id=charserial0
-device isa-serial,chardev=charserial0,id=serial0
-device usb-tablet,id=input0,bus=usb.0,port=1
-vnc 0.0.0.0:0
-device VGA,id=video0,vgamem_mb=16,bus=pci.0,addr=0x5
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6
-msg timestamp=on
And run the script in guest OS:
while true
do
setpci -s 00:06.0 04.b=03
setpci -s 00:06.0 04.b=07
done
I found the reference of node0 HostMemoryBackendFile is a big one.
(gdb) p numa_info[0]->node_memdev->parent.ref
$6 = 1636278
(gdb)
Signed-off-by: King Wang<king.wang@huawei.com>
Message-Id: <20190712065241.11784-1-king.wang@huawei.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
memory.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/memory.c b/memory.c
index 9fbca52..0b49281 100644
--- a/memory.c
+++ b/memory.c
@@ -320,7 +320,7 @@ static bool can_merge(FlatRange *r1, FlatRange *r2)
/* Attempt to simplify a view by merging adjacent ranges */
static void flatview_simplify(FlatView *view)
{
- unsigned i, j;
+ unsigned i, j, k;
i = 0;
while (i < view->nr) {
@@ -331,6 +331,9 @@ static void flatview_simplify(FlatView *view)
++j;
}
++i;
+ for (k = i; k < j; k++) {
+ memory_region_unref(view->ranges[k].mr);
+ }
memmove(&view->ranges[i], &view->ranges[j],
(view->nr - j) * sizeof(view->ranges[j]));
view->nr -= j - i;
--
1.8.3.1

View File

@ -0,0 +1,41 @@
From f995e8b5e5c14f83a16433f192440ec5c82c87fa Mon Sep 17 00:00:00 2001
From: Ying Fang <fangying1@huawei.com>
Date: Mon, 29 Jul 2019 16:16:35 +0800
Subject: [PATCH] pl011: reset read FIFO when UARTTIMSC=0 & UARTICR=0xffff
We can enable ACPI when AArch64 Linux is booted with QEMU and UEFI (AAVMF).
When VM is booting and the SBSA driver has not initialized, writting data
that exceds 32 bytes will cause the read FIFO full and proceeding data will
be lost. The searil port appears to be stuck in this abnormal situation.
A hack to reset read FIFO when UARTTIMSC=0 & UARTICR=0xffff appears to
resolve the issue.
The question is fully discussed at
https://www.spinics.net/lists/linux-serial/msg23163.html
Signed-off-by: Haibin Wang <wanghaibin.wang@huawei.com>
Reviewed-by: Shannon Zhao <shannon.zhaosl@gmail.com>
Reviewed-by: Ying Fang <fangying1@huawei.com>
---
hw/char/pl011.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index e5dd448f..899745ef 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -223,6 +223,10 @@ static void pl011_write(void *opaque, hwaddr offset,
case 17: /* UARTICR */
s->int_level &= ~value;
pl011_update(s);
+ if (!s->int_enabled && !s->int_level) {
+ s->read_count = 0;
+ s->read_pos = 0;
+ }
break;
case 18: /* UARTDMACR */
s->dmacr = value;
--
2.19.1

View File

@ -0,0 +1,49 @@
From 68d4653b5ffde629e9b05d5de13b6adcde9d153b Mon Sep 17 00:00:00 2001
From: Ying Fang <fangying1@huawei.com>
Date: Mon, 29 Jul 2019 16:20:51 +0800
Subject: [PATCH] pl031: support rtc-timer property for pl031
This patch adds the rtc-timer property for pl031, we can get the
rtc time (UTC) through qmp command "qom-get date" with this property.
Signed-off-by: Haibin Wang <wanghaibin.wang@huawei.com>
Reviewed-by: Shannon Zhao <shannon.zhaosl@gmail.com>
Reviewed-by: Ying Fang <fangying1@huawei.com>
---
hw/timer/pl031.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c
index 274ad47a..04331472 100644
--- a/hw/timer/pl031.c
+++ b/hw/timer/pl031.c
@@ -57,6 +57,15 @@ static uint32_t pl031_get_count(PL031State *s)
return s->tick_offset + now / NANOSECONDS_PER_SECOND;
}
+static void pl031_get_date(Object *obj, struct tm *current_tm, Error **errp)
+{
+ PL031State *s = PL031(obj);
+ time_t ti = pl031_get_count(s);
+
+ /* Changed to UTC time */
+ gmtime_r(&ti, current_tm);
+}
+
static void pl031_set_alarm(PL031State *s)
{
uint32_t ticks;
@@ -191,6 +200,10 @@ static void pl031_init(Object *obj)
qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
s->timer = timer_new_ns(rtc_clock, pl031_interrupt, s);
+
+ object_property_add_tm(OBJECT(s), "date", pl031_get_date, NULL);
+ object_property_add_alias(qdev_get_machine(), "rtc-time",
+ OBJECT(s), "date", NULL);
}
static int pl031_pre_save(void *opaque)
--
2.19.1

View File

@ -0,0 +1,132 @@
From c87759ce876a7a0b17c2bf4f0b964bd51f0ee871 Mon Sep 17 00:00:00 2001
From: Alex Williamson <alex.williamson@redhat.com>
Date: Tue, 14 May 2019 14:14:41 -0600
Subject: [PATCH] q35: Revert to kernel irqchip
Commit b2fc91db8447 ("q35: set split kernel irqchip as default") changed
the default for the pc-q35-4.0 machine type to use split irqchip, which
turned out to have disasterous effects on vfio-pci INTx support. KVM
resampling irqfds are registered for handling these interrupts, but
these are non-functional in split irqchip mode. We can't simply test
for split irqchip in QEMU as userspace handling of this interrupt is a
significant performance regression versus KVM handling (GeForce GPUs
assigned to Windows VMs are non-functional without forcing MSI mode or
re-enabling kernel irqchip).
The resolution is to revert the change in default irqchip mode in the
pc-q35-4.1 machine and create a pc-q35-4.0.1 machine for the 4.0-stable
branch. The qemu-q35-4.0 machine type should not be used in vfio-pci
configurations for devices requiring legacy INTx support without
explicitly modifying the VM configuration to use kernel irqchip.
Link: https://bugs.launchpad.net/qemu/+bug/1826422
Fixes: b2fc91db8447 ("q35: set split kernel irqchip as default")
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Message-Id: <155786484688.13873.6037015630912983760.stgit@gimli.home>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from commit c87759ce876a7a0b17c2bf4f0b964bd51f0ee871)
---
hw/core/machine.c | 3 +++
hw/i386/pc.c | 3 +++
hw/i386/pc_q35.c | 16 ++++++++++++++--
include/hw/boards.h | 3 +++
include/hw/i386/pc.h | 3 +++
5 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 16ba667434..f1a0f45f9c 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -24,6 +24,9 @@
#include "hw/pci/pci.h"
#include "hw/mem/nvdimm.h"
+GlobalProperty hw_compat_4_0_1[] = {};
+const size_t hw_compat_4_0_1_len = G_N_ELEMENTS(hw_compat_4_0_1);
+
GlobalProperty hw_compat_4_0[] = {};
const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 2632b73f80..edc240bcbf 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -110,6 +110,9 @@ struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
/* Physical Address of PVH entry point read from kernel ELF NOTE */
static size_t pvh_start_addr;
+GlobalProperty pc_compat_4_0_1[] = {};
+const size_t pc_compat_4_0_1_len = G_N_ELEMENTS(pc_compat_4_0_1);
+
GlobalProperty pc_compat_4_0[] = {};
const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 37dd350511..dcddc64662 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -357,7 +357,7 @@ static void pc_q35_machine_options(MachineClass *m)
m->units_per_default_bus = 1;
m->default_machine_opts = "firmware=bios-256k.bin";
m->default_display = "std";
- m->default_kernel_irqchip_split = true;
+ m->default_kernel_irqchip_split = false;
m->no_floppy = 1;
machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE);
machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE);
@@ -374,10 +374,22 @@ static void pc_q35_4_1_machine_options(MachineClass *m)
DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL,
pc_q35_4_1_machine_options);
-static void pc_q35_4_0_machine_options(MachineClass *m)
+static void pc_q35_4_0_1_machine_options(MachineClass *m)
{
pc_q35_4_1_machine_options(m);
m->alias = NULL;
+ compat_props_add(m->compat_props, hw_compat_4_0_1, hw_compat_4_0_1_len);
+ compat_props_add(m->compat_props, pc_compat_4_0_1, pc_compat_4_0_1_len);
+}
+
+DEFINE_Q35_MACHINE(v4_0_1, "pc-q35-4.0.1", NULL,
+ pc_q35_4_0_1_machine_options);
+
+static void pc_q35_4_0_machine_options(MachineClass *m)
+{
+ pc_q35_4_0_1_machine_options(m);
+ m->default_kernel_irqchip_split = true;
+ m->alias = NULL;
compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len);
compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
}
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 6f7916f88f..6ff02bf3e4 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -292,6 +292,9 @@ struct MachineState {
} \
type_init(machine_initfn##_register_types)
+extern GlobalProperty hw_compat_4_0_1[];
+extern const size_t hw_compat_4_0_1_len;
+
extern GlobalProperty hw_compat_4_0[];
extern const size_t hw_compat_4_0_len;
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 43df7230a2..5d5636241e 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -293,6 +293,9 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
int e820_get_num_entries(void);
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
+extern GlobalProperty pc_compat_4_0_1[];
+extern const size_t pc_compat_4_0_1_len;
+
extern GlobalProperty pc_compat_4_0[];
extern const size_t pc_compat_4_0_len;
--
2.19.1

View File

@ -0,0 +1,79 @@
From 360bd07471dfd1830246e8403ffdc9ba9d82f9d4 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Mon, 15 Apr 2019 16:56:07 +0200
Subject: [PATCH] qcow2: Add errp to preallocate_co()
We'll add a bdrv_co_truncate() call in the next patch which can return
an Error that we don't want to discard. So add an errp parameter to
preallocate_co().
Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
(cherry-picked from commit 360bd07471dfd1830246e8403ffdc9ba9d82f9d4)
---
block/qcow2.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index dfac74c264..b4f9f5a240 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2721,7 +2721,7 @@ static int qcow2_set_up_encryption(BlockDriverState *bs,
* Returns: 0 on success, -errno on failure.
*/
static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
- uint64_t new_length)
+ uint64_t new_length, Error **errp)
{
BDRVQcow2State *s = bs->opaque;
uint64_t bytes;
@@ -2738,6 +2738,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes,
&host_offset, &meta);
if (ret < 0) {
+ error_setg_errno(errp, -ret, "Allocating clusters failed");
return ret;
}
@@ -2746,6 +2747,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
ret = qcow2_alloc_cluster_link_l2(bs, meta);
if (ret < 0) {
+ error_setg_errno(errp, -ret, "Mapping clusters failed");
qcow2_free_any_clusters(bs, meta->alloc_offset,
meta->nb_clusters, QCOW2_DISCARD_NEVER);
return ret;
@@ -2775,6 +2777,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
ret = bdrv_pwrite(s->data_file, (host_offset + cur_bytes) - 1,
&data, 1);
if (ret < 0) {
+ error_setg_errno(errp, -ret, "Writing to EOF failed");
return ret;
}
}
@@ -3748,9 +3751,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
break;
case PREALLOC_MODE_METADATA:
- ret = preallocate_co(bs, old_length, offset);
+ ret = preallocate_co(bs, old_length, offset, errp);
if (ret < 0) {
- error_setg_errno(errp, -ret, "Preallocation failed");
goto fail;
}
break;
@@ -3766,9 +3768,8 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
/* With a data file, preallocation means just allocating the metadata
* and forwarding the truncate request to the data file */
if (has_data_file(bs)) {
- ret = preallocate_co(bs, old_length, offset);
+ ret = preallocate_co(bs, old_length, offset, errp);
if (ret < 0) {
- error_setg_errno(errp, -ret, "Preallocation failed");
goto fail;
}
break;
--
2.19.1

View File

@ -0,0 +1,38 @@
From f29fbf7c6b1c9a84f6931c1c222716fbe073e6e4 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Mon, 15 Apr 2019 16:25:01 +0200
Subject: [PATCH] qcow2: Avoid COW during metadata preallocation
Limiting the allocation to INT_MAX bytes isn't particularly clever
because it means that the final cluster will be a partial cluster which
will be completed through a COW operation. This results in unnecessary
data read and write requests which lead to an unwanted non-sparse
filesystem block for metadata preallocation.
Align the maximum allocation size down to the cluster size to avoid this
situation.
Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
(cherry-picked from commit f29fbf7c6b1c9a84f6931c1c222716fbe073e6e4)
---
block/qcow2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index 3ace3b2209..dfac74c264 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2734,7 +2734,7 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
bytes = new_length - offset;
while (bytes) {
- cur_bytes = MIN(bytes, INT_MAX);
+ cur_bytes = MIN(bytes, QEMU_ALIGN_DOWN(INT_MAX, s->cluster_size));
ret = qcow2_alloc_cluster_offset(bs, offset, &cur_bytes,
&host_offset, &meta);
if (ret < 0) {
--
2.19.1

View File

@ -0,0 +1,116 @@
From 718c0fce2f56755a8d8f737607779a98aa6e7cc4 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Mon, 15 Apr 2019 16:34:30 +0200
Subject: [PATCH] qcow2: Fix full preallocation with external data file
preallocate_co() already gave the data file the full size without
forwarding the requested preallocation mode to the protocol. When
bdrv_co_truncate() was called later with the preallocation mode, the
file didn't actually grow any more, so the data file stayed unallocated
even if full preallocation was requested.
Pass the right preallocation mode to preallocate_co() and remove the
second bdrv_co_truncate() to fix this. As a side effect, the ugly
one-byte write in preallocate_co() is replaced with a truncate call,
now leaving the last block unallocated on the protocol level as it
should be.
Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
(cherry-picked from commit 718c0fce2f56755a8d8f737607779a98aa6e7cc4)
---
block/qcow2.c | 41 +++++++++++++++++++++++------------------
1 file changed, 23 insertions(+), 18 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index b4f9f5a240..7fbef97aab 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -2721,11 +2721,13 @@ static int qcow2_set_up_encryption(BlockDriverState *bs,
* Returns: 0 on success, -errno on failure.
*/
static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
- uint64_t new_length, Error **errp)
+ uint64_t new_length, PreallocMode mode,
+ Error **errp)
{
BDRVQcow2State *s = bs->opaque;
uint64_t bytes;
uint64_t host_offset = 0;
+ int64_t file_length;
unsigned int cur_bytes;
int ret;
QCowL2Meta *meta;
@@ -2772,12 +2774,19 @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
* all of the allocated clusters (otherwise we get failing reads after
* EOF). Extend the image to the last allocated sector.
*/
- if (host_offset != 0) {
- uint8_t data = 0;
- ret = bdrv_pwrite(s->data_file, (host_offset + cur_bytes) - 1,
- &data, 1);
+ file_length = bdrv_getlength(s->data_file->bs);
+ if (file_length < 0) {
+ error_setg_errno(errp, -file_length, "Could not get file size");
+ return file_length;
+ }
+
+ if (host_offset + cur_bytes > file_length) {
+ if (mode == PREALLOC_MODE_METADATA) {
+ mode = PREALLOC_MODE_OFF;
+ }
+ ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, mode,
+ errp);
if (ret < 0) {
- error_setg_errno(errp, -ret, "Writing to EOF failed");
return ret;
}
}
@@ -3748,10 +3757,16 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
switch (prealloc) {
case PREALLOC_MODE_OFF:
+ if (has_data_file(bs)) {
+ ret = bdrv_co_truncate(s->data_file, offset, prealloc, errp);
+ if (ret < 0) {
+ goto fail;
+ }
+ }
break;
case PREALLOC_MODE_METADATA:
- ret = preallocate_co(bs, old_length, offset, errp);
+ ret = preallocate_co(bs, old_length, offset, prealloc, errp);
if (ret < 0) {
goto fail;
}
@@ -3768,7 +3783,7 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
/* With a data file, preallocation means just allocating the metadata
* and forwarding the truncate request to the data file */
if (has_data_file(bs)) {
- ret = preallocate_co(bs, old_length, offset, errp);
+ ret = preallocate_co(bs, old_length, offset, prealloc, errp);
if (ret < 0) {
goto fail;
}
@@ -3883,16 +3898,6 @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
bs->total_sectors = offset / BDRV_SECTOR_SIZE;
- if (has_data_file(bs)) {
- if (prealloc == PREALLOC_MODE_METADATA) {
- prealloc = PREALLOC_MODE_OFF;
- }
- ret = bdrv_co_truncate(s->data_file, offset, prealloc, errp);
- if (ret < 0) {
- goto fail;
- }
- }
-
/* write updated header.size */
offset = cpu_to_be64(offset);
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
--
2.19.1

View File

@ -0,0 +1,49 @@
From db04524f820582ebf1189223b6378de238511da1 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Mon, 29 Apr 2019 12:52:21 +0200
Subject: [PATCH] qcow2: Fix qcow2_make_empty() with external data file
make_completely_empty() is an optimisated path for bdrv_make_empty()
where completely new metadata is created inside the image file instead
of going through all clusters and discarding them. For an external data
file, however, we actually need to do discard operations on the data
file; just overwriting the qcow2 file doesn't get rid of the data.
The necessary slow path with an explicit discard operation already
exists for other cases. Use it for external data files, too.
Cc: qemu-stable@nongnu.org
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
(cherry-picked from commit db04524f820582ebf1189223b6378de238511da1)
---
block/qcow2.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index 7fbef97aab..840f289a48 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -4384,14 +4384,17 @@ static int qcow2_make_empty(BlockDriverState *bs)
if (s->qcow_version >= 3 && !s->snapshots && !s->nb_bitmaps &&
3 + l1_clusters <= s->refcount_block_size &&
- s->crypt_method_header != QCOW_CRYPT_LUKS) {
+ s->crypt_method_header != QCOW_CRYPT_LUKS &&
+ !has_data_file(bs)) {
/* The following function only works for qcow2 v3 images (it
* requires the dirty flag) and only as long as there are no
* features that reserve extra clusters (such as snapshots,
* LUKS header, or persistent bitmaps), because it completely
* empties the image. Furthermore, the L1 table and three
* additional clusters (image header, refcount table, one
- * refcount block) have to fit inside one refcount block. */
+ * refcount block) have to fit inside one refcount block. It
+ * only resets the image file, i.e. does not work with an
+ * external data file. */
return make_completely_empty(bs);
}
--
2.19.1

View File

@ -0,0 +1,27 @@
From 76ab77108279f9d328e4a7fe1684141084698d97 Mon Sep 17 00:00:00 2001
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
Date: Thu, 25 Jul 2019 16:05:11 +0800
Subject: [PATCH] qcow2: fix memory leak in qcow2_read_extensions
Free feature_table if it is failed in bdrv_pread.
Signed-off-by: fangyi <eric.fangyi@huawei.com>
---
block/qcow2.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/block/qcow2.c b/block/qcow2.c
index 3ace3b22..5e85cf4b 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -258,6 +258,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
void* feature_table = g_malloc0(ext.len + 2 * sizeof(Qcow2Feature));
ret = bdrv_pread(bs->file, offset , feature_table, ext.len);
if (ret < 0) {
+ g_free(feature_table);
error_setg_errno(errp, -ret, "ERROR: ext_feature_table: "
"Could not read table");
return ret;
--
2.19.1

BIN
qemu-4.0.0.tar.xz Normal file

Binary file not shown.

View File

@ -0,0 +1,75 @@
From 3283dde4b5b5cce0f96f48d536bebff66d97ce0b Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Tue, 23 Jul 2019 16:17:53 +0530
Subject: [PATCH 2/2] qemu-bridge-helper: move repeating code in parse_acl_file
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Move repeating error handling sequence in parse_acl_file routine
to an 'err' label.
This patch fixes CVE-2019-13164.
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Li Qiang <liq3ea@gmail.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
(cherry-picked from commit 3283dde4b5b5cce0f96f48d536bebff66d97ce0b)
---
qemu-bridge-helper.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c
index 2058e10454..3d50ec094c 100644
--- a/qemu-bridge-helper.c
+++ b/qemu-bridge-helper.c
@@ -102,9 +102,7 @@ static int parse_acl_file(const char *filename, ACLList *acl_list)
if (arg == NULL) {
fprintf(stderr, "Invalid config line:\n %s\n", line);
- fclose(f);
- errno = EINVAL;
- return -1;
+ goto err;
}
*arg = 0;
@@ -121,9 +119,7 @@ static int parse_acl_file(const char *filename, ACLList *acl_list)
if (!g_str_equal(cmd, "include") && strlen(arg) >= IFNAMSIZ) {
fprintf(stderr, "name `%s' too long: %zu\n", arg, strlen(arg));
- fclose(f);
- errno = EINVAL;
- return -1;
+ goto err;
}
if (strcmp(cmd, "deny") == 0) {
@@ -149,15 +145,18 @@ static int parse_acl_file(const char *filename, ACLList *acl_list)
parse_acl_file(arg, acl_list);
} else {
fprintf(stderr, "Unknown command `%s'\n", cmd);
- fclose(f);
- errno = EINVAL;
- return -1;
+ goto err;
}
}
fclose(f);
-
return 0;
+
+err:
+ fclose(f);
+ errno = EINVAL;
+ return -1;
+
}
static bool has_vnet_hdr(int fd)
--
2.19.1

View File

@ -0,0 +1,60 @@
From 6f5d8671225dc77190647f18a27a0d156d4ca97a Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Tue, 23 Jul 2019 16:17:52 +0530
Subject: [PATCH 1/2] qemu-bridge-helper: restrict interface name to IFNAMSIZ
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The network interface name in Linux is defined to be of size
IFNAMSIZ(=16), including the terminating null('\0') byte.
The same is applied to interface names read from 'bridge.conf'
file to form ACL rules. If user supplied '--br=bridge' name
is not restricted to the same length, it could lead to ACL bypass
issue. Restrict interface name to IFNAMSIZ, including null byte.
This patch fixes CVE-2019-13164.
Reported-by: Riccardo Schirone <rschiron@redhat.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Li Qiang <liq3ea@gmail.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
(cherry-picked from commit 6f5d8671225dc77190647f18a27a0d156d4ca97a)
---
qemu-bridge-helper.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c
index 95624bc300..2058e10454 100644
--- a/qemu-bridge-helper.c
+++ b/qemu-bridge-helper.c
@@ -119,6 +119,13 @@ static int parse_acl_file(const char *filename, ACLList *acl_list)
}
*argend = 0;
+ if (!g_str_equal(cmd, "include") && strlen(arg) >= IFNAMSIZ) {
+ fprintf(stderr, "name `%s' too long: %zu\n", arg, strlen(arg));
+ fclose(f);
+ errno = EINVAL;
+ return -1;
+ }
+
if (strcmp(cmd, "deny") == 0) {
acl_rule = g_malloc(sizeof(*acl_rule));
if (strcmp(arg, "all") == 0) {
@@ -269,6 +276,10 @@ int main(int argc, char **argv)
usage();
return EXIT_FAILURE;
}
+ if (strlen(bridge) >= IFNAMSIZ) {
+ fprintf(stderr, "name `%s' too long: %zu\n", bridge, strlen(bridge));
+ return EXIT_FAILURE;
+ }
/* parse default acl file */
QSIMPLEQ_INIT(&acl_list);
--
2.19.1

439
qemu.spec Normal file
View File

@ -0,0 +1,439 @@
Name: qemu
Version: 4.0.0
Release: 3
Epoch: 2
Summary: QEMU is a generic and open source machine emulator and virtualizer
License: GPLv2 and BSD and MIT and CC-BY
URL: http://www.qemu.org
Source0: https://www.qemu.org/download/%{name}-%{version}%{?rcstr}.tar.xz
Source1: 99-qemu-guest-agent.rules
Source2: bridge.conf
Patch0001: qxl-check-release-info-object.patch
Patch0002: target-i386-define-md-clear-bit.patch
Patch0003: Revert-Enable-build-and-install-of-our-rST-docs.patch
Patch0004: ARM64-record-vtimer-tick-when-cpu-is-stopped.patch
Patch0005: pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch
Patch0006: pl031-support-rtc-timer-property-for-pl031.patch
Patch0007: vhost-cancel-migration-when-vhost-user-restarted.patch
Patch0008: qcow2-fix-memory-leak-in-qcow2_read_extensions.patch
Patch0009: hw-arm-expose-host-CPU-frequency-info-to-guest.patch
Patch0010: block-Fix-AioContext-switch-for-bs-drv-NULL.patch
Patch0011: cutils-Fix-size_to_str-on-32-bit-platforms.patch
Patch0012: qcow2-Avoid-COW-during-metadata-preallocation.patch
Patch0013: qcow2-Add-errp-to-preallocate_co.patch
Patch0014: qcow2-Fix-full-preallocation-with-external-data-file.patch
Patch0015: qcow2-Fix-qcow2_make_empty-with-external-data-file.patch
Patch0016: megasas-fix-mapped-frame-size.patch
Patch0017: kbd-state-fix-autorepeat-handling.patch
Patch0018: block-file-posix-Unaligned-O_DIRECT-block-status.patch
Patch0019: hw-add-compat-machines-for-4.1.patch
Patch0020: q35-Revert-to-kernel-irqchip.patch
Patch0021: hw-Nuke-hw_compat_4_0_1-and-pc_compat_4_0_1.patch
Patch0022: vl-Fix-drive-blockdev-persistent-reservation-managem.patch
Patch0023: vhost-fix-vhost_log-size-overflow-during-migration.patch
Patch0024: virtio-pci-fix-missing-device-properties.patch
Patch0025: i386-acpi-fix-gint-overflow-in-crs_range_compare.patch
Patch0026: ioapic-kvm-Skip-route-updates-for-masked-pins.patch
Patch0027: i386-acpi-show-PCI-Express-bus-on-pxb-pcie-expanders.patch
Patch0028: virtio-balloon-Fix-wrong-sign-extension-of-PFNs.patch
Patch0029: virtio-balloon-Fix-QEMU-crashes-on-pagesize-BALLOON_.patch
Patch0030: virtio-balloon-Simplify-deflate-with-pbp.patch
Patch0031: virtio-balloon-Better-names-for-offset-variables.patch
Patch0032: virtio-balloon-Rework-pbp-tracking-data.patch
Patch0033: virtio-balloon-Use-temporary-PBP-only.patch
Patch0034: virtio-balloon-don-t-track-subpages-for-the-PBP.patch
Patch0035: virtio-balloon-free-pbp-more-aggressively.patch
Patch0036: qemu-bridge-helper-restrict-interface-name-to-IFNAMS.patch
Patch0037: qemu-bridge-helper-move-repeating-code-in-parse_acl.patch
Patch0038: smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch
Patch0039: hw-arm-virt-Introduce-cpu-topology-support.patch
Patch0040: hw-arm64-add-vcpu-cache-info-support.patch
Patch0041: xhci-Fix-memory-leak-in-xhci_address_slot.patch
Patch0042: xhci-Fix-memory-leak-in-xhci_kick_epctx.patch
Patch0043: ehci-fix-queue-dev-null-ptr-dereference.patch
Patch0044: memory-unref-the-memory-region-in-simplify-flatview.patch
Patch0045: scsi-lsi-exit-infinite-loop-while-executing-script-C.patch
Patch0046: util-async-hold-AioContext-ref-to-prevent-use-after-.patch
Patch0047: vhost-user-scsi-prevent-using-uninitialized-vqs.patch
Patch0048: cpu-add-Kunpeng-T82-cpu-support.patch
Patch0049: cpu-parse-feature-to-avoid-failure.patch
Patch0050: cpu-add-Cortex-A72-processor-kvm-target-support.patch
BuildRequires: flex
BuildRequires: bison
BuildRequires: texinfo
BuildRequires: perl-podlators
BuildRequires: kernel
BuildRequires: chrpath
BuildRequires: gettext
BuildRequires: zlib-devel
BuildRequires: gtk3-devel
BuildRequires: gnutls-devel
BuildRequires: numactl-devel
BuildRequires: device-mapper-multipath-devel
BuildRequires: libfdt-devel
BuildRequires: rdma-core-devel
BuildRequires: libcap-devel
BuildRequires: libcap-ng-devel
BuildRequires: cyrus-sasl-devel
BuildRequires: libaio-devel
BuildRequires: virglrenderer-devel
BuildRequires: usbredir-devel >= 0.5.2
BuildRequires: libseccomp-devel >= 2.3.0
BuildRequires: systemd-devel
BuildRequires: libiscsi-devel
BuildRequires: snappy-devel
BuildRequires: lzo-devel
BuildRequires: ncurses-devel
BuildRequires: libattr-devel
BuildRequires: libcurl-devel
BuildRequires: libjpeg-devel
BuildRequires: libpng-devel
BuildRequires: brlapi-devel
BuildRequires: pixman-devel
BuildRequires: libusbx-devel
BuildRequires: bzip2-devel
BuildRequires: libepoxy-devel
BuildRequires: libtasn1-devel
BuildRequires: libxml2-devel
%ifarch x86_64
BuildRequires: libpmem-devel
%endif
BuildRequires: libudev-devel
BuildRequires: pam-devel
BuildRequires: perl-Test-Harness
BuildRequires: python3-devel
Requires(post): /usr/bin/getent
Requires(post): /usr/sbin/groupadd
Requires(post): /usr/sbin/useradd
Requires(post): systemd-units
Requires(preun): systemd-units
Requires(postun): systemd-units
%description
QEMU is a FAST! processor emulator using dynamic translation to achieve good emulation speed.
QEMU has two operating modes:
Full system emulation. In this mode, QEMU emulates a full system (for example a PC),
including one or several processors and various peripherals. It can be used to launch
different Operating Systems without rebooting the PC or to debug system code.
User mode emulation. In this mode, QEMU can launch processes compiled for one CPU on another CPU.
It can be used to launch the Wine Windows API emulator (https://www.winehq.org) or to ease
cross-compilation and cross-debugging.
You can refer to https://www.qemu.org for more infortmation.
%package guest-agent
Summary: QEMU guest agent
Requires(post): systemd-units
Requires(preun): systemd-units
Requires(postun): systemd-units
%description guest-agent
This package provides an agent to run inside guests, which communicates
with the host over a virtio-serial channel named "org.qemu.guest_agent.0"
Please refer to https://wiki.qemu.org/Features/GuestAgent for more information.
%package help
Summary: Documents for qemu
Buildarch: noarch
%description help
This package provides documents for qemu related man help and information.
%package img
Summary: QEMU command line tool for manipulating disk images
%description img
This package provides a command line tool for manipulating disk images
%prep
%setup -q -n qemu-%{version}%{?rcstr}
%autopatch -p1
%build
%ifarch x86_64
buildarch="x86_64-softmmu"
%endif
%ifarch aarch64
buildarch="aarch64-softmmu"
%endif
buildldflags="VL_LDFLAGS=-Wl,--build-id"
./configure \
--prefix=%{_prefix} \
--target-list=${buildarch} \
--extra-cflags="%{optflags} -fPIE -DPIE -fno-inline -fPIC" \
--extra-ldflags="-Wl,--build-id -pie -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack" \
--datadir=%{_datadir} \
--docdir=%{_docdir}/%{name} \
--libdir=%{_libdir} \
--libexecdir=%{_libexecdir} \
--localstatedir=%{_localstatedir} \
--sysconfdir=%{_sysconfdir} \
--interp-prefix=%{_prefix}/qemu-%%M \
--firmwarepath=%{_datadir}/%{name} \
--with-pkgversion=%{name}-%{version}-%{release} \
--disable-strip \
--disable-werror \
--disable-slirp \
--enable-gtk \
--enable-docs \
--enable-guest-agent \
--enable-pie \
--enable-numa \
--enable-mpath \
--disable-libnfs \
--disable-bzip2 \
--enable-fdt \
--enable-kvm \
--enable-tcg \
--enable-rdma \
--enable-linux-aio \
--enable-cap-ng \
--enable-vhost-user \
--enable-virglrenderer \
--enable-cap-ng \
--enable-libusb \
--disable-bluez \
--disable-dmg \
--disable-qcow1 \
--disable-vdi \
--disable-vvfat \
--disable-qed \
--disable-parallels \
--disable-sheepdog \
--disable-capstone \
--disable-smartcard
make %{?_smp_mflags} $buildldflags V=1
cp -a ${buildarch}/qemu-system-* qemu-kvm
%install
make %{?_smp_mflags} DESTDIR=%{buildroot} \
install
%find_lang %{name}
install -m 0755 qemu-kvm %{buildroot}%{_libexecdir}/
rm $RPM_BUILD_ROOT%{_bindir}/qemu-system-*
install -D -p -m 0644 contrib/systemd/qemu-pr-helper.service %{buildroot}%{_unitdir}/qemu-pr-helper.service
install -D -p -m 0644 contrib/systemd/qemu-pr-helper.socket %{buildroot}%{_unitdir}/qemu-pr-helper.socket
install -D -p -m 0644 qemu.sasl %{buildroot}%{_sysconfdir}/sasl2/qemu.conf
install -D -m 0644 %{_sourcedir}/bridge.conf %{buildroot}%{_sysconfdir}/qemu/bridge.conf
# For qemu-guest-agent package
%global _udevdir /lib/udev/rules.d
install -D -p -m 0644 contrib/systemd/qemu-guest-agent.service %{buildroot}%{_unitdir}/qemu-guest-agent.service
install -D -m 0644 %{_sourcedir}/99-qemu-guest-agent.rules %{buildroot}%{_udevdir}/99-qemu-guest-agent.rules
mkdir -p %{buildroot}%{_localstatedir}/log
touch %{buildroot}%{_localstatedir}/log/qga-fsfreeze-hook.log
%global qemudocdir %{_docdir}/%{name}
install -D -p -m 0644 -t %{buildroot}%{qemudocdir} Changelog README COPYING COPYING.LIB LICENSE
chmod -x %{buildroot}%{_mandir}/man1/*
%ifarch aarch64
rm -rf %{buildroot}%{_datadir}/%{name}/vgabios*bin
rm -rf %{buildroot}%{_datadir}/%{name}/bios*.bin
rm -rf %{buildroot}%{_datadir}/%{name}/linuxboot.bin
rm -rf %{buildroot}%{_datadir}/%{name}/kvmvapic.bin
rm -rf %{buildroot}%{_datadir}/%{name}/sgabios.bin
rm -rf %{buildroot}%{_datadir}/%{name}/multiboot.bin
%endif
rm -rf %{buildroot}%{_datadir}/%{name}/openbios-*
rm -rf %{buildroot}%{_datadir}/%{name}/slof.bin
rm -rf %{buildroot}%{_datadir}/%{name}/QEMU,*.bin
rm -rf %{buildroot}%{_datadir}/%{name}/bamboo.dtb
rm -rf %{buildroot}%{_datadir}/%{name}/canyonlands.dtb
rm -rf %{buildroot}%{_datadir}/%{name}/hppa-firmware.img
rm -rf %{buildroot}%{_datadir}/%{name}/linuxboot_dma.bin
rm -rf %{buildroot}%{_datadir}/%{name}/palcode-clipper
rm -rf %{buildroot}%{_datadir}/%{name}/petalogix-*
rm -rf %{buildroot}%{_datadir}/%{name}/ppc_*
rm -rf %{buildroot}%{_datadir}/%{name}/pvh.bin
rm -rf %{buildroot}%{_datadir}/%{name}/qemu_vga.ndrv
rm -rf %{buildroot}%{_datadir}/%{name}/s390-*
rm -rf %{buildroot}%{_datadir}/%{name}/skiboot.lid
rm -rf %{buildroot}%{_datadir}/%{name}/spapr-*
rm -rf %{buildroot}%{_datadir}/%{name}/u-boot*
rm -rf %{buildroot}%{_bindir}/ivshmem*
for f in %{buildroot}%{_bindir}/* %{buildroot}%{_libdir}/* \
%{buildroot}%{_libexecdir}/*; do
if file $f | grep -q ELF | grep -q -i shared; then chrpath --delete $f; fi
done
%check
make check V=1
%pre
getent group kvm >/dev/null || groupadd -g 36 -r kvm
getent group qemu >/dev/null || groupadd -g 107 -r qemu
getent passwd qemu >/dev/null || \
useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
-c "qemu user" qemu
%post guest-agent
%systemd_post qemu-guest-agent.service
%preun guest-agent
%systemd_preun qemu-guest-agent.service
%postun guest-agent
%systemd_postun_with_restart qemu-guest-agent.service
%files -f %{name}.lang
%dir %{_datadir}/%{name}/
%{_libexecdir}/qemu-kvm
%{_datadir}/%{name}/efi-virtio.rom
%{_datadir}/%{name}/efi-e1000.rom
%{_datadir}/%{name}/efi-e1000e.rom
%{_datadir}/%{name}/efi-rtl8139.rom
%{_datadir}/%{name}/efi-pcnet.rom
%{_datadir}/%{name}/efi-ne2k_pci.rom
%{_datadir}/%{name}/efi-eepro100.rom
%{_datadir}/%{name}/efi-vmxnet3.rom
%{_datadir}/%{name}/pxe-virtio.rom
%{_datadir}/%{name}/pxe-e1000.rom
%{_datadir}/%{name}/pxe-ne2k_pci.rom
%{_datadir}/%{name}/pxe-pcnet.rom
%{_datadir}/%{name}/pxe-rtl8139.rom
%{_datadir}/%{name}/pxe-eepro100.rom
%{_datadir}/%{name}/trace-events-all
%{_datadir}/applications/qemu.desktop
%{_datadir}/icons/hicolor/*/apps/*
%{_datadir}/%{name}/keymaps/
%{_bindir}/elf2dmp
%{_bindir}/qemu-edid
%{_bindir}/qemu-keymap
%{_bindir}/qemu-pr-helper
%{_bindir}/virtfs-proxy-helper
%{_unitdir}/qemu-pr-helper.service
%{_unitdir}/qemu-pr-helper.socket
%attr(4755, root, root) %{_libexecdir}/qemu-bridge-helper
%config(noreplace) %{_sysconfdir}/sasl2/qemu.conf
%dir %{_sysconfdir}/qemu
%config(noreplace) %{_sysconfdir}/qemu/bridge.conf
%ifarch x86_64
%{_datadir}/%{name}/bios.bin
%{_datadir}/%{name}/bios-256k.bin
%{_datadir}/%{name}/vgabios.bin
%{_datadir}/%{name}/vgabios-cirrus.bin
%{_datadir}/%{name}/vgabios-qxl.bin
%{_datadir}/%{name}/vgabios-stdvga.bin
%{_datadir}/%{name}/vgabios-vmware.bin
%{_datadir}/%{name}/vgabios-virtio.bin
%{_datadir}/%{name}/vgabios-ramfb.bin
%{_datadir}/%{name}/vgabios-bochs-display.bin
%{_datadir}/%{name}/linuxboot.bin
%{_datadir}/%{name}/multiboot.bin
%{_datadir}/%{name}/kvmvapic.bin
%{_datadir}/%{name}/sgabios.bin
%endif
%files help
%dir %{qemudocdir}
%doc %{qemudocdir}/qemu-doc.html
%doc %{qemudocdir}/qemu-doc.txt
%doc %{qemudocdir}/qemu-ga-ref.html
%doc %{qemudocdir}/qemu-ga-ref.txt
%doc %{qemudocdir}/qemu-qmp-ref.html
%doc %{qemudocdir}/qemu-qmp-ref.txt
%doc %{qemudocdir}/README
%doc %{qemudocdir}/Changelog
%doc %{qemudocdir}/COPYING
%doc %{qemudocdir}/COPYING.LIB
%doc %{qemudocdir}/LICENSE
%{_mandir}/man1/qemu.1*
%{_mandir}/man1/virtfs-proxy-helper.1*
%{_mandir}/man7/qemu-block-drivers.7*
%{_mandir}/man7/qemu-cpu-models.7*
%{_mandir}/man7/qemu-ga-ref.7*
%{_mandir}/man7/qemu-qmp-ref.7*
%{_mandir}/man1/qemu-img.1*
%{_mandir}/man8/qemu-nbd.8*
%files guest-agent
%defattr(-,root,root,-)
%{_bindir}/qemu-ga
%{_mandir}/man8/qemu-ga.8*
%{_unitdir}/qemu-guest-agent.service
%{_udevdir}/99-qemu-guest-agent.rules
%ghost %{_localstatedir}/log/qga-fsfreeze-hook.log
%files img
%{_bindir}/qemu-img
%{_bindir}/qemu-io
%{_bindir}/qemu-nbd
%changelog
* Mon Sep 9 2019 backport from qemu upstream
- ehci-fix-queue-dev-null-ptr-dereference.patch
- memory-unref-the-memory-region-in-simplify-flatview.patch
- scsi-lsi-exit-infinite-loop-while-executing-script-C.patch
- util-async-hold-AioContext-ref-to-prevent-use-after-.patch
- vhost-user-scsi-prevent-using-uninitialized-vqs.patch
* Fri Aug 30 2019 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- xhci: Fix memory leak in xhci_address_slot
- xhci: Fix memory leak in xhci_kick_epctx
* Wed Aug 7 2019 Huawei Technologies Co., Ltd. <zhang.zhanghailiang@huawei.com>
- hw/arm/virt: Introduce cpu topology support
- hw/arm64: add vcpu cache info support
* Tue Aug 6 2019 Huawei Technologies Co., Ltd. <zhang.zhanghailiang@huawei.com>
- Update release version to 4.0.0-2
* Mon Aug 5 2019 Huawei Technologies Co., Ltd. <zhang.zhanghailiang@huawei.com>
- enable make check
- smbios: Add missing member of type 4 for smbios 3.0
* Mon Aug 5 2019 fix CVE-2019-13164
- qemu-bridge-helper: restrict interface name to IFNAMSIZ
- qemu-bridge-helper: move repeating code in parse_acl_file
* Wed Jul 31 2019 backport from qemu upstream
- block: Fix AioContext switch for bs->drv == NULL
- cutils: Fix size_to_str() on 32-bit platforms
- qcow2: Avoid COW during metadata preallocation
- qcow2: Add errp to preallocate_co()
- qcow2: qcow2: Fix full preallocation with external data file
- qcow2: Fix qcow2_make_empty() with external data file
- megasas: fix mapped frame size
- kbd-state: fix autorepeat handling
- block/file-posix: Unaligned O_DIRECT block-status
- hw: add compat machines for 4.1
- q35: Revert to kernel irqchip
- hw: Nuke hw_compat_4_0_1 and pc_compat_4_0_1
- vl: Fix -drive / -blockdev persistent reservation management
- vhost: fix vhost_log size overflow during migration
- virtio-pci: fix missing device properties
- i386/acpi: fix gint overflow in crs_range_compare
- ioapic: kvm: Skip route updates for masked pins
- i386/acpi: show PCI Express bus on pxb-pcie expanders
- virtio-balloon: Fix wrong sign extension of PFNs
- virtio-balloon: Fix QEMU crashes on pagesize > BALLOON_PAGE_SIZE
- virtio-balloon: Simplify deflate with pbp
- virtio-balloon: Better names for offset variables in inflate/deflate code
- virtio-balloon: Rework pbp tracking data
- virtio-balloon: Use temporary PBP only
- virtio-balloon: virtio-balloon: don't track subpages for the PBP
- virtio-balloon: free pbp more aggressively
* Tue Jul 30 2019 Huawei Technologies Co., Ltd. <zhang.zhanghailiang@huawei.com
- qcow2: fix memory leak in qcow2_read_extensions
- hw/arm: expose host CPU frequency info to guest
* Fri Jul 26 2019 Huawei Technologies Co., Ltd. <fangying1@huawei.com>
- vhost: cancel migration when vhost-user restarted
- pl031: support rtc-timer property for pl031
- pl011: reset read FIFO when UARTTIMSC=0 & UARTICR=0xffff
- ARM64: record vtimer tick when cpu is stopped
* Tue Jul 23 2019 openEuler Buildteam <buildteam@openeuler.org> - version-release
- Package init

View File

@ -0,0 +1,36 @@
From cbed4e0108ca1403f1f47cde292330b87a0d8bf2 Mon Sep 17 00:00:00 2001
From: Prasad J Pandit <pjp@fedoraproject.org>
Date: Thu, 25 Apr 2019 12:05:34 +0530
Subject: [PATCH] qxl: check release info object
When releasing spice resources in release_resource() routine,
if release info object 'ext.info' is null, it leads to null
pointer dereference. Add check to avoid it.
(This is cherry-pick d52680fc932efb8a2f334cc6993e705ed1e31e99)
Reported-by: Bugs SysSec <bugs-syssec@rub.de>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Message-id: 20190425063534.32747-1-ppandit@redhat.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
hw/display/qxl.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index c8ce578..632923a 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -777,6 +777,9 @@ static void interface_release_resource(QXLInstance *sin,
QXLReleaseRing *ring;
uint64_t *item, id;
+ if (!ext.info) {
+ return;
+ }
if (ext.group_id == MEMSLOT_GROUP_HOST) {
/* host group -> vga mode update request */
QXLCommandExt *cmdext = (void *)(intptr_t)(ext.info->id);
--
1.8.3.1

View File

@ -0,0 +1,104 @@
From dee1c7242e6b11d502728840f36d021ceedce140 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Wed, 14 Aug 2019 17:35:21 +0530
Subject: [PATCH 3/5] scsi: lsi: exit infinite loop while executing script
(CVE-2019-12068)
When executing script in lsi_execute_script(), the LSI scsi adapter
emulator advances 's->dsp' index to read next opcode. This can lead
to an infinite loop if the next opcode is empty. Move the existing
loop exit after 10k iterations so that it covers no-op opcodes as
well.
Reported-by: Bugs SysSec <bugs-syssec@rub.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from commit de594e47659029316bbf9391efb79da0a1a08e08)
---
hw/scsi/lsi53c895a.c | 41 +++++++++++++++++++++++++++--------------
1 file changed, 27 insertions(+), 14 deletions(-)
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index da7239d..d3380b6 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -184,6 +184,9 @@ static const char *names[] = {
/* Flag set if this is a tagged command. */
#define LSI_TAG_VALID (1 << 16)
+/* Maximum instructions to process. */
+#define LSI_MAX_INSN 10000
+
typedef struct lsi_request {
SCSIRequest *req;
uint32_t tag;
@@ -1131,7 +1134,21 @@ static void lsi_execute_script(LSIState *s)
s->istat1 |= LSI_ISTAT1_SRUN;
again:
- insn_processed++;
+ if (++insn_processed > LSI_MAX_INSN) {
+ /* Some windows drivers make the device spin waiting for a memory
+ location to change. If we have been executed a lot of code then
+ assume this is the case and force an unexpected device disconnect.
+ This is apparently sufficient to beat the drivers into submission.
+ */
+ if (!(s->sien0 & LSI_SIST0_UDC)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "lsi_scsi: inf. loop with UDC masked");
+ }
+ lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0);
+ lsi_disconnect(s);
+ trace_lsi_execute_script_stop();
+ return;
+ }
insn = read_dword(s, s->dsp);
if (!insn) {
/* If we receive an empty opcode increment the DSP by 4 bytes
@@ -1568,19 +1585,7 @@ again:
}
}
}
- if (insn_processed > 10000 && s->waiting == LSI_NOWAIT) {
- /* Some windows drivers make the device spin waiting for a memory
- location to change. If we have been executed a lot of code then
- assume this is the case and force an unexpected device disconnect.
- This is apparently sufficient to beat the drivers into submission.
- */
- if (!(s->sien0 & LSI_SIST0_UDC)) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "lsi_scsi: inf. loop with UDC masked");
- }
- lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0);
- lsi_disconnect(s);
- } else if (s->istat1 & LSI_ISTAT1_SRUN && s->waiting == LSI_NOWAIT) {
+ if (s->istat1 & LSI_ISTAT1_SRUN && s->waiting == LSI_NOWAIT) {
if (s->dcntl & LSI_DCNTL_SSM) {
lsi_script_dma_interrupt(s, LSI_DSTAT_SSI);
} else {
@@ -1968,6 +1973,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
case 0x2f: /* DSP[24:31] */
s->dsp &= 0x00ffffff;
s->dsp |= val << 24;
+ /*
+ * FIXME: if s->waiting != LSI_NOWAIT, this will only execute one
+ * instruction. Is this correct?
+ */
if ((s->dmode & LSI_DMODE_MAN) == 0
&& (s->istat1 & LSI_ISTAT1_SRUN) == 0)
lsi_execute_script(s);
@@ -1986,6 +1995,10 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
break;
case 0x3b: /* DCNTL */
s->dcntl = val & ~(LSI_DCNTL_PFF | LSI_DCNTL_STD);
+ /*
+ * FIXME: if s->waiting != LSI_NOWAIT, this will only execute one
+ * instruction. Is this correct?
+ */
if ((val & LSI_DCNTL_STD) && (s->istat1 & LSI_ISTAT1_SRUN) == 0)
lsi_execute_script(s);
break;
--
1.8.3.1

View File

@ -0,0 +1,57 @@
From e52fdbd850b49304c5bbd5f19c9f518b80efef42 Mon Sep 17 00:00:00 2001
From: zhanghailiang <zhang.zhanghailiang@huawei.com>
Date: Wed, 31 Jul 2019 15:40:55 +0800
Subject: [PATCH] smbios: Add missing member of type 4 for smbios 3.0
According to smbios 3.0 spec, for processor information (type 4),
it adds three new members (Core Count 2, Core enabled 2, thread count 2) for 3.0,
Without this three members, we can not get correct cpu frequency from dmi,
Because it will failed to check the length of Processor Infomation in DMI.
The corresponding codes in kernel is like:
if (dm->type == DMI_ENTRY_PROCESSOR &&
dm->length >= DMI_ENTRY_PROCESSOR_MIN_LENGTH) {
u16 val = (u16)get_unaligned((const u16 *)
(dmi_data + DMI_PROCESSOR_MAX_SPEED));
*mhz = val > *mhz ? val : *mhz;
}
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
---
hw/smbios/smbios.c | 4 +++-
include/hw/firmware/smbios.h | 3 +++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index 47be9071..b11ec6e3 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -600,7 +600,9 @@ static void smbios_build_type_4_table(unsigned instance)
t->thread_count = smp_threads;
t->processor_characteristics = cpu_to_le16(0x02); /* Unknown */
t->processor_family2 = cpu_to_le16(0x01); /* Other */
-
+ t->corecount2 = 0;
+ t->enabledcorecount2 = 0;
+ t->threadcount2 = 0;
SMBIOS_BUILD_TABLE_POST;
smbios_type4_count++;
}
diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
index 6fef32a3..70eb7304 100644
--- a/include/hw/firmware/smbios.h
+++ b/include/hw/firmware/smbios.h
@@ -193,6 +193,9 @@ struct smbios_type_4 {
uint8_t thread_count;
uint16_t processor_characteristics;
uint16_t processor_family2;
+ uint16_t corecount2;
+ uint16_t enabledcorecount2;
+ uint16_t threadcount2;
} QEMU_PACKED;
/* SMBIOS type 11 - OEM strings */
--
2.19.1

View File

@ -0,0 +1,29 @@
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Wed, 15 May 2019 15:10:10 +0100
Subject: [PATCH] target/i386: define md-clear bit
md-clear is a new CPUID bit which is set when microcode provides the
mechanism to invoke a flush of various exploitable CPU buffers by invoking
the VERW instruction.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20190515141011.5315-2-berrange@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
(cherry picked from commit b2ae52101fca7f9547ac2f388085dbc58f8fe1c0)
---
target/i386/cpu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index d6bb57d210..4ea78a4939 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1076,7 +1076,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
.feat_names = {
NULL, NULL, "avx512-4vnniw", "avx512-4fmaps",
NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
+ NULL, NULL, "md-clear", NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,

View File

@ -0,0 +1,63 @@
From e965bc6c633921ab238b1f5ea64055975b24e2bb Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Tue, 23 Jul 2019 20:06:23 +0100
Subject: [PATCH 4/5] util/async: hold AioContext ref to prevent use-after-free
The tests/test-bdrv-drain /bdrv-drain/iothread/drain test case does the
following:
1. The preadv coroutine calls aio_bh_schedule_oneshot() and then yields.
2. The one-shot BH executes in another AioContext. All it does is call
aio_co_wakeup(preadv_co).
3. The preadv coroutine is re-entered and returns.
There is a race condition in aio_co_wake() where the preadv coroutine
returns and the test case destroys the preadv IOThread. aio_co_wake()
can still be running in the other AioContext and it performs an access
to the freed IOThread AioContext.
Here is the race in aio_co_schedule():
QSLIST_INSERT_HEAD_ATOMIC(&ctx->scheduled_coroutines,
co, co_scheduled_next);
<-- race: co may execute before we invoke qemu_bh_schedule()!
qemu_bh_schedule(ctx->co_schedule_bh);
So if co causes ctx to be freed then we're in trouble. Fix this problem
by holding a reference to ctx.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 20190723190623.21537-1-stefanha@redhat.com
Message-Id: <20190723190623.21537-1-stefanha@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry-picked from commit f0f81002873c06fdef9bb2a272ddfd26af65b851)
---
util/async.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/util/async.c b/util/async.c
index c10642a..afc17fb 100644
--- a/util/async.c
+++ b/util/async.c
@@ -460,9 +460,17 @@ void aio_co_schedule(AioContext *ctx, Coroutine *co)
abort();
}
+ /* The coroutine might run and release the last ctx reference before we
+ * invoke qemu_bh_schedule(). Take a reference to keep ctx alive until
+ * we're done.
+ */
+ aio_context_ref(ctx);
+
QSLIST_INSERT_HEAD_ATOMIC(&ctx->scheduled_coroutines,
co, co_scheduled_next);
qemu_bh_schedule(ctx->co_schedule_bh);
+
+ aio_context_unref(ctx);
}
void aio_co_wake(struct Coroutine *co)
--
1.8.3.1

View File

@ -0,0 +1,60 @@
From 750328e01afe4776eaddacde406063978dbf1291 Mon Sep 17 00:00:00 2001
From: Ying Fang <fangying1@huawei.com>
Date: Mon, 29 Jul 2019 16:22:12 +0800
Subject: [PATCH] vhost: cancel migration when vhost-user restarted during
migraiton
Qemu will abort when vhost-user process is restarted during migration
when vhost_log_global_start/stop is called. The reason is clear that
vhost_dev_set_log returns -1 because network connection is temporarily
lost. Let's cancel migraiton and report it to user in this abnormal
situation.
Signed-off-by: Ying Fang <fangying1@huawei.com>
Reviewed-by: Gonglei <arei.gonglei@huawei.com>
---
hw/virtio/vhost.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 7f61018f..f302c506 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -26,6 +26,7 @@
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
#include "migration/blocker.h"
+#include "migration/migration.h"
#include "sysemu/dma.h"
#include "trace.h"
@@ -808,20 +809,24 @@ static int vhost_migration_log(MemoryListener *listener, int enable)
static void vhost_log_global_start(MemoryListener *listener)
{
int r;
+ Error *errp = NULL;
r = vhost_migration_log(listener, true);
if (r < 0) {
- abort();
+ error_setg(&errp, "Failed to start vhost migration log");
+ migrate_fd_error(migrate_get_current(), errp);
}
}
static void vhost_log_global_stop(MemoryListener *listener)
{
int r;
+ Error *errp = NULL;
r = vhost_migration_log(listener, false);
if (r < 0) {
- abort();
+ error_setg(&errp, "Failed to stop vhost migration log");
+ migrate_fd_error(migrate_get_current(), errp);
}
}
--
2.19.1

View File

@ -0,0 +1,69 @@
From 240e647a14df9677b3a501f7b8b870e40aac3fd5 Mon Sep 17 00:00:00 2001
From: Li Hangjing <lihangjing@baidu.com>
Date: Mon, 3 Jun 2019 14:15:24 +0800
Subject: [PATCH] vhost: fix vhost_log size overflow during migration
When a guest which doesn't support multiqueue is migrated with a multi queues
vhost-user-blk deivce, a crash will occur like:
0 qemu_memfd_alloc (name=<value optimized out>, size=562949953421312, seals=<value optimized out>, fd=0x7f87171fe8b4, errp=0x7f87171fe8a8) at util/memfd.c:153
1 0x00007f883559d7cf in vhost_log_alloc (size=70368744177664, share=true) at hw/virtio/vhost.c:186
2 0x00007f88355a0758 in vhost_log_get (listener=0x7f8838bd7940, enable=1) at qemu-2-12/hw/virtio/vhost.c:211
3 vhost_dev_log_resize (listener=0x7f8838bd7940, enable=1) at hw/virtio/vhost.c:263
4 vhost_migration_log (listener=0x7f8838bd7940, enable=1) at hw/virtio/vhost.c:787
5 0x00007f88355463d6 in memory_global_dirty_log_start () at memory.c:2503
6 0x00007f8835550577 in ram_init_bitmaps (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2173
7 ram_init_all (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2192
8 ram_save_setup (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2219
9 0x00007f88357a419d in qemu_savevm_state_setup (f=0x7f88384ce600) at migration/savevm.c:1002
10 0x00007f883579fc3e in migration_thread (opaque=0x7f8837530400) at migration/migration.c:2382
11 0x00007f8832447893 in start_thread () from /lib64/libpthread.so.0
12 0x00007f8832178bfd in clone () from /lib64/libc.so.6
This is because vhost_get_log_size() returns a overflowed vhost-log size.
In this function, it uses the uninitialized variable vqs->used_phys and
vqs->used_size to get the vhost-log size.
Signed-off-by: Li Hangjing <lihangjing@baidu.com>
Reviewed-by: Xie Yongji <xieyongji@baidu.com>
Reviewed-by: Chai Wen <chaiwen@baidu.com>
Message-Id: <20190603061524.24076-1-lihangjing@baidu.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry-pick from commit 240e647a14df9677b3a501f7b8b870e40aac3fd5)
---
hw/virtio/vhost.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 60747a6f93..bc899fc60e 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -131,6 +131,11 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
}
for (i = 0; i < dev->nvqs; ++i) {
struct vhost_virtqueue *vq = dev->vqs + i;
+
+ if (!vq->used_phys && !vq->used_size) {
+ continue;
+ }
+
vhost_dev_sync_region(dev, section, start_addr, end_addr, vq->used_phys,
range_get_last(vq->used_phys, vq->used_size));
}
@@ -168,6 +173,11 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev)
}
for (i = 0; i < dev->nvqs; ++i) {
struct vhost_virtqueue *vq = dev->vqs + i;
+
+ if (!vq->used_phys && !vq->used_size) {
+ continue;
+ }
+
uint64_t last = vq->used_phys + vq->used_size - 1;
log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1);
}
--
2.19.1

View File

@ -0,0 +1,43 @@
From 19d56f560879081de411f359417eaaa2998c9e3a Mon Sep 17 00:00:00 2001
From: Raphael Norwitz <raphael.norwitz@nutanix.com>
Date: Tue, 11 Jun 2019 17:35:17 -0700
Subject: [PATCH 5/5] vhost-user-scsi: prevent using uninitialized vqs
Of the 3 virtqueues, seabios only sets cmd, leaving ctrl
and event without a physical address. This can cause
vhost_verify_ring_part_mapping to return ENOMEM, causing
the following logs:
qemu-system-x86_64: Unable to map available ring for ring 0
qemu-system-x86_64: Verify ring failure on region 0
The qemu commit e6cc11d64fc998c11a4dfcde8fda3fc33a74d844
has already resolved the issue for vhost scsi devices but
the fix was never applied to vhost-user scsi devices.
Signed-off-by: Raphael Norwitz <raphael.norwitz@nutanix.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 1560299717-177734-1-git-send-email-raphael.norwitz@nutanix.com
Message-Id: <1560299717-177734-1-git-send-email-raphael.norwitz@nutanix.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry-picked from commit 5d4c1ed3d46d7e2010b389fe5f3376f605182ab0)
---
hw/scsi/vhost-user-scsi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c
index 8b1e687..241631f 100644
--- a/hw/scsi/vhost-user-scsi.c
+++ b/hw/scsi/vhost-user-scsi.c
@@ -90,7 +90,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
}
vsc->dev.nvqs = 2 + vs->conf.num_queues;
- vsc->dev.vqs = g_new(struct vhost_virtqueue, vsc->dev.nvqs);
+ vsc->dev.vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs);
vsc->dev.vq_index = 0;
vsc->dev.backend_features = 0;
--
1.8.3.1

View File

@ -0,0 +1,113 @@
From e6129b271b9dccca22c84870e313c315f2c70063 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Mon, 22 Jul 2019 15:41:06 +0200
Subject: [PATCH] virtio-balloon: Better names for offset variables in
inflate/deflate code
"host_page_base" is really confusing, let's make this clearer, also
rename the other offsets to indicate to which base they apply.
offset -> mr_offset
ram_offset -> rb_offset
host_page_base -> rb_aligned_offset
While at it, use QEMU_ALIGN_DOWN() instead of a handcrafted computation
and move the computation to the place where it is needed.
Acked-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190722134108.22151-5-david@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry-picked from commit e6129b271b9dccca22c84870e313c315f2c70063)
---
hw/virtio/virtio-balloon.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 04a7e6c772..f206cc8bf7 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -41,24 +41,23 @@ struct PartiallyBalloonedPage {
};
static void balloon_inflate_page(VirtIOBalloon *balloon,
- MemoryRegion *mr, hwaddr offset)
+ MemoryRegion *mr, hwaddr mr_offset)
{
- void *addr = memory_region_get_ram_ptr(mr) + offset;
+ void *addr = memory_region_get_ram_ptr(mr) + mr_offset;
+ ram_addr_t rb_offset, rb_aligned_offset;
RAMBlock *rb;
size_t rb_page_size;
int subpages;
- ram_addr_t ram_offset, host_page_base;
/* XXX is there a better way to get to the RAMBlock than via a
* host address? */
- rb = qemu_ram_block_from_host(addr, false, &ram_offset);
+ rb = qemu_ram_block_from_host(addr, false, &rb_offset);
rb_page_size = qemu_ram_pagesize(rb);
- host_page_base = ram_offset & ~(rb_page_size - 1);
if (rb_page_size == BALLOON_PAGE_SIZE) {
/* Easy case */
- ram_block_discard_range(rb, ram_offset, rb_page_size);
+ ram_block_discard_range(rb, rb_offset, rb_page_size);
/* We ignore errors from ram_block_discard_range(), because it
* has already reported them, and failing to discard a balloon
* page is not fatal */
@@ -74,11 +73,12 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
warn_report_once(
"Balloon used with backing page size > 4kiB, this may not be reliable");
+ rb_aligned_offset = QEMU_ALIGN_DOWN(rb_offset, rb_page_size);
subpages = rb_page_size / BALLOON_PAGE_SIZE;
if (balloon->pbp
&& (rb != balloon->pbp->rb
- || host_page_base != balloon->pbp->base)) {
+ || rb_aligned_offset != balloon->pbp->base)) {
/* We've partially ballooned part of a host page, but now
* we're trying to balloon part of a different one. Too hard,
* give up on the old partial page */
@@ -91,10 +91,10 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
size_t bitlen = BITS_TO_LONGS(subpages) * sizeof(unsigned long);
balloon->pbp = g_malloc0(sizeof(PartiallyBalloonedPage) + bitlen);
balloon->pbp->rb = rb;
- balloon->pbp->base = host_page_base;
+ balloon->pbp->base = rb_aligned_offset;
}
- set_bit((ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
+ set_bit((rb_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
balloon->pbp->bitmap);
if (bitmap_full(balloon->pbp->bitmap, subpages)) {
@@ -112,18 +112,18 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
}
static void balloon_deflate_page(VirtIOBalloon *balloon,
- MemoryRegion *mr, hwaddr offset)
+ MemoryRegion *mr, hwaddr mr_offset)
{
- void *addr = memory_region_get_ram_ptr(mr) + offset;
+ void *addr = memory_region_get_ram_ptr(mr) + mr_offset;
+ ram_addr_t rb_offset;
RAMBlock *rb;
size_t rb_page_size;
- ram_addr_t ram_offset;
void *host_addr;
int ret;
/* XXX is there a better way to get to the RAMBlock than via a
* host address? */
- rb = qemu_ram_block_from_host(addr, false, &ram_offset);
+ rb = qemu_ram_block_from_host(addr, false, &rb_offset);
rb_page_size = qemu_ram_pagesize(rb);
if (balloon->pbp) {
--
2.19.1

View File

@ -0,0 +1,64 @@
From 483f13524bb2a08b7ff6a7560b846564ed3b0c33 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Mon, 22 Jul 2019 15:41:04 +0200
Subject: [PATCH] virtio-balloon: Fix QEMU crashes on pagesize >
BALLOON_PAGE_SIZE
We are using the wrong functions to set/clear bits, effectively touching
multiple bits, writing out of range of the bitmap, resulting in memory
corruptions. We have to use set_bit()/clear_bit() instead.
Can easily be reproduced by starting a qemu guest on hugetlbfs memory,
inflating the balloon. QEMU crashes. This never could have worked
properly - especially, also pages would have been discarded when the
first sub-page would be inflated (the whole bitmap would be set).
While testing I realized, that on hugetlbfs it is pretty much impossible
to discard a page - the guest just frees the 4k sub-pages in random order
most of the time. I was only able to discard a hugepage a handful of
times - so I hope that now works correctly.
Fixes: ed48c59875b6 ("virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size")
Fixes: b27b32391404 ("virtio-balloon: Fix possible guest memory corruption with inflates & deflates")
Cc: qemu-stable@nongnu.org #v4.0.0
Acked-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190722134108.22151-3-david@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry-pick from commit 483f13524bb2a08b7ff6a7560b846564ed3b0c33)
---
hw/virtio/virtio-balloon.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 515abf6553..a78d2d2184 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -94,9 +94,8 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
balloon->pbp->base = host_page_base;
}
- bitmap_set(balloon->pbp->bitmap,
- (ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
- subpages);
+ set_bit((ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
+ balloon->pbp->bitmap);
if (bitmap_full(balloon->pbp->bitmap, subpages)) {
/* We've accumulated a full host page, we can actually discard
@@ -140,9 +139,8 @@ static void balloon_deflate_page(VirtIOBalloon *balloon,
* for a guest to do this in practice, but handle it anyway,
* since getting it wrong could mean discarding memory the
* guest is still using. */
- bitmap_clear(balloon->pbp->bitmap,
- (ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
- subpages);
+ clear_bit((ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
+ balloon->pbp->bitmap);
if (bitmap_empty(balloon->pbp->bitmap, subpages)) {
g_free(balloon->pbp);
--
2.19.1

View File

@ -0,0 +1,41 @@
From ffa207d08253ffffb3993a1dbe09e40af4fc91f1 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Mon, 22 Jul 2019 15:41:03 +0200
Subject: [PATCH] virtio-balloon: Fix wrong sign extension of PFNs
If we directly cast from int to uint64_t, we will first sign-extend to
an int64_t, which is wrong. We actually want to treat the PFNs like
unsigned values.
As far as I can see, this dates back to the initial virtio-balloon
commit, but wasn't triggered as fairly big guests would be required.
Cc: qemu-stable@nongnu.org
Reported-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190722134108.22151-2-david@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
(cherry-picked from commit ffa207d08253ffffb3993a1dbe09e40af4fc91f1)
---
hw/virtio/virtio-balloon.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index e85d1c0d5c..515abf6553 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -343,8 +343,8 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
}
while (iov_to_buf(elem->out_sg, elem->out_num, offset, &pfn, 4) == 4) {
+ unsigned int p = virtio_ldl_p(vdev, &pfn);
hwaddr pa;
- int p = virtio_ldl_p(vdev, &pfn);
pa = (hwaddr) p << VIRTIO_BALLOON_PFN_SHIFT;
offset += 4;
--
2.19.1

View File

@ -0,0 +1,144 @@
From 1c5cfc2b7153dd72bf4b8ddc456408eb2b9b66d8 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Mon, 22 Jul 2019 15:41:07 +0200
Subject: [PATCH] virtio-balloon: Rework pbp tracking data
Using the address of a RAMBlock to test for a matching pbp is not really
safe. Instead, let's use the guest physical address of the base page
along with the page size (via the number of subpages).
Also, let's allocate the bitmap separately. This makes the code
easier to read and maintain - we can reuse bitmap_new().
Prepare the code to move the PBP out of the device.
Fixes: ed48c59875b6 ("virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size")
Fixes: b27b32391404 ("virtio-balloon: Fix possible guest memory corruption with inflates & deflates")
Cc: qemu-stable@nongnu.org #v4.0.0
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190722134108.22151-6-david@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry-picked from commit 1c5cfc2b7153dd72bf4b8ddc456408eb2b9b66d8)
---
hw/virtio/virtio-balloon.c | 69 +++++++++++++++++++++++++-------------
1 file changed, 46 insertions(+), 23 deletions(-)
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index f206cc8bf7..40d493a31a 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -35,16 +35,44 @@
#define BALLOON_PAGE_SIZE (1 << VIRTIO_BALLOON_PFN_SHIFT)
struct PartiallyBalloonedPage {
- RAMBlock *rb;
- ram_addr_t base;
- unsigned long bitmap[];
+ ram_addr_t base_gpa;
+ long subpages;
+ unsigned long *bitmap;
};
+static void virtio_balloon_pbp_free(PartiallyBalloonedPage *pbp)
+{
+ if (!pbp) {
+ return;
+ }
+ g_free(pbp->bitmap);
+ g_free(pbp);
+}
+
+static PartiallyBalloonedPage *virtio_balloon_pbp_alloc(ram_addr_t base_gpa,
+ long subpages)
+{
+ PartiallyBalloonedPage *pbp = g_new0(PartiallyBalloonedPage, 1);
+
+ pbp->base_gpa = base_gpa;
+ pbp->subpages = subpages;
+ pbp->bitmap = bitmap_new(subpages);
+
+ return pbp;
+}
+
+static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp,
+ ram_addr_t base_gpa, long subpages)
+{
+ return pbp->subpages == subpages && pbp->base_gpa == base_gpa;
+}
+
static void balloon_inflate_page(VirtIOBalloon *balloon,
MemoryRegion *mr, hwaddr mr_offset)
{
void *addr = memory_region_get_ram_ptr(mr) + mr_offset;
- ram_addr_t rb_offset, rb_aligned_offset;
+ ram_addr_t rb_offset, rb_aligned_offset, base_gpa;
+ PartiallyBalloonedPage **pbp = &balloon->pbp;
RAMBlock *rb;
size_t rb_page_size;
int subpages;
@@ -75,39 +103,34 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
rb_aligned_offset = QEMU_ALIGN_DOWN(rb_offset, rb_page_size);
subpages = rb_page_size / BALLOON_PAGE_SIZE;
+ base_gpa = memory_region_get_ram_addr(mr) + mr_offset -
+ (rb_offset - rb_aligned_offset);
- if (balloon->pbp
- && (rb != balloon->pbp->rb
- || rb_aligned_offset != balloon->pbp->base)) {
+ if (*pbp && !virtio_balloon_pbp_matches(*pbp, base_gpa, subpages)) {
/* We've partially ballooned part of a host page, but now
* we're trying to balloon part of a different one. Too hard,
* give up on the old partial page */
- g_free(balloon->pbp);
- balloon->pbp = NULL;
+ virtio_balloon_pbp_free(*pbp);
+ *pbp = NULL;
}
- if (!balloon->pbp) {
- /* Starting on a new host page */
- size_t bitlen = BITS_TO_LONGS(subpages) * sizeof(unsigned long);
- balloon->pbp = g_malloc0(sizeof(PartiallyBalloonedPage) + bitlen);
- balloon->pbp->rb = rb;
- balloon->pbp->base = rb_aligned_offset;
+ if (!*pbp) {
+ *pbp = virtio_balloon_pbp_alloc(base_gpa, subpages);
}
- set_bit((rb_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
- balloon->pbp->bitmap);
+ set_bit((rb_offset - rb_aligned_offset) / BALLOON_PAGE_SIZE,
+ (*pbp)->bitmap);
- if (bitmap_full(balloon->pbp->bitmap, subpages)) {
+ if (bitmap_full((*pbp)->bitmap, subpages)) {
/* We've accumulated a full host page, we can actually discard
* it now */
- ram_block_discard_range(rb, balloon->pbp->base, rb_page_size);
+ ram_block_discard_range(rb, rb_aligned_offset, rb_page_size);
/* We ignore errors from ram_block_discard_range(), because it
* has already reported them, and failing to discard a balloon
* page is not fatal */
-
- g_free(balloon->pbp);
- balloon->pbp = NULL;
+ virtio_balloon_pbp_free(*pbp);
+ *pbp = NULL;
}
}
@@ -128,7 +151,7 @@ static void balloon_deflate_page(VirtIOBalloon *balloon,
if (balloon->pbp) {
/* Let's play safe and always reset the pbp on deflation requests. */
- g_free(balloon->pbp);
+ virtio_balloon_pbp_free(balloon->pbp);
balloon->pbp = NULL;
}
--
2.19.1

View File

@ -0,0 +1,67 @@
From 2ffc49eea1bbd454913a88a0ad872c2649b36950 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Mon, 22 Jul 2019 15:41:05 +0200
Subject: [PATCH] virtio-balloon: Simplify deflate with pbp
Let's simplify this - the case we are optimizing for is very hard to
trigger and not worth the effort. If we're switching from inflation to
deflation, let's reset the pbp.
Acked-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190722134108.22151-4-david@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry-picked from commit 2ffc49eea1bbd454913a88a0ad872c2649b36950)
---
hw/virtio/virtio-balloon.c | 26 +++++---------------------
1 file changed, 5 insertions(+), 21 deletions(-)
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index a78d2d2184..04a7e6c772 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -117,7 +117,7 @@ static void balloon_deflate_page(VirtIOBalloon *balloon,
void *addr = memory_region_get_ram_ptr(mr) + offset;
RAMBlock *rb;
size_t rb_page_size;
- ram_addr_t ram_offset, host_page_base;
+ ram_addr_t ram_offset;
void *host_addr;
int ret;
@@ -125,27 +125,11 @@ static void balloon_deflate_page(VirtIOBalloon *balloon,
* host address? */
rb = qemu_ram_block_from_host(addr, false, &ram_offset);
rb_page_size = qemu_ram_pagesize(rb);
- host_page_base = ram_offset & ~(rb_page_size - 1);
-
- if (balloon->pbp
- && rb == balloon->pbp->rb
- && host_page_base == balloon->pbp->base) {
- int subpages = rb_page_size / BALLOON_PAGE_SIZE;
- /*
- * This means the guest has asked to discard some of the 4kiB
- * subpages of a host page, but then changed its mind and
- * asked to keep them after all. It's exceedingly unlikely
- * for a guest to do this in practice, but handle it anyway,
- * since getting it wrong could mean discarding memory the
- * guest is still using. */
- clear_bit((ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
- balloon->pbp->bitmap);
-
- if (bitmap_empty(balloon->pbp->bitmap, subpages)) {
- g_free(balloon->pbp);
- balloon->pbp = NULL;
- }
+ if (balloon->pbp) {
+ /* Let's play safe and always reset the pbp on deflation requests. */
+ g_free(balloon->pbp);
+ balloon->pbp = NULL;
}
host_addr = (void *)((uintptr_t)addr & ~(rb_page_size - 1));
--
2.19.1

View File

@ -0,0 +1,132 @@
From a8cd64d488325f3be5c4ddec4bf07efb3b8c7330 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Mon, 22 Jul 2019 15:41:08 +0200
Subject: [PATCH] virtio-balloon: Use temporary PBP only
We still have multiple issues in the current code
- The PBP is not freed during unrealize()
- The PBP is not reset on device resets: After a reset, the PBP is stale.
- We are not indicating VIRTIO_BALLOON_F_MUST_TELL_HOST, therefore
guests (esp. legacy guests) will reuse pages without deflating,
turning the PBP stale. Adding that would require compat handling.
Instead, let's use the PBP only temporarily, when processing one bulk of
inflation requests. This will keep guest_page_size > 4k working (with
Linux guests). There is nothing to do for deflation requests anymore.
The pbp is only used for a limited amount of time.
Fixes: ed48c59875b6 ("virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size")
Cc: qemu-stable@nongnu.org #v4.0.0
Suggested-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190722134108.22151-7-david@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
(cherry-picked from commit a8cd64d488325f3be5c4ddec4bf07efb3b8c7330)
---
hw/virtio/virtio-balloon.c | 21 +++++++++------------
include/hw/virtio/virtio-balloon.h | 3 ---
2 files changed, 9 insertions(+), 15 deletions(-)
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index ccd766d2..d4b4a05b 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -34,11 +34,11 @@
#define BALLOON_PAGE_SIZE (1 << VIRTIO_BALLOON_PFN_SHIFT)
-struct PartiallyBalloonedPage {
+typedef struct PartiallyBalloonedPage {
ram_addr_t base_gpa;
long subpages;
unsigned long *bitmap;
-};
+} PartiallyBalloonedPage;
static void virtio_balloon_pbp_free(PartiallyBalloonedPage *pbp)
{
@@ -68,11 +68,11 @@ static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp,
}
static void balloon_inflate_page(VirtIOBalloon *balloon,
- MemoryRegion *mr, hwaddr mr_offset)
+ MemoryRegion *mr, hwaddr mr_offset,
+ PartiallyBalloonedPage **pbp)
{
void *addr = memory_region_get_ram_ptr(mr) + mr_offset;
ram_addr_t rb_offset, rb_aligned_offset, base_gpa;
- PartiallyBalloonedPage **pbp = &balloon->pbp;
RAMBlock *rb;
size_t rb_page_size;
int subpages;
@@ -149,12 +149,6 @@ static void balloon_deflate_page(VirtIOBalloon *balloon,
rb = qemu_ram_block_from_host(addr, false, &rb_offset);
rb_page_size = qemu_ram_pagesize(rb);
- if (balloon->pbp) {
- /* Let's play safe and always reset the pbp on deflation requests. */
- virtio_balloon_pbp_free(balloon->pbp);
- balloon->pbp = NULL;
- }
-
host_addr = (void *)((uintptr_t)addr & ~(rb_page_size - 1));
/* When a page is deflated, we hint the whole host page it lives
@@ -336,6 +330,7 @@ static void balloon_stats_set_poll_interval(Object *obj, Visitor *v,
static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
+ PartiallyBalloonedPage *pbp = NULL;
VirtQueueElement *elem;
MemoryRegionSection section;
@@ -344,7 +339,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
uint32_t pfn;
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
if (!elem) {
- return;
+ break;
}
while (iov_to_buf(elem->out_sg, elem->out_num, offset, &pfn, 4) == 4) {
@@ -373,7 +368,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
if (!qemu_balloon_is_inhibited()) {
if (vq == s->ivq) {
balloon_inflate_page(s, section.mr,
- section.offset_within_region);
+ section.offset_within_region, &pbp);
} else if (vq == s->dvq) {
balloon_deflate_page(s, section.mr, section.offset_within_region);
} else {
@@ -387,6 +382,8 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
virtio_notify(vdev, vq);
g_free(elem);
}
+
+ virtio_balloon_pbp_free(pbp);
}
static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
index 1afafb12..503349a3 100644
--- a/include/hw/virtio/virtio-balloon.h
+++ b/include/hw/virtio/virtio-balloon.h
@@ -33,8 +33,6 @@ typedef struct virtio_balloon_stat_modern {
uint64_t val;
} VirtIOBalloonStatModern;
-typedef struct PartiallyBalloonedPage PartiallyBalloonedPage;
-
enum virtio_balloon_free_page_report_status {
FREE_PAGE_REPORT_S_STOP = 0,
FREE_PAGE_REPORT_S_REQUESTED = 1,
@@ -70,7 +68,6 @@ typedef struct VirtIOBalloon {
int64_t stats_last_update;
int64_t stats_poll_interval;
uint32_t host_features;
- PartiallyBalloonedPage *pbp;
} VirtIOBalloon;
#endif

View File

@ -0,0 +1,62 @@
From 9a7ca8a7c920360db9dcaf616ca6f1440c025043 Mon Sep 17 00:00:00 2001
From: David Hildenbrand <david@redhat.com>
Date: Thu, 25 Jul 2019 13:36:38 +0200
Subject: [PATCH] virtio-balloon: don't track subpages for the PBP
As ramblocks cannot get removed/readded while we are processing a bulk
of inflation requests, there is no more need to track the page size
in form of the number of subpages.
Suggested-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190725113638.4702-8-david@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry-picked from commit 9a7ca8a7c920360db9dcaf616ca6f1440c025043)
---
hw/virtio/virtio-balloon.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index a6282d58d4..fe9664e42c 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -36,7 +36,6 @@
typedef struct PartiallyBalloonedPage {
ram_addr_t base_gpa;
- long subpages;
unsigned long *bitmap;
} PartiallyBalloonedPage;
@@ -55,16 +54,15 @@ static PartiallyBalloonedPage *virtio_balloon_pbp_alloc(ram_addr_t base_gpa,
PartiallyBalloonedPage *pbp = g_new0(PartiallyBalloonedPage, 1);
pbp->base_gpa = base_gpa;
- pbp->subpages = subpages;
pbp->bitmap = bitmap_new(subpages);
return pbp;
}
static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp,
- ram_addr_t base_gpa, long subpages)
+ ram_addr_t base_gpa)
{
- return pbp->subpages == subpages && pbp->base_gpa == base_gpa;
+ return pbp->base_gpa == base_gpa;
}
static void balloon_inflate_page(VirtIOBalloon *balloon,
@@ -106,7 +104,7 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
base_gpa = memory_region_get_ram_addr(mr) + mr_offset -
(rb_offset - rb_aligned_offset);
- if (*pbp && !virtio_balloon_pbp_matches(*pbp, base_gpa, subpages)) {
+ if (*pbp && !virtio_balloon_pbp_matches(*pbp, base_gpa)) {
/* We've partially ballooned part of a host page, but now
* we're trying to balloon part of a different one. Too hard,
* give up on the old partial page */
--
2.19.1

View File

@ -0,0 +1,130 @@
From 1b47b37c33ec01ae1efc527f4c97f97f93723bc4 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Thu, 25 Jul 2019 07:54:25 -0400
Subject: [PATCH] virtio-balloon: free pbp more aggressively
Previous patches switched to a temporary pbp but that does not go far
enough: after device uses a buffer, guest is free to reuse it, so
tracking the page and freeing it later is wrong.
Free and reset the pbp after we push each element.
Fixes: ed48c59875b6 ("virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size")
Cc: qemu-stable@nongnu.org #v4.0.0
Cc: David Hildenbrand <david@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry-picked from commit 1b47b37c33ec01ae1efc527f4c97f97f93723bc4)
---
hw/virtio/virtio-balloon.c | 37 ++++++++++++++++---------------------
1 file changed, 16 insertions(+), 21 deletions(-)
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index fe9664e42c..25de154307 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -41,22 +41,19 @@ typedef struct PartiallyBalloonedPage {
static void virtio_balloon_pbp_free(PartiallyBalloonedPage *pbp)
{
- if (!pbp) {
+ if (!pbp->bitmap) {
return;
}
g_free(pbp->bitmap);
- g_free(pbp);
+ pbp->bitmap = NULL;
}
-static PartiallyBalloonedPage *virtio_balloon_pbp_alloc(ram_addr_t base_gpa,
- long subpages)
+static void virtio_balloon_pbp_alloc(PartiallyBalloonedPage *pbp,
+ ram_addr_t base_gpa,
+ long subpages)
{
- PartiallyBalloonedPage *pbp = g_new0(PartiallyBalloonedPage, 1);
-
pbp->base_gpa = base_gpa;
pbp->bitmap = bitmap_new(subpages);
-
- return pbp;
}
static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp,
@@ -67,7 +64,7 @@ static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp,
static void balloon_inflate_page(VirtIOBalloon *balloon,
MemoryRegion *mr, hwaddr mr_offset,
- PartiallyBalloonedPage **pbp)
+ PartiallyBalloonedPage *pbp)
{
void *addr = memory_region_get_ram_ptr(mr) + mr_offset;
ram_addr_t rb_offset, rb_aligned_offset, base_gpa;
@@ -104,22 +101,21 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
base_gpa = memory_region_get_ram_addr(mr) + mr_offset -
(rb_offset - rb_aligned_offset);
- if (*pbp && !virtio_balloon_pbp_matches(*pbp, base_gpa)) {
+ if (pbp->bitmap && !virtio_balloon_pbp_matches(pbp, base_gpa)) {
/* We've partially ballooned part of a host page, but now
* we're trying to balloon part of a different one. Too hard,
* give up on the old partial page */
- virtio_balloon_pbp_free(*pbp);
- *pbp = NULL;
+ virtio_balloon_pbp_free(pbp);
}
- if (!*pbp) {
- *pbp = virtio_balloon_pbp_alloc(base_gpa, subpages);
+ if (!pbp->bitmap) {
+ virtio_balloon_pbp_alloc(pbp, base_gpa, subpages);
}
set_bit((rb_offset - rb_aligned_offset) / BALLOON_PAGE_SIZE,
- (*pbp)->bitmap);
+ pbp->bitmap);
- if (bitmap_full((*pbp)->bitmap, subpages)) {
+ if (bitmap_full(pbp->bitmap, subpages)) {
/* We've accumulated a full host page, we can actually discard
* it now */
@@ -127,8 +123,7 @@ static void balloon_inflate_page(VirtIOBalloon *balloon,
/* We ignore errors from ram_block_discard_range(), because it
* has already reported them, and failing to discard a balloon
* page is not fatal */
- virtio_balloon_pbp_free(*pbp);
- *pbp = NULL;
+ virtio_balloon_pbp_free(pbp);
}
}
@@ -328,13 +323,14 @@ static void balloon_stats_set_poll_interval(Object *obj, Visitor *v,
static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOBalloon *s = VIRTIO_BALLOON(vdev);
- PartiallyBalloonedPage *pbp = NULL;
VirtQueueElement *elem;
MemoryRegionSection section;
for (;;) {
+ PartiallyBalloonedPage pbp = {};
size_t offset = 0;
uint32_t pfn;
+
elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
if (!elem) {
break;
@@ -379,9 +375,8 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
virtqueue_push(vq, elem, offset);
virtio_notify(vdev, vq);
g_free(elem);
+ virtio_balloon_pbp_free(&pbp);
}
-
- virtio_balloon_pbp_free(pbp);
}
static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
--
2.19.1

View File

@ -0,0 +1,101 @@
From b728ea5f2597f97088db8517576caa2877118cb0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Mon, 5 Aug 2019 16:04:40 +0800
Subject: [PATCH] virtio-pci: fix missing device properties
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Since commit a4ee4c8baa37154 ("virtio: Helper for registering virtio
device types"), virtio-gpu-pci, virtio-vga, and virtio-crypto-pci lost
some properties: "ioeventfd" and "vectors". This may cause various
issues, such as failing migration or invalid properties.
Since those VirtioPCI devices do not have a base name, their class are
initialized with virtio_pci_generic_base_class_init(). However, if the
VirtioPCIDeviceTypeInfo provided a class_init which sets dc->props,
the properties were overwritten by virtio_pci_generic_class_init().
Instead, introduce an intermediary base-type to register the generic
properties.
Fixes: a4ee4c8baa37154f42b4dc6a13fee79268d15238
Cc: qemu-stable@nongnu.org
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20190625232333.30752-1-marcandre.lureau@redhat.com>
(cherry-pick from commit 683c1d89efd1eeb111c129a9a91f629b94d90d45)
---
hw/virtio/virtio-pci.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index cb44e19b..497092e8 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1905,13 +1905,6 @@ static void virtio_pci_generic_class_init(ObjectClass *klass, void *data)
dc->props = virtio_pci_generic_properties;
}
-/* Used when the generic type and the base type is the same */
-static void virtio_pci_generic_base_class_init(ObjectClass *klass, void *data)
-{
- virtio_pci_base_class_init(klass, data);
- virtio_pci_generic_class_init(klass, NULL);
-}
-
static void virtio_pci_transitional_instance_init(Object *obj)
{
VirtIOPCIProxy *proxy = VIRTIO_PCI(obj);
@@ -1930,14 +1923,13 @@ static void virtio_pci_non_transitional_instance_init(Object *obj)
void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t)
{
+ char *base_name = NULL;
TypeInfo base_type_info = {
.name = t->base_name,
.parent = t->parent ? t->parent : TYPE_VIRTIO_PCI,
.instance_size = t->instance_size,
.instance_init = t->instance_init,
.class_size = t->class_size,
- .class_init = virtio_pci_base_class_init,
- .class_data = (void *)t,
.abstract = true,
};
TypeInfo generic_type_info = {
@@ -1953,13 +1945,20 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t)
if (!base_type_info.name) {
/* No base type -> register a single generic device type */
- base_type_info.name = t->generic_name;
- base_type_info.class_init = virtio_pci_generic_base_class_init;
- base_type_info.interfaces = generic_type_info.interfaces;
- base_type_info.abstract = false;
- generic_type_info.name = NULL;
+ /* use intermediate %s-base-type to add generic device props */
+ base_name = g_strdup_printf("%s-base-type", t->generic_name);
+ base_type_info.name = base_name;
+ base_type_info.class_init = virtio_pci_generic_class_init;
+
+ generic_type_info.parent = base_name;
+ generic_type_info.class_init = virtio_pci_base_class_init;
+ generic_type_info.class_data = (void *)t;
+
assert(!t->non_transitional_name);
assert(!t->transitional_name);
+ } else {
+ base_type_info.class_init = virtio_pci_base_class_init;
+ base_type_info.class_data = (void *)t;
}
type_register(&base_type_info);
@@ -1997,6 +1996,7 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t)
};
type_register(&transitional_type_info);
}
+ g_free(base_name);
}
/* virtio-pci-bus */
--
2.19.1

View File

@ -0,0 +1,55 @@
From 9ea18ed25a36527167e9676f25d983df5e7f76e6 Mon Sep 17 00:00:00 2001
From: Markus Armbruster <armbru@redhat.com>
Date: Tue, 4 Jun 2019 17:12:50 +0200
Subject: [PATCH] vl: Fix -drive / -blockdev persistent reservation management
qemu-system-FOO's main() acts on command line arguments in its own
idiosyncratic order. There's not much method to its madness.
Whenever we find a case where one kind of command line argument needs
to refer to something created for another kind later, we rejigger the
order.
Recent commit cda4aa9a5a "vl: Create block backends before setting
machine properties" was such a rejigger. Block backends are now
created before "delayed" objects. This broke persistent reservation
management. Reproducer:
$ qemu-system-x86_64 -object pr-manager-helper,id=pr-helper0,path=/tmp/pr-helper0.sock-drive -drive file=/dev/mapper/crypt,file.pr-manager=pr-helper0,format=raw,if=none,id=drive-scsi0-0-0-2
qemu-system-x86_64: -drive file=/dev/mapper/crypt,file.pr-manager=pr-helper0,format=raw,if=none,id=drive-scsi0-0-0-2: No persistent reservation manager with id 'pr-helper0'
The delayed pr-manager-helper object is created too late for use by
-drive or -blockdev. Normal objects are still created in time.
pr-manager-helper has always been a delayed object (commit 7c9e527659
"scsi, file-posix: add support for persistent reservation
management"). Turns out there's no real reason for that. Make it a
normal object.
Fixes: cda4aa9a5a08777cf13e164c0543bd4888b8adce
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20190604151251.9903-2-armbru@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry-picked from commit 9ea18ed25a36527167e9676f25d983df5e7f76e6)
---
vl.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/vl.c b/vl.c
index f023a8ca73..cc6246d2af 100644
--- a/vl.c
+++ b/vl.c
@@ -2751,8 +2751,7 @@ static bool object_create_initial(const char *type, QemuOpts *opts)
exit(0);
}
- if (g_str_equal(type, "rng-egd") ||
- g_str_has_prefix(type, "pr-manager-")) {
+ if (g_str_equal(type, "rng-egd")) {
return false;
}
--
2.19.1

View File

@ -0,0 +1,47 @@
From c0de0a04d03183f524c2f60cda8ae1e886197a7d Mon Sep 17 00:00:00 2001
From: Ying Fang <fangying1@huawei.com>
Date: Tue, 27 Aug 2019 10:54:48 +0800
Subject: [PATCH] xhci: Fix memory leak in xhci_address_slot
Address Sanitizer shows memory leak in xhci_address_slot
hw/usb/hcd-xhci.c:2156 and the stack is as bellow:
Direct leak of 64 byte(s) in 4 object(s) allocated from:
#0 0xffff91c6f5ab in realloc (/lib64/libasan.so.4+0xd35ab)
#1 0xffff91987243 in g_realloc (/lib64/libglib-2.0.so.0+0x57243)
#2 0xaaaab0b26a1f in qemu_iovec_add util/iov.c:296
#3 0xaaaab07e5ce3 in xhci_address_slot hw/usb/hcd-xhci.c:2156
#4 0xaaaab07e5ce3 in xhci_process_commands hw/usb/hcd-xhci.c:2493
#5 0xaaaab00058d7 in memory_region_write_accessor qemu/memory.c:507
#6 0xaaaab0000d87 in access_with_adjusted_size memory.c:573
#7 0xaaaab000abcf in memory_region_dispatch_write memory.c:1516
#8 0xaaaaaff59947 in flatview_write_continue exec.c:3367
#9 0xaaaaaff59c33 in flatview_write exec.c:3406
#10 0xaaaaaff63b3b in address_space_write exec.c:3496
#11 0xaaaab002f263 in kvm_cpu_exec accel/kvm/kvm-all.c:2288
#12 0xaaaaaffee427 in qemu_kvm_cpu_thread_fn cpus.c:1290
#13 0xaaaab0b1a943 in qemu_thread_start util/qemu-thread-posix.c:502
#14 0xffff908ce8bb in start_thread (/lib64/libpthread.so.0+0x78bb)
#15 0xffff908165cb in thread_start (/lib64/libc.so.6+0xd55cb)
Cc: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
hw/usb/hcd-xhci.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index f578264948..471759cd4c 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -2161,6 +2161,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
DeviceOutRequest | USB_REQ_SET_ADDRESS,
slotid, 0, 0, NULL);
assert(p.status != USB_RET_ASYNC);
+ usb_packet_cleanup(&p);
}
res = xhci_enable_ep(xhci, slotid, 1, octx+32, ep0_ctx);
--
2.19.1

View File

@ -0,0 +1,44 @@
From 2212f37e0e477d8da0cff02cfc8b7a921ca11bef Mon Sep 17 00:00:00 2001
From: fangying <fangying1@huawei.com>
Date: Wed, 28 Aug 2019 14:02:22 +0800
Subject: [PATCH] xhci: Fix memory leak in xhci_kick_epctx
Address Sanitizer shows memory leak in xhci_kick_epctx hw/usb/hcd-xhci.c:1912.
A sglist is leaked when a packet is retired and returns USB_RET_NAK status.
The leak stack is as bellow:
Direct leak of 2688 byte(s) in 168 object(s) allocated from:
#0 0xffffae8b11db in __interceptor_malloc (/lib64/libasan.so.4+0xd31db)
#1 0xffffae5c9163 in g_malloc (/lib64/libglib-2.0.so.0+0x57163)
#2 0xaaaabb6fb3f7 in qemu_sglist_init dma-helpers.c:43
#3 0xaaaabba705a7 in pci_dma_sglist_init include/hw/pci/pci.h:837
#4 0xaaaabba705a7 in xhci_xfer_create_sgl hw/usb/hcd-xhci.c:1443
#5 0xaaaabba705a7 in xhci_setup_packet hw/usb/hcd-xhci.c:1615
#6 0xaaaabba77a6f in xhci_kick_epctx hw/usb/hcd-xhci.c:1912
#7 0xaaaabbdaad27 in timerlist_run_timers util/qemu-timer.c:592
#8 0xaaaabbdab19f in qemu_clock_run_timers util/qemu-timer.c:606
#9 0xaaaabbdab19f in qemu_clock_run_all_timers util/qemu-timer.c:692
#10 0xaaaabbdab9a3 in main_loop_wait util/main-loop.c:524
#11 0xaaaabb6ff5e7 in main_loop vl.c:1806
#12 0xaaaabb1e1453 in main vl.c:4488
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
hw/usb/hcd-xhci.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 6e1ec786..e10fbd3d 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1911,6 +1911,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
}
usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
if (xfer->packet.status == USB_RET_NAK) {
+ xhci_xfer_unmap(xfer);
return;
}
xhci_try_complete_packet(xfer);
--
2.19.1