diff --git a/0003-cpu-add-Cortex-A72-processor-kvm-target-support.patch b/0003-cpu-add-Cortex-A72-processor-kvm-target-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..a98198975b194350bdfc574a426704f213f5cbba --- /dev/null +++ b/0003-cpu-add-Cortex-A72-processor-kvm-target-support.patch @@ -0,0 +1,59 @@ +From 8ddc2bcb196a34cc641d50b057550e4b11dc8700 Mon Sep 17 00:00:00 2001 +From: Xu Yandong +Date: Wed, 9 Feb 2022 17:39:34 +0800 +Subject: [PATCH 3/3] 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 +Signed-off-by: Mingwang Li +--- + 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 26419fe994..1b56261964 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -202,6 +202,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_NEON); + set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); +@@ -265,7 +266,6 @@ static void aarch64_kunpeng_920_initfn(Object *obj) + cpu->isar.id_aa64dfr0 = 0x110305408; + cpu->isar.id_aa64isar0 = 0x10211120; + cpu->isar.id_aa64mmfr0 = 0x101125; +- cpu->kvm_target = KVM_ARM_TARGET_GENERIC_V8; + } + + void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) +diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h +index 580f1c1fee..5f1311ade7 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 +@@ -141,6 +143,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); + + #define CP_REG_ARM64 0x6000000000000000ULL + #define CP_REG_ARM_COPROC_MASK 0x000000000FFF0000 +-- +2.27.0 + diff --git a/9pfs-local-Fix-possible-memory-leak-in-local_link.patch b/9pfs-local-Fix-possible-memory-leak-in-local_link.patch deleted file mode 100644 index 56b7acb14b023fe3d9f94e22ece7c995a73c3fa6..0000000000000000000000000000000000000000 --- a/9pfs-local-Fix-possible-memory-leak-in-local_link.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 841b8d099c462cd4282c4ced8c2a6512899fd8d9 Mon Sep 17 00:00:00 2001 -From: Jiajun Chen -Date: Mon, 20 Jan 2020 15:11:39 +0100 -Subject: [PATCH] 9pfs: local: Fix possible memory leak in local_link() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -There is a possible memory leak while local_link return -1 without free -odirpath and oname. - -Reported-by: Euler Robot -Signed-off-by: Jaijun Chen -Signed-off-by: Xiang Zheng -Reviewed-by: Christian Schoenebeck -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Greg Kurz -(cherry picked from commit 841b8d099c462cd4282c4ced8c2a6512899fd8d9) ---- - hw/9pfs/9p-local.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c -index ca64139..d0592c3 100644 ---- a/hw/9pfs/9p-local.c -+++ b/hw/9pfs/9p-local.c -@@ -947,7 +947,7 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath, - if (ctx->export_flags & V9FS_SM_MAPPED_FILE && - local_is_mapped_file_metadata(ctx, name)) { - errno = EINVAL; -- return -1; -+ goto out; - } - - odirfd = local_opendir_nofollow(ctx, odirpath); --- -1.8.3.1 - diff --git a/ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp.patch b/ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp.patch deleted file mode 100644 index 3012512988402756527c95341aa921a362c9e43e..0000000000000000000000000000000000000000 --- a/ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp.patch +++ /dev/null @@ -1,64 +0,0 @@ -From e3a7ec839fa4f823666d726989c375dcf73348a4 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 15 Apr 2020 16:14:50 +0800 -Subject: [PATCH] ARM: KVM: Check KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 for smp_cpus > - 256 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Host kernel within [4.18, 5.3] report an erroneous KVM_MAX_VCPUS=512 -for ARM. The actual capability to instantiate more than 256 vcpus -was fixed in 5.4 with the upgrade of the KVM_IRQ_LINE ABI to support -vcpu id encoded on 12 bits instead of 8 and a redistributor consuming -a single KVM IO device instead of 2. - -So let's check this capability when attempting to use more than 256 -vcpus within any ARM kvm accelerated machine. - -Signed-off-by: Eric Auger -Reviewed-by: Richard Henderson -Reviewed-by: Andrew Jones -Acked-by: Marc Zyngier -Message-id: 20191003154640.22451-4-eric.auger@redhat.com -Signed-off-by: Peter Maydell -(cherry-picked from commit fff9f5558d0e0813d4f80bfe1602acf225eca4fd) -[yu: Use the legacy smp_cpus instead of ms->smp.cpus, as we don't have - ¦struct CpuTopology in MachineState at that time. See commit - ¦edeeec911702 for details.] -Signed-off-by: Zenghui Yu ---- - target/arm/kvm.c | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - -diff --git a/target/arm/kvm.c b/target/arm/kvm.c -index 50e86f8b..cc7a46df 100644 ---- a/target/arm/kvm.c -+++ b/target/arm/kvm.c -@@ -173,6 +173,8 @@ int kvm_arm_get_max_vm_ipa_size(MachineState *ms) - - int kvm_arch_init(MachineState *ms, KVMState *s) - { -+ int ret = 0; -+ unsigned int smp_cpus = ms->smp.cpus; - /* For ARM interrupt delivery is always asynchronous, - * whether we are using an in-kernel VGIC or not. - */ -@@ -186,7 +188,14 @@ int kvm_arch_init(MachineState *ms, KVMState *s) - - cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE); - -- return 0; -+ if (smp_cpus > 256 && -+ !kvm_check_extension(s, KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)) { -+ error_report("Using more than 256 vcpus requires a host kernel " -+ "with KVM_CAP_ARM_IRQ_LINE_LAYOUT_2"); -+ ret = -EINVAL; -+ } -+ -+ return ret; - } - - unsigned long kvm_arch_vcpu_id(CPUState *cpu) --- -2.23.0 diff --git a/ARM64-record-vtimer-tick-when-cpu-is-stopped.patch b/ARM64-record-vtimer-tick-when-cpu-is-stopped.patch deleted file mode 100644 index 4681e9f33f6877f199768b7a06a65df5356e6a7f..0000000000000000000000000000000000000000 --- a/ARM64-record-vtimer-tick-when-cpu-is-stopped.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 4646a24045cf53f2cc5e0ef1974da88ef50ef676 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 27 May 2020 11:54:31 +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 -Signed-off-by: Haibin Wang -Signed-off-by: Ying Fang ---- - cpus.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ - target/arm/cpu.h | 2 ++ - target/arm/machine.c | 1 + - 3 files changed, 61 insertions(+) - -diff --git a/cpus.c b/cpus.c -index 927a00aa..b9aa51f8 100644 ---- a/cpus.c -+++ b/cpus.c -@@ -1066,6 +1066,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, ®); -+ 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; -@@ -1073,6 +1095,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) { -@@ -1918,11 +1945,42 @@ 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) { -+ 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, ®); -+ 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 86eb79cd..aec6a214 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -262,6 +262,8 @@ typedef struct CPUARMState { - 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 ee3c59a6..ec28b839 100644 ---- a/target/arm/machine.c -+++ b/target/arm/machine.c -@@ -814,6 +814,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.23.0 - diff --git a/Add-mtod_check.patch b/Add-mtod_check.patch deleted file mode 100644 index 7309bc4342c71e6bf41d7835f589826e203e8a82..0000000000000000000000000000000000000000 --- a/Add-mtod_check.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 8cb4d202d4e5713e9b2b5f0ec817234941623f10 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Fri, 4 Jun 2021 15:58:25 +0400 -Subject: [PATCH 1/6] Add mtod_check() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Recent security issues demonstrate the lack of safety care when casting -a mbuf to a particular structure type. At least, it should check that -the buffer is large enough. The following patches will make use of this -function. - -Signed-off-by: Marc-André Lureau -Signed-off-by: imxcc ---- - slirp/src/mbuf.c | 11 +++++++++++ - slirp/src/mbuf.h | 1 + - 2 files changed, 12 insertions(+) - -diff --git a/slirp/src/mbuf.c b/slirp/src/mbuf.c -index 4fd62282..6d0653ed 100644 ---- a/slirp/src/mbuf.c -+++ b/slirp/src/mbuf.c -@@ -222,3 +222,14 @@ struct mbuf *dtom(Slirp *slirp, void *dat) - - return (struct mbuf *)0; - } -+ -+void *mtod_check(struct mbuf *m, size_t len) -+{ -+ if (m->m_len >= len) { -+ return m->m_data; -+ } -+ -+ DEBUG_ERROR("mtod failed"); -+ -+ return NULL; -+} -diff --git a/slirp/src/mbuf.h b/slirp/src/mbuf.h -index 546e7852..2015e323 100644 ---- a/slirp/src/mbuf.h -+++ b/slirp/src/mbuf.h -@@ -118,6 +118,7 @@ void m_inc(struct mbuf *, int); - void m_adj(struct mbuf *, int); - int m_copy(struct mbuf *, struct mbuf *, int, int); - struct mbuf *dtom(Slirp *, void *); -+void *mtod_check(struct mbuf *, size_t len); - - static inline void ifs_init(struct mbuf *ifm) - { --- -2.27.0 - diff --git a/BinDir.tar.gz b/BinDir.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..3642262e92563a532519a197d212fa3de78d3d6e Binary files /dev/null and b/BinDir.tar.gz differ diff --git a/Bugfix-hw-acpi-Use-max_cpus-instead-of-cpus-when-bui.patch b/Bugfix-hw-acpi-Use-max_cpus-instead-of-cpus-when-bui.patch deleted file mode 100644 index 8d492058d77ba70d51c88bffcbef7a1ae7b28adb..0000000000000000000000000000000000000000 --- a/Bugfix-hw-acpi-Use-max_cpus-instead-of-cpus-when-bui.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 38734e26ce3840d459da13607a9d46de24a15388 Mon Sep 17 00:00:00 2001 -From: kevinZhu -Date: Thu, 29 Oct 2020 19:24:48 +0800 -Subject: [PATCH] Bugfix: hw/acpi: Use max_cpus instead of cpus when build PPTT - table - -The field "cpus" is the initial number of CPU for guest, and the field "max_cpus" -is the max number of CPU after CPU hotplug. When building PPTT for guest, we -should take all CPUs into account, otherwise the "smp_sockets" is wrong. - -Fixes: 7cfcd8c8a2fe ("build smt processor structure to support smt topology") -Signed-off-by: Keqian Zhu ---- - hw/acpi/aml-build.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c -index 8a3b51c835..f01669df57 100644 ---- a/hw/acpi/aml-build.c -+++ b/hw/acpi/aml-build.c -@@ -167,7 +167,7 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus) - struct offset_status offset; - const MachineState *ms = MACHINE(qdev_get_machine()); - unsigned int smp_cores = ms->smp.cores; -- unsigned int smp_sockets = ms->smp.cpus / (smp_cores * ms->smp.threads); -+ unsigned int smp_sockets = ms->smp.max_cpus / (smp_cores * ms->smp.threads); - - acpi_data_push(table_data, sizeof(AcpiTableHeader)); - --- -2.27.0 - diff --git a/COLO-compare-Fix-incorrect-if-logic.patch b/COLO-compare-Fix-incorrect-if-logic.patch deleted file mode 100644 index 8deb1b31bb0f1f801ec552f6695503809f148acb..0000000000000000000000000000000000000000 --- a/COLO-compare-Fix-incorrect-if-logic.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 124032e79e354f5e7cc28958f2ca6b9f898da719 Mon Sep 17 00:00:00 2001 -From: Fan Yang -Date: Tue, 24 Sep 2019 22:08:29 +0800 -Subject: [PATCH] COLO-compare: Fix incorrect `if` logic -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -'colo_mark_tcp_pkt' should return 'true' when packets are the same, and -'false' otherwise. However, it returns 'true' when -'colo_compare_packet_payload' returns non-zero while -'colo_compare_packet_payload' is just a 'memcmp'. The result is that -COLO-compare reports inconsistent TCP packets when they are actually -the same. - -Fixes: f449c9e549c ("colo: compare the packet based on the tcp sequence number") -Cc: qemu-stable@nongnu.org -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Fan Yang -Signed-off-by: Jason Wang -(cherry picked from commit 1e907a32b77e5d418538453df5945242e43224fa) -Signed-off-by: Michael Roth ---- - net/colo-compare.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/net/colo-compare.c b/net/colo-compare.c -index bf10526..9827c0e 100644 ---- a/net/colo-compare.c -+++ b/net/colo-compare.c -@@ -287,7 +287,7 @@ static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt, - *mark = 0; - - if (ppkt->tcp_seq == spkt->tcp_seq && ppkt->seq_end == spkt->seq_end) { -- if (colo_compare_packet_payload(ppkt, spkt, -+ if (!colo_compare_packet_payload(ppkt, spkt, - ppkt->header_size, spkt->header_size, - ppkt->payload_size)) { - *mark = COLO_COMPARE_FREE_SECONDARY | COLO_COMPARE_FREE_PRIMARY; -@@ -297,7 +297,7 @@ static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt, - - /* one part of secondary packet payload still need to be compared */ - if (!after(ppkt->seq_end, spkt->seq_end)) { -- if (colo_compare_packet_payload(ppkt, spkt, -+ if (!colo_compare_packet_payload(ppkt, spkt, - ppkt->header_size + ppkt->offset, - spkt->header_size + spkt->offset, - ppkt->payload_size - ppkt->offset)) { -@@ -316,7 +316,7 @@ static bool colo_mark_tcp_pkt(Packet *ppkt, Packet *spkt, - /* primary packet is longer than secondary packet, compare - * the same part and mark the primary packet offset - */ -- if (colo_compare_packet_payload(ppkt, spkt, -+ if (!colo_compare_packet_payload(ppkt, spkt, - ppkt->header_size + ppkt->offset, - spkt->header_size + spkt->offset, - spkt->payload_size - spkt->offset)) { --- -1.8.3.1 - diff --git a/Currently-while-kvm-and-qemu-can-not-handle-some-kvm.patch b/Currently-while-kvm-and-qemu-can-not-handle-some-kvm.patch new file mode 100644 index 0000000000000000000000000000000000000000..b0071b50932b38fd7736dad548a083f356980f7f --- /dev/null +++ b/Currently-while-kvm-and-qemu-can-not-handle-some-kvm.patch @@ -0,0 +1,27 @@ +From 9e2158495059b485f2c28bb649c8b4a87fb3105c Mon Sep 17 00:00:00 2001 +From: Chuan Zheng +Date: Wed, 9 Feb 2022 11:24:32 +0800 +Subject: [PATCH 12/15] Currently, while kvm and qemu can not handle some kvm + exit, qemu will do vm_stop, which will make vm in pause state. This action + make vm unrecoverable, so send guest panic to libvirt instead. + +--- + accel/kvm/kvm-all.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index eecd8031cf..b128d311c2 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -2970,7 +2970,7 @@ int kvm_cpu_exec(CPUState *cpu) + + if (ret < 0) { + cpu_dump_state(cpu, stderr, CPU_DUMP_CODE); +- vm_stop(RUN_STATE_INTERNAL_ERROR); ++ qemu_system_guest_panicked(cpu_get_crash_info(cpu)); + } + + qatomic_set(&cpu->exit_request, 0); +-- +2.27.0 + diff --git a/Drop-bogus-IPv6-messages.patch b/Drop-bogus-IPv6-messages.patch deleted file mode 100644 index 2fc1e0e780e34b1570fbcfcc4581138c79e7fa46..0000000000000000000000000000000000000000 --- a/Drop-bogus-IPv6-messages.patch +++ /dev/null @@ -1,30 +0,0 @@ -From e8b555c08061ad78920611a5e98ee14fcd967692 Mon Sep 17 00:00:00 2001 -From: Ralf Haferkamp -Date: Fri, 11 Sep 2020 10:55:49 +0800 -Subject: [PATCH] Drop bogus IPv6 messages - -Drop IPv6 message shorter than what's mentioned in the playload -length header (+the size of IPv6 header). They're invalid and could -lead to data leakage in icmp6_send_echoreply(). - -diff --git a/slirp/src/ip6_input.c b/slirp/src/ip6_input.c -index d9d2b7e..c2dce52 100644 ---- a/slirp/src/ip6_input.c -+++ b/slirp/src/ip6_input.c -@@ -49,6 +49,13 @@ void ip6_input(struct mbuf *m) - goto bad; - } - -+ // Check if the message size is big enough to hold what's -+ // set in the payload length header. If not this is an invalid -+ // packet -+ if (m->m_len < ntohs(ip6->ip_pl) + sizeof(struct ip6)) { -+ goto bad; -+ } -+ - /* check ip_ttl for a correct ICMP reply */ - if (ip6->ip_hl == 0) { - icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS); --- -1.8.3.1 - diff --git a/Fix-use-after-free-in-vfio_migration_probe.patch b/Fix-use-after-free-in-vfio_migration_probe.patch deleted file mode 100644 index f0a94e60054da414102dbda43f9d111c4bc2e6d9..0000000000000000000000000000000000000000 --- a/Fix-use-after-free-in-vfio_migration_probe.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 126fc13ebe9c5e58a5b1daeb4e102e6fa5845779 Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Fri, 6 Nov 2020 23:32:24 +0530 -Subject: [PATCH] Fix use after free in vfio_migration_probe -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fixes Coverity issue: -CID 1436126: Memory - illegal accesses (USE_AFTER_FREE) - -Fixes: a9e271ec9b36 ("vfio: Add migration region initialization and finalize function") -Signed-off-by: Kirti Wankhede -Reviewed-by: David Edmondson -Reviewed-by: Alex Bennée -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Alex Williamson -Signed-off-by: Kunkun Jiang ---- - hw/vfio/migration.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -index 1a97784486..8546075706 100644 ---- a/hw/vfio/migration.c -+++ b/hw/vfio/migration.c -@@ -903,8 +903,8 @@ int vfio_migration_probe(VFIODevice *vbasedev, Error **errp) - goto add_blocker; - } - -- g_free(info); - trace_vfio_migration_probe(vbasedev->name, info->index); -+ g_free(info); - return 0; - - add_blocker: --- -2.27.0 - diff --git a/Fixed-integer-overflow-in-e1000e.patch b/Fixed-integer-overflow-in-e1000e.patch deleted file mode 100644 index 004390fc5a3d60d2aaf4912d0679c4fa471d28a2..0000000000000000000000000000000000000000 --- a/Fixed-integer-overflow-in-e1000e.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 41077af2c4283c15c0a822017ea51612d15b68f8 Mon Sep 17 00:00:00 2001 -From: Andrew Melnychenko -Date: Wed, 4 Mar 2020 16:20:58 +0200 -Subject: [PATCH 1/5] Fixed integer overflow in e1000e -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1737400 -Fixed setting max_queue_num if there are no peers in -NICConf. qemu_new_nic() creates NICState with 1 NetClientState(index -0) without peers, set max_queue_num to 0 - It prevents undefined -behavior and possible crashes, especially during pcie hotplug. - -Fixes: 6f3fbe4ed06 ("net: Introduce e1000e device emulation") -Signed-off-by: Andrew Melnychenko -Reviewed-by: Philippe Mathieu-Daudé -Reviewed-by: Dmitry Fleytman -Signed-off-by: Jason Wang -Signed-off-by: Zhenyu Ye ---- - hw/net/e1000e.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c -index 581f7d03..1e827c4f 100644 ---- a/hw/net/e1000e.c -+++ b/hw/net/e1000e.c -@@ -325,7 +325,7 @@ e1000e_init_net_peer(E1000EState *s, PCIDevice *pci_dev, uint8_t *macaddr) - s->nic = qemu_new_nic(&net_e1000e_info, &s->conf, - object_get_typename(OBJECT(s)), dev->id, s); - -- s->core.max_queue_num = s->conf.peers.queues - 1; -+ s->core.max_queue_num = s->conf.peers.queues ? s->conf.peers.queues - 1 : 0; - - trace_e1000e_mac_set_permanent(MAC_ARG(macaddr)); - memcpy(s->core.permanent_mac, macaddr, sizeof(s->core.permanent_mac)); --- -2.22.0.windows.1 - diff --git a/IPv6-add-support-for-IPv6-protocol.patch b/IPv6-add-support-for-IPv6-protocol.patch new file mode 100644 index 0000000000000000000000000000000000000000..23ed9a27cb5c99375ccadda8c94cefa17496fd72 --- /dev/null +++ b/IPv6-add-support-for-IPv6-protocol.patch @@ -0,0 +1,28 @@ +From 039e70e84d966ee28267f3fe76c8558ef65619f9 Mon Sep 17 00:00:00 2001 +From: Yan Wang +Date: Sat, 12 Feb 2022 14:31:00 +0800 +Subject: [PATCH] IPv6: add support for IPv6 protocol + +Add support for IPv6 protocol. + +Signed-off-by: Yan Wang +--- + roms/ipxe/src/config/general.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/roms/ipxe/src/config/general.h b/roms/ipxe/src/config/general.h +index 3c14a2c..e7ce2b9 100644 +--- a/roms/ipxe/src/config/general.h ++++ b/roms/ipxe/src/config/general.h +@@ -35,7 +35,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + */ + + #define NET_PROTO_IPV4 /* IPv4 protocol */ +-#undef NET_PROTO_IPV6 /* IPv6 protocol */ ++#define NET_PROTO_IPV6 /* IPv6 protocol */ + #undef NET_PROTO_FCOE /* Fibre Channel over Ethernet protocol */ + #define NET_PROTO_STP /* Spanning Tree protocol */ + #define NET_PROTO_LACP /* Link Aggregation control protocol */ +-- +1.9.1 + diff --git a/Revert-cpu-add-Cortex-A72-processor-kvm-target-suppo.patch b/Revert-cpu-add-Cortex-A72-processor-kvm-target-suppo.patch new file mode 100644 index 0000000000000000000000000000000000000000..684893c93f9c04880af0d0177503b8b0afaf9ffd --- /dev/null +++ b/Revert-cpu-add-Cortex-A72-processor-kvm-target-suppo.patch @@ -0,0 +1,49 @@ +From 7474971c6fd6c6f77e66ded125e5f2521c7e12a2 Mon Sep 17 00:00:00 2001 +From: Mingwang Li +Date: Wed, 9 Feb 2022 17:35:52 +0800 +Subject: [PATCH 2/3] Revert "cpu: add Cortex-A72 processor kvm target support" + +This reverts commit f0da7fa5230b5f771570b2c12288e4a56a20dd97. + +Signed-off-by: Mingwang Li +--- + target/arm/cpu64.c | 1 - + target/arm/kvm-consts.h | 3 --- + 2 files changed, 4 deletions(-) + +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index bd8e5b5676..26419fe994 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -202,7 +202,6 @@ 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_NEON); + set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); +diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h +index 5f1311ade7..580f1c1fee 100644 +--- a/target/arm/kvm-consts.h ++++ b/target/arm/kvm-consts.h +@@ -130,8 +130,6 @@ 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 +@@ -143,7 +141,6 @@ 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); + + #define CP_REG_ARM64 0x6000000000000000ULL + #define CP_REG_ARM_COPROC_MASK 0x000000000FFF0000 +-- +2.27.0 + diff --git a/Revert-cpu-parse-feature-to-avoid-failure.patch b/Revert-cpu-parse-feature-to-avoid-failure.patch new file mode 100644 index 0000000000000000000000000000000000000000..038edb892f46cd97b3a0b59dd6f6f1436a7e5442 --- /dev/null +++ b/Revert-cpu-parse-feature-to-avoid-failure.patch @@ -0,0 +1,67 @@ +From cae52ca5b1dd4a295eaabc9649481f3d6a684f06 Mon Sep 17 00:00:00 2001 +From: Mingwang Li +Date: Wed, 9 Feb 2022 17:33:26 +0800 +Subject: [PATCH 1/3] Revert "cpu: parse +/- feature to avoid failure" + +This reverts commit ef83cde8dd2c9b404527354489b14d2bd238733d. + +Signed-off-by: Mingwang Li +--- + target/arm/cpu64.c | 37 ------------------------------------- + 1 file changed, 37 deletions(-) + +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 08d886de7b..bd8e5b5676 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -983,47 +983,10 @@ 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->gdb_read_register = aarch64_cpu_gdb_read_register; + cc->gdb_write_register = aarch64_cpu_gdb_write_register; + cc->gdb_num_core_regs = 34; +-- +2.27.0 + diff --git a/Revert-ide-ahci-Check-for-ECANCELED-in-aio-callbacks.patch b/Revert-ide-ahci-Check-for-ECANCELED-in-aio-callbacks.patch deleted file mode 100644 index 200e0b2df02607b11e3117863afd00a346419e27..0000000000000000000000000000000000000000 --- a/Revert-ide-ahci-Check-for-ECANCELED-in-aio-callbacks.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 73a5bf472921068e6db10e7e325b7ac46f111834 Mon Sep 17 00:00:00 2001 -From: John Snow -Date: Mon, 29 Jul 2019 18:36:05 -0400 -Subject: [PATCH] Revert "ide/ahci: Check for -ECANCELED in aio callbacks" - -This reverts commit 0d910cfeaf2076b116b4517166d5deb0fea76394. - -It's not correct to just ignore an error code in a callback; we need to -handle that error and possible report failure to the guest so that they -don't wait indefinitely for an operation that will now never finish. - -This ought to help cases reported by Nutanix where iSCSI returns a -legitimate -ECANCELED for certain operations which should be propagated -normally. - -Reported-by: Shaju Abraham -Signed-off-by: John Snow -Message-id: 20190729223605.7163-1-jsnow@redhat.com -Signed-off-by: John Snow -(cherry picked from commit 8ec41c4265714255d5a138f8b538faf3583dcff6) -Signed-off-by: Michael Roth ---- - hw/ide/ahci.c | 3 --- - hw/ide/core.c | 14 -------------- - 2 files changed, 17 deletions(-) - -diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c -index 00ba422a48..6aaf66534a 100644 ---- a/hw/ide/ahci.c -+++ b/hw/ide/ahci.c -@@ -1023,9 +1023,6 @@ static void ncq_cb(void *opaque, int ret) - IDEState *ide_state = &ncq_tfs->drive->port.ifs[0]; - - ncq_tfs->aiocb = NULL; -- if (ret == -ECANCELED) { -- return; -- } - - if (ret < 0) { - bool is_read = ncq_tfs->cmd == READ_FPDMA_QUEUED; -diff --git a/hw/ide/core.c b/hw/ide/core.c -index 6afadf894f..8e1624f7ce 100644 ---- a/hw/ide/core.c -+++ b/hw/ide/core.c -@@ -722,9 +722,6 @@ static void ide_sector_read_cb(void *opaque, int ret) - s->pio_aiocb = NULL; - s->status &= ~BUSY_STAT; - -- if (ret == -ECANCELED) { -- return; -- } - if (ret != 0) { - if (ide_handle_rw_error(s, -ret, IDE_RETRY_PIO | - IDE_RETRY_READ)) { -@@ -840,10 +837,6 @@ static void ide_dma_cb(void *opaque, int ret) - uint64_t offset; - bool stay_active = false; - -- if (ret == -ECANCELED) { -- return; -- } -- - if (ret == -EINVAL) { - ide_dma_error(s); - return; -@@ -975,10 +968,6 @@ static void ide_sector_write_cb(void *opaque, int ret) - IDEState *s = opaque; - int n; - -- if (ret == -ECANCELED) { -- return; -- } -- - s->pio_aiocb = NULL; - s->status &= ~BUSY_STAT; - -@@ -1058,9 +1047,6 @@ static void ide_flush_cb(void *opaque, int ret) - - s->pio_aiocb = NULL; - -- if (ret == -ECANCELED) { -- return; -- } - if (ret < 0) { - /* XXX: What sector number to set here? */ - if (ide_handle_rw_error(s, -ret, IDE_RETRY_FLUSH)) { --- -2.23.0 diff --git a/Revert-qmp-add-command-to-query-used-memslots-of-vho.patch b/Revert-qmp-add-command-to-query-used-memslots-of-vho.patch new file mode 100644 index 0000000000000000000000000000000000000000..02f8797078723c92d08fabe7243a9cc1dbdfd5a5 --- /dev/null +++ b/Revert-qmp-add-command-to-query-used-memslots-of-vho.patch @@ -0,0 +1,133 @@ +From 92e9fb334c38cd21652ce8adde9ec01ab4412426 Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Tue, 15 Feb 2022 15:18:17 +0800 +Subject: [PATCH] Revert "qmp: add command to query used memslots of vhost-net + and vhost-user" + +This reverts commit 1545a60a8b78490c7dc8909b7012bca63dba63cd. + +Signed-off-by: Jinhua Cao +--- + hw/virtio/vhost-backend.c | 2 +- + hw/virtio/vhost-user.c | 2 +- + include/hw/virtio/vhost-backend.h | 2 -- + monitor/qmp-cmds.c | 12 ------------ + qapi/net.json | 18 ------------------ + qapi/pragma.json | 4 +--- + 6 files changed, 3 insertions(+), 37 deletions(-) + +diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c +index d8e1710758..2acfb750fd 100644 +--- a/hw/virtio/vhost-backend.c ++++ b/hw/virtio/vhost-backend.c +@@ -300,7 +300,7 @@ static void vhost_kernel_set_used_memslots(struct vhost_dev *dev) + vhost_kernel_used_memslots = dev->mem->nregions; + } + +-unsigned int vhost_kernel_get_used_memslots(void) ++static unsigned int vhost_kernel_get_used_memslots(void) + { + return vhost_kernel_used_memslots; + } +diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c +index 8f69a3b850..176cae9244 100644 +--- a/hw/virtio/vhost-user.c ++++ b/hw/virtio/vhost-user.c +@@ -2544,7 +2544,7 @@ static void vhost_user_set_used_memslots(struct vhost_dev *dev) + vhost_user_used_memslots = counter; + } + +-unsigned int vhost_user_get_used_memslots(void) ++static unsigned int vhost_user_get_used_memslots(void) + { + return vhost_user_used_memslots; + } +diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h +index 7bbc658161..a64708f456 100644 +--- a/include/hw/virtio/vhost-backend.h ++++ b/include/hw/virtio/vhost-backend.h +@@ -190,6 +190,4 @@ int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev, + + int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd); + +-unsigned int vhost_kernel_get_used_memslots(void); +-unsigned int vhost_user_get_used_memslots(void); + #endif /* VHOST_BACKEND_H */ +diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c +index a138e7dd4b..d71beace6a 100644 +--- a/monitor/qmp-cmds.c ++++ b/monitor/qmp-cmds.c +@@ -37,7 +37,6 @@ + #include "qapi/qapi-commands-machine.h" + #include "qapi/qapi-commands-misc.h" + #include "qapi/qapi-commands-ui.h" +-#include "qapi/qapi-commands-net.h" + #include "qapi/type-helpers.h" + #include "qapi/qmp/qerror.h" + #include "exec/ramlist.h" +@@ -45,7 +44,6 @@ + #include "hw/acpi/acpi_dev_interface.h" + #include "hw/intc/intc.h" + #include "hw/rdma/rdma.h" +-#include "hw/virtio/vhost-backend.h" + + NameInfo *qmp_query_name(Error **errp) + { +@@ -476,13 +474,3 @@ int64_t qmp_query_rtc_date_diff(Error **errp) + { + return get_rtc_date_diff(); + } +- +-uint32_t qmp_query_vhost_kernel_used_memslots(Error **errp) +-{ +- return vhost_kernel_get_used_memslots(); +-} +- +-uint32_t qmp_query_vhost_user_used_memslots(Error **errp) +-{ +- return vhost_user_get_used_memslots(); +-} +diff --git a/qapi/net.json b/qapi/net.json +index c9ff849eed..7fab2e7cd8 100644 +--- a/qapi/net.json ++++ b/qapi/net.json +@@ -696,21 +696,3 @@ + ## + { 'event': 'FAILOVER_NEGOTIATED', + 'data': {'device-id': 'str'} } +- +-## +-# @query-vhost-kernel-used-memslots: +-# +-# Get vhost-kernel nic used memslots +-# +-# Since: 4.1 +-## +-{ 'command': 'query-vhost-kernel-used-memslots', 'returns': 'uint32' } +- +-## +-# @query-vhost-user-used-memslots: +-# +-# Get vhost-user nic used memslots +-# +-# Since: 4.1 +-## +-{ 'command': 'query-vhost-user-used-memslots', 'returns': 'uint32' } +diff --git a/qapi/pragma.json b/qapi/pragma.json +index d35c897acb..b37f6de445 100644 +--- a/qapi/pragma.json ++++ b/qapi/pragma.json +@@ -27,9 +27,7 @@ + 'query-tpm-models', + 'query-tpm-types', + 'ringbuf-read', +- 'query-rtc-date-diff', +- 'query-vhost-user-used-memslots', +- 'query-vhost-kernel-used-memslots' ], ++ 'query-rtc-date-diff' ], + # Externally visible types whose member names may use uppercase + 'member-name-exceptions': [ # visible in: + 'ACPISlotType', # query-acpi-ospm-status +-- +2.27.0 + diff --git a/Revert-vtimer-compat-cross-version-migration-from-v4.patch b/Revert-vtimer-compat-cross-version-migration-from-v4.patch deleted file mode 100644 index 082f1763f9b445ba3816e2051c47129a6c64528a..0000000000000000000000000000000000000000 --- a/Revert-vtimer-compat-cross-version-migration-from-v4.patch +++ /dev/null @@ -1,37 +0,0 @@ -From ced290d644a00e18e70046194d042bcaa2703b65 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 27 May 2020 11:16:53 +0800 -Subject: [PATCH] Revert: "vtimer: compat cross version migration from v4.0.1" - -This reverts commit patch: -vtimer-compat-cross-version-migration-from-v4.0.1.patch - -Signed-off-by: Ying Fang - -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index 2609113d..86eb79cd 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -261,7 +261,6 @@ 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 is stopped */ - - /* System control coprocessor (cp15) */ - struct { -diff --git a/target/arm/machine.c b/target/arm/machine.c -index ec28b839..ee3c59a6 100644 ---- a/target/arm/machine.c -+++ b/target/arm/machine.c -@@ -814,7 +814,6 @@ 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.23.0 - diff --git a/Typo-Correct-the-name-of-CPU-hotplug-memory-region.patch b/Typo-Correct-the-name-of-CPU-hotplug-memory-region.patch deleted file mode 100644 index bc1fd44d163beb57f08c3b58918d305772b0c362..0000000000000000000000000000000000000000 --- a/Typo-Correct-the-name-of-CPU-hotplug-memory-region.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 843f593280b93e03bb7b0d0001da7488d61f13f6 Mon Sep 17 00:00:00 2001 -From: Keqian Zhu -Date: Mon, 6 Apr 2020 08:55:17 +0800 -Subject: [PATCH] Typo: Correct the name of CPU hotplug memory region - -Replace "acpi-mem-hotplug" with "acpi-cpu-hotplug" - -Signed-off-by: Keqian Zhu ---- - hw/acpi/cpu.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c -index 7a90c8f82d..0c0bfe479a 100644 ---- a/hw/acpi/cpu.c -+++ b/hw/acpi/cpu.c -@@ -203,7 +203,7 @@ void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner, - state->devs[i].arch_id = id_list->cpus[i].arch_id; - } - memory_region_init_io(&state->ctrl_reg, owner, &cpu_hotplug_ops, state, -- "acpi-mem-hotplug", ACPI_CPU_HOTPLUG_REG_LEN); -+ "acpi-cpu-hotplug", ACPI_CPU_HOTPLUG_REG_LEN); - memory_region_add_subregion(as, base_addr, &state->ctrl_reg); - } - --- -2.19.1 diff --git a/Use-post-increment-only-in-inffast.c.patch b/Use-post-increment-only-in-inffast.c.patch new file mode 100644 index 0000000000000000000000000000000000000000..e5d16d054cf49281aea941f54758d69e981d7a8c --- /dev/null +++ b/Use-post-increment-only-in-inffast.c.patch @@ -0,0 +1,250 @@ +From 97021cac0565f57d14a3e285399dd2208c66c358 Mon Sep 17 00:00:00 2001 +From: Yan Wang +Date: Sat, 12 Feb 2022 15:00:25 +0800 +Subject: [PATCH] Use post-increment only in inffast.c. + +Fix CVE-2016-9841 + +patch link: https://github.com/madler/zlib/commit/9aaec95 + +An old inffast.c optimization turns out to not be optimal anymore +with modern compilers, and furthermore was not compliant with the +C standard, for which decrementing a pointer before its allocated +memory is undefined. Per the recommendation of a security audit of +the zlib code by Trail of Bits and TrustInSoft, in support of the +Mozilla Foundation, this "optimization" was removed, in order to +avoid the possibility of undefined behavior. + +Signed-off-by: Yan Wang +--- + roms/u-boot/lib/zlib/inffast.c | 87 +++++++++++++++++------------------------- + 1 file changed, 34 insertions(+), 53 deletions(-) + +diff --git a/roms/u-boot/lib/zlib/inffast.c b/roms/u-boot/lib/zlib/inffast.c +index e3c7f3b..cdc778e 100644 +--- a/roms/u-boot/lib/zlib/inffast.c ++++ b/roms/u-boot/lib/zlib/inffast.c +@@ -12,25 +12,6 @@ + + #ifndef ASMINF + +-/* Allow machine dependent optimization for post-increment or pre-increment. +- Based on testing to date, +- Pre-increment preferred for: +- - PowerPC G3 (Adler) +- - MIPS R5000 (Randers-Pehrson) +- Post-increment preferred for: +- - none +- No measurable difference: +- - Pentium III (Anderson) +- - M68060 (Nikl) +- */ +-#ifdef POSTINC +-# define OFF 0 +-# define PUP(a) *(a)++ +-#else +-# define OFF 1 +-# define PUP(a) *++(a) +-#endif +- + /* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is +@@ -97,7 +78,7 @@ void inflate_fast(z_streamp strm, unsigned start) + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; +- in = strm->next_in - OFF; ++ in = strm->next_in; + last = in + (strm->avail_in - 5); + if (in > last && strm->avail_in > 5) { + /* +@@ -107,7 +88,7 @@ void inflate_fast(z_streamp strm, unsigned start) + strm->avail_in = 0xffffffff - (uintptr_t)in; + last = in + (strm->avail_in - 5); + } +- out = strm->next_out - OFF; ++ out = strm->next_out; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); + #ifdef INFLATE_STRICT +@@ -128,9 +109,9 @@ void inflate_fast(z_streamp strm, unsigned start) + input data or output space */ + do { + if (bits < 15) { +- hold += (unsigned long)(PUP(in)) << bits; ++ hold += (unsigned long)(*in++) << bits; + bits += 8; +- hold += (unsigned long)(PUP(in)) << bits; ++ hold += (unsigned long)(*in++) << bits; + bits += 8; + } + this = lcode[hold & lmask]; +@@ -143,14 +124,14 @@ void inflate_fast(z_streamp strm, unsigned start) + Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", this.val)); +- PUP(out) = (unsigned char)(this.val); ++ *out++ = (unsigned char)(this.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { +- hold += (unsigned long)(PUP(in)) << bits; ++ hold += (unsigned long)(*in++) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); +@@ -159,9 +140,9 @@ void inflate_fast(z_streamp strm, unsigned start) + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { +- hold += (unsigned long)(PUP(in)) << bits; ++ hold += (unsigned long)(*in++) << bits; + bits += 8; +- hold += (unsigned long)(PUP(in)) << bits; ++ hold += (unsigned long)(*in++) << bits; + bits += 8; + } + this = dcode[hold & dmask]; +@@ -174,10 +155,10 @@ void inflate_fast(z_streamp strm, unsigned start) + dist = (unsigned)(this.val); + op &= 15; /* number of extra bits */ + if (bits < op) { +- hold += (unsigned long)(PUP(in)) << bits; ++ hold += (unsigned long)(*in++) << bits; + bits += 8; + if (bits < op) { +- hold += (unsigned long)(PUP(in)) << bits; ++ hold += (unsigned long)(*in++) << bits; + bits += 8; + } + } +@@ -200,13 +181,13 @@ void inflate_fast(z_streamp strm, unsigned start) + state->mode = BAD; + break; + } +- from = window - OFF; ++ from = window; + if (write == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { +- PUP(out) = PUP(from); ++ *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } +@@ -217,14 +198,14 @@ void inflate_fast(z_streamp strm, unsigned start) + if (op < len) { /* some from end of window */ + len -= op; + do { +- PUP(out) = PUP(from); ++ *out++ = *from++; + } while (--op); +- from = window - OFF; ++ from = window; + if (write < len) { /* some from start of window */ + op = write; + len -= op; + do { +- PUP(out) = PUP(from); ++ *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } +@@ -235,21 +216,21 @@ void inflate_fast(z_streamp strm, unsigned start) + if (op < len) { /* some from window */ + len -= op; + do { +- PUP(out) = PUP(from); ++ *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { +- PUP(out) = PUP(from); +- PUP(out) = PUP(from); +- PUP(out) = PUP(from); ++ *out++ = *from++; ++ *out++ = *from++; ++ *out++ = *from++; + len -= 3; + } + if (len) { +- PUP(out) = PUP(from); ++ *out++ = *from++; + if (len > 1) +- PUP(out) = PUP(from); ++ *out++ = *from++; + } + } + else { +@@ -259,25 +240,25 @@ void inflate_fast(z_streamp strm, unsigned start) + from = out - dist; /* copy direct from output */ + /* minimum length is three */ + /* Align out addr */ +- if (!((long)(out - 1 + OFF) & 1)) { +- PUP(out) = PUP(from); ++ if (!((long)(out - 1) & 1)) { ++ *out++ = *from++; + len--; + } +- sout = (unsigned short *)(out - OFF); ++ sout = (unsigned short *)(out); + if (dist > 2 ) { + unsigned short *sfrom; + +- sfrom = (unsigned short *)(from - OFF); ++ sfrom = (unsigned short *)(from); + loops = len >> 1; + do +- PUP(sout) = get_unaligned(++sfrom); ++ *sout++ = get_unaligned(++sfrom); + while (--loops); +- out = (unsigned char *)sout + OFF; +- from = (unsigned char *)sfrom + OFF; ++ out = (unsigned char *)sout; ++ from = (unsigned char *)sfrom; + } else { /* dist == 1 or dist == 2 */ + unsigned short pat16; + +- pat16 = *(sout-2+2*OFF); ++ pat16 = *(sout-2); + if (dist == 1) + #if defined(__BIG_ENDIAN) + pat16 = (pat16 & 0xff) | ((pat16 & 0xff ) << 8); +@@ -288,12 +269,12 @@ void inflate_fast(z_streamp strm, unsigned start) + #endif + loops = len >> 1; + do +- PUP(sout) = pat16; ++ *sout++ = pat16; + while (--loops); +- out = (unsigned char *)sout + OFF; ++ out = (unsigned char *)sout; + } + if (len & 1) +- PUP(out) = PUP(from); ++ *out++ = *from++; + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ +@@ -329,8 +310,8 @@ void inflate_fast(z_streamp strm, unsigned start) + hold &= (1U << bits) - 1; + + /* update state and return */ +- strm->next_in = in + OFF; +- strm->next_out = out + OFF; ++ strm->next_in = in; ++ strm->next_out = out; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); +-- +1.9.1 + diff --git a/accel-kvm-Add-pre-park-vCPU-support.patch b/accel-kvm-Add-pre-park-vCPU-support.patch index 9bc81178581c30504ca1b32d1f47ba8cbc1a5b85..e3433842aefc7dd4faf0e827c8824f0898363652 100644 --- a/accel-kvm-Add-pre-park-vCPU-support.patch +++ b/accel-kvm-Add-pre-park-vCPU-support.patch @@ -1,4 +1,4 @@ -From 135119d2e82e99adc67346572c761fbe54d73e4a Mon Sep 17 00:00:00 2001 +From c950cda47386360e37a89dfa7029d83e33888a40 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Fri, 10 Apr 2020 13:04:40 +0800 Subject: [PATCH] accel/kvm: Add pre-park vCPU support @@ -14,13 +14,13 @@ Signed-off-by: Salil Mehta 2 files changed, 24 insertions(+) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c -index f450f25295..84edbe8bb1 100644 +index 8a98446b7c..f2ce5cd45a 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c -@@ -339,6 +339,29 @@ err: - return ret; +@@ -433,6 +433,29 @@ void kvm_destroy_vcpu(CPUState *cpu) + } } - + +int kvm_create_parked_vcpu(unsigned long vcpu_id) +{ + KVMState *s = kvm_state; @@ -48,16 +48,17 @@ index f450f25295..84edbe8bb1 100644 { struct KVMParkedVcpu *cpu; diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h -index acd90aebb6..565adb4e2c 100644 +index 7b22aeb6ae..2623775c27 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h -@@ -216,6 +216,7 @@ int kvm_has_many_ioeventfds(void); +@@ -221,6 +221,7 @@ int kvm_has_pit_state2(void); + int kvm_has_many_ioeventfds(void); int kvm_has_gsi_routing(void); int kvm_has_intx_set_mask(void); - +int kvm_create_parked_vcpu(unsigned long vcpu_id); - int kvm_init_vcpu(CPUState *cpu); - int kvm_cpu_exec(CPUState *cpu); - int kvm_destroy_vcpu(CPUState *cpu); --- -2.19.1 + + /** + * kvm_arm_supports_user_irq +-- +2.27.0 + diff --git a/accel-kvm-Fix-memory-waste-under-mismatch-page-size.patch b/accel-kvm-Fix-memory-waste-under-mismatch-page-size.patch deleted file mode 100644 index daff52e901686e17c1c492e899165b773db96258..0000000000000000000000000000000000000000 --- a/accel-kvm-Fix-memory-waste-under-mismatch-page-size.patch +++ /dev/null @@ -1,45 +0,0 @@ -From b50b9a0e2e5e8262c830df5994f3abbe0a37655a Mon Sep 17 00:00:00 2001 -From: Keqian Zhu -Date: Thu, 17 Dec 2020 09:49:40 +0800 -Subject: [PATCH] accel: kvm: Fix memory waste under mismatch page size - -When handle dirty log, we face qemu_real_host_page_size and -TARGET_PAGE_SIZE. The first one is the granule of KVM dirty -bitmap, and the second one is the granule of QEMU dirty bitmap. - -As qemu_real_host_page_size >= TARGET_PAGE_SIZE (kvm_init() -enforced it), misuse TARGET_PAGE_SIZE to init kvmslot dirty_bmap -may waste memory. For example, when qemu_real_host_page_size is -64K and TARGET_PAGE_SIZE is 4K, it wastes 93.75% (15/16) memory. - -Signed-off-by: Keqian Zhu -Reviewed-by: Andrew Jones -Reviewed-by: Peter Xu -Message-Id: <20201217014941.22872-2-zhukeqian1@huawei.com> -Signed-off-by: Paolo Bonzini -Signed-off-by: Kunkun Jiang ---- - accel/kvm/kvm-all.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c -index 5a6b89cc2a..4daff563a0 100644 ---- a/accel/kvm/kvm-all.c -+++ b/accel/kvm/kvm-all.c -@@ -551,8 +551,12 @@ static void kvm_memslot_init_dirty_bitmap(KVMSlot *mem) - * too, in most cases). - * So for now, let's align to 64 instead of HOST_LONG_BITS here, in - * a hope that sizeof(long) won't become >8 any time soon. -+ * -+ * Note: the granule of kvm dirty log is qemu_real_host_page_size. -+ * And mem->memory_size is aligned to it (otherwise this mem can't -+ * be registered to KVM). - */ -- hwaddr bitmap_size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS), -+ hwaddr bitmap_size = ALIGN(mem->memory_size / qemu_real_host_page_size, - /*HOST_LONG_BITS*/ 64) / 8; - mem->dirty_bmap = g_malloc0(bitmap_size); - } --- -2.27.0 - diff --git a/acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch b/acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch index 0506d1b73c1586699dd0fe92254baa5d0af26a7b..49477add34fd88544d959e8e973d97fa348a022c 100644 --- a/acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch +++ b/acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch @@ -1,4 +1,4 @@ -From 107c267ebe5b8c461268a4ff8384ad2f2b9e8ce0 Mon Sep 17 00:00:00 2001 +From 1ab75151c0a486ebdbe50d29c9677c7bc1f05929 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Wed, 22 Apr 2020 16:11:13 +0800 Subject: [PATCH] acpi/cpu: Prepare build_cpus_aml for arm virt @@ -17,16 +17,16 @@ Besides, CPU CPPC building is injected. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta --- - hw/acpi/cpu.c | 32 +++++++++++++++++++++++++------- + hw/acpi/cpu.c | 27 ++++++++++++++++++++------- hw/i386/acpi-build.c | 2 +- include/hw/acpi/cpu.h | 3 ++- - 3 files changed, 28 insertions(+), 9 deletions(-) + 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c -index 0c0bfe479a..72ad1fcff2 100644 +index b20903ea30..a9c2ee952a 100644 --- a/hw/acpi/cpu.c +++ b/hw/acpi/cpu.c -@@ -314,7 +314,8 @@ const VMStateDescription vmstate_cpu_hotplug = { +@@ -343,7 +343,8 @@ const VMStateDescription vmstate_cpu_hotplug = { void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, hwaddr io_base, const char *res_root, @@ -36,9 +36,9 @@ index 0c0bfe479a..72ad1fcff2 100644 { Aml *ifctx; Aml *field; -@@ -342,13 +343,18 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, +@@ -371,13 +372,18 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0)); - + crs = aml_resource_template(); - aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1, - ACPI_CPU_HOTPLUG_REG_LEN)); @@ -50,18 +50,18 @@ index 0c0bfe479a..72ad1fcff2 100644 + ACPI_CPU_HOTPLUG_REG_LEN, AML_READ_WRITE)); + } aml_append(cpu_ctrl_dev, aml_name_decl("_CRS", crs)); - + /* declare CPU hotplug MMIO region with related access fields */ aml_append(cpu_ctrl_dev, - aml_operation_region("PRST", AML_SYSTEM_IO, aml_int(io_base), + aml_operation_region("PRST", rs, aml_int(io_base), ACPI_CPU_HOTPLUG_REG_LEN)); - + field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, -@@ -517,6 +523,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, +@@ -663,6 +669,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, aml_append(dev, aml_name_decl("_UID", uid)); } - + + assert(adevc); + if (adevc->cpu_cppc) { + adevc->cpu_cppc(adev, i, arch_ids->len, dev); @@ -70,22 +70,10 @@ index 0c0bfe479a..72ad1fcff2 100644 method = aml_method("_STA", 0, AML_SERIALIZED); aml_append(method, aml_return(aml_call1(CPU_STS_METHOD, uid))); aml_append(dev, method); -@@ -535,6 +546,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, - apic->flags = cpu_to_le32(1); - break; - } -+ case ACPI_APIC_GENERIC_CPU_INTERFACE: { -+ AcpiMadtGenericCpuInterface *gicc = (void *)madt_buf->data; -+ gicc->flags = cpu_to_le32(1); -+ break; -+ } - default: - assert(0); - } -@@ -570,9 +586,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, +@@ -703,9 +714,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, aml_append(sb_scope, cpus_dev); aml_append(table, sb_scope); - + - method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED); - aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD)); - aml_append(table, method); @@ -94,35 +82,36 @@ index 0c0bfe479a..72ad1fcff2 100644 + aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD)); + aml_append(table, method); + } - + g_free(cphp_res_path); } diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c -index 749218561a..c97731ecb3 100644 +index a99c6e4fe3..1ce2d67c2e 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c -@@ -1869,7 +1869,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, - .acpi_1_compatible = true, .has_legacy_cphp = true +@@ -1513,7 +1513,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, + .fw_unplugs_cpu = pm->smi_on_cpu_unplug, }; build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base, - "\\_SB.PCI0", "\\_GPE._E02"); + "\\_SB.PCI0", "\\_GPE._E02", AML_SYSTEM_IO); } - + if (pcms->memhp_io_base && nr_mem) { diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h -index 62f0278ba2..a30ec84a4f 100644 +index 999caaf510..a0fdc44bdd 100644 --- a/include/hw/acpi/cpu.h +++ b/include/hw/acpi/cpu.h -@@ -55,7 +55,8 @@ typedef struct CPUHotplugFeatures { +@@ -58,7 +58,8 @@ typedef struct CPUHotplugFeatures { void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, hwaddr io_base, const char *res_root, - const char *event_handler_method); + const char *event_handler_method, + AmlRegionSpace rs); - + void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list); + +-- +2.27.0 --- -2.19.1 diff --git a/acpi-ged-Add-virt_madt_cpu_entry-to-madt_cpu-hook.patch b/acpi-ged-Add-virt_madt_cpu_entry-to-madt_cpu-hook.patch deleted file mode 100644 index f4e0a25c050e7948c1c7e1e2e0721c0b43d27fcc..0000000000000000000000000000000000000000 --- a/acpi-ged-Add-virt_madt_cpu_entry-to-madt_cpu-hook.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 3cd6df0b9e7d7b544673ce9a63b405e236d8265b Mon Sep 17 00:00:00 2001 -From: Keqian Zhu -Date: Fri, 10 Apr 2020 10:05:54 +0800 -Subject: [PATCH] acpi/ged: Add virt_madt_cpu_entry to madt_cpu hook - -In build_cpus_aml, we will invoke this hook to build _MAT -aml mehtod for cpus. - -Signed-off-by: Keqian Zhu -Signed-off-by: Salil Mehta ---- - hw/acpi/generic_event_device.c | 1 + - include/hw/acpi/generic_event_device.h | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c -index 9cee90cc70..b834ae3ff6 100644 ---- a/hw/acpi/generic_event_device.c -+++ b/hw/acpi/generic_event_device.c -@@ -288,6 +288,7 @@ static void acpi_ged_class_init(ObjectClass *class, void *data) - hc->plug = acpi_ged_device_plug_cb; - - adevc->send_event = acpi_ged_send_event; -+ adevc->madt_cpu = virt_madt_cpu_entry; - } - - static const TypeInfo acpi_ged_info = { -diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h -index d157eac088..f99efad7a3 100644 ---- a/include/hw/acpi/generic_event_device.h -+++ b/include/hw/acpi/generic_event_device.h -@@ -61,6 +61,7 @@ - - #include "hw/sysbus.h" - #include "hw/acpi/memory_hotplug.h" -+#include "hw/arm/virt.h" - - #define ACPI_POWER_BUTTON_DEVICE "PWRB" - --- -2.19.1 diff --git a/acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch b/acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch index 57247e6797da5a977685f737e9454427ab2c41df..12a279ea615113b4d249e5bf8524f961778fb3b3 100644 --- a/acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch +++ b/acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch @@ -1,4 +1,4 @@ -From 05d22b55133db1a2526cfe305102e075e883b5e2 Mon Sep 17 00:00:00 2001 +From 603cbcc5efdd35f518a5bd0a5067d40c2c4eb8d6 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Fri, 3 Apr 2020 15:41:01 +0800 Subject: [PATCH] acpi/ged: Extend ACPI GED to support CPU hotplug @@ -26,45 +26,45 @@ Signed-off-by: Salil Mehta 6 files changed, 44 insertions(+), 2 deletions(-) diff --git a/docs/specs/acpi_hw_reduced_hotplug.rst b/docs/specs/acpi_hw_reduced_hotplug.rst -index 911a98255b..deb481555d 100644 +index 0bd3f9399f..3acd6fcd8b 100644 --- a/docs/specs/acpi_hw_reduced_hotplug.rst +++ b/docs/specs/acpi_hw_reduced_hotplug.rst -@@ -63,7 +63,8 @@ GED IO interface (4 byte access) - bits: +@@ -64,7 +64,8 @@ GED IO interface (4 byte access) 0: Memory hotplug event 1: System power down event -- 2-31: Reserved -+ 2: CPU hotplug event -+ 3-31: Reserved - + 2: NVDIMM hotplug event +- 3-31: Reserved ++ 3: CPU hotplug event ++ 4-31: Reserved + **write_access:** - + diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c -index 72ad1fcff2..cb6bb67f3c 100644 +index a9c2ee952a..f9ce0a7f41 100644 --- a/hw/acpi/cpu.c +++ b/hw/acpi/cpu.c @@ -6,7 +6,6 @@ #include "trace.h" #include "sysemu/numa.h" - + -#define ACPI_CPU_HOTPLUG_REG_LEN 12 #define ACPI_CPU_SELECTOR_OFFSET_WR 0 #define ACPI_CPU_FLAGS_OFFSET_RW 4 #define ACPI_CPU_CMD_OFFSET_WR 5 diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c -index 82139b4314..478a4ee87c 100644 +index e28457a7d1..042a8ef8a5 100644 --- a/hw/acpi/generic_event_device.c +++ b/hw/acpi/generic_event_device.c -@@ -23,6 +23,7 @@ - static const uint32_t ged_supported_events[] = { +@@ -25,6 +25,7 @@ static const uint32_t ged_supported_events[] = { ACPI_GED_MEM_HOTPLUG_EVT, ACPI_GED_PWR_DOWN_EVT, + ACPI_GED_NVDIMM_HOTPLUG_EVT, + ACPI_GED_CPU_HOTPLUG_EVT, }; - + /* -@@ -110,6 +111,9 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, - aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE), +@@ -117,6 +118,9 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, + aml_notify(aml_name("\\_SB.NVDR"), aml_int(0x80))); break; + case ACPI_GED_CPU_HOTPLUG_EVT: @@ -73,28 +73,28 @@ index 82139b4314..478a4ee87c 100644 default: /* * Please make sure all the events in ged_supported_events[] -@@ -176,6 +180,8 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, - - if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { +@@ -234,6 +238,8 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, + } else { acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp); + } + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + acpi_cpu_plug_cb(hotplug_dev, &s->cpuhp_state, dev, errp); } else { error_setg(errp, "virt: device plug request for unsupported device" " type: %s", object_get_typename(OBJECT(dev))); -@@ -192,6 +198,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) - sel = ACPI_GED_MEM_HOTPLUG_EVT; - } else if (ev & ACPI_POWER_DOWN_STATUS) { +@@ -279,6 +285,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) sel = ACPI_GED_PWR_DOWN_EVT; + } else if (ev & ACPI_NVDIMM_HOTPLUG_STATUS) { + sel = ACPI_GED_NVDIMM_HOTPLUG_EVT; + } else if (ev & ACPI_CPU_HOTPLUG_STATUS) { + sel = ACPI_GED_CPU_HOTPLUG_EVT; } else { /* Unknown event. Return without generating interrupt. */ warn_report("GED: Unsupported event %d. No irq injected", ev); -@@ -224,6 +232,16 @@ static const VMStateDescription vmstate_memhp_state = { +@@ -311,6 +319,16 @@ static const VMStateDescription vmstate_memhp_state = { } }; - + +static const VMStateDescription vmstate_cpuhp_state = { + .name = "acpi-ged/cpuhp", + .version_id = 1, @@ -108,26 +108,26 @@ index 82139b4314..478a4ee87c 100644 static const VMStateDescription vmstate_ged_state = { .name = "acpi-ged-state", .version_id = 1, -@@ -244,6 +262,7 @@ static const VMStateDescription vmstate_acpi_ged = { - }, +@@ -360,6 +378,7 @@ static const VMStateDescription vmstate_acpi_ged = { .subsections = (const VMStateDescription * []) { &vmstate_memhp_state, + &vmstate_ghes_state, + &vmstate_cpuhp_state, NULL } }; -@@ -254,6 +273,7 @@ static void acpi_ged_initfn(Object *obj) +@@ -370,6 +389,7 @@ static void acpi_ged_initfn(Object *obj) AcpiGedState *s = ACPI_GED(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); GEDState *ged_st = &s->ged_state; + MachineClass *mc; - - memory_region_init_io(&ged_st->io, obj, &ged_ops, ged_st, + + memory_region_init_io(&ged_st->evt, obj, &ged_evt_ops, ged_st, TYPE_ACPI_GED, ACPI_GED_EVT_SEL_LEN); -@@ -273,6 +293,21 @@ static void acpi_ged_initfn(Object *obj) - sysbus_init_mmio(sbd, &s->container_memhp); - acpi_memory_hotplug_init(&s->container_memhp, OBJECT(dev), - &s->memhp_state, 0); +@@ -393,6 +413,21 @@ static void acpi_ged_initfn(Object *obj) + memory_region_init_io(&ged_st->regs, obj, &ged_regs_ops, ged_st, + TYPE_ACPI_GED "-regs", ACPI_GED_REG_COUNT); + sysbus_init_mmio(sbd, &ged_st->regs); + + mc = MACHINE_GET_CLASS(qdev_get_machine()); + if (!mc->possible_cpu_arch_ids) { @@ -144,54 +144,54 @@ index 82139b4314..478a4ee87c 100644 + cpu_hotplug_hw_init(&s->container_cpuhp, OBJECT(dev), + &s->cpuhp_state, 0); } - + static void acpi_ged_class_init(ObjectClass *class, void *data) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig -index ad7f7c089b..15e18b0a48 100644 +index 2d37d29f02..006a4b4c4b 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig -@@ -24,6 +24,7 @@ config ARM_VIRT +@@ -27,6 +27,7 @@ config ARM_VIRT select DIMM - select ACPI_MEMORY_HOTPLUG select ACPI_HW_REDUCED + select ACPI_APEI + select ACPI_CPU_HOTPLUG - + config CHEETAH bool diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h -index a30ec84a4f..e726414459 100644 +index a0fdc44bdd..d521025830 100644 --- a/include/hw/acpi/cpu.h +++ b/include/hw/acpi/cpu.h @@ -17,6 +17,8 @@ #include "hw/acpi/aml-build.h" #include "hw/hotplug.h" - + +#define ACPI_CPU_HOTPLUG_REG_LEN 12 + typedef struct AcpiCpuStatus { struct CPUState *cpu; uint64_t arch_id; diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h -index f99efad7a3..e702ff1e18 100644 +index d49217c445..6bb2ade385 100644 --- a/include/hw/acpi/generic_event_device.h +++ b/include/hw/acpi/generic_event_device.h -@@ -62,6 +62,7 @@ - #include "hw/sysbus.h" +@@ -63,6 +63,7 @@ #include "hw/acpi/memory_hotplug.h" - #include "hw/arm/virt.h" + #include "hw/acpi/ghes.h" + #include "qom/object.h" +#include "hw/acpi/cpu.h" - + #define ACPI_POWER_BUTTON_DEVICE "PWRB" - -@@ -83,6 +84,7 @@ - */ + +@@ -97,6 +98,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED) #define ACPI_GED_MEM_HOTPLUG_EVT 0x1 #define ACPI_GED_PWR_DOWN_EVT 0x2 -+#define ACPI_GED_CPU_HOTPLUG_EVT 0x4 - + #define ACPI_GED_NVDIMM_HOTPLUG_EVT 0x4 ++#define ACPI_GED_CPU_HOTPLUG_EVT 0x8 + typedef struct GEDState { - MemoryRegion io; -@@ -93,6 +95,8 @@ typedef struct AcpiGedState { + MemoryRegion evt; +@@ -108,6 +110,8 @@ struct AcpiGedState { SysBusDevice parent_obj; MemHotplugState memhp_state; MemoryRegion container_memhp; @@ -200,5 +200,6 @@ index f99efad7a3..e702ff1e18 100644 GEDState ged_state; uint32_t ged_event_bitmap; qemu_irq irq; --- -2.19.1 +-- +2.27.0 + diff --git a/acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch b/acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch index 30f210b33b66332cc0c16b5d2ddb706a177a2130..47d18ea6aa6fff4b8e8fce353f5fa0c3405b8291 100644 --- a/acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch +++ b/acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch @@ -1,4 +1,4 @@ -From 0288d98f0ef4d17a73cf2bad1b928cd7c044e318 Mon Sep 17 00:00:00 2001 +From 8bd05cdb811e868c54ef28ac558c7efb7cf610b9 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Fri, 10 Apr 2020 13:40:44 +0800 Subject: [PATCH] acpi/madt: Add pre-sizing capability to MADT GICC struct @@ -9,87 +9,76 @@ of MADT GICC struct, so we should pre-sizing MADT GICC too. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta --- - hw/arm/virt-acpi-build.c | 26 +++++++++++++++++++++----- - include/hw/acpi/acpi-defs.h | 1 + - 2 files changed, 22 insertions(+), 5 deletions(-) + hw/arm/virt-acpi-build.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c -index dbe9acb148..efac788ba1 100644 +index 7cb320d9f2..a16b54086e 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c -@@ -678,6 +678,13 @@ void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid, - const MemMapEntry *memmap = vms->memmap; - AcpiMadtGenericCpuInterface *gicc = acpi_data_push(entry, sizeof(*gicc)); - ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(uid)); +@@ -787,8 +787,16 @@ void virt_madt_cpu_entry(AcpiDeviceIf *adev, int i, + ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); + uint64_t physical_base_address = 0, gich = 0, gicv = 0; + uint32_t vgic_interrupt = vms->virt ? PPI(ARCH_GIC_MAINT_IRQ) : 0; +- uint32_t pmu_interrupt = arm_feature(&armcpu->env, ARM_FEATURE_PMU) ? +- PPI(VIRTUAL_PMU_IRQ) : 0; ++ uint32_t pmu_interrupt, enabled; + static bool pmu; + -+ if (uid == 0) { ++ if (i == 0) { + pmu = arm_feature(&armcpu->env, ARM_FEATURE_PMU); + } + /* FEATURE_PMU should be all enabled or disabled for CPUs */ + assert(!armcpu || arm_feature(&armcpu->env, ARM_FEATURE_PMU) == pmu); - - gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE; - gicc->length = sizeof(*gicc); -@@ -687,11 +694,15 @@ void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid, - gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base); - } - gicc->cpu_interface_number = cpu_to_le32(uid); -- gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity); -+ gicc->arm_mpidr = possible_cpus->cpus[uid].arch_id; - gicc->uid = cpu_to_le32(uid); -- gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED); -+ if (armcpu) { -+ gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED); -+ } else { -+ gicc->flags = cpu_to_le32(ACPI_MADT_GICC_DISABLED); -+ } - -- if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { -+ if (pmu) { - gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ)); - } - if (vms->virt) { -@@ -704,12 +715,17 @@ static void - build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) ++ pmu_interrupt = pmu ? PPI(VIRTUAL_PMU_IRQ) : 0; ++ enabled = armcpu || force_enabled ? 1 /* Enabled */ : 0 /* Disabled */; + + if (vms->gic_version == 2) { + physical_base_address = memmap[VIRT_GIC_CPU].base; +@@ -803,7 +811,7 @@ void virt_madt_cpu_entry(AcpiDeviceIf *adev, int i, + build_append_int_noprefix(table_data, i, 4); /* GIC ID */ + build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */ + /* Flags */ +- build_append_int_noprefix(table_data, 1, 4); /* Enabled */ ++ build_append_int_noprefix(table_data, enabled, 4); /* Enabled */ + /* Parking Protocol Version */ + build_append_int_noprefix(table_data, 0, 4); + /* Performance Interrupt GSIV */ +@@ -817,7 +825,7 @@ void virt_madt_cpu_entry(AcpiDeviceIf *adev, int i, + build_append_int_noprefix(table_data, vgic_interrupt, 4); + build_append_int_noprefix(table_data, 0, 8); /* GICR Base Address*/ + /* MPIDR */ +- build_append_int_noprefix(table_data, armcpu->mp_affinity, 8); ++ build_append_int_noprefix(table_data, possible_cpus->cpus[i].arch_id, 8); + } + + static void +@@ -825,9 +833,14 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) { + int i; VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); + MachineClass *mc = MACHINE_GET_CLASS(vms); + MachineState *ms = MACHINE(vms); + const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); - int madt_start = table_data->len; const MemMapEntry *memmap = vms->memmap; - const int *irqmap = vms->irqmap; - AcpiMultipleApicTable *madt; - AcpiMadtGenericDistributor *gicd; - AcpiMadtGenericMsiFrame *gic_msi; + AcpiTable table = { .sig = "APIC", .rev = 3, .oem_id = vms->oem_id, + .oem_table_id = vms->oem_table_id }; + /* The MADT GICC numbers */ -+ int num_cpu = vms->smp_cpus; - int i; - - madt = acpi_data_push(table_data, sizeof *madt); -@@ -720,8 +736,8 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) - gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base); - gicd->version = vms->gic_version; - -- for (i = 0; i < vms->smp_cpus; i++) { -- virt_madt_cpu_entry(NULL, i, NULL, table_data); ++ int num_cpu = ms->smp.cpus; + + acpi_table_begin(&table, table_data); + /* Local Interrupt Controller Address */ +@@ -846,8 +859,8 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + build_append_int_noprefix(table_data, vms->gic_version, 1); + build_append_int_noprefix(table_data, 0, 3); /* Reserved */ + +- for (i = 0; i < MACHINE(vms)->smp.cpus; i++) { +- virt_madt_cpu_entry(NULL, i, NULL, table_data, false); + for (i = 0; i < num_cpu; i++) { -+ virt_madt_cpu_entry(NULL, i, possible_cpus, table_data); ++ virt_madt_cpu_entry(NULL, i, possible_cpus, table_data, false); } - + if (vms->gic_version == 3) { -diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h -index 39ae91d3b8..6bfa7f9152 100644 ---- a/include/hw/acpi/acpi-defs.h -+++ b/include/hw/acpi/acpi-defs.h -@@ -306,6 +306,7 @@ typedef struct AcpiMadtGenericCpuInterface AcpiMadtGenericCpuInterface; - - /* GICC CPU Interface Flags */ - #define ACPI_MADT_GICC_ENABLED 1 -+#define ACPI_MADT_GICC_DISABLED 0 +-- +2.27.0 - struct AcpiMadtGenericDistributor { - ACPI_SUB_HEADER_DEF --- -2.19.1 diff --git a/acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch b/acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch index 6bda35c51a3952121a155081bf0a37ce3534da25..d322c8d1098dedcfcdc328c8e5e9c5b2bf035010 100644 --- a/acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch +++ b/acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch @@ -1,4 +1,4 @@ -From a3097eed8b642dc6fe891112340821e869b90cc2 Mon Sep 17 00:00:00 2001 +From 4f50ed900713acc14c971c07165fa83670d3f2b8 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Mon, 13 Jan 2020 19:02:20 +0800 Subject: [PATCH] acpi/madt: Factor out the building of MADT GICC struct @@ -10,99 +10,127 @@ out the GICC building code from ACPI MADT and reuse it in build_cpus_aml. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta --- - hw/arm/virt-acpi-build.c | 51 +++++++++++++++++++++++----------------- - include/hw/arm/virt.h | 3 +++ - 2 files changed, 32 insertions(+), 22 deletions(-) + hw/arm/virt-acpi-build.c | 77 ++++++++++++++++++++++------------------ + include/hw/arm/virt.h | 4 +++ + 2 files changed, 47 insertions(+), 34 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c -index f48733d9f2..4b6aace433 100644 +index 1ca705654b..64b1ed8672 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c -@@ -664,6 +664,34 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) - table_data->len - gtdt_start, 2, NULL, NULL); +@@ -771,6 +771,48 @@ static void build_append_gicr(GArray *table_data, uint64_t base, uint32_t size) + build_append_int_noprefix(table_data, size, 4); /* Discovery Range Length */ } - -+void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid, -+ const CPUArchIdList *possible_cpus, GArray *entry) + ++void virt_madt_cpu_entry(AcpiDeviceIf *adev, int i, ++ const CPUArchIdList *possible_cpus, GArray *table_data, ++ bool force_enabled) +{ + VirtMachineState *vms = VIRT_MACHINE(qdev_get_machine()); + const MemMapEntry *memmap = vms->memmap; -+ AcpiMadtGenericCpuInterface *gicc = acpi_data_push(entry, sizeof(*gicc)); -+ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(uid)); ++ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); ++ uint64_t physical_base_address = 0, gich = 0, gicv = 0; ++ uint32_t vgic_interrupt = vms->virt ? PPI(ARCH_GIC_MAINT_IRQ) : 0; ++ uint32_t pmu_interrupt = arm_feature(&armcpu->env, ARM_FEATURE_PMU) ? ++ PPI(VIRTUAL_PMU_IRQ) : 0; + -+ gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE; -+ gicc->length = sizeof(*gicc); + if (vms->gic_version == 2) { -+ gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base); -+ gicc->gich_base_address = cpu_to_le64(memmap[VIRT_GIC_HYP].base); -+ gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base); ++ physical_base_address = memmap[VIRT_GIC_CPU].base; ++ gicv = memmap[VIRT_GIC_VCPU].base; ++ gich = memmap[VIRT_GIC_HYP].base; + } -+ gicc->cpu_interface_number = cpu_to_le32(uid); -+ gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity); -+ gicc->uid = cpu_to_le32(uid); -+ gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED); + -+ if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { -+ gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ)); -+ } -+ if (vms->virt) { -+ gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GIC_MAINT_IRQ)); -+ } ++ /* 5.2.12.14 GIC Structure */ ++ build_append_int_noprefix(table_data, 0xB, 1); /* Type */ ++ build_append_int_noprefix(table_data, 76, 1); /* Length */ ++ build_append_int_noprefix(table_data, 0, 2); /* Reserved */ ++ build_append_int_noprefix(table_data, i, 4); /* GIC ID */ ++ build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */ ++ /* Flags */ ++ build_append_int_noprefix(table_data, 1, 4); /* Enabled */ ++ /* Parking Protocol Version */ ++ build_append_int_noprefix(table_data, 0, 4); ++ /* Performance Interrupt GSIV */ ++ build_append_int_noprefix(table_data, pmu_interrupt, 4); ++ build_append_int_noprefix(table_data, 0, 8); /* Parked Address */ ++ /* Physical Base Address */ ++ build_append_int_noprefix(table_data, physical_base_address, 8); ++ build_append_int_noprefix(table_data, gicv, 8); /* GICV */ ++ build_append_int_noprefix(table_data, gich, 8); /* GICH */ ++ /* VGIC Maintenance interrupt */ ++ build_append_int_noprefix(table_data, vgic_interrupt, 4); ++ build_append_int_noprefix(table_data, 0, 8); /* GICR Base Address*/ ++ /* MPIDR */ ++ build_append_int_noprefix(table_data, armcpu->mp_affinity, 8); +} + - /* MADT */ static void build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) -@@ -686,28 +714,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) - gicd->version = vms->gic_version; - - for (i = 0; i < vms->smp_cpus; i++) { -- AcpiMadtGenericCpuInterface *gicc = acpi_data_push(table_data, -- sizeof(*gicc)); + { +@@ -798,40 +840,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + build_append_int_noprefix(table_data, 0, 3); /* Reserved */ + + for (i = 0; i < MACHINE(vms)->smp.cpus; i++) { - ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); +- uint64_t physical_base_address = 0, gich = 0, gicv = 0; +- uint32_t vgic_interrupt = vms->virt ? PPI(ARCH_GIC_MAINT_IRQ) : 0; +- uint32_t pmu_interrupt = arm_feature(&armcpu->env, ARM_FEATURE_PMU) ? +- PPI(VIRTUAL_PMU_IRQ) : 0; - -- gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE; -- gicc->length = sizeof(*gicc); - if (vms->gic_version == 2) { -- gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base); -- gicc->gich_base_address = cpu_to_le64(memmap[VIRT_GIC_HYP].base); -- gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base); +- physical_base_address = memmap[VIRT_GIC_CPU].base; +- gicv = memmap[VIRT_GIC_VCPU].base; +- gich = memmap[VIRT_GIC_HYP].base; - } -- gicc->cpu_interface_number = cpu_to_le32(i); -- gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity); -- gicc->uid = cpu_to_le32(i); -- gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED); - -- if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { -- gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ)); -- } -- if (vms->virt) { -- gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GIC_MAINT_IRQ)); -- } -+ virt_madt_cpu_entry(NULL, i, NULL, table_data); +- /* 5.2.12.14 GIC Structure */ +- build_append_int_noprefix(table_data, 0xB, 1); /* Type */ +- build_append_int_noprefix(table_data, 76, 1); /* Length */ +- build_append_int_noprefix(table_data, 0, 2); /* Reserved */ +- build_append_int_noprefix(table_data, i, 4); /* GIC ID */ +- build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */ +- /* Flags */ +- build_append_int_noprefix(table_data, 1, 4); /* Enabled */ +- /* Parking Protocol Version */ +- build_append_int_noprefix(table_data, 0, 4); +- /* Performance Interrupt GSIV */ +- build_append_int_noprefix(table_data, pmu_interrupt, 4); +- build_append_int_noprefix(table_data, 0, 8); /* Parked Address */ +- /* Physical Base Address */ +- build_append_int_noprefix(table_data, physical_base_address, 8); +- build_append_int_noprefix(table_data, gicv, 8); /* GICV */ +- build_append_int_noprefix(table_data, gich, 8); /* GICH */ +- /* VGIC Maintenance interrupt */ +- build_append_int_noprefix(table_data, vgic_interrupt, 4); +- build_append_int_noprefix(table_data, 0, 8); /* GICR Base Address*/ +- /* MPIDR */ +- build_append_int_noprefix(table_data, armcpu->mp_affinity, 8); ++ virt_madt_cpu_entry(NULL, i, NULL, table_data, false); } - + if (vms->gic_version == 3) { diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h -index 3dfefca93b..6b1f10b231 100644 +index a4356cf736..36639e8d3e 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h -@@ -37,6 +37,7 @@ - #include "hw/block/flash.h" +@@ -38,6 +38,7 @@ #include "sysemu/kvm.h" #include "hw/intc/arm_gicv3_common.h" + #include "qom/object.h" +#include "hw/acpi/acpi_dev_interface.h" - + #define NUM_GICV2M_SPIS 64 #define NUM_VIRTIO_TRANSPORTS 32 -@@ -154,6 +155,8 @@ typedef struct { - OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE) - +@@ -181,6 +182,9 @@ OBJECT_DECLARE_TYPE(VirtMachineState, VirtMachineClass, VIRT_MACHINE) + void virt_acpi_setup(VirtMachineState *vms); + bool virt_is_acpi_enabled(VirtMachineState *vms); +void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid, -+ const CPUArchIdList *cpu_list, GArray *entry); - ++ const CPUArchIdList *cpu_list, GArray *entry, ++ bool force_enabled); + /* Return the number of used redistributor regions */ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms) --- -2.19.1 +-- +2.27.0 + diff --git a/add-Phytium-s-CPU-models-FT-2000-and-Tengyun-S2500.patch b/add-Phytium-s-CPU-models-FT-2000-and-Tengyun-S2500.patch index bdf4931105e9f568e3da3ca54c014bdc48b47062..0bc4707a244ebc8366648250c75755e8446c6e44 100644 --- a/add-Phytium-s-CPU-models-FT-2000-and-Tengyun-S2500.patch +++ b/add-Phytium-s-CPU-models-FT-2000-and-Tengyun-S2500.patch @@ -1,34 +1,35 @@ -From ea7a395de920cfecd9bf99f0cf55914d47718edf Mon Sep 17 00:00:00 2001 +From ec35c96006851a956a7e401f29af0ffe137c4bb9 Mon Sep 17 00:00:00 2001 From: Jiadong Zeng -Date: Thu, 11 Nov 2021 14:25:38 +0800 +Date: Tue, 8 Feb 2022 22:56:37 +0800 Subject: [PATCH] add Phytium's CPU models: FT-2000+ and Tengyun-S2500. Signed-off-by: Jiadong Zeng +Signed-off-by: Mingwang Li --- hw/arm/virt.c | 2 ++ target/arm/cpu64.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 7506d0ff32..0e46260116 100644 +index a4a35584e9..3c972fdab0 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -195,6 +195,8 @@ static const char *valid_cpus[] = { +@@ -202,6 +202,8 @@ static const char *valid_cpus[] = { ARM_CPU_TYPE_NAME("cortex-a57"), ARM_CPU_TYPE_NAME("cortex-a72"), ARM_CPU_TYPE_NAME("Kunpeng-920"), + ARM_CPU_TYPE_NAME("FT-2000+"), + ARM_CPU_TYPE_NAME("Tengyun-S2500"), + ARM_CPU_TYPE_NAME("a64fx"), ARM_CPU_TYPE_NAME("host"), ARM_CPU_TYPE_NAME("max"), - }; diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index a1649f8844..4cf5b89db0 100644 +index 556b6f3691..08d886de7b 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c -@@ -327,6 +327,32 @@ static void cpu_max_set_sve_vq(Object *obj, Visitor *v, const char *name, - error_propagate(errp, err); - } +@@ -676,6 +676,32 @@ static Property arm_cpu_pauth_property = + static Property arm_cpu_pauth_impdef_property = + DEFINE_PROP_BOOL("pauth-impdef", ARMCPU, prop_pauth_impdef, false); +static void aarch64_max_ft2000plus_initfn(Object *obj) +{ @@ -59,14 +60,14 @@ index a1649f8844..4cf5b89db0 100644 /* -cpu max: if KVM is enabled, like -cpu host (best possible with this host); * otherwise, a CPU with as many features enabled as our emulation supports. * The version of '-cpu max' for qemu-system-arm is defined in cpu.c; -@@ -442,6 +468,8 @@ static const ARMCPUInfo aarch64_cpus[] = { +@@ -914,6 +940,8 @@ static const ARMCPUInfo aarch64_cpus[] = { { .name = "cortex-a53", .initfn = aarch64_a53_initfn }, { .name = "cortex-a72", .initfn = aarch64_a72_initfn }, - { .name = "Kunpeng-920", .initfn = aarch64_kunpeng_920_initfn }, + { .name = "Kunpeng-920", .initfn = aarch64_kunpeng_920_initfn}, + { .name = "FT-2000+", .initfn = aarch64_max_ft2000plus_initfn }, + { .name = "Tengyun-S2500", .initfn = aarch64_max_tengyun_s2500_initfn }, + { .name = "a64fx", .initfn = aarch64_a64fx_initfn }, { .name = "max", .initfn = aarch64_max_initfn }, - { .name = NULL } }; -- 2.27.0 diff --git a/aio-wait-delegate-polling-of-main-AioContext-if-BQL-not-held.patch b/aio-wait-delegate-polling-of-main-AioContext-if-BQL-not-held.patch deleted file mode 100644 index 7926e7fa0db4ef16737a89782ea661273ef8c4d3..0000000000000000000000000000000000000000 --- a/aio-wait-delegate-polling-of-main-AioContext-if-BQL-not-held.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 929d29ec7bf9dd6ec3802bea2148a041ff30d59b Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Tue, 14 Apr 2020 21:17:09 +0800 -Subject: [PATCH] aio-wait: delegate polling of main AioContext if BQL not held - -Any thread that is not a iothread returns NULL for qemu_get_current_aio_context(). -As a result, it would also return true for -in_aio_context_home_thread(qemu_get_aio_context()), causing -AIO_WAIT_WHILE to invoke aio_poll() directly. This is incorrect -if the BQL is not held, because aio_poll() does not expect to -run concurrently from multiple threads, and it can actually -happen when savevm writes to the vmstate file from the -migration thread. - -Therefore, restrict in_aio_context_home_thread to return true -for the main AioContext only if the BQL is held. - -The function is moved to aio-wait.h because it is mostly used -there and to avoid a circular reference between main-loop.h -and block/aio.h. - -Signed-off-by: Paolo Bonzini -Message-Id: <20200407140746.8041-5-pbonzini@redhat.com> -Signed-off-by: Stefan Hajnoczi ---- - include/block/aio-wait.h | 22 ++++++++++++++++++++++ - include/block/aio.h | 29 ++++++++++------------------- - 2 files changed, 32 insertions(+), 19 deletions(-) - -diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h -index afeeb18f..716d2639 100644 ---- a/include/block/aio-wait.h -+++ b/include/block/aio-wait.h -@@ -26,6 +26,7 @@ - #define QEMU_AIO_WAIT_H - - #include "block/aio.h" -+#include "qemu/main-loop.h" - - /** - * AioWait: -@@ -124,4 +125,25 @@ void aio_wait_kick(void); - */ - void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque); - -+/** -+ * in_aio_context_home_thread: -+ * @ctx: the aio context -+ * -+ * Return whether we are running in the thread that normally runs @ctx. Note -+ * that acquiring/releasing ctx does not affect the outcome, each AioContext -+ * still only has one home thread that is responsible for running it. -+ */ -+static inline bool in_aio_context_home_thread(AioContext *ctx) -+{ -+ if (ctx == qemu_get_current_aio_context()) { -+ return true; -+ } -+ -+ if (ctx == qemu_get_aio_context()) { -+ return qemu_mutex_iothread_locked(); -+ } else { -+ return false; -+ } -+} -+ - #endif /* QEMU_AIO_WAIT_H */ -diff --git a/include/block/aio.h b/include/block/aio.h -index 6b0d52f7..9d28e247 100644 ---- a/include/block/aio.h -+++ b/include/block/aio.h -@@ -60,12 +60,16 @@ struct AioContext { - QLIST_HEAD(, AioHandler) aio_handlers; - - /* Used to avoid unnecessary event_notifier_set calls in aio_notify; -- * accessed with atomic primitives. If this field is 0, everything -- * (file descriptors, bottom halves, timers) will be re-evaluated -- * before the next blocking poll(), thus the event_notifier_set call -- * can be skipped. If it is non-zero, you may need to wake up a -- * concurrent aio_poll or the glib main event loop, making -- * event_notifier_set necessary. -+ * only written from the AioContext home thread, or under the BQL in -+ * the case of the main AioContext. However, it is read from any -+ * thread so it is still accessed with atomic primitives. -+ * -+ * If this field is 0, everything (file descriptors, bottom halves, -+ * timers) will be re-evaluated before the next blocking poll() or -+ * io_uring wait; therefore, the event_notifier_set call can be -+ * skipped. If it is non-zero, you may need to wake up a concurrent -+ * aio_poll or the glib main event loop, making event_notifier_set -+ * necessary. - * - * Bit 0 is reserved for GSource usage of the AioContext, and is 1 - * between a call to aio_ctx_prepare and the next call to aio_ctx_check. -@@ -580,19 +584,6 @@ void aio_co_enter(AioContext *ctx, struct Coroutine *co); - */ - AioContext *qemu_get_current_aio_context(void); - --/** -- * in_aio_context_home_thread: -- * @ctx: the aio context -- * -- * Return whether we are running in the thread that normally runs @ctx. Note -- * that acquiring/releasing ctx does not affect the outcome, each AioContext -- * still only has one home thread that is responsible for running it. -- */ --static inline bool in_aio_context_home_thread(AioContext *ctx) --{ -- return ctx == qemu_get_current_aio_context(); --} -- - /** - * aio_context_setup: - * @ctx: the aio context --- -2.23.0 diff --git a/apic-Use-32bit-APIC-ID-for-migration-instance-ID.patch b/apic-Use-32bit-APIC-ID-for-migration-instance-ID.patch deleted file mode 100644 index 4a96fc5ce1372f0e2f59ab9019cf8d72e0ee7bee..0000000000000000000000000000000000000000 --- a/apic-Use-32bit-APIC-ID-for-migration-instance-ID.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 3bdd21c4b7d80cacc6b5f1b26ab52ef3a0aceb06 Mon Sep 17 00:00:00 2001 -From: Peter Xu -Date: Wed, 16 Oct 2019 10:29:32 +0800 -Subject: [PATCH 7/8] apic: Use 32bit APIC ID for migration instance ID - -Migration is silently broken now with x2apic config like this: - - -smp 200,maxcpus=288,sockets=2,cores=72,threads=2 \ - -device intel-iommu,intremap=on,eim=on - -After migration, the guest kernel could hang at anything, due to -x2apic bit not migrated correctly in IA32_APIC_BASE on some vcpus, so -any operations related to x2apic could be broken then (e.g., RDMSR on -x2apic MSRs could fail because KVM would think that the vcpu hasn't -enabled x2apic at all). - -The issue is that the x2apic bit was never applied correctly for vcpus -whose ID > 255 when migrate completes, and that's because when we -migrate APIC we use the APICCommonState.id as instance ID of the -migration stream, while that's too short for x2apic. - -Let's use the newly introduced initial_apic_id for that. - -Signed-off-by: Peter Xu -Reviewed-by: Juan Quintela -Reviewed-by: Eduardo Habkost -Signed-off-by: Juan Quintela ---- - hw/intc/apic_common.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c -index 07adba0..2c0cb1e 100644 ---- a/hw/intc/apic_common.c -+++ b/hw/intc/apic_common.c -@@ -313,7 +313,10 @@ static void apic_common_realize(DeviceState *dev, Error **errp) - APICCommonState *s = APIC_COMMON(dev); - APICCommonClass *info; - static DeviceState *vapic; -- uint32_t instance_id = s->id; -+ uint32_t instance_id = s->initial_apic_id; -+ -+ /* Normally initial APIC ID should be no more than hundreds */ -+ assert(instance_id != VMSTATE_INSTANCE_ID_ANY); - - info = APIC_COMMON_GET_CLASS(s); - info->realize(dev, errp); --- -1.8.3.1 - diff --git a/arm-cpu-Fixed-function-undefined-error-at-compile-ti.patch b/arm-cpu-Fixed-function-undefined-error-at-compile-ti.patch deleted file mode 100644 index 68814a8d8135faf707bacbff017fe8bc84d71f54..0000000000000000000000000000000000000000 --- a/arm-cpu-Fixed-function-undefined-error-at-compile-ti.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 6d795b30ff09bc1f799daa454f776d682cc77197 Mon Sep 17 00:00:00 2001 -From: zhanghao1 -Date: Tue, 11 May 2021 20:17:16 +0800 -Subject: [PATCH] arm/cpu: Fixed function undefined error at compile time under - arm - - Add the compilation option CONFIG_KVM while using - "kvm_arm_cpu_feature_supported" and "kvm_arm_get_one_reg". - In arm, the default value of CONFIG_KVM is no. - - While the target is arm, the compilation fails because - the function "kvm_arm_cpu_feature_supporte" is declared - or the function "kvm_arm_get_one_reg" is not defined. - -Signed-off-by: zhanghao1 ---- - target/arm/helper.c | 4 ++++ - target/arm/kvm_arm.h | 4 ++++ - 2 files changed, 8 insertions(+) - -diff --git a/target/arm/helper.c b/target/arm/helper.c -index bddd355fa0..9d2b2659f6 100644 ---- a/target/arm/helper.c -+++ b/target/arm/helper.c -@@ -284,6 +284,7 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) - - newval = read_raw_cp_reg(&cpu->env, ri); - if (kvm_sync) { -+#ifdef CONFIG_KVM - if (is_id_reg(ri)) { - /* Only sync if we can sync to KVM successfully. */ - uint64_t oldval; -@@ -306,6 +307,7 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) - - kvm_arm_set_one_reg(cpu, cpu->cpreg_indexes[i], &oldval); - } else { -+#endif - /* - * Only sync if the previous list->cpustate sync succeeded. - * Rather than tracking the success/failure state for every -@@ -324,7 +326,9 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) - } - - write_raw_cp_reg(&cpu->env, ri, newval); -+#ifdef CONFIG_KVM - } -+#endif - } - cpu->cpreg_values[i] = newval; - } -diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h -index 49e80878f4..a223967d4d 100644 ---- a/target/arm/kvm_arm.h -+++ b/target/arm/kvm_arm.h -@@ -312,6 +312,10 @@ static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) - - static inline void kvm_arm_add_vcpu_properties(Object *obj) {} - -+static inline bool kvm_arm_cpu_feature_supported(void) { -+ return false; -+} -+ - static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms) - { - return -ENOENT; --- -2.27.0 - diff --git a/arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch b/arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch index 84903c34d5a86cac12aadf7d35271295b49f143d..91c7181ebca41c090d7909392cd1ac884c70869b 100644 --- a/arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch +++ b/arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch @@ -1,4 +1,4 @@ -From d8e0b51447d8c64788cd7f9b0fa75c4ccb06f8eb Mon Sep 17 00:00:00 2001 +From 42072fd4b33125959d825a0c5cee0d1122072f71 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Fri, 10 Apr 2020 10:17:27 +0800 Subject: [PATCH] arm/cpu: assign arm_get_arch_id handler to get_arch_id hook @@ -13,13 +13,13 @@ Signed-off-by: Salil Mehta 1 file changed, 8 insertions(+) diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index 39bbe7e2d7..1ccb30e5eb 100644 +index 65163f5135..f06ba29885 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c -@@ -2575,6 +2575,13 @@ static gchar *arm_gdb_arch_name(CPUState *cs) - return g_strdup("arm"); - } - +@@ -2557,6 +2557,13 @@ static const struct TCGCPUOps arm_tcg_ops = { + }; + #endif /* CONFIG_TCG */ + +static int64_t arm_cpu_get_arch_id(CPUState *cs) +{ + ARMCPU *cpu = ARM_CPU(cs); @@ -30,13 +30,14 @@ index 39bbe7e2d7..1ccb30e5eb 100644 static void arm_cpu_class_init(ObjectClass *oc, void *data) { ARMCPUClass *acc = ARM_CPU_CLASS(oc); -@@ -2596,6 +2603,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) - cc->synchronize_from_tb = arm_cpu_synchronize_from_tb; +@@ -2575,6 +2582,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) + cc->set_pc = arm_cpu_set_pc; cc->gdb_read_register = arm_cpu_gdb_read_register; cc->gdb_write_register = arm_cpu_gdb_write_register; + cc->get_arch_id = arm_cpu_get_arch_id; #ifndef CONFIG_USER_ONLY - cc->do_interrupt = arm_cpu_do_interrupt; - cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug; --- -2.19.1 + cc->sysemu_ops = &arm_sysemu_ops; + #endif +-- +2.27.0 + diff --git a/arm-translate-a64-fix-uninitialized-variable-warning.patch b/arm-translate-a64-fix-uninitialized-variable-warning.patch deleted file mode 100644 index 8e31bbf51e12d63818e74aca17f94020301c7855..0000000000000000000000000000000000000000 --- a/arm-translate-a64-fix-uninitialized-variable-warning.patch +++ /dev/null @@ -1,36 +0,0 @@ -From b4bab3bf6a75d97d2f1098c4dc52d35ced003c70 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Mon, 13 Jan 2020 17:01:11 +0800 -Subject: [PATCH] arm/translate-a64: fix uninitialized variable warning - -Fixes: -target/arm/translate-a64.c: In function 'disas_crypto_three_reg_sha512': -target/arm/translate-a64.c:13625:9: error: 'genfn' may be used uninitialized in this function [-Werror=maybe-uninitialized] - genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr); - ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -qemu/target/arm/translate-a64.c:13609:8: error: 'feature' may be used uninitialized in this function [-Werror=maybe-uninitialized] - if (!feature) { - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan ---- - target/arm/translate-a64.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c -index dcdeb801..5f423d5d 100644 ---- a/target/arm/translate-a64.c -+++ b/target/arm/translate-a64.c -@@ -13767,6 +13767,8 @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn) - feature = dc_isar_feature(aa64_sha3, s); - genfn = NULL; - break; -+ default: -+ g_assert_not_reached(); - } - } else { - switch (opcode) { --- -2.18.1 - - diff --git a/arm-virt-Add-CPU-hotplug-framework.patch b/arm-virt-Add-CPU-hotplug-framework.patch index 5de672afeab55fe5af5da3d2ce58aa2e9ae1435d..4fdcf9f088e9c309a8b5b935978ef389d3af5aee 100644 --- a/arm-virt-Add-CPU-hotplug-framework.patch +++ b/arm-virt-Add-CPU-hotplug-framework.patch @@ -1,4 +1,4 @@ -From 6d287b3f1d961cc4adda1c6a452f41db84466f5a Mon Sep 17 00:00:00 2001 +From 209b3e4e522b8f7f41e495feaade96ee9a91e46a Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Fri, 3 Apr 2020 16:16:18 +0800 Subject: [PATCH] arm/virt: Add CPU hotplug framework @@ -14,13 +14,13 @@ Signed-off-by: Salil Mehta 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index d09a5773df..0bd37af26c 100644 +index 9b73c479c4..11155fcb70 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -2077,11 +2077,25 @@ out: - error_propagate(errp, local_err); +@@ -2586,6 +2586,18 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev, + dev, &error_abort); } - + +static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ @@ -36,31 +36,34 @@ index d09a5773df..0bd37af26c 100644 static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { - virt_memory_pre_plug(hotplug_dev, dev, errp); +@@ -2619,6 +2631,8 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, + qdev_prop_set_uint32(dev, "len-reserved-regions", 1); + qdev_prop_set_string(dev, "reserved-regions[0]", resv_prop_str); + g_free(resv_prop_str); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + virt_cpu_pre_plug(hotplug_dev, dev, errp); } } - -@@ -2098,6 +2112,8 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, + +@@ -2637,6 +2651,8 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, } if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { virt_memory_plug(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { + virt_cpu_plug(hotplug_dev, dev, errp); } - } - -@@ -2112,7 +2128,8 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, - DeviceState *dev) - { - if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE) || + if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { + PCIDevice *pdev = PCI_DEVICE(dev); +@@ -2717,7 +2733,8 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, + MachineClass *mc = MACHINE_GET_CLASS(machine); + + if (device_is_dynamic_sysbus(mc, dev) || - (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM))) { -+ object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || -+ object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { ++ (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) || ++ (object_dynamic_cast(OBJECT(dev), TYPE_CPU))) { return HOTPLUG_HANDLER(machine); } + if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { +-- +2.27.0 --- -2.19.1 diff --git a/arm-virt-Add-CPU-topology-support.patch b/arm-virt-Add-CPU-topology-support.patch index c7813c637449328c5fecf7575d27a06fa1fa0700..016b3ed684491491637525b2edad0b24d099d0d2 100644 --- a/arm-virt-Add-CPU-topology-support.patch +++ b/arm-virt-Add-CPU-topology-support.patch @@ -1,4 +1,4 @@ -From cde57fcae2ed16a10e1ef7f2da0ec368883988ba Mon Sep 17 00:00:00 2001 +From 5454c00908236dcabcbf9ae246ccb69e1fcea72e Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Mon, 6 Apr 2020 10:54:35 +0800 Subject: [PATCH] arm/virt: Add CPU topology support @@ -10,18 +10,19 @@ plug or unplug. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta --- - hw/arm/virt.c | 68 +++++++++++++++++++++++++++++++++++++-- - include/hw/arm/topology.h | 61 +++++++++++++++++++++++++++++++++++ - target/arm/cpu.c | 3 ++ - target/arm/cpu.h | 3 ++ - 4 files changed, 133 insertions(+), 2 deletions(-) + hw/arm/virt.c | 87 ++++++++++++++++++++++++++++++++++++++- + include/hw/arm/topology.h | 68 ++++++++++++++++++++++++++++++ + qapi/machine.json | 2 + + target/arm/cpu.c | 4 ++ + target/arm/cpu.h | 4 ++ + 5 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 include/hw/arm/topology.h diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 0bd37af26c..64532b61b2 100644 +index 11155fcb70..a12e718686 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -36,6 +36,7 @@ +@@ -39,6 +39,7 @@ #include "hw/sysbus.h" #include "hw/arm/boot.h" #include "hw/arm/primecell.h" @@ -29,15 +30,15 @@ index 0bd37af26c..64532b61b2 100644 #include "hw/arm/virt.h" #include "hw/block/flash.h" #include "hw/vfio/vfio-calxeda-xgmac.h" -@@ -2020,6 +2021,7 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) +@@ -2524,6 +2525,7 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) int n; unsigned int max_cpus = ms->smp.max_cpus; VirtMachineState *vms = VIRT_MACHINE(ms); + ARMCPUTopoInfo topo; - + if (ms->possible_cpus) { assert(ms->possible_cpus->len == max_cpus); -@@ -2031,10 +2033,17 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) +@@ -2535,10 +2537,19 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) ms->possible_cpus->len = max_cpus; for (n = 0; n < ms->possible_cpus->len; n++) { ms->possible_cpus->cpus[n].type = ms->cpu_type; @@ -45,9 +46,11 @@ index 0bd37af26c..64532b61b2 100644 ms->possible_cpus->cpus[n].arch_id = virt_cpu_mp_affinity(vms, n); + -+ topo_ids_from_idx(n, ms->smp.cores, ms->smp.threads, &topo); ++ topo_ids_from_idx(n, ms->smp.clusters, ms->smp.cores, ms->smp.threads, &topo); + ms->possible_cpus->cpus[n].props.has_socket_id = true; + ms->possible_cpus->cpus[n].props.socket_id = topo.pkg_id; ++ ms->possible_cpus->cpus[n].props.has_cluster_id = true; ++ ms->possible_cpus->cpus[n].props.cluster_id = topo.cluster_id; + ms->possible_cpus->cpus[n].props.has_core_id = true; + ms->possible_cpus->cpus[n].props.core_id = topo.core_id; ms->possible_cpus->cpus[n].props.has_thread_id = true; @@ -56,7 +59,7 @@ index 0bd37af26c..64532b61b2 100644 } return ms->possible_cpus; } -@@ -2080,7 +2089,62 @@ out: +@@ -2589,7 +2600,79 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev, static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -65,17 +68,25 @@ index 0bd37af26c..64532b61b2 100644 + ARMCPUTopoInfo topo; + ARMCPU *cpu = ARM_CPU(dev); + MachineState *ms = MACHINE(hotplug_dev); ++ int smp_clusters = ms->smp.clusters; + int smp_cores = ms->smp.cores; + int smp_threads = ms->smp.threads; + -+ /* if cpu idx is not set, set it based on socket/core/thread properties */ ++ /* if cpu idx is not set, set it based on socket/cluster/core/thread ++ * properties ++ */ + if (cs->cpu_index == UNASSIGNED_CPU_INDEX) { -+ int max_socket = ms->smp.max_cpus / smp_threads / smp_cores; ++ int max_socket = ms->smp.max_cpus / smp_threads / smp_cores / smp_clusters; + if (cpu->socket_id < 0 || cpu->socket_id >= max_socket) { + error_setg(errp, "Invalid CPU socket-id: %u must be in range 0:%u", + cpu->socket_id, max_socket - 1); + return; + } ++ if (cpu->cluster_id < 0 || cpu->cluster_id >= smp_clusters) { ++ error_setg(errp, "Invalid CPU cluster-id: %u must be in range 0:%u", ++ cpu->cluster_id, smp_clusters - 1); ++ return; ++ } + if (cpu->core_id < 0 || cpu->core_id >= smp_cores) { + error_setg(errp, "Invalid CPU core-id: %u must be in range 0:%u", + cpu->core_id, smp_cores - 1); @@ -88,15 +99,17 @@ index 0bd37af26c..64532b61b2 100644 + } + + topo.pkg_id = cpu->socket_id; ++ topo.cluster_id = cpu->cluster_id; + topo.core_id = cpu->core_id; + topo.smt_id = cpu->thread_id; -+ cs->cpu_index = idx_from_topo_ids(smp_cores, smp_threads, &topo); ++ cs->cpu_index = idx_from_topo_ids(smp_clusters, smp_cores, smp_threads, &topo); + } + -+ /* if 'address' properties socket-id/core-id/thread-id are not set, set them -+ * so that machine_query_hotpluggable_cpus would show correct values ++ /* if 'address' properties socket-id/cluster-id/core-id/thread-id are not ++ * set, set them so that machine_query_hotpluggable_cpus would show correct ++ * values + */ -+ topo_ids_from_idx(cs->cpu_index, smp_cores, smp_threads, &topo); ++ topo_ids_from_idx(cs->cpu_index, smp_clusters, smp_cores, smp_threads, &topo); + if (cpu->socket_id != -1 && cpu->socket_id != topo.pkg_id) { + error_setg(errp, "property socket-id: %u doesn't match set idx:" + " 0x%x (socket-id: %u)", cpu->socket_id, cs->cpu_index, topo.pkg_id); @@ -104,6 +117,13 @@ index 0bd37af26c..64532b61b2 100644 + } + cpu->socket_id = topo.pkg_id; + ++ if (cpu->cluster_id != -1 && cpu->cluster_id != topo.cluster_id) { ++ error_setg(errp, "property cluster-id: %u doesn't match set idx:" ++ " 0x%x (cluster-id: %u)", cpu->cluster_id, cs->cpu_index, topo.cluster_id); ++ return; ++ } ++ cpu->cluster_id = topo.cluster_id; ++ + if (cpu->core_id != -1 && cpu->core_id != topo.core_id) { + error_setg(errp, "property core-id: %u doesn't match set idx:" + " 0x%x (core-id: %u)", cpu->core_id, cs->cpu_index, topo.core_id); @@ -118,14 +138,14 @@ index 0bd37af26c..64532b61b2 100644 + } + cpu->thread_id = topo.smt_id; } - + static void virt_cpu_plug(HotplugHandler *hotplug_dev, diff --git a/include/hw/arm/topology.h b/include/hw/arm/topology.h new file mode 100644 -index 0000000000..a3e5f436c5 +index 0000000000..d0dad1a9a3 --- /dev/null +++ b/include/hw/arm/topology.h -@@ -0,0 +1,61 @@ +@@ -0,0 +1,68 @@ +/* + * ARM CPU topology data structures and functions + * @@ -150,70 +170,100 @@ index 0000000000..a3e5f436c5 + +typedef struct ARMCPUTopoInfo { + unsigned pkg_id; ++ unsigned cluster_id; + unsigned core_id; + unsigned smt_id; +} ARMCPUTopoInfo; + +/* Calculate (contiguous) CPU index based on topology */ -+static inline unsigned idx_from_topo_ids(unsigned nr_cores, ++static inline unsigned idx_from_topo_ids(unsigned nr_clusters, ++ unsigned nr_cores, + unsigned nr_threads, + const ARMCPUTopoInfo *topo) +{ ++ assert(nr_clusters > 0); + assert(nr_cores > 0); + assert(nr_threads > 0); + assert(topo != NULL); + -+ return topo->pkg_id * nr_cores * nr_threads + ++ return topo->pkg_id * nr_clusters * nr_cores * nr_threads + ++ topo->cluster_id * nr_cores + + topo->core_id * nr_threads + + topo->smt_id; +} + -+/* Calculate thread/core/package topology ++/* Calculate thread/core/cluster/package topology + * based on (contiguous) CPU index + */ +static inline void topo_ids_from_idx(unsigned cpu_index, ++ unsigned nr_clusters, + unsigned nr_cores, + unsigned nr_threads, + ARMCPUTopoInfo *topo) +{ ++ assert(nr_clusters > 0); + assert(nr_cores > 0); + assert(nr_threads > 0); + assert(topo != NULL); + + topo->smt_id = cpu_index % nr_threads; + topo->core_id = cpu_index / nr_threads % nr_cores; -+ topo->pkg_id = cpu_index / nr_threads / nr_cores; ++ topo->cluster_id = cpu_index / nr_threads / nr_cores % nr_clusters; ++ topo->pkg_id = cpu_index / nr_threads / nr_cores / nr_clusters; +} + +#endif /* HW_ARM_TOPOLOGY_H */ + +diff --git a/qapi/machine.json b/qapi/machine.json +index 8faa51074e..6822cafe2e 100644 +--- a/qapi/machine.json ++++ b/qapi/machine.json +@@ -868,6 +868,7 @@ + # @node-id: NUMA node ID the CPU belongs to + # @socket-id: socket number within node/board the CPU belongs to + # @die-id: die number within socket the CPU belongs to (since 4.1) ++# @cluster-id: cluster number within die the CPU belongs to (since 6.2) + # @core-id: core number within die the CPU belongs to + # @thread-id: thread number within core the CPU belongs to + # +@@ -883,6 +884,7 @@ + 'data': { '*node-id': 'int', + '*socket-id': 'int', + '*die-id': 'int', ++ '*cluster-id': 'int', + '*core-id': 'int', + '*thread-id': 'int' + } diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index 1ccb30e5eb..91f1e36cd8 100644 +index f06ba29885..9fd8e57971 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c -@@ -2560,6 +2560,9 @@ static Property arm_cpu_properties[] = { +@@ -2507,6 +2507,10 @@ static Property arm_cpu_properties[] = { DEFINE_PROP_UINT64("mp-affinity", ARMCPU, mp_affinity, ARM64_AFFINITY_INVALID), DEFINE_PROP_INT32("node-id", ARMCPU, node_id, CPU_UNSET_NUMA_NODE_ID), + DEFINE_PROP_INT32("socket-id", ARMCPU, socket_id, -1), ++ DEFINE_PROP_INT32("cluster-id", ARMCPU, cluster_id, -1), + DEFINE_PROP_INT32("core-id", ARMCPU, core_id, -1), + DEFINE_PROP_INT32("thread-id", ARMCPU, thread_id, -1), DEFINE_PROP_INT32("core-count", ARMCPU, core_count, -1), DEFINE_PROP_END_OF_LIST() }; diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index e19531a77b..219c222b89 100644 +index 947897d5ac..eb804dffaa 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h -@@ -916,6 +916,9 @@ struct ARMCPU { +@@ -1006,6 +1006,10 @@ struct ARMCPU { QLIST_HEAD(, ARMELChangeHook) el_change_hooks; - + int32_t node_id; /* NUMA node this CPU belongs to */ + int32_t socket_id; ++ int32_t cluster_id; + int32_t core_id; + int32_t thread_id; - + /* Used to synchronize KVM and QEMU in-kernel device levels */ uint8_t device_irq_level; --- -2.19.1 +-- +2.27.0 + diff --git a/arm-virt-Add-cpu_hotplug_enabled-field.patch b/arm-virt-Add-cpu_hotplug_enabled-field.patch index 0b8bc47f6d31dba63e1148c22cc803204ce82e70..0ae840c7cdae03104a7bb317f98c872399e4eafb 100644 --- a/arm-virt-Add-cpu_hotplug_enabled-field.patch +++ b/arm-virt-Add-cpu_hotplug_enabled-field.patch @@ -1,4 +1,4 @@ -From 31873c4c0454fb17654f57adece2bc396415f8bf Mon Sep 17 00:00:00 2001 +From 965eb25b03f6977a7656dce3ac5cdb4c95bfe003 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Fri, 10 Apr 2020 13:50:40 +0800 Subject: [PATCH] arm/virt: Add cpu_hotplug_enabled field @@ -14,10 +14,10 @@ Signed-off-by: Salil Mehta 2 files changed, 8 insertions(+) diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index dda22194b5..304a4c2d31 100644 +index b1224fb1e4..45a0a045b1 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -1645,6 +1645,7 @@ static void machvirt_init(MachineState *machine) +@@ -2008,6 +2008,7 @@ static void machvirt_init(MachineState *machine) { VirtMachineState *vms = VIRT_MACHINE(machine); VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine); @@ -25,37 +25,38 @@ index dda22194b5..304a4c2d31 100644 MachineClass *mc = MACHINE_GET_CLASS(machine); const CPUArchIdList *possible_cpus; MemoryRegion *sysmem = get_system_memory(); -@@ -1655,6 +1656,7 @@ static void machvirt_init(MachineState *machine) +@@ -2017,6 +2018,7 @@ static void machvirt_init(MachineState *machine) bool has_ged = !vmc->no_ged; unsigned int smp_cpus = machine->smp.cpus; unsigned int max_cpus = machine->smp.max_cpus; + ObjectClass *cpu_class; - + /* * In accelerated mode, the memory map is computed earlier in kvm_type() -@@ -1760,6 +1762,11 @@ static void machvirt_init(MachineState *machine) - +@@ -2106,6 +2108,11 @@ static void machvirt_init(MachineState *machine) create_fdt(vms); - + qemu_log("cpu init start\n"); + + cpu_class = object_class_by_name(ms->cpu_type); + vms->cpu_hotplug_enabled = has_ged && firmware_loaded && -+ acpi_enabled && vms->gic_version == 3 && ++ virt_is_acpi_enabled(vms) && vms->gic_version == 3 && + !!object_class_dynamic_cast(cpu_class, TYPE_AARCH64_CPU); + possible_cpus = mc->possible_cpu_arch_ids(machine); + assert(possible_cpus->len == max_cpus); for (n = 0; n < possible_cpus->len; n++) { - Object *cpuobj; diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h -index beef4c8002..b4c53d920e 100644 +index 947d41f767..c371d377e0 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h -@@ -126,6 +126,7 @@ typedef struct { - bool highmem_ecam; +@@ -149,6 +149,7 @@ struct VirtMachineState { bool its; + bool tcg_its; bool virt; + bool cpu_hotplug_enabled; - int32_t gic_version; - VirtIOMMUType iommu; - struct arm_boot_info bootinfo; --- -2.19.1 + bool ras; + bool mte; + OnOffAuto acpi; +-- +2.27.0 + diff --git a/arm-virt-Add-some-sanity-checks-in-cpu_pre_plug-hook.patch b/arm-virt-Add-some-sanity-checks-in-cpu_pre_plug-hook.patch deleted file mode 100644 index c81227d8a3ef4ff3ffc74f7b848b42e8cc79c762..0000000000000000000000000000000000000000 --- a/arm-virt-Add-some-sanity-checks-in-cpu_pre_plug-hook.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 7cfb37c50209208f853c6fbd0df6673a95e03ef9 Mon Sep 17 00:00:00 2001 -From: Keqian Zhu -Date: Fri, 10 Apr 2020 14:16:40 +0800 -Subject: [PATCH] arm/virt: Add some sanity checks in cpu_pre_plug hook - -For that user will try to hotplug a CPU when preconditions -are not satisfied, check these CPU hotplug preconditions in -pre_plug hook. - -Signed-off-by: Keqian Zhu -Signed-off-by: Salil Mehta ---- - hw/arm/virt.c | 27 +++++++++++++++++++++++++++ - 1 file changed, 27 insertions(+) - -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 983084c459..c6a99e683a 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -2086,10 +2086,30 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, - VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); - VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(hotplug_dev); - const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); -+ const CPUArchId *cpu_slot = NULL; - MemoryRegion *sysmem = get_system_memory(); - int smp_cores = ms->smp.cores; - int smp_threads = ms->smp.threads; - -+ /* Some hotplug capability checks */ -+ -+ if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) { -+ error_setg(errp, "Invalid CPU type, expected cpu type: '%s'", -+ ms->cpu_type); -+ return; -+ } -+ -+ if (dev->hotplugged && !vms->acpi_dev) { -+ error_setg(errp, "CPU hotplug is disabled: missing acpi device."); -+ return; -+ } -+ -+ if (dev->hotplugged && !vms->cpu_hotplug_enabled) { -+ error_setg(errp, "CPU hotplug is disabled: " -+ "should use AArch64 CPU and GICv3."); -+ return; -+ } -+ - /* if cpu idx is not set, set it based on socket/core/thread properties */ - if (cs->cpu_index == UNASSIGNED_CPU_INDEX) { - int max_socket = ms->smp.max_cpus / smp_threads / smp_cores; -@@ -2145,6 +2165,13 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, - object_property_set_int(cpuobj, possible_cpus->cpus[cs->cpu_index].arch_id, - "mp-affinity", NULL); - -+ cpu_slot = &possible_cpus->cpus[cs->cpu_index]; -+ if (cpu_slot->cpu) { -+ error_setg(errp, "CPU[%d] with mp_affinity %" PRIu64 " exists", -+ cs->cpu_index, cpu->mp_affinity); -+ return; -+ } -+ - numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj), - &error_fatal); - --- -2.19.1 diff --git a/arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch b/arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch index ade3ccfd9fe50a78c8ef33ded3463e52b5f6d6c3..174c3de0ee3cd29515413a2316c8ad0cd70441a9 100644 --- a/arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch +++ b/arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch @@ -1,4 +1,4 @@ -From d38d1d4e859450535ddc6bf0c7a59f6217b1403c Mon Sep 17 00:00:00 2001 +From 6b0f94aee82c7558d79e5ec28437483c4873dc65 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Sun, 5 Apr 2020 16:03:15 +0800 Subject: [PATCH] arm/virt: Attach ACPI CPU hotplug support to virt @@ -16,26 +16,26 @@ Signed-off-by: Salil Mehta 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c -index 8b68a15d76..dbe9acb148 100644 +index a93d223879..7cb320d9f2 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c -@@ -806,6 +806,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) - MachineState *ms = MACHINE(vms); - const MemMapEntry *memmap = vms->memmap; +@@ -937,6 +937,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) const int *irqmap = vms->irqmap; + AcpiTable table = { .sig = "DSDT", .rev = 2, .oem_id = vms->oem_id, + .oem_table_id = vms->oem_table_id }; + bool cpu_aml_built = false; - + + acpi_table_begin(&table, table_data); dsdt = init_aml_allocator(); - /* Reserve space for header */ -@@ -817,7 +818,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) +@@ -947,7 +948,6 @@ 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, vms); +- acpi_dsdt_add_cpus(scope, vms); acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], (irqmap[VIRT_UART] + ARM_SPI_BASE)); - acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); -@@ -845,6 +845,19 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + if (vmc->acpi_expose_flash) { +@@ -977,6 +977,19 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) AML_SYSTEM_MEMORY, memmap[VIRT_PCDIMM_ACPI].base); } @@ -51,50 +51,53 @@ index 8b68a15d76..dbe9acb148 100644 + } + + if (!cpu_aml_built) { -+ acpi_dsdt_add_cpus(scope, vms->smp_cpus, vms); ++ acpi_dsdt_add_cpus(scope, vms); } - + acpi_dsdt_add_power_button(scope); diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 8638aeedb7..d09a5773df 100644 +index 3299d674c8..9b73c479c4 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -140,6 +140,7 @@ static const MemMapEntry base_memmap[] = { - [VIRT_SMMU] = { 0x09050000, 0x00020000 }, - [VIRT_PCDIMM_ACPI] = { 0x09070000, MEMORY_HOTPLUG_IO_LEN }, - [VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN }, -+ [VIRT_CPU_ACPI] = { 0x09090000, ACPI_CPU_HOTPLUG_REG_LEN }, +@@ -154,6 +154,7 @@ static const MemMapEntry base_memmap[] = { + [VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN}, + [VIRT_PVTIME] = { 0x090a0000, 0x00010000 }, + [VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 }, ++ [VIRT_CPU_ACPI] = { 0x090c0000, ACPI_CPU_HOTPLUG_REG_LEN }, [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, - [VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 }, + [VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ -@@ -645,11 +646,16 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) - event |= ACPI_GED_MEM_HOTPLUG_EVT; +@@ -697,6 +698,10 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + event |= ACPI_GED_NVDIMM_HOTPLUG_EVT; } - + + /* event |= ACPI_GED_CPU_HOTPLUG_EVT; + * Currently CPU hotplug is not enabled. + */ + - dev = qdev_create(NULL, TYPE_ACPI_GED); + dev = qdev_new(TYPE_ACPI_GED); qdev_prop_set_uint32(dev, "ged-event", event); - + +@@ -706,6 +711,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); -+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, vms->memmap[VIRT_CPU_ACPI].base); ++ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 3, vms->memmap[VIRT_CPU_ACPI].base); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq)); - - qdev_init_nofail(dev); + + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h -index cbdea7ff32..6880ebe07c 100644 +index fe26709e1a..2a838620d8 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h -@@ -81,6 +81,7 @@ enum { - VIRT_SECURE_MEM, - VIRT_PCDIMM_ACPI, +@@ -88,6 +88,7 @@ enum { VIRT_ACPI_GED, + VIRT_NVDIMM_ACPI, + VIRT_PVTIME, + VIRT_CPU_ACPI, VIRT_LOWMEMMAP_LAST, }; + +-- +2.27.0 --- -2.19.1 diff --git a/arm-virt-Pre-sizing-MADT-GICC-PPTT-GICv3-and-Pre-par.patch b/arm-virt-Pre-sizing-MADT-GICC-GICv3-and-Pre-park-KVM.patch similarity index 46% rename from arm-virt-Pre-sizing-MADT-GICC-PPTT-GICv3-and-Pre-par.patch rename to arm-virt-Pre-sizing-MADT-GICC-GICv3-and-Pre-park-KVM.patch index c2d9a3cb0a48436433a30670e8517d7dafb9bca4..134cdbe252c59ee6cad7494c9635e8436acbdd7f 100644 --- a/arm-virt-Pre-sizing-MADT-GICC-PPTT-GICv3-and-Pre-par.patch +++ b/arm-virt-Pre-sizing-MADT-GICC-GICv3-and-Pre-park-KVM.patch @@ -1,78 +1,54 @@ -From bf47ef282bfe8b0a98e1f87d8708051ffa7192a1 Mon Sep 17 00:00:00 2001 +From 3063d421cd68937ece290bc02151cc15b7ec33d0 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Fri, 10 Apr 2020 13:55:11 +0800 -Subject: [PATCH] arm/virt: Pre-sizing MADT-GICC PPTT GICv3 and Pre-park KVM - vCPU +Subject: [PATCH] arm/virt: Pre-sizing MADT-GICC GICv3 and Pre-park KVM vCPU Establish all pre-sizing facilities based on cpu_hotplug_enabled field. +Note: PPTT is constructed for possible_cpus, so it does not need +to pre-sizing it. + Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta --- - hw/arm/virt-acpi-build.c | 12 +++++++++++- + hw/arm/virt-acpi-build.c | 3 +++ hw/arm/virt.c | 14 ++++++++++++-- - target/arm/kvm.c | 6 +++--- - 3 files changed, 26 insertions(+), 6 deletions(-) + target/arm/kvm.c | 4 ++-- + 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c -index efac788ba1..2cfac7b84f 100644 +index a16b54086e..1101161d70 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c -@@ -736,6 +736,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) - gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base); - gicd->version = vms->gic_version; - +@@ -859,6 +859,9 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) + build_append_int_noprefix(table_data, vms->gic_version, 1); + build_append_int_noprefix(table_data, 0, 3); /* Reserved */ + + if (vms->cpu_hotplug_enabled) { + num_cpu = ms->smp.max_cpus; + } for (i = 0; i < num_cpu; i++) { - virt_madt_cpu_entry(NULL, i, possible_cpus, table_data); + virt_madt_cpu_entry(NULL, i, possible_cpus, table_data, false); } -@@ -902,9 +905,11 @@ static - void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) - { - VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); -+ MachineState *ms = MACHINE(vms); - GArray *table_offsets; - unsigned dsdt, xsdt; - GArray *tables_blob = tables->table_data; -+ int num_cpus; - - table_offsets = g_array_new(false, true /* clear */, - sizeof(uint32_t)); -@@ -923,7 +928,12 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) - - acpi_add_table(table_offsets, tables_blob); - -- build_pptt(tables_blob, tables->linker, vms->smp_cpus); -+ if (vms->cpu_hotplug_enabled) { -+ num_cpus = ms->smp.max_cpus; -+ } else { -+ num_cpus = ms->smp.cpus; -+ } -+ build_pptt(tables_blob, tables->linker, num_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 304a4c2d31..983084c459 100644 +index 45a0a045b1..4eb1b44729 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -767,6 +767,9 @@ static void create_gic(VirtMachineState *vms) +@@ -833,6 +833,9 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem) unsigned int smp_cpus = ms->smp.cpus; uint32_t nb_redist_regions = 0; - + + if (vms->cpu_hotplug_enabled) { + num_cpus = ms->smp.max_cpus; + } assert(num_cpus >= smp_cpus); - + gictype = (type == 3) ? gicv3_class_name() : gic_class_name(); -@@ -1772,8 +1775,15 @@ static void machvirt_init(MachineState *machine) +@@ -2119,8 +2122,15 @@ static void machvirt_init(MachineState *machine) Object *cpuobj; CPUState *cs; - + + if (kvm_enabled() && vms->cpu_hotplug_enabled) { + if (kvm_create_parked_vcpu(n) < 0) { + error_report("mach-virt: Create KVM parked vCPU failed"); @@ -84,41 +60,33 @@ index 304a4c2d31..983084c459 100644 - break; + continue; } - + cpuobj = object_new(possible_cpus->cpus[n].type); -@@ -1857,7 +1867,7 @@ static void machvirt_init(MachineState *machine) - vms->bootinfo.kernel_filename = machine->kernel_filename; - vms->bootinfo.kernel_cmdline = machine->kernel_cmdline; - vms->bootinfo.initrd_filename = machine->initrd_filename; +@@ -2208,7 +2218,7 @@ static void machvirt_init(MachineState *machine) + } + + vms->bootinfo.ram_size = machine->ram_size; - vms->bootinfo.nb_cpus = smp_cpus; + vms->bootinfo.nb_cpus = vms->cpu_hotplug_enabled ? max_cpus : smp_cpus; vms->bootinfo.board_id = -1; vms->bootinfo.loader_start = vms->memmap[VIRT_MEM].base; vms->bootinfo.get_dtb = machvirt_dtb; diff --git a/target/arm/kvm.c b/target/arm/kvm.c -index 327b3bc338..4f131f687d 100644 +index 59d556724f..29ac3f40e0 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c -@@ -202,7 +202,7 @@ int kvm_arm_get_max_vm_ipa_size(MachineState *ms) - int kvm_arch_init(MachineState *ms, KVMState *s) - { - int ret = 0; -- unsigned int smp_cpus = ms->smp.cpus; -+ unsigned int max_cpus = ms->smp.max_cpus; - /* For ARM interrupt delivery is always asynchronous, - * whether we are using an in-kernel VGIC or not. - */ -@@ -216,9 +216,9 @@ int kvm_arch_init(MachineState *ms, KVMState *s) - +@@ -262,9 +262,9 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE); - -- if (smp_cpus > 256 && -+ if (max_cpus > 256 && + +- if (ms->smp.cpus > 256 && ++ if (ms->smp.max_cpus > 256 && !kvm_check_extension(s, KVM_CAP_ARM_IRQ_LINE_LAYOUT_2)) { - error_report("Using more than 256 vcpus requires a host kernel " + error_report("Using more than max 256 vcpus requires a host kernel " "with KVM_CAP_ARM_IRQ_LINE_LAYOUT_2"); ret = -EINVAL; } --- -2.19.1 +-- +2.27.0 + diff --git a/arm-virt-Start-up-CPU-hot-plug.patch b/arm-virt-Start-up-CPU-hot-plug-and-cold-plug.patch similarity index 42% rename from arm-virt-Start-up-CPU-hot-plug.patch rename to arm-virt-Start-up-CPU-hot-plug-and-cold-plug.patch index 5ba620a2215710682afa4ccdfd0d5cad53556680..d4970f16b93686535d83709d379356dd68a4e14c 100644 --- a/arm-virt-Start-up-CPU-hot-plug.patch +++ b/arm-virt-Start-up-CPU-hot-plug-and-cold-plug.patch @@ -1,49 +1,107 @@ -From 11f9628ceff019259ff12ce469deafbf50eb3075 Mon Sep 17 00:00:00 2001 +From a2d8cf86a379bb161cdae850824c9e80fb370599 Mon Sep 17 00:00:00 2001 From: Keqian Zhu -Date: Fri, 10 Apr 2020 14:20:59 +0800 -Subject: [PATCH] arm/virt: Start up CPU hot-plug +Date: Fri, 10 Apr 2020 14:16:40 +0800 +Subject: [PATCH] arm/virt: Start up CPU hot-plug and cold-plug All the CPU hotplug facilities are ready. Assemble them to start up CPU hot-plug capability for arm/virt. -Signed-off-by: Keqian Zhu +This also adds CPU cold plug support to arm virt machine +board. CPU cold plug means adding CPU by using "-device +xx-arm-cpu" when we bring up Qemu. + Signed-off-by: Salil Mehta +Signed-off-by: Keqian Zhu --- - hw/arm/virt.c | 61 ++++++++++++++++++++++++++++++++++++++++--- - include/hw/arm/virt.h | 1 + - qom/cpu.c | 5 ++++ - target/arm/cpu.c | 2 ++ - 4 files changed, 65 insertions(+), 4 deletions(-) + hw/arm/virt.c | 110 ++++++++++++++++++++++++++++++++++++++++-- + hw/core/cpu-common.c | 4 ++ + include/hw/arm/virt.h | 1 + + target/arm/cpu.c | 2 + + 4 files changed, 113 insertions(+), 4 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index c6a99e683a..112a6ae7cb 100644 +index 4eb1b44729..b81d22d68f 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -48,6 +48,8 @@ - #include "sysemu/cpus.h" - #include "sysemu/sysemu.h" +@@ -52,6 +52,8 @@ + #include "sysemu/tpm.h" #include "sysemu/kvm.h" + #include "sysemu/hvf.h" +#include "sysemu/cpus.h" +#include "sysemu/hw_accel.h" #include "hw/loader.h" - #include "exec/address-spaces.h" + #include "qapi/error.h" #include "qemu/bitops.h" -@@ -649,9 +651,9 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) - event |= ACPI_GED_MEM_HOTPLUG_EVT; +@@ -703,9 +705,9 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + event |= ACPI_GED_NVDIMM_HOTPLUG_EVT; } - + - /* event |= ACPI_GED_CPU_HOTPLUG_EVT; - * Currently CPU hotplug is not enabled. - */ + if (vms->cpu_hotplug_enabled) { + event |= ACPI_GED_CPU_HOTPLUG_EVT; + } - - dev = qdev_create(NULL, TYPE_ACPI_GED); + + dev = qdev_new(TYPE_ACPI_GED); qdev_prop_set_uint32(dev, "ged-event", event); -@@ -2214,12 +2216,62 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, - object_property_set_link(cpuobj, OBJECT(secure_sysmem), - "secure-memory", &error_abort); +@@ -2555,11 +2557,18 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(hotplug_dev); + const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); ++ const CPUArchId *cpu_slot = NULL; + MemoryRegion *sysmem = get_system_memory(); + int smp_clusters = ms->smp.clusters; + int smp_cores = ms->smp.cores; + int smp_threads = ms->smp.threads; + ++ if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) { ++ error_setg(errp, "Invalid CPU type, expected cpu type: '%s'", ++ ms->cpu_type); ++ return; ++ } ++ + /* if cpu idx is not set, set it based on socket/cluster/core/thread + * properties + */ +@@ -2593,6 +2602,20 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + cs->cpu_index = idx_from_topo_ids(smp_clusters, smp_cores, smp_threads, &topo); + } + ++ /* Some hotplug capability checks */ ++ if (cs->cpu_index >= ms->smp.cpus) { ++ if (!vms->acpi_dev) { ++ error_setg(errp, "CPU cold/hot plug is disabled: " ++ "missing acpi device."); ++ return; ++ } ++ if (!vms->cpu_hotplug_enabled) { ++ error_setg(errp, "CPU cold/hot plug is disabled: " ++ "should use AArch64 CPU and GICv3."); ++ return; ++ } ++ } ++ + /* if 'address' properties socket-id/cluster-id/core-id/thread-id are not + * set, set them so that machine_query_hotpluggable_cpus would show correct + * values +@@ -2631,6 +2654,13 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + object_property_set_int(cpuobj, "mp-affinity", + possible_cpus->cpus[cs->cpu_index].arch_id, NULL); + ++ cpu_slot = &possible_cpus->cpus[cs->cpu_index]; ++ if (cpu_slot->cpu) { ++ error_setg(errp, "CPU[%d] with mp_affinity %" PRIu64 " exists", ++ cs->cpu_index, cpu->mp_affinity); ++ return; ++ } ++ + numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj), + &error_fatal); + +@@ -2716,12 +2746,83 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, + &error_abort); + } } + + /* If we use KVM accel, we should pause all vcpus to @@ -53,7 +111,7 @@ index c6a99e683a..112a6ae7cb 100644 + pause_all_vcpus(); + } } - + static void virt_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -63,11 +121,15 @@ index c6a99e683a..112a6ae7cb 100644 + int ncpu = cs->cpu_index; + MachineState *ms = MACHINE(hotplug_dev); + VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); ++ bool pmu = object_property_get_bool(OBJECT(first_cpu), "pmu", NULL); ++ bool steal_time = object_property_get_bool(OBJECT(first_cpu), ++ "kvm-steal-time", NULL); + GICv3State *gicv3; + ARMGICv3CommonClass *agcc; + Error *local_err = NULL; + -+ if (dev->hotplugged) { ++ /* For CPU that is cold/hot plugged */ ++ if (ncpu >= ms->smp.cpus) { + /* Realize GIC related parts of CPU */ + assert(vms->gic_version == 3); + gicv3 = ARM_GICV3_COMMON(vms->gic); @@ -75,15 +137,32 @@ index c6a99e683a..112a6ae7cb 100644 + agcc->cpu_hotplug_realize(gicv3, ncpu); + connect_gic_cpu_irqs(vms, ncpu); + ++ /* Init PMU and steal_time part */ ++ if (kvm_enabled()) { ++ hwaddr pvtime_reg_base = vms->memmap[VIRT_PVTIME].base; ++ ++ if (pmu) { ++ assert(arm_feature(&ARM_CPU(cs)->env, ARM_FEATURE_PMU)); ++ if (kvm_irqchip_in_kernel()) { ++ kvm_arm_pmu_set_irq(cs, PPI(VIRTUAL_PMU_IRQ)); ++ } ++ kvm_arm_pmu_init(cs); ++ } ++ if (steal_time) { ++ kvm_arm_pvtime_init(cs, pvtime_reg_base + ++ ncpu * PVTIME_SIZE_PER_CPU); ++ } ++ } ++ + /* Register CPU reset and trigger it manually */ + cpu_synchronize_state(cs); + cpu_hotplug_register_reset(ncpu); + cpu_hotplug_reset_manually(ncpu); + cpu_synchronize_post_reset(cs); ++ } + -+ if (kvm_enabled()) { -+ resume_all_vcpus(); -+ } ++ if (dev->hotplugged && kvm_enabled()) { ++ resume_all_vcpus(); + } + + if (vms->acpi_dev) { @@ -103,9 +182,9 @@ index c6a99e683a..112a6ae7cb 100644 +out: + error_propagate(errp, local_err); } - + static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, -@@ -2324,6 +2376,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) +@@ -2940,6 +3041,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15"); mc->get_default_cpu_node_id = virt_get_default_cpu_node_id; mc->kvm_type = virt_kvm_type; @@ -113,11 +192,26 @@ index c6a99e683a..112a6ae7cb 100644 assert(!mc->get_hotplug_handler); mc->get_hotplug_handler = virt_machine_get_hotplug_handler; hc->pre_plug = virt_machine_device_pre_plug_cb; +diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c +index 9e3241b430..b8d1d820cb 100644 +--- a/hw/core/cpu-common.c ++++ b/hw/core/cpu-common.c +@@ -208,6 +208,10 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp) + + if (dev->hotplugged) { + cpu_synchronize_post_init(cpu); ++ ++#ifdef __aarch64__ ++ if (!kvm_enabled()) ++#endif + cpu_resume(cpu); + } + diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h -index b4c53d920e..a9429bed25 100644 +index c371d377e0..4ddee19b18 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h -@@ -140,6 +140,7 @@ typedef struct { +@@ -168,6 +168,7 @@ struct VirtMachineState { uint32_t msi_phandle; uint32_t iommu_phandle; int psci_conduit; @@ -125,35 +219,19 @@ index b4c53d920e..a9429bed25 100644 hwaddr highest_gpa; DeviceState *gic; DeviceState *acpi_dev; -diff --git a/qom/cpu.c b/qom/cpu.c -index f376f782d8..58cd9d5bbc 100644 ---- a/qom/cpu.c -+++ b/qom/cpu.c -@@ -342,7 +342,12 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp) - - if (dev->hotplugged) { - cpu_synchronize_post_init(cpu); -+ -+#ifdef __aarch64__ -+ if (!kvm_enabled()) -+#endif - cpu_resume(cpu); -+ - } - - /* NOTE: latest generic point where the cpu is fully realized */ diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index 91f1e36cd8..811e5c6365 100644 +index 9fd8e57971..d550022f18 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c -@@ -2598,6 +2598,8 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) - acc->parent_reset = cc->reset; - cc->reset = arm_cpu_reset; - +@@ -2580,6 +2580,8 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) + device_class_set_props(dc, arm_cpu_properties); + device_class_set_parent_reset(dc, arm_cpu_reset, &acc->parent_reset); + + dc->user_creatable = true; + cc->class_by_name = arm_cpu_class_by_name; cc->has_work = arm_cpu_has_work; - cc->cpu_exec_interrupt = arm_cpu_exec_interrupt; --- -2.19.1 + cc->dump_state = arm_cpu_dump_state; +-- +2.27.0 + diff --git a/arm-virt-Support-CPU-cold-plug.patch b/arm-virt-Support-CPU-cold-plug.patch deleted file mode 100644 index 3f96fede24c1e4f18d0f05c1987b20cc5a883b93..0000000000000000000000000000000000000000 --- a/arm-virt-Support-CPU-cold-plug.patch +++ /dev/null @@ -1,92 +0,0 @@ -From e3a1af72fca5bbcc840fba44d512bbe69ec55ca9 Mon Sep 17 00:00:00 2001 -From: Keqian Zhu -Date: Tue, 12 May 2020 15:05:06 +0800 -Subject: [PATCH] arm/virt: Support CPU cold plug - -This adds CPU cold plug support to arm virt machine board. -CPU cold plug means adding CPU by using "-device xx-arm-cpu" -when we bring up Qemu. - -Signed-off-by: Keqian Zhu ---- - hw/arm/virt.c | 36 +++++++++++++++++++----------------- - 1 file changed, 19 insertions(+), 17 deletions(-) - -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 112a6ae7cb..4c7279392f 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -2093,25 +2093,12 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, - int smp_cores = ms->smp.cores; - int smp_threads = ms->smp.threads; - -- /* Some hotplug capability checks */ -- - if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) { - error_setg(errp, "Invalid CPU type, expected cpu type: '%s'", - ms->cpu_type); - return; - } - -- if (dev->hotplugged && !vms->acpi_dev) { -- error_setg(errp, "CPU hotplug is disabled: missing acpi device."); -- return; -- } -- -- if (dev->hotplugged && !vms->cpu_hotplug_enabled) { -- error_setg(errp, "CPU hotplug is disabled: " -- "should use AArch64 CPU and GICv3."); -- return; -- } -- - /* if cpu idx is not set, set it based on socket/core/thread properties */ - if (cs->cpu_index == UNASSIGNED_CPU_INDEX) { - int max_socket = ms->smp.max_cpus / smp_threads / smp_cores; -@@ -2137,6 +2124,20 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, - cs->cpu_index = idx_from_topo_ids(smp_cores, smp_threads, &topo); - } - -+ /* Some hotplug capability checks */ -+ if (cs->cpu_index >= ms->smp.cpus) { -+ if (!vms->acpi_dev) { -+ error_setg(errp, "CPU cold/hot plug is disabled: " -+ "missing acpi device."); -+ return; -+ } -+ if (!vms->cpu_hotplug_enabled) { -+ error_setg(errp, "CPU cold/hot plug is disabled: " -+ "should use AArch64 CPU and GICv3."); -+ return; -+ } -+ } -+ - /* if 'address' properties socket-id/core-id/thread-id are not set, set them - * so that machine_query_hotpluggable_cpus would show correct values - */ -@@ -2237,7 +2238,8 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev, - ARMGICv3CommonClass *agcc; - Error *local_err = NULL; - -- if (dev->hotplugged) { -+ /* For CPU that is cold/hot plugged */ -+ if (ncpu >= ms->smp.cpus) { - /* Realize GIC related parts of CPU */ - assert(vms->gic_version == 3); - gicv3 = ARM_GICV3_COMMON(vms->gic); -@@ -2250,10 +2252,10 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev, - cpu_hotplug_register_reset(ncpu); - cpu_hotplug_reset_manually(ncpu); - cpu_synchronize_post_reset(cs); -+ } - -- if (kvm_enabled()) { -- resume_all_vcpus(); -- } -+ if (dev->hotplugged && kvm_enabled()) { -+ resume_all_vcpus(); - } - - if (vms->acpi_dev) { --- -2.19.1 - diff --git a/arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch b/arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch index 297ccf633fe69840b863f10109ee4271f16c11a1..501573c5e2cd6e783537befb38024aa6d17b24bd 100644 --- a/arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch +++ b/arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch @@ -1,4 +1,4 @@ -From 91fed8840b004ec7bc91969afa10f03e13f311c4 Mon Sep 17 00:00:00 2001 +From e3522e63a2f14c3c7d8cd603099b6bb51087f43b Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Wed, 22 Apr 2020 19:52:58 +0800 Subject: [PATCH] arm/virt/acpi: Extend cpufreq to support max_cpus @@ -12,21 +12,21 @@ Signed-off-by: Keqian Zhu 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/hw/acpi/cpufreq.c b/hw/acpi/cpufreq.c -index d02a25a6de..38dcab5683 100644 +index a84db490b3..a76f7b8fa2 100644 --- a/hw/acpi/cpufreq.c +++ b/hw/acpi/cpufreq.c -@@ -84,6 +84,7 @@ typedef struct CpuhzState { +@@ -83,6 +83,7 @@ typedef struct CpuhzState { uint32_t PerformanceLimited; uint32_t LowestFreq; uint32_t NominalFreq; + uint32_t num_cpu; uint32_t reg_size; } CpuhzState; - -@@ -95,10 +96,7 @@ static uint64_t cpufreq_read(void *opaque, hwaddr offset, + +@@ -93,10 +94,7 @@ static uint64_t cpufreq_read(void *opaque, hwaddr offset, unsigned size) uint64_t r; uint64_t n; - + - MachineState *ms = MACHINE(qdev_get_machine()); - unsigned int smp_cpus = ms->smp.cpus; - @@ -35,7 +35,7 @@ index d02a25a6de..38dcab5683 100644 warn_report("cpufreq_read: offset 0x%lx out of range", offset); return 0; } -@@ -166,11 +164,10 @@ static uint64_t cpufreq_read(void *opaque, hwaddr offset, +@@ -163,11 +161,10 @@ static uint64_t cpufreq_read(void *opaque, hwaddr offset, unsigned size) static void cpufreq_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { @@ -43,23 +43,24 @@ index d02a25a6de..38dcab5683 100644 uint64_t n; - MachineState *ms = MACHINE(qdev_get_machine()); - unsigned int smp_cpus = ms->smp.cpus; - + - if (offset >= smp_cpus * CPPC_REG_PER_CPU_STRIDE) { + if (offset >= s->num_cpu * CPPC_REG_PER_CPU_STRIDE) { error_printf("cpufreq_write: offset 0x%lx out of range", offset); return; } -@@ -251,9 +248,9 @@ static void cpufreq_init(Object *obj) +@@ -248,9 +245,9 @@ static void cpufreq_init(Object *obj) CpuhzState *s = CPUFREQ(obj); - + MachineState *ms = MACHINE(qdev_get_machine()); - unsigned int smp_cpus = ms->smp.cpus; + s->num_cpu = ms->smp.max_cpus; - + - s->reg_size = smp_cpus * CPPC_REG_PER_CPU_STRIDE; + s->reg_size = s->num_cpu * 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); --- -2.19.1 +-- +2.27.0 + diff --git a/arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch b/arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch index f08f83de6505d7810cb7b6753bd00034e3921862..fe171fe867386edc37f5ae7a84868623699549f4 100644 --- a/arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch +++ b/arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch @@ -1,4 +1,4 @@ -From 2fdece10dac6161cb6c1f0f05247391aa3269eed Mon Sep 17 00:00:00 2001 +From 06837491e2ece2fdd6fe6cc8572aaab52fbdcb3e Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Wed, 22 Apr 2020 15:58:27 +0800 Subject: [PATCH] arm/virt/acpi: Factor out CPPC building from DSDT CPU aml @@ -9,33 +9,21 @@ in build_cpus_aml. Signed-off-by: Keqian Zhu --- - hw/acpi/generic_event_device.c | 1 + hw/arm/virt-acpi-build.c | 33 +++++++++++++++++----------- + hw/arm/virt.c | 1 + include/hw/acpi/acpi_dev_interface.h | 2 ++ include/hw/arm/virt.h | 2 ++ 4 files changed, 25 insertions(+), 13 deletions(-) -diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c -index b834ae3ff6..82139b4314 100644 ---- a/hw/acpi/generic_event_device.c -+++ b/hw/acpi/generic_event_device.c -@@ -289,6 +289,7 @@ static void acpi_ged_class_init(ObjectClass *class, void *data) - - adevc->send_event = acpi_ged_send_event; - adevc->madt_cpu = virt_madt_cpu_entry; -+ adevc->cpu_cppc = virt_acpi_dsdt_cpu_cppc; - } - - static const TypeInfo acpi_ged_info = { diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c -index 4b6aace433..8b68a15d76 100644 +index 64b1ed8672..a93d223879 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c -@@ -111,8 +111,24 @@ static void acpi_dsdt_add_cppc(Aml *dev, uint64_t cpu_base, int *regs_offset) +@@ -120,8 +120,24 @@ static void acpi_dsdt_add_cppc(Aml *dev, uint64_t cpu_base, int *regs_offset) aml_append(dev, aml_name_decl("_CPC", cpc)); } - --static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus, + +-static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms, - const MemMapEntry *cppc_memmap) +void virt_acpi_dsdt_cpu_cppc(AcpiDeviceIf *adev, int ncpu, int num_cpu, Aml *dev) +{ @@ -54,14 +42,14 @@ index 4b6aace433..8b68a15d76 100644 + } +} + -+static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus, VirtMachineState *vms) ++static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms) { + MachineState *ms = MACHINE(vms); uint16_t i; - -@@ -121,16 +137,7 @@ static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus, +@@ -131,16 +147,7 @@ static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms, 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 @@ -70,52 +58,65 @@ index 4b6aace433..8b68a15d76 100644 - acpi_dsdt_add_cppc(dev, - cppc_memmap->base + i * CPPC_REG_PER_CPU_STRIDE, - cppc_regs_offset); -- acpi_dsdt_add_psd(dev, smp_cpus); +- acpi_dsdt_add_psd(dev, ms->smp.cpus); - } -+ virt_acpi_dsdt_cpu_cppc(NULL, i, smp_cpus, dev); - ++ virt_acpi_dsdt_cpu_cppc(NULL, i, ms->smp.cpus, dev); + aml_append(scope, dev); } -@@ -810,7 +817,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) +@@ -940,7 +947,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, &memmap[VIRT_CPUFREQ]); -+ acpi_dsdt_add_cpus(scope, vms->smp_cpus, vms); +- acpi_dsdt_add_cpus(scope, vms, &memmap[VIRT_CPUFREQ]); ++ acpi_dsdt_add_cpus(scope, vms); acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], (irqmap[VIRT_UART] + ARM_SPI_BASE)); - acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); + if (vmc->acpi_expose_flash) { +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 44c29070c4..3299d674c8 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -702,6 +702,7 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + + adevc = ACPI_DEVICE_IF_GET_CLASS(dev); + adevc->madt_cpu = virt_madt_cpu_entry; ++ adevc->cpu_cppc = virt_acpi_dsdt_cpu_cppc; + + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h -index adcb3a816c..2952914569 100644 +index ea6056ab92..601931433a 100644 --- a/include/hw/acpi/acpi_dev_interface.h +++ b/include/hw/acpi/acpi_dev_interface.h -@@ -3,6 +3,7 @@ - +@@ -5,6 +5,7 @@ #include "qom/object.h" #include "hw/boards.h" + #include "hw/qdev-core.h" +#include "hw/acpi/aml-build.h" - + /* These values are part of guest ABI, and can not be changed */ typedef enum { -@@ -55,5 +56,6 @@ typedef struct AcpiDeviceIfClass { - void (*send_event)(AcpiDeviceIf *adev, AcpiEventStatusBits ev); +@@ -55,5 +56,6 @@ struct AcpiDeviceIfClass { void (*madt_cpu)(AcpiDeviceIf *adev, int uid, - const CPUArchIdList *apic_ids, GArray *entry); + const CPUArchIdList *apic_ids, GArray *entry, + bool force_enabled); + void (*cpu_cppc)(AcpiDeviceIf *adev, int uid, int num_cpu, Aml *dev); - } AcpiDeviceIfClass; + }; #endif diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h -index 6b1f10b231..cbdea7ff32 100644 +index 36639e8d3e..fe26709e1a 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h -@@ -157,6 +157,8 @@ typedef struct { - void virt_acpi_setup(VirtMachineState *vms); +@@ -185,6 +185,8 @@ bool virt_is_acpi_enabled(VirtMachineState *vms); void virt_madt_cpu_entry(AcpiDeviceIf *adev, int uid, - const CPUArchIdList *cpu_list, GArray *entry); + const CPUArchIdList *cpu_list, GArray *entry, + bool force_enabled); +void virt_acpi_dsdt_cpu_cppc(AcpiDeviceIf *adev, int uid, + int num_cpu, Aml *dev); - + /* Return the number of used redistributor regions */ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms) --- -2.19.1 +-- +2.27.0 + diff --git a/arm-virt-gic-Construct-irqs-connection-from-create_g.patch b/arm-virt-gic-Construct-irqs-connection-from-create_g.patch index 7e9506425f1de938d2ba70a3fb31a83561a4154e..c16cb0ecacb898a5348c2fe50f12b5ba79ff3f6e 100644 --- a/arm-virt-gic-Construct-irqs-connection-from-create_g.patch +++ b/arm-virt-gic-Construct-irqs-connection-from-create_g.patch @@ -1,4 +1,4 @@ -From 92124743f4560c490780a229f53ea5881f706383 Mon Sep 17 00:00:00 2001 +From 03e050611d6dc9909166fd31dd11abf6fd5012ea Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Sun, 5 Apr 2020 15:29:16 +0800 Subject: [PATCH] arm/virt/gic: Construct irqs connection from create_gic @@ -12,13 +12,13 @@ Signed-off-by: Salil Mehta 1 file changed, 49 insertions(+), 41 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 83f4887e57..55d403bad6 100644 +index 149e0245d7..0af0a996a1 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -706,6 +706,54 @@ static void create_v2m(VirtMachineState *vms) - fdt_add_v2m_gic_node(vms); +@@ -772,6 +772,54 @@ static void create_v2m(VirtMachineState *vms) + vms->msi_controller = VIRT_MSI_CTRL_GICV2M; } - + +static void connect_gic_cpu_irqs(VirtMachineState *vms, int i) +{ + DeviceState *cpudev = DEVICE(qemu_get_cpu(i)); @@ -67,10 +67,10 @@ index 83f4887e57..55d403bad6 100644 + qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); +} + - static void create_gic(VirtMachineState *vms) + static void create_gic(VirtMachineState *vms, MemoryRegion *mem) { MachineState *ms = MACHINE(vms); -@@ -775,47 +823,7 @@ static void create_gic(VirtMachineState *vms) +@@ -849,47 +897,7 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem) * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs. */ for (i = 0; i < smp_cpus; i++) { @@ -117,7 +117,8 @@ index 83f4887e57..55d403bad6 100644 - qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); + connect_gic_cpu_irqs(vms, i); } - + fdt_add_gic_node(vms); --- -2.19.1 +-- +2.27.0 + diff --git a/hw-arm-expose-host-CPU-frequency-info-to-guest.patch b/arm64-Add-the-cpufreq-device-to-show-cpufreq-info-to.patch similarity index 77% rename from hw-arm-expose-host-CPU-frequency-info-to-guest.patch rename to arm64-Add-the-cpufreq-device-to-show-cpufreq-info-to.patch index f0093812ed61e769afec350993e0298a4c5f9e10..005ac1e8d8ba2b927c4a4e5644d26cb83a3e50d6 100644 --- a/hw-arm-expose-host-CPU-frequency-info-to-guest.patch +++ b/arm64-Add-the-cpufreq-device-to-show-cpufreq-info-to.patch @@ -1,7 +1,8 @@ -From b70d020dba72283d7b16a77c377512c84aab5f81 Mon Sep 17 00:00:00 2001 +From e7e28e79988eb671051d0d2af0eb010314c83d41 Mon Sep 17 00:00:00 2001 From: Ying Fang -Date: Mon, 20 Apr 2020 10:38:12 +0800 -Subject: [PATCH] arm64: Add the cpufreq device to show cpufreq info to guest +Date: Tue, 8 Feb 2022 21:01:09 +0800 +Subject: [PATCH 24/24] arm64: Add the cpufreq device to show cpufreq info to + guest On ARM64 platform, cpu frequency is retrieved via ACPI CPPC. A virtual cpufreq device based on ACPI CPPC is created to @@ -22,46 +23,39 @@ This series is backported from: https://patchwork.kernel.org/cover/11379943/ Signed-off-by: Ying Fang +Signed-off-by: Yanan Wang --- - default-configs/aarch64-softmmu.mak | 1 + - hw/acpi/Makefile.objs | 1 + - hw/acpi/aml-build.c | 22 +++ - hw/acpi/cpufreq.c | 287 ++++++++++++++++++++++++++++ - 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, 446 insertions(+), 2 deletions(-) + configs/devices/aarch64-softmmu/default.mak | 1 + + hw/acpi/aml-build.c | 22 ++ + hw/acpi/cpufreq.c | 283 ++++++++++++++++++++ + hw/acpi/meson.build | 1 + + hw/arm/virt-acpi-build.c | 77 +++++- + 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 + + tests/data/acpi/virt/DSDT | Bin 5196 -> 5669 bytes + tests/data/acpi/virt/DSDT.memhp | Bin 6557 -> 7030 bytes + tests/data/acpi/virt/DSDT.numamem | Bin 5196 -> 5669 bytes + tests/data/acpi/virt/DSDT.pxb | Bin 7679 -> 8152 bytes + 14 files changed, 441 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 958b1e08..0a030e85 100644 ---- a/default-configs/aarch64-softmmu.mak -+++ b/default-configs/aarch64-softmmu.mak -@@ -6,3 +6,4 @@ include arm-softmmu.mak +diff --git a/configs/devices/aarch64-softmmu/default.mak b/configs/devices/aarch64-softmmu/default.mak +index cf43ac8da1..c7a710a0f1 100644 +--- a/configs/devices/aarch64-softmmu/default.mak ++++ b/configs/devices/aarch64-softmmu/default.mak +@@ -6,3 +6,4 @@ include ../arm-softmmu/default.mak CONFIG_XLNX_ZYNQMP_ARM=y CONFIG_XLNX_VERSAL=y CONFIG_SBSA_REF=y +CONFIG_CPUFREQ=y -diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs -index 9bb2101e..1a720c38 100644 ---- a/hw/acpi/Makefile.objs -+++ b/hw/acpi/Makefile.objs -@@ -13,6 +13,7 @@ common-obj-y += bios-linker-loader.o - common-obj-y += aml-build.o utils.o - common-obj-$(CONFIG_ACPI_PCI) += pci.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 +index bebf49622b..c4edaafa4a 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c -@@ -1369,6 +1369,28 @@ Aml *aml_sleep(uint64_t msec) +@@ -1554,6 +1554,28 @@ Aml *aml_sleep(uint64_t msec) return var; } @@ -92,10 +86,10 @@ index 555c24f2..73f97751 100644 int hi, lo; diff --git a/hw/acpi/cpufreq.c b/hw/acpi/cpufreq.c new file mode 100644 -index 00000000..d02a25a6 +index 0000000000..a84db490b3 --- /dev/null +++ b/hw/acpi/cpufreq.c -@@ -0,0 +1,287 @@ +@@ -0,0 +1,283 @@ +/* + * ACPI CPPC register device + * @@ -142,7 +136,6 @@ index 00000000..d02a25a6 + */ +#define DEFAULT_HZ 2400 + -+ +int cppc_regs_offset[CPPC_REG_COUNT] = { + [HIGHEST_PERF] = 0, + [NOMINAL_PERF] = 4, @@ -186,8 +179,7 @@ index 00000000..d02a25a6 +} CpuhzState; + + -+static uint64_t cpufreq_read(void *opaque, hwaddr offset, -+ unsigned size) ++static uint64_t cpufreq_read(void *opaque, hwaddr offset, unsigned size) +{ + CpuhzState *s = (CpuhzState *)opaque; + uint64_t r; @@ -231,7 +223,7 @@ index 00000000..d02a25a6 + break; + /* + * Guest may still access the register by 32bit; add the process to -+ * eliminate unnecessary warnings ++ * eliminate unnecessary warnings. + */ + case 28: + r = s->ReferencePerformanceCounter >> 32; @@ -260,7 +252,6 @@ index 00000000..d02a25a6 + return r; +} + -+ +static void cpufreq_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ @@ -292,7 +283,7 @@ index 00000000..d02a25a6 + const char *endptr = NULL; + int ret; + -+ fd = qemu_open(hostpath, O_RDONLY); ++ fd = qemu_open_old(hostpath, O_RDONLY); + if (fd < 0) { + return 0; + } @@ -382,21 +373,27 @@ index 00000000..d02a25a6 +} + +type_init(cpufreq_register_types) -+ +diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build +index adf6347bc4..448ea6afb4 100644 +--- a/hw/acpi/meson.build ++++ b/hw/acpi/meson.build +@@ -25,6 +25,7 @@ acpi_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true: files('ich9.c', 'tco.c')) + acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'), if_false: files('ipmi-stub.c')) + acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c')) + acpi_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c')) ++acpi_ss.add(when: 'CONFIG_CPUFREQ', if_true: files('cpufreq.c')) + softmmu_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c')) + softmmu_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss) + softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-stub.c', 'aml-build-stub.c', diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c -index 0afb3727..29494ebd 100644 +index 674f902652..1ca705654b 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" +@@ -60,7 +60,68 @@ - #define ARM_SPI_BASE 32 - #define ACPI_POWER_BUTTON_DEVICE "PWRB" + #define ACPI_BUILD_TABLE_SIZE 0x20000 --static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) +-static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms) +static void acpi_dsdt_add_psd(Aml *dev, int cpus) +{ + Aml *pkg; @@ -457,12 +454,12 @@ index 0afb3727..29494ebd 100644 + aml_append(dev, aml_name_decl("_CPC", cpc)); +} + -+static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus, ++static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms, + const MemMapEntry *cppc_memmap) { + MachineState *ms = MACHINE(vms); uint16_t i; - -@@ -57,6 +119,18 @@ static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus) +@@ -69,6 +130,18 @@ static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms) 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))); @@ -475,78 +472,78 @@ index 0afb3727..29494ebd 100644 + acpi_dsdt_add_cppc(dev, + cppc_memmap->base + i * CPPC_REG_PER_CPU_STRIDE, + cppc_regs_offset); -+ acpi_dsdt_add_psd(dev, smp_cpus); ++ acpi_dsdt_add_psd(dev, ms->smp.cpus); + } + aml_append(scope, dev); } } -@@ -718,7 +792,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) +@@ -858,7 +931,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_cpus(scope, vms); ++ acpi_dsdt_add_cpus(scope, vms, &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]); + if (vmc->acpi_expose_flash) { diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index d9496c93..0fa355ba 100644 +index 529c0d38b6..0538d258fa 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -135,6 +135,7 @@ static const MemMapEntry base_memmap[] = { - [VIRT_SECURE_UART] = { 0x09040000, 0x00001000 }, - [VIRT_SMMU] = { 0x09050000, 0x00020000 }, +@@ -154,6 +154,7 @@ static const MemMapEntry base_memmap[] = { + [VIRT_PVTIME] = { 0x090a0000, 0x00010000 }, + [VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 }, [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, -+ [VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 }, ++ [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 }, -@@ -731,6 +732,16 @@ static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, +@@ -931,6 +932,16 @@ static void create_uart(const VirtMachineState *vms, 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"); ++ DeviceState *dev = qdev_new("cpufreq"); + SysBusDevice *s = SYS_BUS_DEVICE(dev); + -+ qdev_init_nofail(dev); ++ sysbus_realize_and_unref(s, &error_fatal); + memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0)); +} + - static void create_rtc(const VirtMachineState *vms, qemu_irq *pic) + static void create_rtc(const VirtMachineState *vms) { char *nodename; -@@ -1682,6 +1693,8 @@ static void machvirt_init(MachineState *machine) +@@ -2190,6 +2201,8 @@ static void machvirt_init(MachineState *machine) - create_uart(vms, pic, VIRT_UART, sysmem, serial_hd(0)); + create_uart(vms, 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)); + create_secure_ram(vms, secure_sysmem, secure_tag_sysmem); + create_uart(vms, VIRT_SECURE_UART, secure_sysmem, serial_hd(1)); diff --git a/hw/char/Kconfig b/hw/char/Kconfig -index 40e7a8b8..2f61bf53 100644 +index 6b6cf2fc1d..335a60c2c1 100644 --- a/hw/char/Kconfig +++ b/hw/char/Kconfig -@@ -46,3 +46,7 @@ config SCLPCONSOLE +@@ -71,3 +71,7 @@ config GOLDFISH_TTY - config TERMINAL3270 + config SHAKTI_UART bool + +config CPUFREQ -+ bool -+ default y ++ bool ++ default y diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h -index 57a3f58b..39ae91d3 100644 +index c97e8633ad..ab86583228 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h -@@ -634,4 +634,42 @@ struct AcpiIortRC { - } QEMU_PACKED; - typedef struct AcpiIortRC AcpiIortRC; +@@ -92,4 +92,42 @@ typedef struct AcpiFadtData { + #define ACPI_FADT_ARM_PSCI_COMPLIANT (1 << 0) + #define ACPI_FADT_ARM_PSCI_USE_HVC (1 << 1) +/* + * CPPC register definition from kernel header @@ -588,13 +585,13 @@ index 57a3f58b..39ae91d3 100644 + #endif diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h -index 1a563ad7..375335ab 100644 +index 8e8ad8029e..2e00d2e208 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, +@@ -429,6 +429,9 @@ Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz, uint8_t channel); Aml *aml_sleep(uint64_t msec); + Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source); +Aml *aml_generic_register(AmlRegionSpace rs, uint8_t reg_width, + uint8_t reg_offset, AmlAccessType type, + uint64_t addr); @@ -602,10 +599,10 @@ index 1a563ad7..375335ab 100644 /* 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 a7209420..43a6ce91 100644 +index dc6b66ffc8..a4356cf736 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h -@@ -66,6 +66,7 @@ enum { +@@ -70,6 +70,7 @@ enum { VIRT_GIC_REDIST, VIRT_SMMU, VIRT_UART, @@ -613,6 +610,7 @@ index a7209420..43a6ce91 100644 VIRT_MMIO, VIRT_RTC, VIRT_FW_CFG, + -- -2.23.0 +2.27.0 diff --git a/async-use-explicit-memory-barriers.patch b/async-use-explicit-memory-barriers.patch deleted file mode 100644 index 7fb68c949ad4e95cc0f908c44042096b69cf9295..0000000000000000000000000000000000000000 --- a/async-use-explicit-memory-barriers.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 787af8ed2bc86dc8688727d62a251965d9c42e00 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Fri, 10 Apr 2020 16:19:50 +0000 -Subject: [PATCH 2/2] async: use explicit memory barriers - -When using C11 atomics, non-seqcst reads and writes do not participate -in the total order of seqcst operations. In util/async.c and util/aio-posix.c, -in particular, the pattern that we use - - write ctx->notify_me write bh->scheduled - read bh->scheduled read ctx->notify_me - if !bh->scheduled, sleep if ctx->notify_me, notify - -needs to use seqcst operations for both the write and the read. In -general this is something that we do not want, because there can be -many sources that are polled in addition to bottom halves. The -alternative is to place a seqcst memory barrier between the write -and the read. This also comes with a disadvantage, in that the -memory barrier is implicit on strongly-ordered architectures and -it wastes a few dozen clock cycles. - -Fortunately, ctx->notify_me is never written concurrently by two -threads, so we can assert that and relax the writes to ctx->notify_me. -The resulting solution works and performs well on both aarch64 and x86. - -Note that the atomic_set/atomic_read combination is not an atomic -read-modify-write, and therefore it is even weaker than C11 ATOMIC_RELAXED; -on x86, ATOMIC_RELAXED compiles to a locked operation. - -upstream_url: https://patchwork.kernel.org/patch/11482103/ - -Analyzed-by: Ying Fang -Signed-off-by: Paolo Bonzini -Tested-by: Ying Fang -Message-Id: <20200407140746.8041-6-pbonzini@redhat.com> -Signed-off-by: Stefan Hajnoczi ---- - util/aio-posix.c | 16 ++++++++++++++-- - util/aio-win32.c | 17 ++++++++++++++--- - util/async.c | 16 ++++++++++++---- - 3 files changed, 40 insertions(+), 9 deletions(-) - -diff --git a/util/aio-posix.c b/util/aio-posix.c -index 6fbfa792..ca58b9a4 100644 ---- a/util/aio-posix.c -+++ b/util/aio-posix.c -@@ -613,6 +613,11 @@ bool aio_poll(AioContext *ctx, bool blocking) - int64_t timeout; - int64_t start = 0; - -+ /* -+ * There cannot be two concurrent aio_poll calls for the same AioContext (or -+ * an aio_poll concurrent with a GSource prepare/check/dispatch callback). -+ * We rely on this below to avoid slow locked accesses to ctx->notify_me. -+ */ - assert(in_aio_context_home_thread(ctx)); - - /* aio_notify can avoid the expensive event_notifier_set if -@@ -623,7 +628,13 @@ bool aio_poll(AioContext *ctx, bool blocking) - * so disable the optimization now. - */ - if (blocking) { -- atomic_add(&ctx->notify_me, 2); -+ atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) + 2); -+ /* -+ * Write ctx->notify_me before computing the timeout -+ * (reading bottom half flags, etc.). Pairs with -+ * smp_mb in aio_notify(). -+ */ -+ smp_mb(); - } - - qemu_lockcnt_inc(&ctx->list_lock); -@@ -668,7 +679,8 @@ bool aio_poll(AioContext *ctx, bool blocking) - } - - if (blocking) { -- atomic_sub(&ctx->notify_me, 2); -+ /* Finish the poll before clearing the flag. */ -+ atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) - 2); - aio_notify_accept(ctx); - } - -diff --git a/util/aio-win32.c b/util/aio-win32.c -index a23b9c36..729d533f 100644 ---- a/util/aio-win32.c -+++ b/util/aio-win32.c -@@ -321,6 +321,12 @@ bool aio_poll(AioContext *ctx, bool blocking) - int count; - int timeout; - -+ /* -+ * There cannot be two concurrent aio_poll calls for the same AioContext (or -+ * an aio_poll concurrent with a GSource prepare/check/dispatch callback). -+ * We rely on this below to avoid slow locked accesses to ctx->notify_me. -+ */ -+ assert(in_aio_context_home_thread(ctx)); - progress = false; - - /* aio_notify can avoid the expensive event_notifier_set if -@@ -331,7 +337,13 @@ bool aio_poll(AioContext *ctx, bool blocking) - * so disable the optimization now. - */ - if (blocking) { -- atomic_add(&ctx->notify_me, 2); -+ atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) + 2); -+ /* -+ * Write ctx->notify_me before computing the timeout -+ * (reading bottom half flags, etc.). Pairs with -+ * smp_mb in aio_notify(). -+ */ -+ smp_mb(); - } - - qemu_lockcnt_inc(&ctx->list_lock); -@@ -364,8 +376,7 @@ bool aio_poll(AioContext *ctx, bool blocking) - ret = WaitForMultipleObjects(count, events, FALSE, timeout); - if (blocking) { - assert(first); -- assert(in_aio_context_home_thread(ctx)); -- atomic_sub(&ctx->notify_me, 2); -+ atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) - 2); - aio_notify_accept(ctx); - } - -diff --git a/util/async.c b/util/async.c -index afc17fb3..12b33204 100644 ---- a/util/async.c -+++ b/util/async.c -@@ -221,7 +221,14 @@ aio_ctx_prepare(GSource *source, gint *timeout) - { - AioContext *ctx = (AioContext *) source; - -- atomic_or(&ctx->notify_me, 1); -+ atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) | 1); -+ -+ /* -+ * Write ctx->notify_me before computing the timeout -+ * (reading bottom half flags, etc.). Pairs with -+ * smp_mb in aio_notify(). -+ */ -+ smp_mb(); - - /* We assume there is no timeout already supplied */ - *timeout = qemu_timeout_ns_to_ms(aio_compute_timeout(ctx)); -@@ -239,7 +246,8 @@ aio_ctx_check(GSource *source) - AioContext *ctx = (AioContext *) source; - QEMUBH *bh; - -- atomic_and(&ctx->notify_me, ~1); -+ /* Finish computing the timeout before clearing the flag. */ -+ atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) & ~1); - aio_notify_accept(ctx); - - for (bh = ctx->first_bh; bh; bh = bh->next) { -@@ -344,10 +352,10 @@ LinuxAioState *aio_get_linux_aio(AioContext *ctx) - void aio_notify(AioContext *ctx) - { - /* Write e.g. bh->scheduled before reading ctx->notify_me. Pairs -- * with atomic_or in aio_ctx_prepare or atomic_add in aio_poll. -+ * with smp_mb in aio_ctx_prepare or aio_poll. - */ - smp_mb(); -- if (ctx->notify_me) { -+ if (atomic_read(&ctx->notify_me)) { - event_notifier_set(&ctx->notifier); - atomic_mb_set(&ctx->notified, true); - } --- -2.25.2 - diff --git a/ati-check-x-y-display-parameter-values.patch b/ati-check-x-y-display-parameter-values.patch deleted file mode 100644 index 22a38b28067a612f181c4fc0a2cf1b9f6d049493..0000000000000000000000000000000000000000 --- a/ati-check-x-y-display-parameter-values.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 9557ba506470517668ffecb4d5ef4804eca4fd88 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Wed, 18 Nov 2020 10:22:32 +0800 -Subject: [PATCH] ati: check x y display parameter values - -fix CVE-2020-24352 - -The source and destination x,y display parameters in ati_2d_blt() -may run off the vga limits if either of s->regs.[src|dst]_[xy] is -zero. Check the parameter values to avoid potential crash. - -Reported-by: Gaoning Pan -Signed-off-by: Prasad J Pandit -Message-id: 20201021103818.1704030-1-ppandit@redhat.com -Signed-off-by: Gerd Hoffmann - -cherry-pick from commit ca1f9cbfdce4d63b10d57de80fef89a89d92a540 -Signed-off-by: Jiajie Li ---- - hw/display/ati_2d.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c -index 23a8ae0cd8..4dc10ea795 100644 ---- a/hw/display/ati_2d.c -+++ b/hw/display/ati_2d.c -@@ -75,8 +75,9 @@ void ati_2d_blt(ATIVGAState *s) - dst_stride *= bpp; - } - uint8_t *end = s->vga.vram_ptr + s->vga.vram_size; -- if (dst_bits >= end || dst_bits + dst_x + (dst_y + s->regs.dst_height) * -- dst_stride >= end) { -+ if (dst_x > 0x3fff || dst_y > 0x3fff || dst_bits >= end -+ || dst_bits + dst_x -+ + (dst_y + s->regs.dst_height) * dst_stride >= end) { - qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); - return; - } -@@ -107,8 +108,9 @@ void ati_2d_blt(ATIVGAState *s) - src_bits += s->regs.crtc_offset & 0x07ffffff; - src_stride *= bpp; - } -- if (src_bits >= end || src_bits + src_x + -- (src_y + s->regs.dst_height) * src_stride >= end) { -+ if (src_x > 0x3fff || src_y > 0x3fff || src_bits >= end -+ || src_bits + src_x -+ + (src_y + s->regs.dst_height) * src_stride >= end) { - qemu_log_mask(LOG_UNIMP, "blt outside vram not implemented\n"); - return; - } --- -2.27.0 - diff --git a/ati-use-vga_read_byte-in-ati_cursor_define.patch b/ati-use-vga_read_byte-in-ati_cursor_define.patch deleted file mode 100644 index a4b7e806600c341d865ca6acaf75ed4ce6b9c9b8..0000000000000000000000000000000000000000 --- a/ati-use-vga_read_byte-in-ati_cursor_define.patch +++ /dev/null @@ -1,198 +0,0 @@ -From 1ebe0e71d04bfdc76777a3a672e873f006d207e2 Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Fri, 5 Feb 2021 10:38:24 +0800 -Subject: [PATCH] ati: use vga_read_byte in ati_cursor_define -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -fix CVE-2019-20808 - -This makes sure reads are confined to vga video memory. - -v3: use uint32_t, fix cut+paste bug. -v2: fix ati_cursor_draw_line too. - -Reported-by: xu hang -Signed-off-by: Gerd Hoffmann -Reviewed-by: BALATON Zoltan -Reviewed-by: Philippe Mathieu-Daudé -Message-id: 20190917111441.27405-3-kraxel@redhat.com - -cherry-pick from aab0e2a661b2b6bf7915c0aefe807fb60d6d9d13 -Signed-off-by: Jiajie Li ---- - hw/display/ati.c | 21 ++++++++--------- - hw/display/vga-access.h | 49 ++++++++++++++++++++++++++++++++++++++++ - hw/display/vga-helpers.h | 27 +--------------------- - 3 files changed, 60 insertions(+), 37 deletions(-) - create mode 100644 hw/display/vga-access.h - -diff --git a/hw/display/ati.c b/hw/display/ati.c -index 5943040416..b17569874e 100644 ---- a/hw/display/ati.c -+++ b/hw/display/ati.c -@@ -19,6 +19,7 @@ - #include "qemu/osdep.h" - #include "ati_int.h" - #include "ati_regs.h" -+#include "vga-access.h" - #include "vga_regs.h" - #include "qemu/log.h" - #include "qemu/module.h" -@@ -125,20 +126,19 @@ static void ati_vga_switch_mode(ATIVGAState *s) - static void ati_cursor_define(ATIVGAState *s) - { - uint8_t data[1024]; -- uint8_t *src; -+ uint32_t srcoff; - int i, j, idx = 0; - - if ((s->regs.cur_offset & BIT(31)) || s->cursor_guest_mode) { - return; /* Do not update cursor if locked or rendered by guest */ - } - /* FIXME handle cur_hv_offs correctly */ -- src = s->vga.vram_ptr + (s->regs.crtc_offset & 0x07ffffff) + -- s->regs.cur_offset - (s->regs.cur_hv_offs >> 16) - -- (s->regs.cur_hv_offs & 0xffff) * 16; -+ srcoff = s->regs.cur_offset - -+ (s->regs.cur_hv_offs >> 16) - (s->regs.cur_hv_offs & 0xffff) * 16; - for (i = 0; i < 64; i++) { - for (j = 0; j < 8; j++, idx++) { -- data[idx] = src[i * 16 + j]; -- data[512 + idx] = src[i * 16 + j + 8]; -+ data[idx] = vga_read_byte(&s->vga, srcoff + i * 16 + j); -+ data[512 + idx] = vga_read_byte(&s->vga, srcoff + i * 16 + j + 8); - } - } - if (!s->cursor) { -@@ -180,7 +180,7 @@ static void ati_cursor_invalidate(VGACommonState *vga) - static void ati_cursor_draw_line(VGACommonState *vga, uint8_t *d, int scr_y) - { - ATIVGAState *s = container_of(vga, ATIVGAState, vga); -- uint8_t *src; -+ uint32_t srcoff; - uint32_t *dp = (uint32_t *)d; - int i, j, h; - -@@ -190,14 +190,13 @@ static void ati_cursor_draw_line(VGACommonState *vga, uint8_t *d, int scr_y) - return; - } - /* FIXME handle cur_hv_offs correctly */ -- src = s->vga.vram_ptr + (s->regs.crtc_offset & 0x07ffffff) + -- s->cursor_offset + (scr_y - vga->hw_cursor_y) * 16; -+ srcoff = s->cursor_offset + (scr_y - vga->hw_cursor_y) * 16; - dp = &dp[vga->hw_cursor_x]; - h = ((s->regs.crtc_h_total_disp >> 16) + 1) * 8; - for (i = 0; i < 8; i++) { - uint32_t color; -- uint8_t abits = src[i]; -- uint8_t xbits = src[i + 8]; -+ uint8_t abits = vga_read_byte(vga, srcoff + i); -+ uint8_t xbits = vga_read_byte(vga, srcoff + i + 8); - for (j = 0; j < 8; j++, abits <<= 1, xbits <<= 1) { - if (abits & BIT(7)) { - if (xbits & BIT(7)) { -diff --git a/hw/display/vga-access.h b/hw/display/vga-access.h -new file mode 100644 -index 0000000000..c0fbd9958b ---- /dev/null -+++ b/hw/display/vga-access.h -@@ -0,0 +1,49 @@ -+/* -+ * QEMU VGA Emulator templates -+ * -+ * Copyright (c) 2003 Fabrice Bellard -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+ -+static inline uint8_t vga_read_byte(VGACommonState *vga, uint32_t addr) -+{ -+ return vga->vram_ptr[addr & vga->vbe_size_mask]; -+} -+ -+static inline uint16_t vga_read_word_le(VGACommonState *vga, uint32_t addr) -+{ -+ uint32_t offset = addr & vga->vbe_size_mask & ~1; -+ uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset); -+ return lduw_le_p(ptr); -+} -+ -+static inline uint16_t vga_read_word_be(VGACommonState *vga, uint32_t addr) -+{ -+ uint32_t offset = addr & vga->vbe_size_mask & ~1; -+ uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset); -+ return lduw_be_p(ptr); -+} -+ -+static inline uint32_t vga_read_dword_le(VGACommonState *vga, uint32_t addr) -+{ -+ uint32_t offset = addr & vga->vbe_size_mask & ~3; -+ uint32_t *ptr = (uint32_t *)(vga->vram_ptr + offset); -+ return ldl_le_p(ptr); -+} -diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h -index 5a752b3f9e..5b6c02faa6 100644 ---- a/hw/display/vga-helpers.h -+++ b/hw/display/vga-helpers.h -@@ -21,6 +21,7 @@ - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -+#include "vga-access.h" - - static inline void vga_draw_glyph_line(uint8_t *d, uint32_t font_data, - uint32_t xorcol, uint32_t bgcol) -@@ -95,32 +96,6 @@ static void vga_draw_glyph9(uint8_t *d, int linesize, - } while (--h); - } - --static inline uint8_t vga_read_byte(VGACommonState *vga, uint32_t addr) --{ -- return vga->vram_ptr[addr & vga->vbe_size_mask]; --} -- --static inline uint16_t vga_read_word_le(VGACommonState *vga, uint32_t addr) --{ -- uint32_t offset = addr & vga->vbe_size_mask & ~1; -- uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset); -- return lduw_le_p(ptr); --} -- --static inline uint16_t vga_read_word_be(VGACommonState *vga, uint32_t addr) --{ -- uint32_t offset = addr & vga->vbe_size_mask & ~1; -- uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset); -- return lduw_be_p(ptr); --} -- --static inline uint32_t vga_read_dword_le(VGACommonState *vga, uint32_t addr) --{ -- uint32_t offset = addr & vga->vbe_size_mask & ~3; -- uint32_t *ptr = (uint32_t *)(vga->vram_ptr + offset); -- return ldl_le_p(ptr); --} -- - /* - * 4 color mode - */ --- -2.27.0 - diff --git a/ati-vga-Fix-checks-in-ati_2d_blt-to-avoid-crash.patch b/ati-vga-Fix-checks-in-ati_2d_blt-to-avoid-crash.patch deleted file mode 100644 index ef1d8b646c607a5afb6278ab229efc4a5a15965f..0000000000000000000000000000000000000000 --- a/ati-vga-Fix-checks-in-ati_2d_blt-to-avoid-crash.patch +++ /dev/null @@ -1,91 +0,0 @@ -From ac2071c3791b67fc7af78b8ceb320c01ca1b5df7 Mon Sep 17 00:00:00 2001 -From: BALATON Zoltan -Date: Mon, 6 Apr 2020 22:34:26 +0200 -Subject: [PATCH] ati-vga: Fix checks in ati_2d_blt() to avoid crash - -In some corner cases (that never happen during normal operation but a -malicious guest could program wrong values) pixman functions were -called with parameters that result in a crash. Fix this and add more -checks to disallow such cases. - -Reported-by: Ziming Zhang -Signed-off-by: BALATON Zoltan -Message-id: 20200406204029.19559747D5D@zero.eik.bme.hu -Signed-off-by: Gerd Hoffmann - -diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c -index 42e82311eb..23a8ae0cd8 100644 ---- a/hw/display/ati_2d.c -+++ b/hw/display/ati_2d.c -@@ -53,12 +53,20 @@ void ati_2d_blt(ATIVGAState *s) - s->vga.vbe_start_addr, surface_data(ds), surface_stride(ds), - surface_bits_per_pixel(ds), - (s->regs.dp_mix & GMC_ROP3_MASK) >> 16); -- int dst_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? -- s->regs.dst_x : s->regs.dst_x + 1 - s->regs.dst_width); -- int dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? -- s->regs.dst_y : s->regs.dst_y + 1 - s->regs.dst_height); -+ unsigned dst_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? -+ s->regs.dst_x : s->regs.dst_x + 1 - s->regs.dst_width); -+ unsigned dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? -+ s->regs.dst_y : s->regs.dst_y + 1 - s->regs.dst_height); - int bpp = ati_bpp_from_datatype(s); -+ if (!bpp) { -+ qemu_log_mask(LOG_GUEST_ERROR, "Invalid bpp\n"); -+ return; -+ } - int dst_stride = DEFAULT_CNTL ? s->regs.dst_pitch : s->regs.default_pitch; -+ if (!dst_stride) { -+ qemu_log_mask(LOG_GUEST_ERROR, "Zero dest pitch\n"); -+ return; -+ } - uint8_t *dst_bits = s->vga.vram_ptr + (DEFAULT_CNTL ? - s->regs.dst_offset : s->regs.default_offset); - -@@ -82,12 +90,16 @@ void ati_2d_blt(ATIVGAState *s) - switch (s->regs.dp_mix & GMC_ROP3_MASK) { - case ROP3_SRCCOPY: - { -- int src_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? -- s->regs.src_x : s->regs.src_x + 1 - s->regs.dst_width); -- int src_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? -- s->regs.src_y : s->regs.src_y + 1 - s->regs.dst_height); -+ unsigned src_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? -+ s->regs.src_x : s->regs.src_x + 1 - s->regs.dst_width); -+ unsigned src_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? -+ s->regs.src_y : s->regs.src_y + 1 - s->regs.dst_height); - int src_stride = DEFAULT_CNTL ? - s->regs.src_pitch : s->regs.default_pitch; -+ if (!src_stride) { -+ qemu_log_mask(LOG_GUEST_ERROR, "Zero source pitch\n"); -+ return; -+ } - uint8_t *src_bits = s->vga.vram_ptr + (DEFAULT_CNTL ? - s->regs.src_offset : s->regs.default_offset); - -@@ -137,8 +149,10 @@ void ati_2d_blt(ATIVGAState *s) - dst_y * surface_stride(ds), - s->regs.dst_height * surface_stride(ds)); - } -- s->regs.dst_x += s->regs.dst_width; -- s->regs.dst_y += s->regs.dst_height; -+ s->regs.dst_x = (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? -+ dst_x + s->regs.dst_width : dst_x); -+ s->regs.dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? -+ dst_y + s->regs.dst_height : dst_y); - break; - } - case ROP3_PATCOPY: -@@ -179,7 +193,8 @@ void ati_2d_blt(ATIVGAState *s) - dst_y * surface_stride(ds), - s->regs.dst_height * surface_stride(ds)); - } -- s->regs.dst_y += s->regs.dst_height; -+ s->regs.dst_y = (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? -+ dst_y + s->regs.dst_height : dst_y); - break; - } - default: --- -2.23.0 - diff --git a/ati-vga-check-mm_index-before-recursive-call-CVE-202.patch b/ati-vga-check-mm_index-before-recursive-call-CVE-202.patch deleted file mode 100644 index b80c9dc973015dd83e3d9c0c000dd0b15b303608..0000000000000000000000000000000000000000 --- a/ati-vga-check-mm_index-before-recursive-call-CVE-202.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 89554d2f71d4c79c5d8e804d90d74f3985d7ded5 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Thu, 4 Jun 2020 14:38:30 +0530 -Subject: [PATCH 3/9] ati-vga: check mm_index before recursive call - (CVE-2020-13800) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -While accessing VGA registers via ati_mm_read/write routines, -a guest may set 's->regs.mm_index' such that it leads to infinite -recursion. Check mm_index value to avoid such recursion. Log an -error message for wrong values. - -Reported-by: Ren Ding -Reported-by: Hanqing Zhao -Reported-by: Yi Ren -Message-id: 20200604090830.33885-1-ppandit@redhat.com -Suggested-by: BALATON Zoltan -Suggested-by: Philippe Mathieu-Daudé -Signed-off-by: Prasad J Pandit -Signed-off-by: Gerd Hoffmann ---- - hw/display/ati.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/hw/display/ati.c b/hw/display/ati.c -index a747c4cc98..5943040416 100644 ---- a/hw/display/ati.c -+++ b/hw/display/ati.c -@@ -261,8 +261,11 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size) - if (idx <= s->vga.vram_size - size) { - val = ldn_le_p(s->vga.vram_ptr + idx, size); - } -- } else { -+ } else if (s->regs.mm_index > MM_DATA + 3) { - val = ati_mm_read(s, s->regs.mm_index + addr - MM_DATA, size); -+ } else { -+ qemu_log_mask(LOG_GUEST_ERROR, -+ "ati_mm_read: mm_index too small: %u\n", s->regs.mm_index); - } - break; - case BIOS_0_SCRATCH ... BUS_CNTL - 1: -@@ -472,8 +475,11 @@ static void ati_mm_write(void *opaque, hwaddr addr, - if (idx <= s->vga.vram_size - size) { - stn_le_p(s->vga.vram_ptr + idx, size, data); - } -- } else { -+ } else if (s->regs.mm_index > MM_DATA + 3) { - ati_mm_write(s, s->regs.mm_index + addr - MM_DATA, data, size); -+ } else { -+ qemu_log_mask(LOG_GUEST_ERROR, -+ "ati_mm_write: mm_index too small: %u\n", s->regs.mm_index); - } - break; - case BIOS_0_SCRATCH ... BUS_CNTL - 1: --- -2.25.1 - diff --git a/audio-fix-integer-overflow.patch b/audio-fix-integer-overflow.patch deleted file mode 100644 index 91f5280f1854634460e43b48ae98a4f5eb57b26c..0000000000000000000000000000000000000000 --- a/audio-fix-integer-overflow.patch +++ /dev/null @@ -1,37 +0,0 @@ -From d0c4e8cc25dc3bfed1659c35fb59b2f0418ba1d5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Volker=20R=C3=BCmelin?= -Date: Thu, 19 Dec 2019 21:34:05 +0100 -Subject: [PATCH 2/8] audio: fix integer overflow -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Tell the compiler to do a 32bit * 32bit -> 64bit multiplication -because period_ticks is a 64bit variable. The overflow occurs -for audio timer periods larger than 4294967us. - -Fixes: be1092afa0 "audio: fix audio timer rate conversion bug" - -Signed-off-by: Volker Rümelin -Message-id: 8893a235-66a8-8fbe-7d95-862e29da90b1@t-online.de -Signed-off-by: Gerd Hoffmann ---- - audio/audio.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/audio/audio.c b/audio/audio.c -index 05adf7f..efcb5d4 100644 ---- a/audio/audio.c -+++ b/audio/audio.c -@@ -1473,7 +1473,7 @@ static int audio_init(Audiodev *dev) - if (dev->timer_period <= 0) { - s->period_ticks = 1; - } else { -- s->period_ticks = dev->timer_period * SCALE_US; -+ s->period_ticks = dev->timer_period * (int64_t)SCALE_US; - } - - e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s); --- -1.8.3.1 - diff --git a/backup-Improve-error-for-bdrv_getlength-failure.patch b/backup-Improve-error-for-bdrv_getlength-failure.patch deleted file mode 100644 index df188942c913062b499c1d6579556784661b2985..0000000000000000000000000000000000000000 --- a/backup-Improve-error-for-bdrv_getlength-failure.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0b66aef5389d622434128fc7db9abd2cd4724b51 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Wed, 3 Jun 2020 16:03:19 +0100 -Subject: [PATCH] backup: Improve error for bdrv_getlength() failure - -RH-Author: Kevin Wolf -Message-id: <20200603160325.67506-6-kwolf@redhat.com> -Patchwork-id: 97103 -O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 05/11] backup: Improve error for bdrv_getlength() failure -Bugzilla: 1778593 -RH-Acked-by: Eric Blake -RH-Acked-by: Max Reitz -RH-Acked-by: Stefano Garzarella - -bdrv_get_device_name() will be an empty string with modern management -tools that don't use -drive. Use bdrv_get_device_or_node_name() instead -so that the node name is used if the BlockBackend is anonymous. - -While at it, start with upper case to make the message consistent with -the rest of the function. - -Signed-off-by: Kevin Wolf -Reviewed-by: Vladimir Sementsov-Ogievskiy -Reviewed-by: Alberto Garcia -Message-Id: <20200430142755.315494-3-kwolf@redhat.com> -Signed-off-by: Kevin Wolf -(cherry picked from commit 58226634c4b02af7b10862f7fbd3610a344bfb7f) -Signed-off-by: Kevin Wolf -Signed-off-by: Danilo C. L. de Paula ---- - block/backup.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/block/backup.c b/block/backup.c -index 8761f1f9a7..88354dcb32 100644 ---- a/block/backup.c -+++ b/block/backup.c -@@ -613,8 +613,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, - - len = bdrv_getlength(bs); - if (len < 0) { -- error_setg_errno(errp, -len, "unable to get length for '%s'", -- bdrv_get_device_name(bs)); -+ error_setg_errno(errp, -len, "Unable to get length for '%s'", -+ bdrv_get_device_or_node_name(bs)); - goto error; - } - --- -2.27.0 - diff --git a/bios-tables-test-Allow-changes-to-q35-SSDT.dimmpxm-f.patch b/bios-tables-test-Allow-changes-to-q35-SSDT.dimmpxm-f.patch new file mode 100644 index 0000000000000000000000000000000000000000..8228abcd539d2ad17cd911cfc7a5281b7beda939 --- /dev/null +++ b/bios-tables-test-Allow-changes-to-q35-SSDT.dimmpxm-f.patch @@ -0,0 +1,23 @@ +From 00c4115a1388ee72295b99fce1f6ad49bf761134 Mon Sep 17 00:00:00 2001 +From: Yan Wang +Date: Thu, 10 Feb 2022 17:08:08 +0800 +Subject: [PATCH] bios-tables-test: Allow changes to q35/SSDT.dimmpxm file + +List test/data/acpi/q35/SSDT.dimmpxm as the expected files allowed to +be changed in tests/qtest/bios-tables-test-allowed-diff.h + +Signed-off-by: Yan Wang +--- + tests/qtest/bios-tables-test-allowed-diff.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index dfb8523c8b..81148a604f 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1 +1,2 @@ + /* List of comma-separated changed AML files to ignore */ ++"tests/data/acpi/q35/SSDT.dimmpxm", +-- +2.27.0 + diff --git a/bios-tables-test-Update-expected-q35-SSDT.dimmpxm-fi.patch b/bios-tables-test-Update-expected-q35-SSDT.dimmpxm-fi.patch new file mode 100644 index 0000000000000000000000000000000000000000..6cfa1f203d183536ae36b3eed2255310e0e4e50d --- /dev/null +++ b/bios-tables-test-Update-expected-q35-SSDT.dimmpxm-fi.patch @@ -0,0 +1,79 @@ +From 8940f11a055da0a744d10b53cf999dea7967be25 Mon Sep 17 00:00:00 2001 +From: Yan Wang +Date: Thu, 10 Feb 2022 17:12:35 +0800 +Subject: [PATCH] bios-tables-test: Update expected q35/SSDT.dimmpxm file + +Run ./tests/data/acpi/rebuild-expected-aml.sh from build directory +to update q35/SSDT.dimmpxm file. Also empty bios-tables-test-allowed-diff.h. + +The disassembled differences between actual and expected SSDT.dimmpxm: + + /* + * Intel ACPI Component Architecture + * AML/ASL+ Disassembler version 20210604 (64-bit version) + * Copyright (c) 2000 - 2021 Intel Corporation + * + * Disassembling to symbolic ASL+ operators + * +- * Disassembly of tests/data/acpi/q35/SSDT.dimmpxm, Thu Feb 10 15:03:52 2022 ++ * Disassembly of /tmp/aml-CK68G1, Thu Feb 10 15:03:52 2022 + * + * Original Table Header: + * Signature "SSDT" + * Length 0x000002DE (734) + * Revision 0x01 +- * Checksum 0x06 ++ * Checksum 0x16 + * OEM ID "BOCHS " + * OEM Table ID "NVDIMM " + * OEM Revision 0x00000001 (1) + * Compiler ID "BXPC" + * Compiler Version 0x00000001 (1) + */ + DefinitionBlock ("", "SSDT", 1, "BOCHS ", "NVDIMM ", 0x00000001) + { + Scope (\_SB) + { + Device (NVDR) + { + Name (_HID, "ACPI0012" /* NVDIMM Root Device */) // _HID: Hardware ID + Method (NCAL, 5, Serialized) + { + Local6 = MEMA /* \MEMA */ +@@ -187,19 +187,19 @@ + { + Return (NCAL (Arg0, Arg1, Arg2, Arg3, 0x02)) + } + } + + Device (NV02) + { + Name (_ADR, 0x03) // _ADR: Address + Method (_DSM, 4, NotSerialized) // _DSM: Device-Specific Method + { + Return (NCAL (Arg0, Arg1, Arg2, Arg3, 0x03)) + } + } + } + } + +- Name (MEMA, 0x07FFF000) ++ Name (MEMA, 0x07FFE000) + } + +Signed-off-by: Yan Wang +--- + tests/data/acpi/q35/SSDT.dimmpxm | Bin 734 -> 734 bytes + tests/qtest/bios-tables-test-allowed-diff.h | 1 - + 2 files changed, 1 deletion(-) + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index 81148a604f..dfb8523c8b 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1,2 +1 @@ + /* List of comma-separated changed AML files to ignore */ +-"tests/data/acpi/q35/SSDT.dimmpxm", +-- +2.27.0 + diff --git a/bios-tables-test-prepare-to-change-ARM-virt-ACPI-DSDT.patch b/bios-tables-test-prepare-to-change-ARM-virt-ACPI-DSDT.patch deleted file mode 100644 index 1dc656892b5f124d3ad732aed9c31b0f71a3363b..0000000000000000000000000000000000000000 --- a/bios-tables-test-prepare-to-change-ARM-virt-ACPI-DSDT.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 2892a4b1f7dfc75e06d0ce770d44a062b6334eb0 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 15 Apr 2020 17:03:54 +0800 -Subject: [PATCH] bios-tables-test: prepare to change ARM virt ACPI DSDT - -We will change ARM virt ACPI DSDT table in order to add the cpufreq device, -which use ACPI CPPC to show CPU frequency info to guest. - -Signed-off-by: Ying Fang ---- - tests/bios-tables-test-allowed-diff.h | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/tests/bios-tables-test-allowed-diff.h b/tests/bios-tables-test-allowed-diff.h -index dfb8523c..32a401ae 100644 ---- a/tests/bios-tables-test-allowed-diff.h -+++ b/tests/bios-tables-test-allowed-diff.h -@@ -1 +1,4 @@ - /* List of comma-separated changed AML files to ignore */ -+"tests/data/acpi/virt/DSDT", -+"tests/data/acpi/virt/DSDT.memhp", -+"tests/data/acpi/virt/DSDT.numamem", --- -2.23.0 diff --git a/block-Add-bdrv_co_get_self_request.patch b/block-Add-bdrv_co_get_self_request.patch deleted file mode 100644 index 4972f084649f70253978ad8fb1d3842bbf741d81..0000000000000000000000000000000000000000 --- a/block-Add-bdrv_co_get_self_request.patch +++ /dev/null @@ -1,59 +0,0 @@ -From d9b88f7e0d56feb4d7daa2506e2756fc48e975a1 Mon Sep 17 00:00:00 2001 -From: Max Reitz -Date: Fri, 1 Nov 2019 16:25:09 +0100 -Subject: [PATCH] block: Add bdrv_co_get_self_request() - -Cc: qemu-stable@nongnu.org -Signed-off-by: Max Reitz -Message-id: 20191101152510.11719-3-mreitz@redhat.com -Signed-off-by: Max Reitz -(cherry picked from commit c28107e9e55b11cd35cf3dc2505e3e69d10dcf13) -Signed-off-by: Michael Roth ---- - block/io.c | 18 ++++++++++++++++++ - include/block/block_int.h | 1 + - 2 files changed, 19 insertions(+) - -diff --git a/block/io.c b/block/io.c -index d4ceaaa2ce..65b5102714 100644 ---- a/block/io.c -+++ b/block/io.c -@@ -721,6 +721,24 @@ static bool is_request_serialising_and_aligned(BdrvTrackedRequest *req) - (req->bytes == req->overlap_bytes); - } - -+/** -+ * Return the tracked request on @bs for the current coroutine, or -+ * NULL if there is none. -+ */ -+BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs) -+{ -+ BdrvTrackedRequest *req; -+ Coroutine *self = qemu_coroutine_self(); -+ -+ QLIST_FOREACH(req, &bs->tracked_requests, list) { -+ if (req->co == self) { -+ return req; -+ } -+ } -+ -+ return NULL; -+} -+ - /** - * Round a region to cluster boundaries - */ -diff --git a/include/block/block_int.h b/include/block/block_int.h -index 4465b02242..05ee6b4866 100644 ---- a/include/block/block_int.h -+++ b/include/block/block_int.h -@@ -964,6 +964,7 @@ void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent); - - bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self); - void bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align); -+BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs); - - int get_tmp_filename(char *filename, int size); - BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size, --- -2.23.0 diff --git a/block-Add-error-retry-param-setting.patch b/block-Add-error-retry-param-setting.patch index 72f214b1283635a32308e67ba095ff981368ea2e..4facb3f8c1fca5e941ee5154bd2459ae8309b8f8 100644 --- a/block-Add-error-retry-param-setting.patch +++ b/block-Add-error-retry-param-setting.patch @@ -1,7 +1,7 @@ -From 3464a135565d718d0fedadd67081a0f76d81a9c6 Mon Sep 17 00:00:00 2001 +From a58fda7b158441c645e143bf658d12914ffbc7b8 Mon Sep 17 00:00:00 2001 From: Jiahui Cen Date: Thu, 21 Jan 2021 15:46:50 +0800 -Subject: [PATCH] block: Add error retry param setting +Subject: [PATCH 6/7] block: Add error retry param setting Add "retry_interval" and "retry_timeout" parameter for drive and device option. These parameter are valid only when werror/rerror=retry. @@ -10,6 +10,7 @@ eg. --drive file=image,rerror=retry,retry_interval=1000,retry_timeout=5000 Signed-off-by: Jiahui Cen Signed-off-by: Ying Fang +Signed-off-by: Alex Chen --- block/block-backend.c | 13 +++++++-- blockdev.c | 50 ++++++++++++++++++++++++++++++++++ @@ -19,10 +20,10 @@ Signed-off-by: Ying Fang 5 files changed, 81 insertions(+), 4 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c -index 0fe99ffe52..2d812e2254 100644 +index 37e21c473e..d3d90a95a5 100644 --- a/block/block-backend.c +++ b/block/block-backend.c -@@ -31,9 +31,6 @@ +@@ -35,9 +35,6 @@ static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb); @@ -32,7 +33,7 @@ index 0fe99ffe52..2d812e2254 100644 typedef struct BlockBackendAioNotifier { void (*attached_aio_context)(AioContext *new_context, void *opaque); void (*detach_aio_context)(void *opaque); -@@ -1633,6 +1630,16 @@ void blk_drain_all(void) +@@ -1766,6 +1763,16 @@ void blk_drain_all(void) bdrv_drain_all_end(); } @@ -50,10 +51,10 @@ index 0fe99ffe52..2d812e2254 100644 { /* No timeout set, infinite retries. */ diff --git a/blockdev.c b/blockdev.c -index 0f49fd290e..99c92b96d2 100644 +index 6f1981635b..10a73fa423 100644 --- a/blockdev.c +++ b/blockdev.c -@@ -470,6 +470,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, +@@ -480,6 +480,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, const char *buf; int bdrv_flags = 0; int on_read_error, on_write_error; @@ -61,7 +62,7 @@ index 0f49fd290e..99c92b96d2 100644 bool account_invalid, account_failed; bool writethrough, read_only; BlockBackend *blk; -@@ -565,6 +566,10 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, +@@ -572,6 +573,10 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, } } @@ -72,7 +73,7 @@ index 0f49fd290e..99c92b96d2 100644 if (snapshot) { bdrv_flags |= BDRV_O_SNAPSHOT; } -@@ -629,6 +634,11 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, +@@ -635,6 +640,11 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, blk_set_enable_write_cache(blk, !writethrough); blk_set_on_error(blk, on_read_error, on_write_error); @@ -84,7 +85,7 @@ index 0f49fd290e..99c92b96d2 100644 if (!monitor_add_blk(blk, id, errp)) { blk_unref(blk); -@@ -754,6 +764,14 @@ QemuOptsList qemu_legacy_drive_opts = { +@@ -761,6 +771,14 @@ QemuOptsList qemu_legacy_drive_opts = { .name = "werror", .type = QEMU_OPT_STRING, .help = "write error action", @@ -99,7 +100,7 @@ index 0f49fd290e..99c92b96d2 100644 },{ .name = "copy-on-read", .type = QEMU_OPT_BOOL, -@@ -776,6 +794,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type, +@@ -783,6 +801,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type, BlockInterfaceType type; int max_devs, bus_id, unit_id, index; const char *werror, *rerror; @@ -107,7 +108,7 @@ index 0f49fd290e..99c92b96d2 100644 bool read_only = false; bool copy_on_read; const char *filename; -@@ -992,6 +1011,29 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type, +@@ -990,6 +1009,29 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type, qdict_put_str(bs_opts, "rerror", rerror); } @@ -135,9 +136,9 @@ index 0f49fd290e..99c92b96d2 100644 + } + /* Actual block device init: Functionality shared with blockdev-add */ - blk = blockdev_init(filename, bs_opts, &local_err); + blk = blockdev_init(filename, bs_opts, errp); bs_opts = NULL; -@@ -4593,6 +4635,14 @@ QemuOptsList qemu_common_drive_opts = { +@@ -3806,6 +3848,14 @@ QemuOptsList qemu_common_drive_opts = { .name = "werror", .type = QEMU_OPT_STRING, .help = "write error action", @@ -153,10 +154,10 @@ index 0f49fd290e..99c92b96d2 100644 .name = BDRV_OPT_READ_ONLY, .type = QEMU_OPT_BOOL, diff --git a/hw/block/block.c b/hw/block/block.c -index bf56c7612b..56141940ca 100644 +index d47ebf005a..26c0767552 100644 --- a/hw/block/block.c +++ b/hw/block/block.c -@@ -134,6 +134,16 @@ bool blkconf_apply_backend_options(BlockConf *conf, bool readonly, +@@ -206,6 +206,16 @@ bool blkconf_apply_backend_options(BlockConf *conf, bool readonly, blk_set_enable_write_cache(blk, wce); blk_set_on_error(blk, rerror, werror); @@ -174,10 +175,10 @@ index bf56c7612b..56141940ca 100644 } diff --git a/include/hw/block/block.h b/include/hw/block/block.h -index 607539057a..d12603aabd 100644 +index 5902c0440a..24fb7d77af 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h -@@ -30,6 +30,8 @@ typedef struct BlockConf { +@@ -33,6 +33,8 @@ typedef struct BlockConf { bool share_rw; BlockdevOnError rerror; BlockdevOnError werror; @@ -186,7 +187,7 @@ index 607539057a..d12603aabd 100644 } BlockConf; static inline unsigned int get_physical_block_exp(BlockConf *conf) -@@ -71,7 +73,10 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) +@@ -79,7 +81,10 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) DEFINE_PROP_BLOCKDEV_ON_ERROR("rerror", _state, _conf.rerror, \ BLOCKDEV_ON_ERROR_AUTO), \ DEFINE_PROP_BLOCKDEV_ON_ERROR("werror", _state, _conf.werror, \ @@ -199,7 +200,7 @@ index 607539057a..d12603aabd 100644 /* Backend access helpers */ diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h -index 58dde446ca..dc10e507ae 100644 +index 56a403883d..887c19ff5d 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h @@ -25,6 +25,9 @@ @@ -212,7 +213,7 @@ index 58dde446ca..dc10e507ae 100644 /* Callbacks for block device models */ typedef struct BlockDevOps { /* -@@ -184,6 +187,8 @@ void blk_inc_in_flight(BlockBackend *blk); +@@ -198,6 +201,8 @@ void blk_inc_in_flight(BlockBackend *blk); void blk_dec_in_flight(BlockBackend *blk); void blk_drain(BlockBackend *blk); void blk_drain_all(void); diff --git a/block-Add-sanity-check-when-setting-retry-parameters.patch b/block-Add-sanity-check-when-setting-retry-parameters.patch index 0af7b6e14e2be698821105d386c4c39893c67a83..d48fa5d654a4d5eb2e50b2336715bbeff40242a5 100644 --- a/block-Add-sanity-check-when-setting-retry-parameters.patch +++ b/block-Add-sanity-check-when-setting-retry-parameters.patch @@ -1,24 +1,40 @@ -From 6642b2c6fcad2e1099c61b56f4fe78f3180d005e Mon Sep 17 00:00:00 2001 +From f329ec9bd971ba7776cadb57e7311bfb6da41060 Mon Sep 17 00:00:00 2001 From: Jiahui Cen Date: Thu, 18 Mar 2021 19:45:11 +0800 -Subject: [PATCH] block: Add sanity check when setting retry parameters +Subject: [PATCH 9/9] block: Add sanity check when setting retry parameters Add sanity check when setting retry parameters to avoid invalid retry configuration. Signed-off-by: Jiahui Cen +Signed-off-by: Alex Chen --- - hw/core/qdev-properties.c | 45 ++++++++++++++++++++++++++++++++++++ - include/hw/block/block.h | 7 +++--- - include/hw/qdev-properties.h | 8 +++++++ - 3 files changed, 57 insertions(+), 3 deletions(-) + hw/core/qdev-prop-internal.h | 2 ++ + hw/core/qdev-properties-system.c | 45 +++++++++++++++++++++++++++++ + hw/core/qdev-properties.c | 4 +-- + include/hw/block/block.h | 7 +++-- + include/hw/qdev-properties-system.h | 8 +++++ + 5 files changed, 61 insertions(+), 5 deletions(-) -diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c -index 709f9e0f9d..2601091f8f 100644 ---- a/hw/core/qdev-properties.c -+++ b/hw/core/qdev-properties.c -@@ -628,6 +628,51 @@ const PropertyInfo qdev_prop_blockdev_on_error = { - .set_default_value = set_default_value_enum, +diff --git a/hw/core/qdev-prop-internal.h b/hw/core/qdev-prop-internal.h +index d7b77844fe..68b1b9d10c 100644 +--- a/hw/core/qdev-prop-internal.h ++++ b/hw/core/qdev-prop-internal.h +@@ -22,6 +22,8 @@ void qdev_propinfo_set_default_value_uint(ObjectProperty *op, + + void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp); ++void qdev_propinfo_get_int64(Object *obj, Visitor *v, const char *name, ++ void *opaque, Error **errp); + void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp); + +diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c +index 6a6ff03be7..b93ed9b4dd 100644 +--- a/hw/core/qdev-properties-system.c ++++ b/hw/core/qdev-properties-system.c +@@ -612,6 +612,51 @@ const PropertyInfo qdev_prop_blockdev_on_error = { + .set_default_value = qdev_propinfo_set_default_value_enum, }; +static void set_retry_time(Object *obj, Visitor *v, const char *name, @@ -26,7 +42,7 @@ index 709f9e0f9d..2601091f8f 100644 +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; -+ int64_t value, *ptr = qdev_get_prop_ptr(dev, prop); ++ int64_t value, *ptr = object_field_prop_ptr(obj, prop); + Error *local_err = NULL; + + if (dev->realized) { @@ -53,27 +69,49 @@ index 709f9e0f9d..2601091f8f 100644 +const PropertyInfo qdev_prop_blockdev_retry_interval = { + .name = "BlockdevRetryInterval", + .description = "Interval for retry error handling policy", -+ .get = get_int64, ++ .get = qdev_propinfo_get_int64, + .set = set_retry_time, -+ .set_default_value = set_default_value_int, ++ .set_default_value = qdev_propinfo_set_default_value_int, +}; + +const PropertyInfo qdev_prop_blockdev_retry_timeout = { + .name = "BlockdevRetryTimeout", + .description = "Timeout for retry error handling policy", -+ .get = get_int64, ++ .get = qdev_propinfo_get_int64, + .set = set_retry_time, -+ .set_default_value = set_default_value_int, ++ .set_default_value = qdev_propinfo_set_default_value_int, +}; + /* --- BIOS CHS translation */ QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int)); +diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c +index c34aac6ebc..2d5f662663 100644 +--- a/hw/core/qdev-properties.c ++++ b/hw/core/qdev-properties.c +@@ -396,7 +396,7 @@ static void set_uint64(Object *obj, Visitor *v, const char *name, + visit_type_uint64(v, name, ptr, errp); + } + +-static void get_int64(Object *obj, Visitor *v, const char *name, ++void qdev_propinfo_get_int64(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) + { + Property *prop = opaque; +@@ -423,7 +423,7 @@ const PropertyInfo qdev_prop_uint64 = { + + const PropertyInfo qdev_prop_int64 = { + .name = "int64", +- .get = get_int64, ++ .get = qdev_propinfo_get_int64, + .set = set_int64, + .set_default_value = qdev_propinfo_set_default_value_int, + }; diff --git a/include/hw/block/block.h b/include/hw/block/block.h -index d12603aabd..c5276fec0d 100644 +index 24fb7d77af..282929e8f0 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h -@@ -74,9 +74,10 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) +@@ -82,9 +82,10 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) BLOCKDEV_ON_ERROR_AUTO), \ DEFINE_PROP_BLOCKDEV_ON_ERROR("werror", _state, _conf.werror, \ BLOCKDEV_ON_ERROR_AUTO), \ @@ -87,12 +125,12 @@ index d12603aabd..c5276fec0d 100644 /* Backend access helpers */ -diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h -index a22a532eb8..d7742be3bc 100644 ---- a/include/hw/qdev-properties.h -+++ b/include/hw/qdev-properties.h -@@ -26,6 +26,8 @@ extern const PropertyInfo qdev_prop_on_off_auto; - extern const PropertyInfo qdev_prop_compress_method; +diff --git a/include/hw/qdev-properties-system.h b/include/hw/qdev-properties-system.h +index 0ac327ae60..906a027676 100644 +--- a/include/hw/qdev-properties-system.h ++++ b/include/hw/qdev-properties-system.h +@@ -9,6 +9,8 @@ extern const PropertyInfo qdev_prop_reserved_region; + extern const PropertyInfo qdev_prop_multifd_compression; extern const PropertyInfo qdev_prop_losttickpolicy; extern const PropertyInfo qdev_prop_blockdev_on_error; +extern const PropertyInfo qdev_prop_blockdev_retry_interval; @@ -100,7 +138,7 @@ index a22a532eb8..d7742be3bc 100644 extern const PropertyInfo qdev_prop_bios_chs_trans; extern const PropertyInfo qdev_prop_fdc_drive_type; extern const PropertyInfo qdev_prop_drive; -@@ -215,6 +217,12 @@ extern const PropertyInfo qdev_prop_pcie_link_width; +@@ -47,6 +49,12 @@ extern const PropertyInfo qdev_prop_pcie_link_width; #define DEFINE_PROP_BLOCKDEV_ON_ERROR(_n, _s, _f, _d) \ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_blockdev_on_error, \ BlockdevOnError) diff --git a/block-Avoid-memleak-on-qcow2-image-info-failure.patch b/block-Avoid-memleak-on-qcow2-image-info-failure.patch deleted file mode 100644 index 13917f5b61ed267f584feac9041450e6fe9bbca6..0000000000000000000000000000000000000000 --- a/block-Avoid-memleak-on-qcow2-image-info-failure.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 6a39af8880c18fb3bcbfb715aef909c64286524e Mon Sep 17 00:00:00 2001 -From: Eric Blake -Date: Fri, 20 Mar 2020 13:36:20 -0500 -Subject: [PATCH 04/14] block: Avoid memleak on qcow2 image info failure - -If we fail to get bitmap info, we must not leak the encryption info. - -Fixes: b8968c875f403 -Fixes: Coverity CID 1421894 -Signed-off-by: Eric Blake -Message-Id: <20200320183620.1112123-1-eblake@redhat.com> -Reviewed-by: Vladimir Sementsov-Ogievskiy -Reviewed-by: Andrey Shinkevich -Tested-by: Andrey Shinkevich -Signed-off-by: Max Reitz -Signed-off-by: Peng Liang ---- - block/qcow2.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/block/qcow2.c b/block/qcow2.c -index 27c54b9905aa..0f4b0940d457 100644 ---- a/block/qcow2.c -+++ b/block/qcow2.c -@@ -4588,6 +4588,7 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs, - if (local_err) { - error_propagate(errp, local_err); - qapi_free_ImageInfoSpecific(spec_info); -+ qapi_free_QCryptoBlockInfo(encrypt_info); - return NULL; - } - *spec_info->u.qcow2.data = (ImageInfoSpecificQCow2){ --- -2.26.2 - diff --git a/block-Call-attention-to-truncation-of-long-NBD-expor.patch b/block-Call-attention-to-truncation-of-long-NBD-expor.patch deleted file mode 100644 index 91745acf1dd03b8186fd70e5a538014727c7099a..0000000000000000000000000000000000000000 --- a/block-Call-attention-to-truncation-of-long-NBD-expor.patch +++ /dev/null @@ -1,105 +0,0 @@ -From e94c1625c0f8155740b1bb7b2c749df759e04526 Mon Sep 17 00:00:00 2001 -From: Eric Blake -Date: Wed, 10 Jun 2020 18:32:02 -0400 -Subject: [PATCH] block: Call attention to truncation of long NBD exports - -RH-Author: Eric Blake -Message-id: <20200610183202.3780750-3-eblake@redhat.com> -Patchwork-id: 97495 -O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 2/2] block: Call attention to truncation of long NBD exports -Bugzilla: 1845384 -RH-Acked-by: Sergio Lopez Pascual -RH-Acked-by: Max Reitz -RH-Acked-by: Stefan Hajnoczi - -Commit 93676c88 relaxed our NBD client code to request export names up -to the NBD protocol maximum of 4096 bytes without NUL terminator, even -though the block layer can't store anything longer than 4096 bytes -including NUL terminator for display to the user. Since this means -there are some export names where we have to truncate things, we can -at least try to make the truncation a bit more obvious for the user. -Note that in spite of the truncated display name, we can still -communicate with an NBD server using such a long export name; this was -deemed nicer than refusing to even connect to such a server (since the -server may not be under our control, and since determining our actual -length limits gets tricky when nbd://host:port/export and -nbd+unix:///export?socket=/path are themselves variable-length -expansions beyond the export name but count towards the block layer -name length). - -Reported-by: Xueqiang Wei -Fixes: https://bugzilla.redhat.com/1843684 -Signed-off-by: Eric Blake -Reviewed-by: Vladimir Sementsov-Ogievskiy -Message-Id: <20200610163741.3745251-3-eblake@redhat.com> -(cherry picked from commit 5c86bdf1208916ece0b87e1151c9b48ee54faa3e) -Signed-off-by: Eric Blake -Signed-off-by: Eduardo Lima (Etrunko) ---- - block.c | 7 +++++-- - block/nbd.c | 21 +++++++++++++-------- - 2 files changed, 18 insertions(+), 10 deletions(-) - -diff --git a/block.c b/block.c -index 38880eabf8..ba36b53a00 100644 ---- a/block.c -+++ b/block.c -@@ -6444,8 +6444,11 @@ void bdrv_refresh_filename(BlockDriverState *bs) - pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename); - } else { - QString *json = qobject_to_json(QOBJECT(bs->full_open_options)); -- snprintf(bs->filename, sizeof(bs->filename), "json:%s", -- qstring_get_str(json)); -+ if (snprintf(bs->filename, sizeof(bs->filename), "json:%s", -+ qstring_get_str(json)) >= sizeof(bs->filename)) { -+ /* Give user a hint if we truncated things. */ -+ strcpy(bs->filename + sizeof(bs->filename) - 4, "..."); -+ } - qobject_unref(json); - } - } -diff --git a/block/nbd.c b/block/nbd.c -index 3977b1efc7..63cdd051ab 100644 ---- a/block/nbd.c -+++ b/block/nbd.c -@@ -1714,6 +1714,7 @@ static void nbd_refresh_filename(BlockDriverState *bs) - { - BDRVNBDState *s = bs->opaque; - const char *host = NULL, *port = NULL, *path = NULL; -+ size_t len = 0; - - if (s->saddr->type == SOCKET_ADDRESS_TYPE_INET) { - const InetSocketAddress *inet = &s->saddr->u.inet; -@@ -1726,17 +1727,21 @@ static void nbd_refresh_filename(BlockDriverState *bs) - } /* else can't represent as pseudo-filename */ - - if (path && s->export) { -- snprintf(bs->exact_filename, sizeof(bs->exact_filename), -- "nbd+unix:///%s?socket=%s", s->export, path); -+ len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), -+ "nbd+unix:///%s?socket=%s", s->export, path); - } else if (path && !s->export) { -- snprintf(bs->exact_filename, sizeof(bs->exact_filename), -- "nbd+unix://?socket=%s", path); -+ len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), -+ "nbd+unix://?socket=%s", path); - } else if (host && s->export) { -- snprintf(bs->exact_filename, sizeof(bs->exact_filename), -- "nbd://%s:%s/%s", host, port, s->export); -+ len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), -+ "nbd://%s:%s/%s", host, port, s->export); - } else if (host && !s->export) { -- snprintf(bs->exact_filename, sizeof(bs->exact_filename), -- "nbd://%s:%s", host, port); -+ len = snprintf(bs->exact_filename, sizeof(bs->exact_filename), -+ "nbd://%s:%s", host, port); -+ } -+ if (len > sizeof(bs->exact_filename)) { -+ /* Name is too long to represent exactly, so leave it empty. */ -+ bs->exact_filename[0] = '\0'; - } - } - --- -2.27.0 - diff --git a/block-Fix-cross-AioContext-blockdev-snapshot.patch b/block-Fix-cross-AioContext-blockdev-snapshot.patch deleted file mode 100644 index a4a4d9dbb4c51b74a8258b6368bd9a9ca88b71c6..0000000000000000000000000000000000000000 --- a/block-Fix-cross-AioContext-blockdev-snapshot.patch +++ /dev/null @@ -1,78 +0,0 @@ -From ec96b9f64c239736003413d70dc3999ad0b8271c Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 10 Mar 2020 12:38:29 +0100 -Subject: [PATCH] block: Fix cross-AioContext blockdev-snapshot - -external_snapshot_prepare() tries to move the overlay to the AioContext -of the backing file (the snapshotted node). However, it's possible that -this doesn't work, but the backing file can instead be moved to the -overlay's AioContext (e.g. opening the backing chain for a mirror -target). - -bdrv_append() already indirectly uses bdrv_attach_node(), which takes -care to move nodes to make sure they use the same AioContext and which -tries both directions. - -So the problem has a simple fix: Just delete the unnecessary extra -bdrv_try_set_aio_context() call in external_snapshot_prepare() and -instead assert in bdrv_append() that both nodes were indeed moved to the -same AioContext. - -Signed-off-by: Kevin Wolf -Message-Id: <20200310113831.27293-6-kwolf@redhat.com> -Tested-by: Peter Krempa -Signed-off-by: Kevin Wolf ---- - block.c | 1 + - blockdev.c | 16 ---------------- - 2 files changed, 1 insertion(+), 16 deletions(-) - -diff --git a/block.c b/block.c -index ba36b53a00..824025f781 100644 ---- a/block.c -+++ b/block.c -@@ -4165,6 +4165,7 @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, - bdrv_ref(from); - - assert(qemu_get_current_aio_context() == qemu_get_aio_context()); -+ assert(bdrv_get_aio_context(from) == bdrv_get_aio_context(to)); - bdrv_drained_begin(from); - - /* Put all parents into @list and calculate their cumulative permissions */ -diff --git a/blockdev.c b/blockdev.c -index 79112be2e6..d1a3b6a630 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -1578,8 +1578,6 @@ static void external_snapshot_prepare(BlkActionState *common, - DO_UPCAST(ExternalSnapshotState, common, common); - TransactionAction *action = common->action; - AioContext *aio_context; -- AioContext *old_context; -- int ret; - - /* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar - * purpose but a different set of parameters */ -@@ -1719,20 +1717,6 @@ static void external_snapshot_prepare(BlkActionState *common, - goto out; - } - -- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */ -- old_context = bdrv_get_aio_context(state->new_bs); -- aio_context_release(aio_context); -- aio_context_acquire(old_context); -- -- ret = bdrv_try_set_aio_context(state->new_bs, aio_context, errp); -- -- aio_context_release(old_context); -- aio_context_acquire(aio_context); -- -- if (ret < 0) { -- goto out; -- } -- - /* This removes our old bs and adds the new bs. This is an operation that - * can fail, so we need to do it in .prepare; undoing it for abort is - * always possible. */ --- -2.27.0 - diff --git a/block-Make-wait-mark-serialising-requests-public.patch b/block-Make-wait-mark-serialising-requests-public.patch deleted file mode 100644 index 162463c7769093014562846d9d7c0da4e131b5e3..0000000000000000000000000000000000000000 --- a/block-Make-wait-mark-serialising-requests-public.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 590cff8230749794ba09b38f3ea4eb6b0f2f73b5 Mon Sep 17 00:00:00 2001 -From: Max Reitz -Date: Fri, 1 Nov 2019 16:25:08 +0100 -Subject: [PATCH] block: Make wait/mark serialising requests public - -Make both bdrv_mark_request_serialising() and -bdrv_wait_serialising_requests() public so they can be used from block -drivers. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Max Reitz -Message-id: 20191101152510.11719-2-mreitz@redhat.com -Signed-off-by: Max Reitz -(cherry picked from commit 304d9d7f034ff7f5e1e66a65b7f720f63a72c57e) - Conflicts: - block/io.c -*drop context dependency on 1acc3466a2 -Signed-off-by: Michael Roth ---- - block/io.c | 24 ++++++++++++------------ - include/block/block_int.h | 3 +++ - 2 files changed, 15 insertions(+), 12 deletions(-) - -diff --git a/block/io.c b/block/io.c -index 07d2d825c3..d4ceaaa2ce 100644 ---- a/block/io.c -+++ b/block/io.c -@@ -694,7 +694,7 @@ static void tracked_request_begin(BdrvTrackedRequest *req, - qemu_co_mutex_unlock(&bs->reqs_lock); - } - --static void mark_request_serialising(BdrvTrackedRequest *req, uint64_t align) -+void bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align) - { - int64_t overlap_offset = req->offset & ~(align - 1); - uint64_t overlap_bytes = ROUND_UP(req->offset + req->bytes, align) -@@ -784,7 +784,7 @@ void bdrv_dec_in_flight(BlockDriverState *bs) - bdrv_wakeup(bs); - } - --static bool coroutine_fn wait_serialising_requests(BdrvTrackedRequest *self) -+bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self) - { - BlockDriverState *bs = self->bs; - BdrvTrackedRequest *req; -@@ -1340,14 +1340,14 @@ static int coroutine_fn bdrv_aligned_preadv(BdrvChild *child, - * with each other for the same cluster. For example, in copy-on-read - * it ensures that the CoR read and write operations are atomic and - * guest writes cannot interleave between them. */ -- mark_request_serialising(req, bdrv_get_cluster_size(bs)); -+ bdrv_mark_request_serialising(req, bdrv_get_cluster_size(bs)); - } - - /* BDRV_REQ_SERIALISING is only for write operation */ - assert(!(flags & BDRV_REQ_SERIALISING)); - - if (!(flags & BDRV_REQ_NO_SERIALISING)) { -- wait_serialising_requests(req); -+ bdrv_wait_serialising_requests(req); - } - - if (flags & BDRV_REQ_COPY_ON_READ) { -@@ -1736,10 +1736,10 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes, - assert(!(flags & ~BDRV_REQ_MASK)); - - if (flags & BDRV_REQ_SERIALISING) { -- mark_request_serialising(req, bdrv_get_cluster_size(bs)); -+ bdrv_mark_request_serialising(req, bdrv_get_cluster_size(bs)); - } - -- waited = wait_serialising_requests(req); -+ waited = bdrv_wait_serialising_requests(req); - - assert(!waited || !req->serialising || - is_request_serialising_and_aligned(req)); -@@ -1905,8 +1905,8 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, - - padding = bdrv_init_padding(bs, offset, bytes, &pad); - if (padding) { -- mark_request_serialising(req, align); -- wait_serialising_requests(req); -+ bdrv_mark_request_serialising(req, align); -+ bdrv_wait_serialising_requests(req); - - bdrv_padding_rmw_read(child, req, &pad, true); - -@@ -1993,8 +1993,8 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child, - } - - if (bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad)) { -- mark_request_serialising(&req, align); -- wait_serialising_requests(&req); -+ bdrv_mark_request_serialising(&req, align); -+ bdrv_wait_serialising_requests(&req); - bdrv_padding_rmw_read(child, &req, &pad, false); - } - -@@ -3078,7 +3078,7 @@ static int coroutine_fn bdrv_co_copy_range_internal( - /* BDRV_REQ_SERIALISING is only for write operation */ - assert(!(read_flags & BDRV_REQ_SERIALISING)); - if (!(read_flags & BDRV_REQ_NO_SERIALISING)) { -- wait_serialising_requests(&req); -+ bdrv_wait_serialising_requests(&req); - } - - ret = src->bs->drv->bdrv_co_copy_range_from(src->bs, -@@ -3205,7 +3205,7 @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, - * new area, we need to make sure that no write requests are made to it - * concurrently or they might be overwritten by preallocation. */ - if (new_bytes) { -- mark_request_serialising(&req, 1); -+ bdrv_mark_request_serialising(&req, 1); - } - if (bs->read_only) { - error_setg(errp, "Image is read-only"); -diff --git a/include/block/block_int.h b/include/block/block_int.h -index 3aa1e832a8..4465b02242 100644 ---- a/include/block/block_int.h -+++ b/include/block/block_int.h -@@ -962,6 +962,9 @@ extern unsigned int bdrv_drain_all_count; - void bdrv_apply_subtree_drain(BdrvChild *child, BlockDriverState *new_parent); - void bdrv_unapply_subtree_drain(BdrvChild *child, BlockDriverState *old_parent); - -+bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self); -+void bdrv_mark_request_serialising(BdrvTrackedRequest *req, uint64_t align); -+ - int get_tmp_filename(char *filename, int size); - BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size, - const char *filename); --- -2.23.0 diff --git a/block-Remove-unused-include.patch b/block-Remove-unused-include.patch deleted file mode 100644 index f643ebc66f0f631e949412b706c3210e9d3aead1..0000000000000000000000000000000000000000 --- a/block-Remove-unused-include.patch +++ /dev/null @@ -1,31 +0,0 @@ -From b353d059bddf4b211c2560e7c123f874ed5c8cf6 Mon Sep 17 00:00:00 2001 -From: AlexChen -Date: Wed, 21 Oct 2020 17:12:52 +0800 -Subject: [PATCH] block: Remove unused include - -The "qemu-common.h" include is not used, remove it. - -Reported-by: Euler Robot -Signed-off-by: AlexChen -Message-Id: <5F8FFB94.3030209@huawei.com> -Signed-off-by: Max Reitz -(cherry-picked from commit 3d86af858e) ---- - block/dmg-lzfse.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/block/dmg-lzfse.c b/block/dmg-lzfse.c -index 19d25bc646..6798cf4fbf 100644 ---- a/block/dmg-lzfse.c -+++ b/block/dmg-lzfse.c -@@ -22,7 +22,6 @@ - * THE SOFTWARE. - */ - #include "qemu/osdep.h" --#include "qemu-common.h" - #include "dmg.h" - #include - --- -2.27.0 - diff --git a/block-backend-Add-device-specific-retry-callback.patch b/block-backend-Add-device-specific-retry-callback.patch index d50d6bc99cdd87e74838b3b2b61a2eabd1df3ed1..04465292d66e8652846ffb8683a6c19c1a2ba701 100644 --- a/block-backend-Add-device-specific-retry-callback.patch +++ b/block-backend-Add-device-specific-retry-callback.patch @@ -1,7 +1,7 @@ -From f74edc7c8c85874691daf8801c159874ef45aae0 Mon Sep 17 00:00:00 2001 +From dfda8c57de71f2f10b57cf21b1e36f18d4ed37a3 Mon Sep 17 00:00:00 2001 From: Jiahui Cen Date: Thu, 21 Jan 2021 15:46:47 +0800 -Subject: [PATCH] block-backend: Add device specific retry callback +Subject: [PATCH 3/7] block-backend: Add device specific retry callback Add retry_request_cb in BlockDevOps to do device specific retry action. Backend's timer would be registered only when the backend is set 'retry' @@ -9,16 +9,17 @@ on errors and the device supports retry action. Signed-off-by: Jiahui Cen Signed-off-by: Ying Fang +Signed-off-by: Alex Chen --- block/block-backend.c | 8 ++++++++ include/sysemu/block-backend.h | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/block/block-backend.c b/block/block-backend.c -index a9a43b1440..b8f535a5fd 100644 +index 257cd775c0..24003adf0b 100644 --- a/block/block-backend.c +++ b/block/block-backend.c -@@ -958,6 +958,14 @@ void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, +@@ -1018,6 +1018,14 @@ void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, blk->dev_ops = ops; blk->dev_opaque = opaque; @@ -34,13 +35,13 @@ index a9a43b1440..b8f535a5fd 100644 if (blk->quiesce_counter && ops->drained_begin) { ops->drained_begin(opaque); diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h -index 733c4957eb..b58dc6bde8 100644 +index e5e1524f06..a7a13d47de 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h -@@ -66,6 +66,10 @@ typedef struct BlockDevOps { - * Runs when the backend's last drain request ends. +@@ -70,6 +70,10 @@ typedef struct BlockDevOps { + * Is the device still busy? */ - void (*drained_end)(void *opaque); + bool (*drained_poll)(void *opaque); + /* + * Runs when retrying failed requests. + */ diff --git a/block-backend-Add-timeout-support-for-retry.patch b/block-backend-Add-timeout-support-for-retry.patch index ac1bc66230f533b542e0f0a31d0035f868f3c06b..a3b79e2e9aaea6752caec1f652acd9957a0574bd 100644 --- a/block-backend-Add-timeout-support-for-retry.patch +++ b/block-backend-Add-timeout-support-for-retry.patch @@ -1,7 +1,7 @@ -From c58269c64af18bc2a22bbef8b92e489214272429 Mon Sep 17 00:00:00 2001 +From 953590f4854d75e6051237f668c9fb393235f471 Mon Sep 17 00:00:00 2001 From: Jiahui Cen Date: Thu, 21 Jan 2021 15:46:49 +0800 -Subject: [PATCH] block-backend: Add timeout support for retry +Subject: [PATCH 5/7] block-backend: Add timeout support for retry Retry should only be triggered when timeout is not reached, so let's check timeout before retry. Device should also reset retry_start_time after @@ -9,16 +9,17 @@ successful retry. Signed-off-by: Jiahui Cen Signed-off-by: Ying Fang +Signed-off-by: Alex Chen --- block/block-backend.c | 25 ++++++++++++++++++++++++- include/sysemu/block-backend.h | 1 + 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/block/block-backend.c b/block/block-backend.c -index 11f8ff4301..0fe99ffe52 100644 +index 5a016d32fa..37e21c473e 100644 --- a/block/block-backend.c +++ b/block/block-backend.c -@@ -1633,6 +1633,29 @@ void blk_drain_all(void) +@@ -1766,6 +1766,29 @@ void blk_drain_all(void) bdrv_drain_all_end(); } @@ -48,7 +49,7 @@ index 11f8ff4301..0fe99ffe52 100644 void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error, BlockdevOnError on_write_error) { -@@ -1661,7 +1684,7 @@ BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read, +@@ -1794,7 +1817,7 @@ BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read, case BLOCKDEV_ON_ERROR_IGNORE: return BLOCK_ERROR_ACTION_IGNORE; case BLOCKDEV_ON_ERROR_RETRY: @@ -58,10 +59,10 @@ index 11f8ff4301..0fe99ffe52 100644 case BLOCKDEV_ON_ERROR_AUTO: default: diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h -index b58dc6bde8..58dde446ca 100644 +index a7a13d47de..56a403883d 100644 --- a/include/sysemu/block-backend.h +++ b/include/sysemu/block-backend.h -@@ -184,6 +184,7 @@ void blk_inc_in_flight(BlockBackend *blk); +@@ -198,6 +198,7 @@ void blk_inc_in_flight(BlockBackend *blk); void blk_dec_in_flight(BlockBackend *blk); void blk_drain(BlockBackend *blk); void blk_drain_all(void); diff --git a/block-backend-Enable-retry-action-on-errors.patch b/block-backend-Enable-retry-action-on-errors.patch index 241f945cff9edae0f464177226b2b3ef33d98ca0..ee56c455009a3946459efa1313b43452efcd3262 100644 --- a/block-backend-Enable-retry-action-on-errors.patch +++ b/block-backend-Enable-retry-action-on-errors.patch @@ -1,22 +1,23 @@ -From 8df36cddd1e5e2b3c3598c83a70e8cbb81c26cec Mon Sep 17 00:00:00 2001 +From 2e1c75e5a0339d2bf417e5a4437d8e627a303286 Mon Sep 17 00:00:00 2001 From: Jiahui Cen Date: Thu, 21 Jan 2021 15:46:48 +0800 -Subject: [PATCH] block-backend: Enable retry action on errors +Subject: [PATCH 4/7] block-backend: Enable retry action on errors Enable retry action when backend's retry timer is available. It would trigger the timer to do device specific retry action. Signed-off-by: Jiahui Cen Signed-off-by: Ying Fang +Signed-off-by: Alex Chen --- block/block-backend.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/block/block-backend.c b/block/block-backend.c -index b8f535a5fd..11f8ff4301 100644 +index 24003adf0b..5a016d32fa 100644 --- a/block/block-backend.c +++ b/block/block-backend.c -@@ -1660,6 +1660,9 @@ BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read, +@@ -1793,6 +1793,9 @@ BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read, return BLOCK_ERROR_ACTION_REPORT; case BLOCKDEV_ON_ERROR_IGNORE: return BLOCK_ERROR_ACTION_IGNORE; @@ -26,7 +27,7 @@ index b8f535a5fd..11f8ff4301 100644 case BLOCKDEV_ON_ERROR_AUTO: default: abort(); -@@ -1707,6 +1710,10 @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action, +@@ -1840,6 +1843,10 @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action, qemu_system_vmstop_request_prepare(); send_qmp_error_event(blk, action, is_read, error); qemu_system_vmstop_request(RUN_STATE_IO_ERROR); diff --git a/block-backend-Introduce-retry-timer.patch b/block-backend-Introduce-retry-timer.patch index e45aacc149860baf2951e34a5b964cae7cc9aea3..5a0bc334c48ee597ca35b3da2771c258e9ee26e8 100644 --- a/block-backend-Introduce-retry-timer.patch +++ b/block-backend-Introduce-retry-timer.patch @@ -1,21 +1,22 @@ -From 805c2e121e1ad612f63bafec458284554e76d034 Mon Sep 17 00:00:00 2001 +From 4dc180e87fb641f64fce7be3a0807488d0cc0a51 Mon Sep 17 00:00:00 2001 From: Jiahui Cen Date: Thu, 21 Jan 2021 15:46:46 +0800 -Subject: [PATCH] block-backend: Introduce retry timer +Subject: [PATCH 2/7] block-backend: Introduce retry timer Add a timer to regularly trigger retry on errors. Signed-off-by: Jiahui Cen Signed-off-by: Ying Fang +Signed-off-by: Alex Chen --- block/block-backend.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/block/block-backend.c b/block/block-backend.c -index 0056b526b8..a9a43b1440 100644 +index 12ef80ea17..257cd775c0 100644 --- a/block/block-backend.c +++ b/block/block-backend.c -@@ -31,6 +31,9 @@ +@@ -35,6 +35,9 @@ static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb); @@ -25,7 +26,7 @@ index 0056b526b8..a9a43b1440 100644 typedef struct BlockBackendAioNotifier { void (*attached_aio_context)(AioContext *new_context, void *opaque); void (*detach_aio_context)(void *opaque); -@@ -88,6 +91,15 @@ struct BlockBackend { +@@ -95,6 +98,15 @@ struct BlockBackend { * Accessed with atomic ops. */ unsigned int in_flight; @@ -41,7 +42,7 @@ index 0056b526b8..a9a43b1440 100644 }; typedef struct BlockBackendAIOCB { -@@ -337,6 +349,11 @@ BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm) +@@ -353,6 +365,11 @@ BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm) blk->on_read_error = BLOCKDEV_ON_ERROR_REPORT; blk->on_write_error = BLOCKDEV_ON_ERROR_ENOSPC; @@ -52,8 +53,8 @@ index 0056b526b8..a9a43b1440 100644 + block_acct_init(&blk->stats); - notifier_list_init(&blk->remove_bs_notifiers); -@@ -423,6 +440,10 @@ static void blk_delete(BlockBackend *blk) + qemu_co_queue_init(&blk->queued_requests); +@@ -471,6 +488,10 @@ static void blk_delete(BlockBackend *blk) QTAILQ_REMOVE(&block_backends, blk, link); drive_info_del(blk->legacy_dinfo); block_acct_cleanup(&blk->stats); diff --git a/block-backend-Stop-retrying-when-draining.patch b/block-backend-Stop-retrying-when-draining.patch index 13f3ad64d1c2d2db02d830ca67ee3f90e893e46a..baf5c6c35333786da98e82334cf8b84eb59eaa38 100644 --- a/block-backend-Stop-retrying-when-draining.patch +++ b/block-backend-Stop-retrying-when-draining.patch @@ -1,7 +1,7 @@ -From da64af4b1e92c345296d937e66136f86027d1ca2 Mon Sep 17 00:00:00 2001 +From 06db37983cfd20d7e92001ac3cb06867a281f1c9 Mon Sep 17 00:00:00 2001 From: Jiahui Cen Date: Thu, 25 Feb 2021 18:03:57 +0800 -Subject: [PATCH] block-backend: Stop retrying when draining +Subject: [PATCH 8/9] block-backend: Stop retrying when draining Retrying failed requests when draining would make the draining hung. So it is better not to trigger the retry timer when draining. And after the @@ -9,15 +9,16 @@ virtual devices go back to work, they would retry those queued requests. Signed-off-by: Jiahui Cen Signed-off-by: Ying Fang +Signed-off-by: Alex Chen --- block/block-backend.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c -index 2d812e2254..f6c918f1d9 100644 +index d3d90a95a5..49d236b2a4 100644 --- a/block/block-backend.c +++ b/block/block-backend.c -@@ -1741,9 +1741,11 @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action, +@@ -1874,9 +1874,11 @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action, send_qmp_error_event(blk, action, is_read, error); qemu_system_vmstop_request(RUN_STATE_IO_ERROR); } else if (action == BLOCK_ERROR_ACTION_RETRY) { diff --git a/block-backup-Add-mirror-sync-mode-bitmap.patch b/block-backup-Add-mirror-sync-mode-bitmap.patch deleted file mode 100644 index fb111206baa228ef558d0a567f7d88421a66ad84..0000000000000000000000000000000000000000 --- a/block-backup-Add-mirror-sync-mode-bitmap.patch +++ /dev/null @@ -1,252 +0,0 @@ -From e0a0150e671e8129f11aa3df907e444e91711f53 Mon Sep 17 00:00:00 2001 -From: John Snow -Date: Mon, 29 Jul 2019 16:35:52 -0400 -Subject: [PATCH] block/backup: Add mirror sync mode 'bitmap' - -We don't need or want a new sync mode for simple differences in -semantics. Create a new mode simply named "BITMAP" that is designed to -make use of the new Bitmap Sync Mode field. - -Because the only bitmap sync mode is 'on-success', this adds no new -functionality to the backup job (yet). The old incremental backup mode -is maintained as a syntactic sugar for sync=bitmap, mode=on-success. - -Add all of the plumbing necessary to support this new instruction. - -Signed-off-by: John Snow -Reviewed-by: Max Reitz -Message-id: 20190709232550.10724-6-jsnow@redhat.com -Signed-off-by: John Snow ---- - block/backup.c | 20 ++++++++++++-------- - block/mirror.c | 6 ++++-- - block/replication.c | 2 +- - blockdev.c | 25 +++++++++++++++++++++++-- - include/block/block_int.h | 4 +++- - qapi/block-core.json | 21 +++++++++++++++------ - 6 files changed, 58 insertions(+), 20 deletions(-) - -diff --git a/block/backup.c b/block/backup.c -index 88354dcb32..e37eda80cd 100644 ---- a/block/backup.c -+++ b/block/backup.c -@@ -38,9 +38,9 @@ typedef struct CowRequest { - typedef struct BackupBlockJob { - BlockJob common; - BlockBackend *target; -- /* bitmap for sync=incremental */ - BdrvDirtyBitmap *sync_bitmap; - MirrorSyncMode sync_mode; -+ BitmapSyncMode bitmap_mode; - BlockdevOnError on_source_error; - BlockdevOnError on_target_error; - CoRwlock flush_rwlock; -@@ -461,7 +461,7 @@ static int coroutine_fn backup_run(Job *job, Error **errp) - - job_progress_set_remaining(job, s->len); - -- if (s->sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) { -+ if (s->sync_mode == MIRROR_SYNC_MODE_BITMAP) { - backup_incremental_init_copy_bitmap(s); - } else { - hbitmap_set(s->copy_bitmap, 0, s->len); -@@ -545,6 +545,7 @@ static int64_t backup_calculate_cluster_size(BlockDriverState *target, - BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, - BlockDriverState *target, int64_t speed, - MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap, -+ BitmapSyncMode bitmap_mode, - bool compress, - BlockdevOnError on_source_error, - BlockdevOnError on_target_error, -@@ -592,10 +593,13 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, - return NULL; - } - -- if (sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) { -+ /* QMP interface should have handled translating this to bitmap mode */ -+ assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL); -+ -+ if (sync_mode == MIRROR_SYNC_MODE_BITMAP) { - if (!sync_bitmap) { - error_setg(errp, "must provide a valid bitmap name for " -- "\"incremental\" sync mode"); -+ "'%s' sync mode", MirrorSyncMode_str(sync_mode)); - return NULL; - } - -@@ -605,8 +609,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, - } - } else if (sync_bitmap) { - error_setg(errp, -- "a sync_bitmap was provided to backup_run, " -- "but received an incompatible sync_mode (%s)", -+ "a bitmap was given to backup_job_create, " -+ "but it received an incompatible sync_mode (%s)", - MirrorSyncMode_str(sync_mode)); - return NULL; - } -@@ -648,8 +652,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, - job->on_source_error = on_source_error; - job->on_target_error = on_target_error; - job->sync_mode = sync_mode; -- job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ? -- sync_bitmap : NULL; -+ job->sync_bitmap = sync_bitmap; -+ job->bitmap_mode = bitmap_mode; - job->compress = compress; - - /* Detect image-fleecing (and similar) schemes */ -diff --git a/block/mirror.c b/block/mirror.c -index abcf60a961..ccae49a28e 100644 ---- a/block/mirror.c -+++ b/block/mirror.c -@@ -1770,8 +1770,10 @@ void mirror_start(const char *job_id, BlockDriverState *bs, - bool is_none_mode; - BlockDriverState *base; - -- if (mode == MIRROR_SYNC_MODE_INCREMENTAL) { -- error_setg(errp, "Sync mode 'incremental' not supported"); -+ if ((mode == MIRROR_SYNC_MODE_INCREMENTAL) || -+ (mode == MIRROR_SYNC_MODE_BITMAP)) { -+ error_setg(errp, "Sync mode '%s' not supported", -+ MirrorSyncMode_str(mode)); - return; - } - is_none_mode = mode == MIRROR_SYNC_MODE_NONE; -diff --git a/block/replication.c b/block/replication.c -index 23b2993d74..936b2f8b5a 100644 ---- a/block/replication.c -+++ b/block/replication.c -@@ -543,7 +543,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, - - s->backup_job = backup_job_create( - NULL, s->secondary_disk->bs, s->hidden_disk->bs, -- 0, MIRROR_SYNC_MODE_NONE, NULL, false, -+ 0, MIRROR_SYNC_MODE_NONE, NULL, 0, false, - BLOCKDEV_ON_ERROR_REPORT, - BLOCKDEV_ON_ERROR_REPORT, JOB_INTERNAL, - backup_job_completed, bs, NULL, &local_err); -diff --git a/blockdev.c b/blockdev.c -index aa15ed1f00..34c8b651e1 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -3508,12 +3508,31 @@ static BlockJob *do_backup_common(BackupCommon *backup, - return NULL; - } - -+ if (backup->sync == MIRROR_SYNC_MODE_INCREMENTAL) { -+ if (backup->has_bitmap_mode && -+ backup->bitmap_mode != BITMAP_SYNC_MODE_ON_SUCCESS) { -+ error_setg(errp, "Bitmap sync mode must be '%s' " -+ "when using sync mode '%s'", -+ BitmapSyncMode_str(BITMAP_SYNC_MODE_ON_SUCCESS), -+ MirrorSyncMode_str(backup->sync)); -+ return NULL; -+ } -+ backup->has_bitmap_mode = true; -+ backup->sync = MIRROR_SYNC_MODE_BITMAP; -+ backup->bitmap_mode = BITMAP_SYNC_MODE_ON_SUCCESS; -+ } -+ - if (backup->has_bitmap) { - bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap); - if (!bmap) { - error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap); - return NULL; - } -+ if (!backup->has_bitmap_mode) { -+ error_setg(errp, "Bitmap sync mode must be given " -+ "when providing a bitmap"); -+ return NULL; -+ } - if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) { - return NULL; - } -@@ -3527,8 +3546,10 @@ static BlockJob *do_backup_common(BackupCommon *backup, - } - - job = backup_job_create(backup->job_id, bs, target_bs, backup->speed, -- backup->sync, bmap, backup->compress, -- backup->on_source_error, backup->on_target_error, -+ backup->sync, bmap, backup->bitmap_mode, -+ backup->compress, -+ backup->on_source_error, -+ backup->on_target_error, - job_flags, NULL, NULL, txn, errp); - return job; - } -diff --git a/include/block/block_int.h b/include/block/block_int.h -index 05ee6b4866..76117a761a 100644 ---- a/include/block/block_int.h -+++ b/include/block/block_int.h -@@ -1152,7 +1152,8 @@ void mirror_start(const char *job_id, BlockDriverState *bs, - * @target: Block device to write to. - * @speed: The maximum speed, in bytes per second, or 0 for unlimited. - * @sync_mode: What parts of the disk image should be copied to the destination. -- * @sync_bitmap: The dirty bitmap if sync_mode is MIRROR_SYNC_MODE_INCREMENTAL. -+ * @sync_bitmap: The dirty bitmap if sync_mode is 'bitmap' or 'incremental' -+ * @bitmap_mode: The bitmap synchronization policy to use. - * @on_source_error: The action to take upon error reading from the source. - * @on_target_error: The action to take upon error writing to the target. - * @creation_flags: Flags that control the behavior of the Job lifetime. -@@ -1168,6 +1169,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, - BlockDriverState *target, int64_t speed, - MirrorSyncMode sync_mode, - BdrvDirtyBitmap *sync_bitmap, -+ BitmapSyncMode bitmap_mode, - bool compress, - BlockdevOnError on_source_error, - BlockdevOnError on_target_error, -diff --git a/qapi/block-core.json b/qapi/block-core.json -index b8d12a4951..97baff3a8c 100644 ---- a/qapi/block-core.json -+++ b/qapi/block-core.json -@@ -1127,12 +1127,15 @@ - # - # @none: only copy data written from now on - # --# @incremental: only copy data described by the dirty bitmap. Since: 2.4 -+# @incremental: only copy data described by the dirty bitmap. (since: 2.4) -+# -+# @bitmap: only copy data described by the dirty bitmap. (since: 4.2) -+# Behavior on completion is determined by the BitmapSyncMode. - # - # Since: 1.3 - ## - { 'enum': 'MirrorSyncMode', -- 'data': ['top', 'full', 'none', 'incremental'] } -+ 'data': ['top', 'full', 'none', 'incremental', 'bitmap'] } - - ## - # @BitmapSyncMode: -@@ -1343,9 +1346,14 @@ - # @speed: the maximum speed, in bytes per second. The default is 0, - # for unlimited. - # --# @bitmap: the name of dirty bitmap if sync is "incremental". --# Must be present if sync is "incremental", must NOT be present --# otherwise. (Since 2.4 (drive-backup), 3.1 (blockdev-backup)) -+# @bitmap: the name of a dirty bitmap if sync is "bitmap" or "incremental". -+# Must be present if sync is "bitmap" or "incremental". -+# Must not be present otherwise. -+# (Since 2.4 (drive-backup), 3.1 (blockdev-backup)) -+# -+# @bitmap-mode: Specifies the type of data the bitmap should contain after -+# the operation concludes. Must be present if sync is "bitmap". -+# Must NOT be present otherwise. (Since 4.2) - # - # @compress: true to compress data, if the target format supports it. - # (default: false) (since 2.8) -@@ -1380,7 +1388,8 @@ - { 'struct': 'BackupCommon', - 'data': { '*job-id': 'str', 'device': 'str', - 'sync': 'MirrorSyncMode', '*speed': 'int', -- '*bitmap': 'str', '*compress': 'bool', -+ '*bitmap': 'str', '*bitmap-mode': 'BitmapSyncMode', -+ '*compress': 'bool', - '*on-source-error': 'BlockdevOnError', - '*on-target-error': 'BlockdevOnError', - '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } } --- -2.27.0 - diff --git a/block-backup-add-never-policy-to-bitmap-sync-mode.patch b/block-backup-add-never-policy-to-bitmap-sync-mode.patch deleted file mode 100644 index e7a3dc356084623f89f89f9421467233e82b7dbb..0000000000000000000000000000000000000000 --- a/block-backup-add-never-policy-to-bitmap-sync-mode.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 98ed0f915cf3335768ed84ee5dfa54f4e99aaf00 Mon Sep 17 00:00:00 2001 -From: John Snow -Date: Mon, 29 Jul 2019 16:35:53 -0400 -Subject: [PATCH] block/backup: add 'never' policy to bitmap sync mode - -This adds a "never" policy for bitmap synchronization. Regardless of if -the job succeeds or fails, we never update the bitmap. This can be used -to perform differential backups, or simply to avoid the job modifying a -bitmap. - -Signed-off-by: John Snow -Reviewed-by: Max Reitz -Message-id: 20190709232550.10724-7-jsnow@redhat.com -Signed-off-by: John Snow ---- - block/backup.c | 7 +++++-- - qapi/block-core.json | 5 ++++- - 2 files changed, 9 insertions(+), 3 deletions(-) - -diff --git a/block/backup.c b/block/backup.c -index e37eda80cd..84a56337ac 100644 ---- a/block/backup.c -+++ b/block/backup.c -@@ -274,8 +274,11 @@ static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret) - BdrvDirtyBitmap *bm; - BlockDriverState *bs = blk_bs(job->common.blk); - -- if (ret < 0) { -- /* Merge the successor back into the parent, delete nothing. */ -+ if (ret < 0 || job->bitmap_mode == BITMAP_SYNC_MODE_NEVER) { -+ /* -+ * Failure, or we don't want to synchronize the bitmap. -+ * Merge the successor back into the parent, delete nothing. -+ */ - bm = bdrv_reclaim_dirty_bitmap(bs, job->sync_bitmap, NULL); - assert(bm); - } else { -diff --git a/qapi/block-core.json b/qapi/block-core.json -index 97baff3a8c..48a0bfab63 100644 ---- a/qapi/block-core.json -+++ b/qapi/block-core.json -@@ -1146,10 +1146,13 @@ - # @on-success: The bitmap is only synced when the operation is successful. - # This is the behavior always used for 'INCREMENTAL' backups. - # -+# @never: The bitmap is never synchronized with the operation, and is -+# treated solely as a read-only manifest of blocks to copy. -+# - # Since: 4.2 - ## - { 'enum': 'BitmapSyncMode', -- 'data': ['on-success'] } -+ 'data': ['on-success', 'never'] } - - ## - # @MirrorCopyMode: --- -2.27.0 - diff --git a/block-backup-deal-with-zero-detection.patch b/block-backup-deal-with-zero-detection.patch deleted file mode 100644 index 9f111e58efff5bb63808d91441f4028bb743fce9..0000000000000000000000000000000000000000 --- a/block-backup-deal-with-zero-detection.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 3cf14b9a7daf0a40eb2af7a86e67cb05f6d2bea6 Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Tue, 30 Jul 2019 19:32:49 +0300 -Subject: [PATCH] block/backup: deal with zero detection - -We have detect_zeroes option, so at least for blockdev-backup user -should define it if zero-detection is needed. For drive-backup leave -detection enabled by default but do it through existing option instead -of open-coding. - -Signed-off-by: Vladimir Sementsov-Ogievskiy -Reviewed-by: John Snow -Reviewed-by: Max Reitz -Message-id: 20190730163251.755248-2-vsementsov@virtuozzo.com -Signed-off-by: John Snow ---- - block/backup.c | 15 ++++++--------- - blockdev.c | 8 ++++---- - 2 files changed, 10 insertions(+), 13 deletions(-) - -diff --git a/block/backup.c b/block/backup.c -index cc19643b47..6023573299 100644 ---- a/block/backup.c -+++ b/block/backup.c -@@ -110,7 +110,10 @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job, - BlockBackend *blk = job->common.blk; - int nbytes; - int read_flags = is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0; -- int write_flags = job->serialize_target_writes ? BDRV_REQ_SERIALISING : 0; -+ int write_flags = -+ (job->serialize_target_writes ? BDRV_REQ_SERIALISING : 0) | -+ (job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0); -+ - - assert(QEMU_IS_ALIGNED(start, job->cluster_size)); - hbitmap_reset(job->copy_bitmap, start, job->cluster_size); -@@ -128,14 +131,8 @@ static int coroutine_fn backup_cow_with_bounce_buffer(BackupBlockJob *job, - goto fail; - } - -- if (buffer_is_zero(*bounce_buffer, nbytes)) { -- ret = blk_co_pwrite_zeroes(job->target, start, -- nbytes, write_flags | BDRV_REQ_MAY_UNMAP); -- } else { -- ret = blk_co_pwrite(job->target, start, -- nbytes, *bounce_buffer, write_flags | -- (job->compress ? BDRV_REQ_WRITE_COMPRESSED : 0)); -- } -+ ret = blk_co_pwrite(job->target, start, nbytes, *bounce_buffer, -+ write_flags); - if (ret < 0) { - trace_backup_do_cow_write_fail(job, start, ret); - if (error_is_read) { -diff --git a/blockdev.c b/blockdev.c -index 0a71a15fa2..94e5aee30b 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -3572,7 +3572,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, - BlockDriverState *source = NULL; - BlockJob *job = NULL; - AioContext *aio_context; -- QDict *options = NULL; -+ QDict *options; - Error *local_err = NULL; - int flags; - int64_t size; -@@ -3645,10 +3645,10 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, - goto out; - } - -+ options = qdict_new(); -+ qdict_put_str(options, "discard", "unmap"); -+ qdict_put_str(options, "detect-zeroes", "unmap"); - if (backup->format) { -- if (!options) { -- options = qdict_new(); -- } - qdict_put_str(options, "driver", backup->format); - } - --- -2.27.0 - diff --git a/block-backup-fix-backup_cow_with_offload-for-last-cl.patch b/block-backup-fix-backup_cow_with_offload-for-last-cl.patch deleted file mode 100644 index 1dfccaca1200b02b9ff0225bf488804f0e7790ae..0000000000000000000000000000000000000000 --- a/block-backup-fix-backup_cow_with_offload-for-last-cl.patch +++ /dev/null @@ -1,35 +0,0 @@ -From adb934c8d2cfd8b920e69712f07a8fb9399fdc2d Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Fri, 20 Sep 2019 17:20:43 +0300 -Subject: [PATCH] block/backup: fix backup_cow_with_offload for last cluster - -We shouldn't try to copy bytes beyond EOF. Fix it. - -Fixes: 9ded4a0114968e -Signed-off-by: Vladimir Sementsov-Ogievskiy -Reviewed-by: Max Reitz -Reviewed-by: John Snow -Message-id: 20190920142056.12778-3-vsementsov@virtuozzo.com -Signed-off-by: Max Reitz -(cherry picked from commit 1048ddf0a32dcdaa952e581bd503d49adad527cc) -Signed-off-by: Michael Roth ---- - block/backup.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/block/backup.c b/block/backup.c -index 8119d3c..55736ea 100644 ---- a/block/backup.c -+++ b/block/backup.c -@@ -169,7 +169,7 @@ static int coroutine_fn backup_cow_with_offload(BackupBlockJob *job, - - assert(QEMU_IS_ALIGNED(job->copy_range_size, job->cluster_size)); - assert(QEMU_IS_ALIGNED(start, job->cluster_size)); -- nbytes = MIN(job->copy_range_size, end - start); -+ nbytes = MIN(job->copy_range_size, MIN(end, job->len) - start); - nr_clusters = DIV_ROUND_UP(nbytes, job->cluster_size); - hbitmap_reset(job->copy_bitmap, start, job->cluster_size * nr_clusters); - ret = blk_co_copy_range(blk, start, job->target, start, nbytes, --- -1.8.3.1 - diff --git a/block-backup-fix-max_transfer-handling-for-copy_rang.patch b/block-backup-fix-max_transfer-handling-for-copy_rang.patch deleted file mode 100644 index 2303b5faf858182f9820d6b3497150d481b4879b..0000000000000000000000000000000000000000 --- a/block-backup-fix-max_transfer-handling-for-copy_rang.patch +++ /dev/null @@ -1,51 +0,0 @@ -From bad8a640a29f16b4d333673577b06880894766e1 Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Fri, 20 Sep 2019 17:20:42 +0300 -Subject: [PATCH] block/backup: fix max_transfer handling for copy_range - -Of course, QEMU_ALIGN_UP is a typo, it should be QEMU_ALIGN_DOWN, as we -are trying to find aligned size which satisfy both source and target. -Also, don't ignore too small max_transfer. In this case seems safer to -disable copy_range. - -Fixes: 9ded4a0114968e -Signed-off-by: Vladimir Sementsov-Ogievskiy -Message-id: 20190920142056.12778-2-vsementsov@virtuozzo.com -Signed-off-by: Max Reitz -(cherry picked from commit 981fb5810aa3f68797ee6e261db338bd78857614) -Signed-off-by: Michael Roth ---- - block/backup.c | 15 +++++++++++---- - 1 file changed, 11 insertions(+), 4 deletions(-) - -diff --git a/block/backup.c b/block/backup.c -index 381659d..8119d3c 100644 ---- a/block/backup.c -+++ b/block/backup.c -@@ -666,12 +666,19 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, - job->cluster_size = cluster_size; - job->copy_bitmap = copy_bitmap; - copy_bitmap = NULL; -- job->use_copy_range = !compress; /* compression isn't supported for it */ - job->copy_range_size = MIN_NON_ZERO(blk_get_max_transfer(job->common.blk), - blk_get_max_transfer(job->target)); -- job->copy_range_size = MAX(job->cluster_size, -- QEMU_ALIGN_UP(job->copy_range_size, -- job->cluster_size)); -+ job->copy_range_size = QEMU_ALIGN_DOWN(job->copy_range_size, -+ job->cluster_size); -+ /* -+ * Set use_copy_range, consider the following: -+ * 1. Compression is not supported for copy_range. -+ * 2. copy_range does not respect max_transfer (it's a TODO), so we factor -+ * that in here. If max_transfer is smaller than the job->cluster_size, -+ * we do not use copy_range (in that case it's zero after aligning down -+ * above). -+ */ -+ job->use_copy_range = !compress && job->copy_range_size > 0; - - /* Required permissions are already taken with target's blk_new() */ - block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL, --- -1.8.3.1 - diff --git a/block-backup-hoist-bitmap-check-into-QMP-interface.patch b/block-backup-hoist-bitmap-check-into-QMP-interface.patch deleted file mode 100644 index 51dc67ccbcd131c09200963de192185c0aa97671..0000000000000000000000000000000000000000 --- a/block-backup-hoist-bitmap-check-into-QMP-interface.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 9cc9e9657aad126502183fa4ceb9b962b55471cb Mon Sep 17 00:00:00 2001 -From: John Snow -Date: Mon, 29 Jul 2019 16:35:55 -0400 -Subject: [PATCH] block/backup: hoist bitmap check into QMP interface - -This is nicer to do in the unified QMP interface that we have now, -because it lets us use the right terminology back at the user. - -Signed-off-by: John Snow -Reviewed-by: Max Reitz -Message-id: 20190716000117.25219-5-jsnow@redhat.com -Signed-off-by: John Snow ---- - block/backup.c | 13 ++++--------- - blockdev.c | 10 ++++++++++ - 2 files changed, 14 insertions(+), 9 deletions(-) - -diff --git a/block/backup.c b/block/backup.c -index 59ac2c0396..cc19643b47 100644 ---- a/block/backup.c -+++ b/block/backup.c -@@ -565,6 +565,10 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, - assert(bs); - assert(target); - -+ /* QMP interface protects us from these cases */ -+ assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL); -+ assert(sync_bitmap || sync_mode != MIRROR_SYNC_MODE_BITMAP); -+ - if (bs == target) { - error_setg(errp, "Source and target cannot be the same"); - return NULL; -@@ -596,16 +600,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, - return NULL; - } - -- /* QMP interface should have handled translating this to bitmap mode */ -- assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL); -- - if (sync_mode == MIRROR_SYNC_MODE_BITMAP) { -- if (!sync_bitmap) { -- error_setg(errp, "must provide a valid bitmap name for " -- "'%s' sync mode", MirrorSyncMode_str(sync_mode)); -- return NULL; -- } -- - /* If we need to write to this bitmap, check that we can: */ - if (bitmap_mode != BITMAP_SYNC_MODE_NEVER && - bdrv_dirty_bitmap_check(sync_bitmap, BDRV_BITMAP_DEFAULT, errp)) { -diff --git a/blockdev.c b/blockdev.c -index efb69d343a..0a71a15fa2 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -3508,6 +3508,16 @@ static BlockJob *do_backup_common(BackupCommon *backup, - return NULL; - } - -+ if ((backup->sync == MIRROR_SYNC_MODE_BITMAP) || -+ (backup->sync == MIRROR_SYNC_MODE_INCREMENTAL)) { -+ /* done before desugaring 'incremental' to print the right message */ -+ if (!backup->has_bitmap) { -+ error_setg(errp, "must provide a valid bitmap name for " -+ "'%s' sync mode", MirrorSyncMode_str(backup->sync)); -+ return NULL; -+ } -+ } -+ - if (backup->sync == MIRROR_SYNC_MODE_INCREMENTAL) { - if (backup->has_bitmap_mode && - backup->bitmap_mode != BITMAP_SYNC_MODE_ON_SUCCESS) { --- -2.27.0 - diff --git a/block-backup-loosen-restriction-on-readonly-bitmaps.patch b/block-backup-loosen-restriction-on-readonly-bitmaps.patch deleted file mode 100644 index ab0617c2b580040a460aad2bd4eb16f3e4687141..0000000000000000000000000000000000000000 --- a/block-backup-loosen-restriction-on-readonly-bitmaps.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 801e9452bc80a38ee26fe12ba42356851acd6a9e Mon Sep 17 00:00:00 2001 -From: John Snow -Date: Mon, 29 Jul 2019 16:35:54 -0400 -Subject: [PATCH] block/backup: loosen restriction on readonly bitmaps - -With the "never" sync policy, we actually can utilize readonly bitmaps -now. Loosen the check at the QMP level, and tighten it based on -provided arguments down at the job creation level instead. - -Signed-off-by: John Snow -Reviewed-by: Max Reitz -Message-id: 20190709232550.10724-19-jsnow@redhat.com -Signed-off-by: John Snow ---- - block/backup.c | 6 ++++++ - blockdev.c | 2 +- - 2 files changed, 7 insertions(+), 1 deletion(-) - -diff --git a/block/backup.c b/block/backup.c -index 84a56337ac..59ac2c0396 100644 ---- a/block/backup.c -+++ b/block/backup.c -@@ -606,6 +606,12 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, - return NULL; - } - -+ /* If we need to write to this bitmap, check that we can: */ -+ if (bitmap_mode != BITMAP_SYNC_MODE_NEVER && -+ bdrv_dirty_bitmap_check(sync_bitmap, BDRV_BITMAP_DEFAULT, errp)) { -+ return NULL; -+ } -+ - /* Create a new bitmap, and freeze/disable this one. */ - if (bdrv_dirty_bitmap_create_successor(bs, sync_bitmap, errp) < 0) { - return NULL; -diff --git a/blockdev.c b/blockdev.c -index 34c8b651e1..efb69d343a 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -3533,7 +3533,7 @@ static BlockJob *do_backup_common(BackupCommon *backup, - "when providing a bitmap"); - return NULL; - } -- if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) { -+ if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_ALLOW_RO, errp)) { - return NULL; - } - } --- -2.27.0 - diff --git a/block-bdrv_set_backing_bs-fix-use-after-free.patch b/block-bdrv_set_backing_bs-fix-use-after-free.patch deleted file mode 100644 index 93ac72169d8518a8fcadc82c7ee01fcfdfcf94fc..0000000000000000000000000000000000000000 --- a/block-bdrv_set_backing_bs-fix-use-after-free.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 3754525eb383f91869634766ccd041cfe40bbf17 Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Mon, 16 Mar 2020 09:06:30 +0300 -Subject: [PATCH 05/14] block: bdrv_set_backing_bs: fix use-after-free -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -There is a use-after-free possible: bdrv_unref_child() leaves -bs->backing freed but not NULL. bdrv_attach_child may produce nested -polling loop due to drain, than access of freed pointer is possible. - -I've produced the following crash on 30 iotest with modified code. It -does not reproduce on master, but still seems possible: - - #0 __strcmp_avx2 () at /lib64/libc.so.6 - #1 bdrv_backing_overridden (bs=0x55c9d3cc2060) at block.c:6350 - #2 bdrv_refresh_filename (bs=0x55c9d3cc2060) at block.c:6404 - #3 bdrv_backing_attach (c=0x55c9d48e5520) at block.c:1063 - #4 bdrv_replace_child_noperm - (child=child@entry=0x55c9d48e5520, - new_bs=new_bs@entry=0x55c9d3cc2060) at block.c:2290 - #5 bdrv_replace_child - (child=child@entry=0x55c9d48e5520, - new_bs=new_bs@entry=0x55c9d3cc2060) at block.c:2320 - #6 bdrv_root_attach_child - (child_bs=child_bs@entry=0x55c9d3cc2060, - child_name=child_name@entry=0x55c9d241d478 "backing", - child_role=child_role@entry=0x55c9d26ecee0 , - ctx=, perm=, shared_perm=21, - opaque=0x55c9d3c5a3d0, errp=0x7ffd117108e0) at block.c:2424 - #7 bdrv_attach_child - (parent_bs=parent_bs@entry=0x55c9d3c5a3d0, - child_bs=child_bs@entry=0x55c9d3cc2060, - child_name=child_name@entry=0x55c9d241d478 "backing", - child_role=child_role@entry=0x55c9d26ecee0 , - errp=errp@entry=0x7ffd117108e0) at block.c:5876 - #8 in bdrv_set_backing_hd - (bs=bs@entry=0x55c9d3c5a3d0, - backing_hd=backing_hd@entry=0x55c9d3cc2060, - errp=errp@entry=0x7ffd117108e0) - at block.c:2576 - #9 stream_prepare (job=0x55c9d49d84a0) at block/stream.c:150 - #10 job_prepare (job=0x55c9d49d84a0) at job.c:761 - #11 job_txn_apply (txn=, fn=) at - job.c:145 - #12 job_do_finalize (job=0x55c9d49d84a0) at job.c:778 - #13 job_completed_txn_success (job=0x55c9d49d84a0) at job.c:832 - #14 job_completed (job=0x55c9d49d84a0) at job.c:845 - #15 job_completed (job=0x55c9d49d84a0) at job.c:836 - #16 job_exit (opaque=0x55c9d49d84a0) at job.c:864 - #17 aio_bh_call (bh=0x55c9d471a160) at util/async.c:117 - #18 aio_bh_poll (ctx=ctx@entry=0x55c9d3c46720) at util/async.c:117 - #19 aio_poll (ctx=ctx@entry=0x55c9d3c46720, - blocking=blocking@entry=true) - at util/aio-posix.c:728 - #20 bdrv_parent_drained_begin_single (poll=true, c=0x55c9d3d558f0) - at block/io.c:121 - #21 bdrv_parent_drained_begin_single (c=c@entry=0x55c9d3d558f0, - poll=poll@entry=true) - at block/io.c:114 - #22 bdrv_replace_child_noperm - (child=child@entry=0x55c9d3d558f0, - new_bs=new_bs@entry=0x55c9d3d27300) at block.c:2258 - #23 bdrv_replace_child - (child=child@entry=0x55c9d3d558f0, - new_bs=new_bs@entry=0x55c9d3d27300) at block.c:2320 - #24 bdrv_root_attach_child - (child_bs=child_bs@entry=0x55c9d3d27300, - child_name=child_name@entry=0x55c9d241d478 "backing", - child_role=child_role@entry=0x55c9d26ecee0 , - ctx=, perm=, shared_perm=21, - opaque=0x55c9d3cc2060, errp=0x7ffd11710c60) at block.c:2424 - #25 bdrv_attach_child - (parent_bs=parent_bs@entry=0x55c9d3cc2060, - child_bs=child_bs@entry=0x55c9d3d27300, - child_name=child_name@entry=0x55c9d241d478 "backing", - child_role=child_role@entry=0x55c9d26ecee0 , - errp=errp@entry=0x7ffd11710c60) at block.c:5876 - #26 bdrv_set_backing_hd - (bs=bs@entry=0x55c9d3cc2060, - backing_hd=backing_hd@entry=0x55c9d3d27300, - errp=errp@entry=0x7ffd11710c60) - at block.c:2576 - #27 stream_prepare (job=0x55c9d495ead0) at block/stream.c:150 - ... - -Signed-off-by: Vladimir Sementsov-Ogievskiy -Message-Id: <20200316060631.30052-2-vsementsov@virtuozzo.com> -Reviewed-by: Philippe Mathieu-Daudé -Reviewed-by: John Snow -Signed-off-by: Max Reitz -Signed-off-by: Peng Liang ---- - block.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/block.c b/block.c -index 29e504b86aff..e834102c87f7 100644 ---- a/block.c -+++ b/block.c -@@ -2549,10 +2549,10 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, - - if (bs->backing) { - bdrv_unref_child(bs, bs->backing); -+ bs->backing = NULL; - } - - if (!backing_hd) { -- bs->backing = NULL; - goto out; - } - --- -2.26.2 - diff --git a/block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch b/block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch new file mode 100644 index 0000000000000000000000000000000000000000..3d454ecc4935d6ff4206b8b47d76962cfc4ee673 --- /dev/null +++ b/block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch @@ -0,0 +1,33 @@ +From d0586db311e8b78732923ce46f149fdf8251a59c Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 16:10:22 +0800 +Subject: [PATCH] block: bugfix: Don't pause vm when NOSPACE EIO happened + +When backend disk is FULL and disk IO type is 'dataplane', +QEMU will pause the vm, and this may cause endless-loop in +QEMU main thread if we do the snapshot merge now. + +When backend disk is FULL, only reporting an error rather +than pausing the virtual machine. + +Signed-off-by: wangjian161 +--- + blockdev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/blockdev.c b/blockdev.c +index 37e3ee6f26..3ce294ec4a 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -556,7 +556,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, + qdict_put_str(bs_opts, "driver", buf); + } + +- on_write_error = BLOCKDEV_ON_ERROR_ENOSPC; ++ on_write_error = BLOCKDEV_ON_ERROR_REPORT; + if ((buf = qemu_opt_get(opts, "werror")) != NULL) { + on_write_error = parse_block_error_action(buf, 0, &error); + if (error) { +-- +2.27.0 + diff --git a/block-bugfix-disable-process-AIO-when-attach-scsi-di.patch b/block-bugfix-disable-process-AIO-when-attach-scsi-di.patch new file mode 100644 index 0000000000000000000000000000000000000000..30a1bacb258e52e0203d081f1aee0b6093735f5f --- /dev/null +++ b/block-bugfix-disable-process-AIO-when-attach-scsi-di.patch @@ -0,0 +1,43 @@ +From 87d8b7dcd880e0cef0c043dfef5ae649652cfe21 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 11:51:43 +0800 +Subject: [PATCH] block: bugfix: disable process AIO when attach scsi disk + +When initializing the virtio-scsi disk, hd_geometry_guess() will +be called to process AIO. At this time, the scsi disk has not +been fully initialized, and some fields in struct SCSIDiskState, +such as vendor and version, are NULL. If processing AIO at this +time, qemu may crash down. + +Add aio_disable_external() before hd_geometry_guess() to disable +processing AIO at that time. + +Signed-off-by: wangjian161 +--- + hw/block/block.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/hw/block/block.c b/hw/block/block.c +index 26c0767552..2cfc93a68e 100644 +--- a/hw/block/block.c ++++ b/hw/block/block.c +@@ -224,9 +224,16 @@ bool blkconf_geometry(BlockConf *conf, int *ptrans, + Error **errp) + { + if (!conf->cyls && !conf->heads && !conf->secs) { ++ AioContext *ctx = blk_get_aio_context(conf->blk); ++ ++ /* Callers may not expect this function to dispatch aio handlers, so ++ * disable external aio such as guest device emulation. ++ */ ++ aio_disable_external(ctx); + hd_geometry_guess(conf->blk, + &conf->cyls, &conf->heads, &conf->secs, + ptrans); ++ aio_enable_external(ctx); + } else if (ptrans && *ptrans == BIOS_ATA_TRANSLATION_AUTO) { + *ptrans = hd_bios_chs_auto_trans(conf->cyls, conf->heads, conf->secs); + } +-- +2.27.0 + diff --git a/block-create-Do-not-abort-if-a-block-driver-is-not-a.patch b/block-create-Do-not-abort-if-a-block-driver-is-not-a.patch deleted file mode 100644 index 73d2b9d0e5e490c3f855304e692ed68fd4029468..0000000000000000000000000000000000000000 --- a/block-create-Do-not-abort-if-a-block-driver-is-not-a.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 088f1e8fd9e790bc5766bd43af134230abcff6dd Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= -Date: Thu, 12 Sep 2019 00:08:49 +0200 -Subject: [PATCH] block/create: Do not abort if a block driver is not available -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The 'blockdev-create' QMP command was introduced as experimental -feature in commit b0292b851b8, using the assert() debug call. -It got promoted to 'stable' command in 3fb588a0f2c, but the -assert call was not removed. - -Some block drivers are optional, and bdrv_find_format() might -return a NULL value, triggering the assertion. - -Stable code is not expected to abort, so return an error instead. - -This is easily reproducible when libnfs is not installed: - - ./configure - [...] - module support no - Block whitelist (rw) - Block whitelist (ro) - libiscsi support yes - libnfs support no - [...] - -Start QEMU: - - $ qemu-system-x86_64 -S -qmp unix:/tmp/qemu.qmp,server,nowait - -Send the 'blockdev-create' with the 'nfs' driver: - - $ ( cat << 'EOF' - {'execute': 'qmp_capabilities'} - {'execute': 'blockdev-create', 'arguments': {'job-id': 'x', 'options': {'size': 0, 'driver': 'nfs', 'location': {'path': '/', 'server': {'host': '::1', 'type': 'inet'}}}}, 'id': 'x'} - EOF - ) | socat STDIO UNIX:/tmp/qemu.qmp - {"QMP": {"version": {"qemu": {"micro": 50, "minor": 1, "major": 4}, "package": "v4.1.0-733-g89ea03a7dc"}, "capabilities": ["oob"]}} - {"return": {}} - -QEMU crashes: - - $ gdb qemu-system-x86_64 core - Program received signal SIGSEGV, Segmentation fault. - (gdb) bt - #0 0x00007ffff510957f in raise () at /lib64/libc.so.6 - #1 0x00007ffff50f3895 in abort () at /lib64/libc.so.6 - #2 0x00007ffff50f3769 in _nl_load_domain.cold.0 () at /lib64/libc.so.6 - #3 0x00007ffff5101a26 in .annobin_assert.c_end () at /lib64/libc.so.6 - #4 0x0000555555d7e1f1 in qmp_blockdev_create (job_id=0x555556baee40 "x", options=0x555557666610, errp=0x7fffffffc770) at block/create.c:69 - #5 0x0000555555c96b52 in qmp_marshal_blockdev_create (args=0x7fffdc003830, ret=0x7fffffffc7f8, errp=0x7fffffffc7f0) at qapi/qapi-commands-block-core.c:1314 - #6 0x0000555555deb0a0 in do_qmp_dispatch (cmds=0x55555645de70 , request=0x7fffdc005c70, allow_oob=false, errp=0x7fffffffc898) at qapi/qmp-dispatch.c:131 - #7 0x0000555555deb2a1 in qmp_dispatch (cmds=0x55555645de70 , request=0x7fffdc005c70, allow_oob=false) at qapi/qmp-dispatch.c:174 - -With this patch applied, QEMU returns a QMP error: - - {'execute': 'blockdev-create', 'arguments': {'job-id': 'x', 'options': {'size': 0, 'driver': 'nfs', 'location': {'path': '/', 'server': {'host': '::1', 'type': 'inet'}}}}, 'id': 'x'} - {"id": "x", "error": {"class": "GenericError", "desc": "Block driver 'nfs' not found or not supported"}} - -Cc: qemu-stable@nongnu.org -Reported-by: Xu Tian -Signed-off-by: Philippe Mathieu-Daudé -Reviewed-by: Eric Blake -Reviewed-by: John Snow -Signed-off-by: Kevin Wolf -(cherry picked from commit d90d5cae2b10efc0e8d0b3cc91ff16201853d3ba) -Signed-off-by: Michael Roth ---- - block/create.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/block/create.c b/block/create.c -index 95341219ef..de5e97bb18 100644 ---- a/block/create.c -+++ b/block/create.c -@@ -63,9 +63,13 @@ void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options, - const char *fmt = BlockdevDriver_str(options->driver); - BlockDriver *drv = bdrv_find_format(fmt); - -+ if (!drv) { -+ error_setg(errp, "Block driver '%s' not found or not supported", fmt); -+ return; -+ } -+ - /* If the driver is in the schema, we know that it exists. But it may not - * be whitelisted. */ -- assert(drv); - if (bdrv_uses_whitelist() && !bdrv_is_whitelisted(drv, false)) { - error_setg(errp, "Driver is not whitelisted"); - return; --- -2.23.0 diff --git a/block-curl-HTTP-header-field-names-are-case-insensit.patch b/block-curl-HTTP-header-field-names-are-case-insensit.patch deleted file mode 100644 index 8f1028d75bbb4db6b16eca9718c90d5fe2e5795e..0000000000000000000000000000000000000000 --- a/block-curl-HTTP-header-field-names-are-case-insensit.patch +++ /dev/null @@ -1,54 +0,0 @@ -From ae2c6d13c4ac625a2c6b217a7f6a17506a2b26e5 Mon Sep 17 00:00:00 2001 -From: Richard Jones -Date: Thu, 28 May 2020 14:27:37 +0100 -Subject: [PATCH] block/curl: HTTP header field names are case insensitive -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -RH-Author: Richard Jones -Message-id: <20200528142737.17318-3-rjones@redhat.com> -Patchwork-id: 96895 -O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 2/2] block/curl: HTTP header field names are case insensitive -Bugzilla: 1841038 -RH-Acked-by: Eric Blake -RH-Acked-by: Max Reitz -RH-Acked-by: Philippe Mathieu-Daudé - -From: David Edmondson - -RFC 7230 section 3.2 indicates that HTTP header field names are case -insensitive. - -Signed-off-by: David Edmondson -Message-Id: <20200224101310.101169-3-david.edmondson@oracle.com> -Reviewed-by: Max Reitz -Signed-off-by: Max Reitz -(cherry picked from commit 69032253c33ae1774233c63cedf36d32242a85fc) -Signed-off-by: Danilo C. L. de Paula ---- - block/curl.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/block/curl.c b/block/curl.c -index bfabe7eabd..a298fcc591 100644 ---- a/block/curl.c -+++ b/block/curl.c -@@ -214,11 +214,12 @@ static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque) - size_t realsize = size * nmemb; - const char *header = (char *)ptr; - const char *end = header + realsize; -- const char *accept_ranges = "Accept-Ranges:"; -+ const char *accept_ranges = "accept-ranges:"; - const char *bytes = "bytes"; - - if (realsize >= strlen(accept_ranges) -- && strncmp(header, accept_ranges, strlen(accept_ranges)) == 0) { -+ && g_ascii_strncasecmp(header, accept_ranges, -+ strlen(accept_ranges)) == 0) { - - char *p = strchr(header, ':') + 1; - --- -2.27.0 - diff --git a/block-curl-HTTP-header-fields-allow-whitespace-aroun.patch b/block-curl-HTTP-header-fields-allow-whitespace-aroun.patch deleted file mode 100644 index 6f3aade47ce62e588e7ce490a7a3fc8f873c49de..0000000000000000000000000000000000000000 --- a/block-curl-HTTP-header-fields-allow-whitespace-aroun.patch +++ /dev/null @@ -1,75 +0,0 @@ -From c8fd37c06fd24d1242629dda329dd16bea20f319 Mon Sep 17 00:00:00 2001 -From: Richard Jones -Date: Thu, 28 May 2020 14:27:36 +0100 -Subject: [PATCH] block/curl: HTTP header fields allow whitespace around values - -RH-Author: Richard Jones -Message-id: <20200528142737.17318-2-rjones@redhat.com> -Patchwork-id: 96894 -O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/2] block/curl: HTTP header fields allow whitespace around values -Bugzilla: 1841038 -RH-Acked-by: Eric Blake -RH-Acked-by: Max Reitz -RH-Acked-by: Danilo de Paula - -From: David Edmondson - -RFC 7230 section 3.2 indicates that whitespace is permitted between -the field name and field value and after the field value. - -Signed-off-by: David Edmondson -Message-Id: <20200224101310.101169-2-david.edmondson@oracle.com> -Reviewed-by: Max Reitz -Signed-off-by: Max Reitz -(cherry picked from commit 7788a319399f17476ff1dd43164c869e320820a2) -Signed-off-by: Danilo C. L. de Paula ---- - block/curl.c | 31 +++++++++++++++++++++++++++---- - 1 file changed, 27 insertions(+), 4 deletions(-) - -diff --git a/block/curl.c b/block/curl.c -index d4c8e94f3e..bfabe7eabd 100644 ---- a/block/curl.c -+++ b/block/curl.c -@@ -212,11 +212,34 @@ static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque) - { - BDRVCURLState *s = opaque; - size_t realsize = size * nmemb; -- const char *accept_line = "Accept-Ranges: bytes"; -+ const char *header = (char *)ptr; -+ const char *end = header + realsize; -+ const char *accept_ranges = "Accept-Ranges:"; -+ const char *bytes = "bytes"; - -- if (realsize >= strlen(accept_line) -- && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) { -- s->accept_range = true; -+ if (realsize >= strlen(accept_ranges) -+ && strncmp(header, accept_ranges, strlen(accept_ranges)) == 0) { -+ -+ char *p = strchr(header, ':') + 1; -+ -+ /* Skip whitespace between the header name and value. */ -+ while (p < end && *p && g_ascii_isspace(*p)) { -+ p++; -+ } -+ -+ if (end - p >= strlen(bytes) -+ && strncmp(p, bytes, strlen(bytes)) == 0) { -+ -+ /* Check that there is nothing but whitespace after the value. */ -+ p += strlen(bytes); -+ while (p < end && *p && g_ascii_isspace(*p)) { -+ p++; -+ } -+ -+ if (p == end || !*p) { -+ s->accept_range = true; -+ } -+ } - } - - return realsize; --- -2.27.0 - diff --git a/block-disallow-block-jobs-when-there-is-a-BDRV_O_INA.patch b/block-disallow-block-jobs-when-there-is-a-BDRV_O_INA.patch new file mode 100644 index 0000000000000000000000000000000000000000..f243df9947f7acea06bb5ca06ebbbf53fb95968c --- /dev/null +++ b/block-disallow-block-jobs-when-there-is-a-BDRV_O_INA.patch @@ -0,0 +1,47 @@ +From 0a2c96ee5a3463e82397afb9cb36f340a93264c2 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 11:29:15 +0800 +Subject: [PATCH] block: disallow block jobs when there is a BDRV_O_INACTIVE + flag + +Currently, migration will put a BDRV_O_INACTIVE flag +on bs's open_flags until another resume being called. In that case, +any IO from vm or block jobs will cause a qemu crash with an assert +'assert(!(bs->open_flags & BDRV_O_INACTIVE))' failure in bdrv_co_pwritev +function. we hereby disallow block jobs by faking a blocker. + +Signed-off-by: wangjian161 +--- + block.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/block.c b/block.c +index 0ac5b163d2..26c3982567 100644 +--- a/block.c ++++ b/block.c +@@ -6692,6 +6692,22 @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp) + bdrv_get_device_or_node_name(bs)); + return true; + } ++ ++ /* ++ * When migration puts a BDRV_O_INACTIVE flag on driver's open_flags, ++ * we fake a blocker that doesn't exist. From now on, block jobs ++ * will not be permitted. ++ */ ++ if ((op == BLOCK_OP_TYPE_RESIZE || op == BLOCK_OP_TYPE_COMMIT_SOURCE || ++ op == BLOCK_OP_TYPE_MIRROR_SOURCE || op == BLOCK_OP_TYPE_MIRROR_TARGET) && ++ (bs->open_flags & BDRV_O_INACTIVE)) { ++ if (errp) { ++ error_setg(errp, "block device is in use by migration with" ++ " a driver BDRV_O_INACTIVE flag setted"); ++ } ++ return true; ++ } ++ + return false; + } + +-- +2.27.0 + diff --git a/block-enable-cache-mode-of-empty-cdrom.patch b/block-enable-cache-mode-of-empty-cdrom.patch new file mode 100644 index 0000000000000000000000000000000000000000..3a5c0b1dcdb858aef4653fbb6155e7fff28deec3 --- /dev/null +++ b/block-enable-cache-mode-of-empty-cdrom.patch @@ -0,0 +1,49 @@ +From 21b172a3ce13c3b499e4265628f7d7c7e1189749 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 11:18:21 +0800 +Subject: [PATCH] block: enable cache mode of empty cdrom + +enable cache mode even if cdrom is empty + +Signed-off-by: wangjian161 +--- + blockdev.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/blockdev.c b/blockdev.c +index 10a73fa423..37e3ee6f26 100644 +--- a/blockdev.c ++++ b/blockdev.c +@@ -492,6 +492,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, + QDict *interval_dict = NULL; + QList *interval_list = NULL; + const char *id; ++ const char *cache; + BlockdevDetectZeroesOptions detect_zeroes = + BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF; + const char *throttling_group = NULL; +@@ -583,6 +584,21 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, + + read_only = qemu_opt_get_bool(opts, BDRV_OPT_READ_ONLY, false); + ++ if (!file || !*file) { ++ cache = qdict_get_try_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH); ++ if (cache && !strcmp(cache, "on")) { ++ bdrv_flags |= BDRV_O_NO_FLUSH; ++ } ++ ++ cache = qdict_get_try_str(bs_opts, BDRV_OPT_CACHE_DIRECT); ++ if (cache && !strcmp(cache, "on")) { ++ bdrv_flags |= BDRV_O_NOCACHE; ++ } ++ ++ qdict_del(bs_opts, BDRV_OPT_CACHE_NO_FLUSH); ++ qdict_del(bs_opts, BDRV_OPT_CACHE_DIRECT); ++ } ++ + /* init */ + if ((!file || !*file) && !qdict_size(bs_opts)) { + BlockBackendRootState *blk_rs; +-- +2.27.0 + diff --git a/block-file-posix-Let-post-EOF-fallocate-serialize.patch b/block-file-posix-Let-post-EOF-fallocate-serialize.patch deleted file mode 100644 index bf7d34a3e54ffe24356a16185d1dfcaef603c455..0000000000000000000000000000000000000000 --- a/block-file-posix-Let-post-EOF-fallocate-serialize.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 7db05c8a732fbdc986a40aadf0de6dd23057d044 Mon Sep 17 00:00:00 2001 -From: Max Reitz -Date: Fri, 1 Nov 2019 16:25:10 +0100 -Subject: [PATCH] block/file-posix: Let post-EOF fallocate serialize - -The XFS kernel driver has a bug that may cause data corruption for qcow2 -images as of qemu commit c8bb23cbdbe32f. We can work around it by -treating post-EOF fallocates as serializing up until infinity (INT64_MAX -in practice). - -Cc: qemu-stable@nongnu.org -Signed-off-by: Max Reitz -Message-id: 20191101152510.11719-4-mreitz@redhat.com -Signed-off-by: Max Reitz -(cherry picked from commit 292d06b925b2787ee6f2430996b95651cae42fce) -Signed-off-by: Michael Roth ---- - block/file-posix.c | 36 ++++++++++++++++++++++++++++++++++++ - 1 file changed, 36 insertions(+) - -diff --git a/block/file-posix.c b/block/file-posix.c -index 992eb4a798..c5df61b477 100644 ---- a/block/file-posix.c -+++ b/block/file-posix.c -@@ -2623,6 +2623,42 @@ raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int bytes, - RawPosixAIOData acb; - ThreadPoolFunc *handler; - -+#ifdef CONFIG_FALLOCATE -+ if (offset + bytes > bs->total_sectors * BDRV_SECTOR_SIZE) { -+ BdrvTrackedRequest *req; -+ uint64_t end; -+ -+ /* -+ * This is a workaround for a bug in the Linux XFS driver, -+ * where writes submitted through the AIO interface will be -+ * discarded if they happen beyond a concurrently running -+ * fallocate() that increases the file length (i.e., both the -+ * write and the fallocate() happen beyond the EOF). -+ * -+ * To work around it, we extend the tracked request for this -+ * zero write until INT64_MAX (effectively infinity), and mark -+ * it as serializing. -+ * -+ * We have to enable this workaround for all filesystems and -+ * AIO modes (not just XFS with aio=native), because for -+ * remote filesystems we do not know the host configuration. -+ */ -+ -+ req = bdrv_co_get_self_request(bs); -+ assert(req); -+ assert(req->type == BDRV_TRACKED_WRITE); -+ assert(req->offset <= offset); -+ assert(req->offset + req->bytes >= offset + bytes); -+ -+ end = INT64_MAX & -(uint64_t)bs->bl.request_alignment; -+ req->bytes = end - req->offset; -+ req->overlap_bytes = req->bytes; -+ -+ bdrv_mark_request_serialising(req, bs->bl.request_alignment); -+ bdrv_wait_serialising_requests(req); -+ } -+#endif -+ - acb = (RawPosixAIOData) { - .bs = bs, - .aio_fildes = s->fd, --- -2.23.0 diff --git a/block-file-posix-Reduce-xfsctl-use.patch b/block-file-posix-Reduce-xfsctl-use.patch deleted file mode 100644 index 69ceb453efac39a1fcfcc26488e04a7bb8eee0df..0000000000000000000000000000000000000000 --- a/block-file-posix-Reduce-xfsctl-use.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 6f1a94035b02d3676a897ea5fa4cda4c62128228 Mon Sep 17 00:00:00 2001 -From: Max Reitz -Date: Fri, 23 Aug 2019 15:03:40 +0200 -Subject: [PATCH] block/file-posix: Reduce xfsctl() use -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This patch removes xfs_write_zeroes() and xfs_discard(). Both functions -have been added just before the same feature was present through -fallocate(): - -- fallocate() has supported PUNCH_HOLE for XFS since Linux 2.6.38 (March - 2011); xfs_discard() was added in December 2010. - -- fallocate() has supported ZERO_RANGE for XFS since Linux 3.15 (June - 2014); xfs_write_zeroes() was added in November 2013. - -Nowadays, all systems that qemu runs on should support both fallocate() -features (RHEL 7's kernel does). - -xfsctl() is still useful for getting the request alignment for O_DIRECT, -so this patch does not remove our dependency on it completely. - -Note that xfs_write_zeroes() had a bug: It calls ftruncate() when the -file is shorter than the specified range (because ZERO_RANGE does not -increase the file length). ftruncate() may yield and then discard data -that parallel write requests have written past the EOF in the meantime. -Dropping the function altogether fixes the bug. - -Suggested-by: Paolo Bonzini -Fixes: 50ba5b2d994853b38fed10e0841b119da0f8b8e5 -Reported-by: Lukáš Doktor -Cc: qemu-stable@nongnu.org -Signed-off-by: Max Reitz -Reviewed-by: Stefano Garzarella -Reviewed-by: John Snow -Tested-by: Stefano Garzarella -Tested-by: John Snow -Signed-off-by: Kevin Wolf -(cherry picked from commit b2c6f23f4a9f6d8f1b648705cd46d3713b78d6a2) -Signed-off-by: Michael Roth ---- - block/file-posix.c | 77 +--------------------------------------------- - 1 file changed, 1 insertion(+), 76 deletions(-) - -diff --git a/block/file-posix.c b/block/file-posix.c -index 4479cc7ab4..992eb4a798 100644 ---- a/block/file-posix.c -+++ b/block/file-posix.c -@@ -1445,59 +1445,6 @@ out: - } - } - --#ifdef CONFIG_XFS --static int xfs_write_zeroes(BDRVRawState *s, int64_t offset, uint64_t bytes) --{ -- int64_t len; -- struct xfs_flock64 fl; -- int err; -- -- len = lseek(s->fd, 0, SEEK_END); -- if (len < 0) { -- return -errno; -- } -- -- if (offset + bytes > len) { -- /* XFS_IOC_ZERO_RANGE does not increase the file length */ -- if (ftruncate(s->fd, offset + bytes) < 0) { -- return -errno; -- } -- } -- -- memset(&fl, 0, sizeof(fl)); -- fl.l_whence = SEEK_SET; -- fl.l_start = offset; -- fl.l_len = bytes; -- -- if (xfsctl(NULL, s->fd, XFS_IOC_ZERO_RANGE, &fl) < 0) { -- err = errno; -- trace_file_xfs_write_zeroes(strerror(errno)); -- return -err; -- } -- -- return 0; --} -- --static int xfs_discard(BDRVRawState *s, int64_t offset, uint64_t bytes) --{ -- struct xfs_flock64 fl; -- int err; -- -- memset(&fl, 0, sizeof(fl)); -- fl.l_whence = SEEK_SET; -- fl.l_start = offset; -- fl.l_len = bytes; -- -- if (xfsctl(NULL, s->fd, XFS_IOC_UNRESVSP64, &fl) < 0) { -- err = errno; -- trace_file_xfs_discard(strerror(errno)); -- return -err; -- } -- -- return 0; --} --#endif -- - static int translate_err(int err) - { - if (err == -ENODEV || err == -ENOSYS || err == -EOPNOTSUPP || -@@ -1553,10 +1500,8 @@ static ssize_t handle_aiocb_write_zeroes_block(RawPosixAIOData *aiocb) - static int handle_aiocb_write_zeroes(void *opaque) - { - RawPosixAIOData *aiocb = opaque; --#if defined(CONFIG_FALLOCATE) || defined(CONFIG_XFS) -- BDRVRawState *s = aiocb->bs->opaque; --#endif - #ifdef CONFIG_FALLOCATE -+ BDRVRawState *s = aiocb->bs->opaque; - int64_t len; - #endif - -@@ -1564,12 +1509,6 @@ static int handle_aiocb_write_zeroes(void *opaque) - return handle_aiocb_write_zeroes_block(aiocb); - } - --#ifdef CONFIG_XFS -- if (s->is_xfs) { -- return xfs_write_zeroes(s, aiocb->aio_offset, aiocb->aio_nbytes); -- } --#endif -- - #ifdef CONFIG_FALLOCATE_ZERO_RANGE - if (s->has_write_zeroes) { - int ret = do_fallocate(s->fd, FALLOC_FL_ZERO_RANGE, -@@ -1632,14 +1571,6 @@ static int handle_aiocb_write_zeroes_unmap(void *opaque) - } - #endif - --#ifdef CONFIG_XFS -- if (s->is_xfs) { -- /* xfs_discard() guarantees that the discarded area reads as all-zero -- * afterwards, so we can use it here. */ -- return xfs_discard(s, aiocb->aio_offset, aiocb->aio_nbytes); -- } --#endif -- - /* If we couldn't manage to unmap while guaranteed that the area reads as - * all-zero afterwards, just write zeroes without unmapping */ - ret = handle_aiocb_write_zeroes(aiocb); -@@ -1716,12 +1647,6 @@ static int handle_aiocb_discard(void *opaque) - ret = -errno; - #endif - } else { --#ifdef CONFIG_XFS -- if (s->is_xfs) { -- return xfs_discard(s, aiocb->aio_offset, aiocb->aio_nbytes); -- } --#endif -- - #ifdef CONFIG_FALLOCATE_PUNCH_HOLE - ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, - aiocb->aio_offset, aiocb->aio_nbytes); --- -2.23.0 diff --git a/block-fix-bdrv_root_attach_child-forget-to-unref-chi.patch b/block-fix-bdrv_root_attach_child-forget-to-unref-chi.patch deleted file mode 100644 index d901f1062659223d2899ab5520759a6a5065545a..0000000000000000000000000000000000000000 --- a/block-fix-bdrv_root_attach_child-forget-to-unref-chi.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 5060ef71fa4621061101a30fa9e0d1690696c5c1 Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Tue, 24 Mar 2020 18:59:21 +0300 -Subject: [PATCH 10/14] block: fix bdrv_root_attach_child forget to unref - child_bs - -bdrv_root_attach_child promises to drop child_bs reference on failure. -It does it on first handled failure path, but not on the second. Fix -that. - -Signed-off-by: Vladimir Sementsov-Ogievskiy -Message-Id: <20200324155921.23822-1-vsementsov@virtuozzo.com> -Signed-off-by: Kevin Wolf -Signed-off-by: Peng Liang ---- - block.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/block.c b/block.c -index e834102c87f7..38880eabf801 100644 ---- a/block.c -+++ b/block.c -@@ -2399,6 +2399,7 @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs, - error_propagate(errp, local_err); - g_free(child); - bdrv_abort_perm_update(child_bs); -+ bdrv_unref(child_bs); - return NULL; - } - } --- -2.26.2 - diff --git a/block-fix-memleaks-in-bdrv_refresh_filename.patch b/block-fix-memleaks-in-bdrv_refresh_filename.patch deleted file mode 100644 index 48682054e6d7db02048c7538f8f1963447020c85..0000000000000000000000000000000000000000 --- a/block-fix-memleaks-in-bdrv_refresh_filename.patch +++ /dev/null @@ -1,56 +0,0 @@ -From d09b8364d9f89c9d5f36dc983c4d4a36bb7388b9 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Thu, 16 Jan 2020 17:29:29 +0800 -Subject: [PATCH] block: fix memleaks in bdrv_refresh_filename - -If we call the qmp 'query-block' while qemu is working on 'block-commit', -it will cause memleaks. The memory leak stack is as follow: - -Indirect leak of 12360 byte(s) in 3 object(s) allocated from: - #0 0x7f80f0b6d970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970) - #1 0x7f80ee86049d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d) - #2 0x55ea95b5bb67 in qdict_new /mnt/sdb/qemu/qobject/qdict.c - #3 0x55ea956cd043 in bdrv_refresh_filename /mnt/sdb/qemu/block.c - #4 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c - #5 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c - #6 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c - #7 0x55ea958818ea in bdrv_block_device_info /mnt/sdb/qemu/block/qapi.c - #8 0x55ea958879de in bdrv_query_info /mnt/sdb/qemu/block/qapi.c - #9 0x55ea9588b58f in qmp_query_block /mnt/sdb/qemu/block/qapi.c - #10 0x55ea95567392 in qmp_marshal_query_block qapi/qapi-commands-block-core.c - -Indirect leak of 4120 byte(s) in 1 object(s) allocated from: - #0 0x7f80f0b6d970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970) - #1 0x7f80ee86049d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d) - #2 0x55ea95b5bb67 in qdict_new /mnt/sdb/qemu/qobject/qdict.c - #3 0x55ea956cd043 in bdrv_refresh_filename /mnt/sdb/qemu/block.c - #4 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c - #5 0x55ea956cc950 in bdrv_refresh_filename /mnt/sdb/qemu/block.c - #6 0x55ea9569f301 in bdrv_backing_attach /mnt/sdb/qemu/block.c - #7 0x55ea956a99dd in bdrv_replace_child_noperm /mnt/sdb/qemu/block.c - #8 0x55ea956b9b53 in bdrv_replace_node /mnt/sdb/qemu/block.c - #9 0x55ea956b9e49 in bdrv_append /mnt/sdb/qemu/block.c - #10 0x55ea958c3472 in commit_start /mnt/sdb/qemu/block/commit.c - #11 0x55ea94b68ab0 in qmp_block_commit /mnt/sdb/qemu/blockdev.c - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan ---- - block.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/block.c b/block.c -index 9ae5c0e..52bad05 100644 ---- a/block.c -+++ b/block.c -@@ -6048,6 +6048,7 @@ void bdrv_refresh_filename(BlockDriverState *bs) - child->bs->exact_filename); - pstrcpy(bs->filename, sizeof(bs->filename), child->bs->filename); - -+ qobject_unref(bs->full_open_options); - bs->full_open_options = qobject_ref(child->bs->full_open_options); - - return; --- -1.8.3.1 - diff --git a/block-io-refactor-padding.patch b/block-io-refactor-padding.patch deleted file mode 100644 index 7a267147f5b5fbfa908edf342c02bd17481b3d70..0000000000000000000000000000000000000000 --- a/block-io-refactor-padding.patch +++ /dev/null @@ -1,481 +0,0 @@ -From 2e2ad02f2cecf419eaad0df982ceb5b41170cc7e Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Tue, 4 Jun 2019 19:15:05 +0300 -Subject: [PATCH] block/io: refactor padding - -We have similar padding code in bdrv_co_pwritev, -bdrv_co_do_pwrite_zeroes and bdrv_co_preadv. Let's combine and unify -it. - -[Squashed in Vladimir's qemu-iotests 077 fix ---Stefan] - -Signed-off-by: Vladimir Sementsov-Ogievskiy -Acked-by: Stefan Hajnoczi -Message-id: 20190604161514.262241-4-vsementsov@virtuozzo.com -Message-Id: <20190604161514.262241-4-vsementsov@virtuozzo.com> -Signed-off-by: Stefan Hajnoczi -(cherry picked from commit 7a3f542fbdfd799be4fa6f8b96dc8c1e6933fce4) -*prereq for 292d06b9 -Signed-off-by: Michael Roth ---- - block/io.c | 365 +++++++++++++++++++++++++++++------------------------ - 1 file changed, 200 insertions(+), 165 deletions(-) - -diff --git a/block/io.c b/block/io.c -index dccf687acc..07d2d825c3 100644 ---- a/block/io.c -+++ b/block/io.c -@@ -1408,28 +1408,177 @@ out: - } - - /* -- * Handle a read request in coroutine context -+ * Request padding -+ * -+ * |<---- align ----->| |<----- align ---->| -+ * |<- head ->|<------------- bytes ------------->|<-- tail -->| -+ * | | | | | | -+ * -*----------$-------*-------- ... --------*-----$------------*--- -+ * | | | | | | -+ * | offset | | end | -+ * ALIGN_DOWN(offset) ALIGN_UP(offset) ALIGN_DOWN(end) ALIGN_UP(end) -+ * [buf ... ) [tail_buf ) -+ * -+ * @buf is an aligned allocation needed to store @head and @tail paddings. @head -+ * is placed at the beginning of @buf and @tail at the @end. -+ * -+ * @tail_buf is a pointer to sub-buffer, corresponding to align-sized chunk -+ * around tail, if tail exists. -+ * -+ * @merge_reads is true for small requests, -+ * if @buf_len == @head + bytes + @tail. In this case it is possible that both -+ * head and tail exist but @buf_len == align and @tail_buf == @buf. -+ */ -+typedef struct BdrvRequestPadding { -+ uint8_t *buf; -+ size_t buf_len; -+ uint8_t *tail_buf; -+ size_t head; -+ size_t tail; -+ bool merge_reads; -+ QEMUIOVector local_qiov; -+} BdrvRequestPadding; -+ -+static bool bdrv_init_padding(BlockDriverState *bs, -+ int64_t offset, int64_t bytes, -+ BdrvRequestPadding *pad) -+{ -+ uint64_t align = bs->bl.request_alignment; -+ size_t sum; -+ -+ memset(pad, 0, sizeof(*pad)); -+ -+ pad->head = offset & (align - 1); -+ pad->tail = ((offset + bytes) & (align - 1)); -+ if (pad->tail) { -+ pad->tail = align - pad->tail; -+ } -+ -+ if ((!pad->head && !pad->tail) || !bytes) { -+ return false; -+ } -+ -+ sum = pad->head + bytes + pad->tail; -+ pad->buf_len = (sum > align && pad->head && pad->tail) ? 2 * align : align; -+ pad->buf = qemu_blockalign(bs, pad->buf_len); -+ pad->merge_reads = sum == pad->buf_len; -+ if (pad->tail) { -+ pad->tail_buf = pad->buf + pad->buf_len - align; -+ } -+ -+ return true; -+} -+ -+static int bdrv_padding_rmw_read(BdrvChild *child, -+ BdrvTrackedRequest *req, -+ BdrvRequestPadding *pad, -+ bool zero_middle) -+{ -+ QEMUIOVector local_qiov; -+ BlockDriverState *bs = child->bs; -+ uint64_t align = bs->bl.request_alignment; -+ int ret; -+ -+ assert(req->serialising && pad->buf); -+ -+ if (pad->head || pad->merge_reads) { -+ uint64_t bytes = pad->merge_reads ? pad->buf_len : align; -+ -+ qemu_iovec_init_buf(&local_qiov, pad->buf, bytes); -+ -+ if (pad->head) { -+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); -+ } -+ if (pad->merge_reads && pad->tail) { -+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); -+ } -+ ret = bdrv_aligned_preadv(child, req, req->overlap_offset, bytes, -+ align, &local_qiov, 0); -+ if (ret < 0) { -+ return ret; -+ } -+ if (pad->head) { -+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD); -+ } -+ if (pad->merge_reads && pad->tail) { -+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); -+ } -+ -+ if (pad->merge_reads) { -+ goto zero_mem; -+ } -+ } -+ -+ if (pad->tail) { -+ qemu_iovec_init_buf(&local_qiov, pad->tail_buf, align); -+ -+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); -+ ret = bdrv_aligned_preadv( -+ child, req, -+ req->overlap_offset + req->overlap_bytes - align, -+ align, align, &local_qiov, 0); -+ if (ret < 0) { -+ return ret; -+ } -+ bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); -+ } -+ -+zero_mem: -+ if (zero_middle) { -+ memset(pad->buf + pad->head, 0, pad->buf_len - pad->head - pad->tail); -+ } -+ -+ return 0; -+} -+ -+static void bdrv_padding_destroy(BdrvRequestPadding *pad) -+{ -+ if (pad->buf) { -+ qemu_vfree(pad->buf); -+ qemu_iovec_destroy(&pad->local_qiov); -+ } -+} -+ -+/* -+ * bdrv_pad_request -+ * -+ * Exchange request parameters with padded request if needed. Don't include RMW -+ * read of padding, bdrv_padding_rmw_read() should be called separately if -+ * needed. -+ * -+ * All parameters except @bs are in-out: they represent original request at -+ * function call and padded (if padding needed) at function finish. -+ * -+ * Function always succeeds. - */ -+static bool bdrv_pad_request(BlockDriverState *bs, QEMUIOVector **qiov, -+ int64_t *offset, unsigned int *bytes, -+ BdrvRequestPadding *pad) -+{ -+ if (!bdrv_init_padding(bs, *offset, *bytes, pad)) { -+ return false; -+ } -+ -+ qemu_iovec_init_extended(&pad->local_qiov, pad->buf, pad->head, -+ *qiov, 0, *bytes, -+ pad->buf + pad->buf_len - pad->tail, pad->tail); -+ *bytes += pad->head + pad->tail; -+ *offset -= pad->head; -+ *qiov = &pad->local_qiov; -+ -+ return true; -+} -+ - int coroutine_fn bdrv_co_preadv(BdrvChild *child, - int64_t offset, unsigned int bytes, QEMUIOVector *qiov, - BdrvRequestFlags flags) - { - BlockDriverState *bs = child->bs; -- BlockDriver *drv = bs->drv; - BdrvTrackedRequest req; -- -- uint64_t align = bs->bl.request_alignment; -- uint8_t *head_buf = NULL; -- uint8_t *tail_buf = NULL; -- QEMUIOVector local_qiov; -- bool use_local_qiov = false; -+ BdrvRequestPadding pad; - int ret; - -- trace_bdrv_co_preadv(child->bs, offset, bytes, flags); -- -- if (!drv) { -- return -ENOMEDIUM; -- } -+ trace_bdrv_co_preadv(bs, offset, bytes, flags); - - ret = bdrv_check_byte_request(bs, offset, bytes); - if (ret < 0) { -@@ -1443,43 +1592,16 @@ int coroutine_fn bdrv_co_preadv(BdrvChild *child, - flags |= BDRV_REQ_COPY_ON_READ; - } - -- /* Align read if necessary by padding qiov */ -- if (offset & (align - 1)) { -- head_buf = qemu_blockalign(bs, align); -- qemu_iovec_init(&local_qiov, qiov->niov + 2); -- qemu_iovec_add(&local_qiov, head_buf, offset & (align - 1)); -- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size); -- use_local_qiov = true; -- -- bytes += offset & (align - 1); -- offset = offset & ~(align - 1); -- } -- -- if ((offset + bytes) & (align - 1)) { -- if (!use_local_qiov) { -- qemu_iovec_init(&local_qiov, qiov->niov + 1); -- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size); -- use_local_qiov = true; -- } -- tail_buf = qemu_blockalign(bs, align); -- qemu_iovec_add(&local_qiov, tail_buf, -- align - ((offset + bytes) & (align - 1))); -- -- bytes = ROUND_UP(bytes, align); -- } -+ bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad); - - tracked_request_begin(&req, bs, offset, bytes, BDRV_TRACKED_READ); -- ret = bdrv_aligned_preadv(child, &req, offset, bytes, align, -- use_local_qiov ? &local_qiov : qiov, -- flags); -+ ret = bdrv_aligned_preadv(child, &req, offset, bytes, -+ bs->bl.request_alignment, -+ qiov, flags); - tracked_request_end(&req); - bdrv_dec_in_flight(bs); - -- if (use_local_qiov) { -- qemu_iovec_destroy(&local_qiov); -- qemu_vfree(head_buf); -- qemu_vfree(tail_buf); -- } -+ bdrv_padding_destroy(&pad); - - return ret; - } -@@ -1775,44 +1897,34 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, - BdrvTrackedRequest *req) - { - BlockDriverState *bs = child->bs; -- uint8_t *buf = NULL; - QEMUIOVector local_qiov; - uint64_t align = bs->bl.request_alignment; -- unsigned int head_padding_bytes, tail_padding_bytes; - int ret = 0; -+ bool padding; -+ BdrvRequestPadding pad; - -- head_padding_bytes = offset & (align - 1); -- tail_padding_bytes = (align - (offset + bytes)) & (align - 1); -- -- -- assert(flags & BDRV_REQ_ZERO_WRITE); -- if (head_padding_bytes || tail_padding_bytes) { -- buf = qemu_blockalign(bs, align); -- qemu_iovec_init_buf(&local_qiov, buf, align); -- } -- if (head_padding_bytes) { -- uint64_t zero_bytes = MIN(bytes, align - head_padding_bytes); -- -- /* RMW the unaligned part before head. */ -+ padding = bdrv_init_padding(bs, offset, bytes, &pad); -+ if (padding) { - mark_request_serialising(req, align); - wait_serialising_requests(req); -- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); -- ret = bdrv_aligned_preadv(child, req, offset & ~(align - 1), align, -- align, &local_qiov, 0); -- if (ret < 0) { -- goto fail; -- } -- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD); - -- memset(buf + head_padding_bytes, 0, zero_bytes); -- ret = bdrv_aligned_pwritev(child, req, offset & ~(align - 1), align, -- align, &local_qiov, -- flags & ~BDRV_REQ_ZERO_WRITE); -- if (ret < 0) { -- goto fail; -+ bdrv_padding_rmw_read(child, req, &pad, true); -+ -+ if (pad.head || pad.merge_reads) { -+ int64_t aligned_offset = offset & ~(align - 1); -+ int64_t write_bytes = pad.merge_reads ? pad.buf_len : align; -+ -+ qemu_iovec_init_buf(&local_qiov, pad.buf, write_bytes); -+ ret = bdrv_aligned_pwritev(child, req, aligned_offset, write_bytes, -+ align, &local_qiov, -+ flags & ~BDRV_REQ_ZERO_WRITE); -+ if (ret < 0 || pad.merge_reads) { -+ /* Error or all work is done */ -+ goto out; -+ } -+ offset += write_bytes - pad.head; -+ bytes -= write_bytes - pad.head; - } -- offset += zero_bytes; -- bytes -= zero_bytes; - } - - assert(!bytes || (offset & (align - 1)) == 0); -@@ -1822,7 +1934,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, - ret = bdrv_aligned_pwritev(child, req, offset, aligned_bytes, align, - NULL, flags); - if (ret < 0) { -- goto fail; -+ goto out; - } - bytes -= aligned_bytes; - offset += aligned_bytes; -@@ -1830,26 +1942,17 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child, - - assert(!bytes || (offset & (align - 1)) == 0); - if (bytes) { -- assert(align == tail_padding_bytes + bytes); -- /* RMW the unaligned part after tail. */ -- mark_request_serialising(req, align); -- wait_serialising_requests(req); -- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); -- ret = bdrv_aligned_preadv(child, req, offset, align, -- align, &local_qiov, 0); -- if (ret < 0) { -- goto fail; -- } -- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); -+ assert(align == pad.tail + bytes); - -- memset(buf, 0, bytes); -+ qemu_iovec_init_buf(&local_qiov, pad.tail_buf, align); - ret = bdrv_aligned_pwritev(child, req, offset, align, align, - &local_qiov, flags & ~BDRV_REQ_ZERO_WRITE); - } --fail: -- qemu_vfree(buf); -- return ret; - -+out: -+ bdrv_padding_destroy(&pad); -+ -+ return ret; - } - - /* -@@ -1862,10 +1965,7 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child, - BlockDriverState *bs = child->bs; - BdrvTrackedRequest req; - uint64_t align = bs->bl.request_alignment; -- uint8_t *head_buf = NULL; -- uint8_t *tail_buf = NULL; -- QEMUIOVector local_qiov; -- bool use_local_qiov = false; -+ BdrvRequestPadding pad; - int ret; - - trace_bdrv_co_pwritev(child->bs, offset, bytes, flags); -@@ -1892,86 +1992,21 @@ int coroutine_fn bdrv_co_pwritev(BdrvChild *child, - goto out; - } - -- if (offset & (align - 1)) { -- QEMUIOVector head_qiov; -- -+ if (bdrv_pad_request(bs, &qiov, &offset, &bytes, &pad)) { - mark_request_serialising(&req, align); - wait_serialising_requests(&req); -- -- head_buf = qemu_blockalign(bs, align); -- qemu_iovec_init_buf(&head_qiov, head_buf, align); -- -- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_HEAD); -- ret = bdrv_aligned_preadv(child, &req, offset & ~(align - 1), align, -- align, &head_qiov, 0); -- if (ret < 0) { -- goto fail; -- } -- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_HEAD); -- -- qemu_iovec_init(&local_qiov, qiov->niov + 2); -- qemu_iovec_add(&local_qiov, head_buf, offset & (align - 1)); -- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size); -- use_local_qiov = true; -- -- bytes += offset & (align - 1); -- offset = offset & ~(align - 1); -- -- /* We have read the tail already if the request is smaller -- * than one aligned block. -- */ -- if (bytes < align) { -- qemu_iovec_add(&local_qiov, head_buf + bytes, align - bytes); -- bytes = align; -- } -- } -- -- if ((offset + bytes) & (align - 1)) { -- QEMUIOVector tail_qiov; -- size_t tail_bytes; -- bool waited; -- -- mark_request_serialising(&req, align); -- waited = wait_serialising_requests(&req); -- assert(!waited || !use_local_qiov); -- -- tail_buf = qemu_blockalign(bs, align); -- qemu_iovec_init_buf(&tail_qiov, tail_buf, align); -- -- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_TAIL); -- ret = bdrv_aligned_preadv(child, &req, (offset + bytes) & ~(align - 1), -- align, align, &tail_qiov, 0); -- if (ret < 0) { -- goto fail; -- } -- bdrv_debug_event(bs, BLKDBG_PWRITEV_RMW_AFTER_TAIL); -- -- if (!use_local_qiov) { -- qemu_iovec_init(&local_qiov, qiov->niov + 1); -- qemu_iovec_concat(&local_qiov, qiov, 0, qiov->size); -- use_local_qiov = true; -- } -- -- tail_bytes = (offset + bytes) & (align - 1); -- qemu_iovec_add(&local_qiov, tail_buf + tail_bytes, align - tail_bytes); -- -- bytes = ROUND_UP(bytes, align); -+ bdrv_padding_rmw_read(child, &req, &pad, false); - } - - ret = bdrv_aligned_pwritev(child, &req, offset, bytes, align, -- use_local_qiov ? &local_qiov : qiov, -- flags); -+ qiov, flags); - --fail: -+ bdrv_padding_destroy(&pad); - -- if (use_local_qiov) { -- qemu_iovec_destroy(&local_qiov); -- } -- qemu_vfree(head_buf); -- qemu_vfree(tail_buf); - out: - tracked_request_end(&req); - bdrv_dec_in_flight(bs); -+ - return ret; - } - --- -2.23.0 diff --git a/block-iscsi-use-MIN-between-mx_sb_len-and-sb_len_wr.patch b/block-iscsi-use-MIN-between-mx_sb_len-and-sb_len_wr.patch deleted file mode 100644 index ba53c1ddb4381562aa1fe486ad7f0ce56923d1d7..0000000000000000000000000000000000000000 --- a/block-iscsi-use-MIN-between-mx_sb_len-and-sb_len_wr.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 547b06bb04287eb97ffb02e213aa8466c15cce65 Mon Sep 17 00:00:00 2001 -From: Chen Qun -Date: Mon, 16 Mar 2020 14:35:34 +0800 -Subject: [PATCH] block/iscsi: use MIN() between mx_sb_len and sb_len_wr - -Use MIN() macro between mx_sb_len and sb_len_wr the len for sbp copy data. - -Reported-by: Euler Robot -Signed-off-by: Chen Qun ---- - block/iscsi.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/block/iscsi.c b/block/iscsi.c -index 3f86aaf..5c3c598 100644 ---- a/block/iscsi.c -+++ b/block/iscsi.c -@@ -989,8 +989,7 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status, - acb->ioh->driver_status |= SG_ERR_DRIVER_SENSE; - - acb->ioh->sb_len_wr = acb->task->datain.size - 2; -- ss = (acb->ioh->mx_sb_len >= acb->ioh->sb_len_wr) ? -- acb->ioh->mx_sb_len : acb->ioh->sb_len_wr; -+ ss = MIN(acb->ioh->mx_sb_len, acb->ioh->sb_len_wr); - memcpy(acb->ioh->sbp, &acb->task->datain.data[2], ss); - } - --- -1.8.3.1 - diff --git a/block-mirror-fix-file-system-went-to-read-only-after.patch b/block-mirror-fix-file-system-went-to-read-only-after.patch new file mode 100644 index 0000000000000000000000000000000000000000..2126e83278425742c52f2cbd5f391fee7a70c3a0 --- /dev/null +++ b/block-mirror-fix-file-system-went-to-read-only-after.patch @@ -0,0 +1,32 @@ +From 7448eb87ee59856aa0f0853f2aa5b803c832fccf Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Thu, 10 Feb 2022 21:37:49 +0800 +Subject: [PATCH] block/mirror: fix file-system went to read-only after + block-mirror + +config vm disk with prdm, keep the disk writing data continuously +during block-mirror, the file-system will went to read-only after +block-mirror, fix it. + +Signed-off-by: caojinhua +Signed-off-by: jiangdongxu +--- + block/mirror.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/mirror.c b/block/mirror.c +index efec2c7674..b7f0cba9b9 100644 +--- a/block/mirror.c ++++ b/block/mirror.c +@@ -1640,7 +1640,7 @@ static BlockJob *mirror_start_job( + * reads on the top, while disabling it in the intermediate nodes, and make + * the backing chain writable. */ + mirror_top_bs = bdrv_new_open_driver(&bdrv_mirror_top, filter_node_name, +- BDRV_O_RDWR, errp); ++ BDRV_O_RDWR | BDRV_O_NOCACHE, errp); + if (mirror_top_bs == NULL) { + return NULL; + } +-- +2.27.0 + diff --git a/block-mirror-fix-use-after-free-of-local_err.patch b/block-mirror-fix-use-after-free-of-local_err.patch deleted file mode 100644 index ea2f739410164f7df43f020192cd60653a3b8cf0..0000000000000000000000000000000000000000 --- a/block-mirror-fix-use-after-free-of-local_err.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 682d23829adf0a872d5a3ca6eb4b31c424f558fc Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Tue, 24 Mar 2020 18:36:26 +0300 -Subject: [PATCH 09/14] block/mirror: fix use after free of local_err - -local_err is used again in mirror_exit_common() after -bdrv_set_backing_hd(), so we must zero it. Otherwise try to set -non-NULL local_err will crash. - -Signed-off-by: Vladimir Sementsov-Ogievskiy -Message-Id: <20200324153630.11882-3-vsementsov@virtuozzo.com> -Reviewed-by: Eric Blake -Reviewed-by: John Snow -Signed-off-by: Max Reitz -Signed-off-by: Peng Liang ---- - block/mirror.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/block/mirror.c b/block/mirror.c -index 681b305de650..ef6c958ff9b3 100644 ---- a/block/mirror.c -+++ b/block/mirror.c -@@ -674,6 +674,7 @@ static int mirror_exit_common(Job *job) - bdrv_set_backing_hd(target_bs, backing, &local_err); - if (local_err) { - error_report_err(local_err); -+ local_err = NULL; - ret = -EPERM; - } - } --- -2.26.2 - diff --git a/block-nbd-extract-the-common-cleanup-code.patch b/block-nbd-extract-the-common-cleanup-code.patch deleted file mode 100644 index 4cc24818b7c96cc8c85a0c8ac97dc2452c234610..0000000000000000000000000000000000000000 --- a/block-nbd-extract-the-common-cleanup-code.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 1196a2079a558cbb673e06142fa67a401c5e6c30 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Thu, 5 Dec 2019 11:45:27 +0800 -Subject: [PATCH 6/9] block/nbd: extract the common cleanup code - -The BDRVNBDState cleanup code is common in two places, add -nbd_clear_bdrvstate() function to do these cleanups. - -Suggested-by: Stefano Garzarella -Signed-off-by: Pan Nengyuan -Reviewed-by: Vladimir Sementsov-Ogievskiy -Message-Id: <1575517528-44312-2-git-send-email-pannengyuan@huawei.com> -Reviewed-by: Eric Blake -[eblake: fix compilation error and commit message] -Signed-off-by: Eric Blake -Signed-off-by: AlexChen ---- - block/nbd.c | 19 ++++++++++++------- - 1 file changed, 12 insertions(+), 7 deletions(-) - -diff --git a/block/nbd.c b/block/nbd.c -index 57c1a20..3977b1e 100644 ---- a/block/nbd.c -+++ b/block/nbd.c -@@ -73,6 +73,16 @@ typedef struct BDRVNBDState { - char *export, *tlscredsid; - } BDRVNBDState; - -+static void nbd_clear_bdrvstate(BDRVNBDState *s) -+{ -+ qapi_free_SocketAddress(s->saddr); -+ s->saddr = NULL; -+ g_free(s->export); -+ s->export = NULL; -+ g_free(s->tlscredsid); -+ s->tlscredsid = NULL; -+} -+ - static void nbd_recv_coroutines_wake_all(BDRVNBDState *s) - { - int i; -@@ -1640,9 +1650,7 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags, - object_unref(OBJECT(tlscreds)); - } - if (ret < 0) { -- qapi_free_SocketAddress(s->saddr); -- g_free(s->export); -- g_free(s->tlscredsid); -+ nbd_clear_bdrvstate(s); - } - qemu_opts_del(opts); - return ret; -@@ -1692,10 +1700,7 @@ static void nbd_close(BlockDriverState *bs) - BDRVNBDState *s = bs->opaque; - - nbd_client_close(bs); -- -- qapi_free_SocketAddress(s->saddr); -- g_free(s->export); -- g_free(s->tlscredsid); -+ nbd_clear_bdrvstate(s); - } - - static int64_t nbd_getlength(BlockDriverState *bs) --- -1.8.3.1 - diff --git a/block-nfs-tear-down-aio-before-nfs_close.patch b/block-nfs-tear-down-aio-before-nfs_close.patch deleted file mode 100644 index ea116d0a381c18521da88b94d3ea914f0357939d..0000000000000000000000000000000000000000 --- a/block-nfs-tear-down-aio-before-nfs_close.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0694c489cd240620fee5675e8d24c7ce02d1d67d Mon Sep 17 00:00:00 2001 -From: Peter Lieven -Date: Tue, 10 Sep 2019 17:41:09 +0200 -Subject: [PATCH] block/nfs: tear down aio before nfs_close - -nfs_close is a sync call from libnfs and has its own event -handler polling on the nfs FD. Avoid that both QEMU and libnfs -are intefering here. - -CC: qemu-stable@nongnu.org -Signed-off-by: Peter Lieven -Signed-off-by: Kevin Wolf -(cherry picked from commit 601dc6559725f7a614b6f893611e17ff0908e914) -Signed-off-by: Michael Roth ---- - block/nfs.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/block/nfs.c b/block/nfs.c -index d93241b3bb..2b7a078241 100644 ---- a/block/nfs.c -+++ b/block/nfs.c -@@ -390,12 +390,14 @@ static void nfs_attach_aio_context(BlockDriverState *bs, - static void nfs_client_close(NFSClient *client) - { - if (client->context) { -+ qemu_mutex_lock(&client->mutex); -+ aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), -+ false, NULL, NULL, NULL, NULL); -+ qemu_mutex_unlock(&client->mutex); - if (client->fh) { - nfs_close(client->context, client->fh); - client->fh = NULL; - } -- aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), -- false, NULL, NULL, NULL, NULL); - nfs_destroy_context(client->context); - client->context = NULL; - } --- -2.23.0 diff --git a/block-posix-Always-allocate-the-first-block.patch b/block-posix-Always-allocate-the-first-block.patch deleted file mode 100644 index 166d73957ce0569929276d446a1934be17cad612..0000000000000000000000000000000000000000 --- a/block-posix-Always-allocate-the-first-block.patch +++ /dev/null @@ -1,343 +0,0 @@ -From 3d018ff3bdd8aec260254036b600cfa8d694ced4 Mon Sep 17 00:00:00 2001 -From: Nir Soffer -Date: Tue, 27 Aug 2019 04:05:27 +0300 -Subject: [PATCH] block: posix: Always allocate the first block - -When creating an image with preallocation "off" or "falloc", the first -block of the image is typically not allocated. When using Gluster -storage backed by XFS filesystem, reading this block using direct I/O -succeeds regardless of request length, fooling alignment detection. - -In this case we fallback to a safe value (4096) instead of the optimal -value (512), which may lead to unneeded data copying when aligning -requests. Allocating the first block avoids the fallback. - -Since we allocate the first block even with preallocation=off, we no -longer create images with zero disk size: - - $ ./qemu-img create -f raw test.raw 1g - Formatting 'test.raw', fmt=raw size=1073741824 - - $ ls -lhs test.raw - 4.0K -rw-r--r--. 1 nsoffer nsoffer 1.0G Aug 16 23:48 test.raw - -And converting the image requires additional cluster: - - $ ./qemu-img measure -f raw -O qcow2 test.raw - required size: 458752 - fully allocated size: 1074135040 - -When using format like vmdk with multiple files per image, we allocate -one block per file: - - $ ./qemu-img create -f vmdk -o subformat=twoGbMaxExtentFlat test.vmdk 4g - Formatting 'test.vmdk', fmt=vmdk size=4294967296 compat6=off hwversion=undefined subformat=twoGbMaxExtentFlat - - $ ls -lhs test*.vmdk - 4.0K -rw-r--r--. 1 nsoffer nsoffer 2.0G Aug 27 03:23 test-f001.vmdk - 4.0K -rw-r--r--. 1 nsoffer nsoffer 2.0G Aug 27 03:23 test-f002.vmdk - 4.0K -rw-r--r--. 1 nsoffer nsoffer 353 Aug 27 03:23 test.vmdk - -I did quick performance test for copying disks with qemu-img convert to -new raw target image to Gluster storage with sector size of 512 bytes: - - for i in $(seq 10); do - rm -f dst.raw - sleep 10 - time ./qemu-img convert -f raw -O raw -t none -T none src.raw dst.raw - done - -Here is a table comparing the total time spent: - -Type Before(s) After(s) Diff(%) ---------------------------------------- -real 530.028 469.123 -11.4 -user 17.204 10.768 -37.4 -sys 17.881 7.011 -60.7 - -We can see very clear improvement in CPU usage. - -Signed-off-by: Nir Soffer -Message-id: 20190827010528.8818-2-nsoffer@redhat.com -Reviewed-by: Max Reitz -Signed-off-by: Max Reitz - -(cherry picked from commit 3a20013fbb26d2a1bd11ef148eefdb1508783787) - -Signed-off-by: Michael Roth ---- - block/file-posix.c | 51 +++++++++++++++++++ - tests/qemu-iotests/059.out | 2 +- - tests/qemu-iotests/{150.out => 150.out.qcow2} | 0 - tests/qemu-iotests/150.out.raw | 12 +++++ - tests/qemu-iotests/175 | 19 ++++--- - tests/qemu-iotests/175.out | 8 +-- - tests/qemu-iotests/178.out.qcow2 | 4 +- - tests/qemu-iotests/221.out | 12 +++-- - tests/qemu-iotests/253.out | 12 +++-- - 9 files changed, 99 insertions(+), 21 deletions(-) - rename tests/qemu-iotests/{150.out => 150.out.qcow2} (100%) - create mode 100644 tests/qemu-iotests/150.out.raw - -diff --git a/block/file-posix.c b/block/file-posix.c -index be32dd8c51..2184aa980c 100644 ---- a/block/file-posix.c -+++ b/block/file-posix.c -@@ -1674,6 +1674,43 @@ static int handle_aiocb_discard(void *opaque) - return ret; - } - -+/* -+ * Help alignment probing by allocating the first block. -+ * -+ * When reading with direct I/O from unallocated area on Gluster backed by XFS, -+ * reading succeeds regardless of request length. In this case we fallback to -+ * safe alignment which is not optimal. Allocating the first block avoids this -+ * fallback. -+ * -+ * fd may be opened with O_DIRECT, but we don't know the buffer alignment or -+ * request alignment, so we use safe values. -+ * -+ * Returns: 0 on success, -errno on failure. Since this is an optimization, -+ * caller may ignore failures. -+ */ -+static int allocate_first_block(int fd, size_t max_size) -+{ -+ size_t write_size = (max_size < MAX_BLOCKSIZE) -+ ? BDRV_SECTOR_SIZE -+ : MAX_BLOCKSIZE; -+ size_t max_align = MAX(MAX_BLOCKSIZE, getpagesize()); -+ void *buf; -+ ssize_t n; -+ int ret; -+ -+ buf = qemu_memalign(max_align, write_size); -+ memset(buf, 0, write_size); -+ -+ do { -+ n = pwrite(fd, buf, write_size, 0); -+ } while (n == -1 && errno == EINTR); -+ -+ ret = (n == -1) ? -errno : 0; -+ -+ qemu_vfree(buf); -+ return ret; -+} -+ - static int handle_aiocb_truncate(void *opaque) - { - RawPosixAIOData *aiocb = opaque; -@@ -1713,6 +1750,17 @@ static int handle_aiocb_truncate(void *opaque) - /* posix_fallocate() doesn't set errno. */ - error_setg_errno(errp, -result, - "Could not preallocate new data"); -+ } else if (current_length == 0) { -+ /* -+ * posix_fallocate() uses fallocate() if the filesystem -+ * supports it, or fallback to manually writing zeroes. If -+ * fallocate() was used, unaligned reads from the fallocated -+ * area in raw_probe_alignment() will succeed, hence we need to -+ * allocate the first block. -+ * -+ * Optimize future alignment probing; ignore failures. -+ */ -+ allocate_first_block(fd, offset); - } - } else { - result = 0; -@@ -1774,6 +1822,9 @@ static int handle_aiocb_truncate(void *opaque) - if (ftruncate(fd, offset) != 0) { - result = -errno; - error_setg_errno(errp, -result, "Could not resize file"); -+ } else if (current_length == 0 && offset > current_length) { -+ /* Optimize future alignment probing; ignore failures. */ -+ allocate_first_block(fd, offset); - } - return result; - default: -diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out -index 4fab42a28c..fe3f861f3c 100644 ---- a/tests/qemu-iotests/059.out -+++ b/tests/qemu-iotests/059.out -@@ -27,7 +27,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000 subformat=twoGbMax - image: TEST_DIR/t.vmdk - file format: vmdk - virtual size: 0.977 TiB (1073741824000 bytes) --disk size: 16 KiB -+disk size: 1.97 MiB - Format specific information: - cid: XXXXXXXX - parent cid: XXXXXXXX -diff --git a/tests/qemu-iotests/150.out b/tests/qemu-iotests/150.out.qcow2 -similarity index 100% -rename from tests/qemu-iotests/150.out -rename to tests/qemu-iotests/150.out.qcow2 -diff --git a/tests/qemu-iotests/150.out.raw b/tests/qemu-iotests/150.out.raw -new file mode 100644 -index 0000000000..3cdc7727a5 ---- /dev/null -+++ b/tests/qemu-iotests/150.out.raw -@@ -0,0 +1,12 @@ -+QA output created by 150 -+ -+=== Mapping sparse conversion === -+ -+Offset Length File -+0 0x1000 TEST_DIR/t.IMGFMT -+ -+=== Mapping non-sparse conversion === -+ -+Offset Length File -+0 0x100000 TEST_DIR/t.IMGFMT -+*** done -diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175 -index 51e62c8276..7ba28b3c1b 100755 ---- a/tests/qemu-iotests/175 -+++ b/tests/qemu-iotests/175 -@@ -37,14 +37,16 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 - # the file size. This function hides the resulting difference in the - # stat -c '%b' output. - # Parameter 1: Number of blocks an empty file occupies --# Parameter 2: Image size in bytes -+# Parameter 2: Minimal number of blocks in an image -+# Parameter 3: Image size in bytes - _filter_blocks() - { - extra_blocks=$1 -- img_size=$2 -+ min_blocks=$2 -+ img_size=$3 - -- sed -e "s/blocks=$extra_blocks\\(\$\\|[^0-9]\\)/nothing allocated/" \ -- -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/everything allocated/" -+ sed -e "s/blocks=$min_blocks\\(\$\\|[^0-9]\\)/min allocation/" \ -+ -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/max allocation/" - } - - # get standard environment, filters and checks -@@ -60,16 +62,21 @@ size=$((1 * 1024 * 1024)) - touch "$TEST_DIR/empty" - extra_blocks=$(stat -c '%b' "$TEST_DIR/empty") - -+# We always write the first byte; check how many blocks this filesystem -+# allocates to match empty image alloation. -+printf "\0" > "$TEST_DIR/empty" -+min_blocks=$(stat -c '%b' "$TEST_DIR/empty") -+ - echo - echo "== creating image with default preallocation ==" - _make_test_img $size | _filter_imgfmt --stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size -+stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size - - for mode in off full falloc; do - echo - echo "== creating image with preallocation $mode ==" - IMGOPTS=preallocation=$mode _make_test_img $size | _filter_imgfmt -- stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size -+ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size - done - - # success, all done -diff --git a/tests/qemu-iotests/175.out b/tests/qemu-iotests/175.out -index 6d9a5ed84e..263e521262 100644 ---- a/tests/qemu-iotests/175.out -+++ b/tests/qemu-iotests/175.out -@@ -2,17 +2,17 @@ QA output created by 175 - - == creating image with default preallocation == - Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 --size=1048576, nothing allocated -+size=1048576, min allocation - - == creating image with preallocation off == - Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=off --size=1048576, nothing allocated -+size=1048576, min allocation - - == creating image with preallocation full == - Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=full --size=1048576, everything allocated -+size=1048576, max allocation - - == creating image with preallocation falloc == - Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=falloc --size=1048576, everything allocated -+size=1048576, max allocation - *** done -diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2 -index 55a8dc926f..9e7d8c44df 100644 ---- a/tests/qemu-iotests/178.out.qcow2 -+++ b/tests/qemu-iotests/178.out.qcow2 -@@ -101,7 +101,7 @@ converted image file size in bytes: 196608 - == raw input image with data (human) == - - Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824 --required size: 393216 -+required size: 458752 - fully allocated size: 1074135040 - wrote 512/512 bytes at offset 512 - 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -@@ -257,7 +257,7 @@ converted image file size in bytes: 196608 - - Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824 - { -- "required": 393216, -+ "required": 458752, - "fully-allocated": 1074135040 - } - wrote 512/512 bytes at offset 512 -diff --git a/tests/qemu-iotests/221.out b/tests/qemu-iotests/221.out -index 9f9dd52bb0..dca024a0c3 100644 ---- a/tests/qemu-iotests/221.out -+++ b/tests/qemu-iotests/221.out -@@ -3,14 +3,18 @@ QA output created by 221 - === Check mapping of unaligned raw image === - - Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65537 --[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] --[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] -+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, -+{ "start": 4096, "length": 61952, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] -+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, -+{ "start": 4096, "length": 61952, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] - wrote 1/1 bytes at offset 65536 - 1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) --[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, -+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, -+{ "start": 4096, "length": 61440, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, - { "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, - { "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] --[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, -+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, -+{ "start": 4096, "length": 61440, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, - { "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, - { "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] - *** done -diff --git a/tests/qemu-iotests/253.out b/tests/qemu-iotests/253.out -index 607c0baa0b..3d08b305d7 100644 ---- a/tests/qemu-iotests/253.out -+++ b/tests/qemu-iotests/253.out -@@ -3,12 +3,16 @@ QA output created by 253 - === Check mapping of unaligned raw image === - - Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048575 --[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] --[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] -+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, -+{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] -+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, -+{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] - wrote 65535/65535 bytes at offset 983040 - 63.999 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) --[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, -+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, -+{ "start": 4096, "length": 978944, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, - { "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] --[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, -+[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, -+{ "start": 4096, "length": 978944, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, - { "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] - *** done --- -2.23.0 diff --git a/block-qcow2-Fix-corruption-introduced-by-commit-8ac0.patch b/block-qcow2-Fix-corruption-introduced-by-commit-8ac0.patch deleted file mode 100644 index f77cc06c60dd36ccd84a5ad5c5e9748bb2126c08..0000000000000000000000000000000000000000 --- a/block-qcow2-Fix-corruption-introduced-by-commit-8ac0.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 84f22c728520792f1010074e0d5ac2ec8e2e372c Mon Sep 17 00:00:00 2001 -From: Maxim Levitsky -Date: Sun, 15 Sep 2019 23:36:53 +0300 -Subject: [PATCH] block/qcow2: Fix corruption introduced by commit 8ac0f15f335 - -This fixes subtle corruption introduced by luks threaded encryption -in commit 8ac0f15f335 - -Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1745922 - -The corruption happens when we do a write that - * writes to two or more unallocated clusters at once - * doesn't fully cover the first sector - * doesn't fully cover the last sector - * uses luks encryption - -In this case, when allocating the new clusters we COW both areas -prior to the write and after the write, and we encrypt them. - -The above mentioned commit accidentally made it so we encrypt the -second COW area using the physical cluster offset of the first area. - -The problem is that offset_in_cluster in do_perform_cow_encrypt -can be larger that the cluster size, thus cluster_offset -will no longer point to the start of the cluster at which encrypted -area starts. - -Next patch in this series will refactor the code to avoid all these -assumptions. - -In the bugreport that was triggered by rebasing a luks image to new, -zero filled base, which lot of such writes, and causes some files -with zero areas to contain garbage there instead. -But as described above it can happen elsewhere as well - -Signed-off-by: Maxim Levitsky -Reviewed-by: Vladimir Sementsov-Ogievskiy -Message-id: 20190915203655.21638-2-mlevitsk@redhat.com -Reviewed-by: Max Reitz -Signed-off-by: Max Reitz -(cherry picked from commit 38e7d54bdc518b5a05a922467304bcace2396945) -Signed-off-by: Michael Roth ---- - block/qcow2-cluster.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c -index cc5609e27a..760564c8fb 100644 ---- a/block/qcow2-cluster.c -+++ b/block/qcow2-cluster.c -@@ -473,9 +473,10 @@ static bool coroutine_fn do_perform_cow_encrypt(BlockDriverState *bs, - assert((offset_in_cluster & ~BDRV_SECTOR_MASK) == 0); - assert((bytes & ~BDRV_SECTOR_MASK) == 0); - assert(s->crypto); -- if (qcow2_co_encrypt(bs, cluster_offset, -- src_cluster_offset + offset_in_cluster, -- buffer, bytes) < 0) { -+ if (qcow2_co_encrypt(bs, -+ start_of_cluster(s, cluster_offset + offset_in_cluster), -+ src_cluster_offset + offset_in_cluster, -+ buffer, bytes) < 0) { - return false; - } - } --- -2.23.0 diff --git a/block-qcow2-do-free-crypto_opts-in-qcow2_close.patch b/block-qcow2-do-free-crypto_opts-in-qcow2_close.patch deleted file mode 100644 index 44b0ea19e95b95bbd583034e9c830e3dd6d647e6..0000000000000000000000000000000000000000 --- a/block-qcow2-do-free-crypto_opts-in-qcow2_close.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 88ef4e1862987227f8b87228cff94be3af66d054 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Thu, 27 Feb 2020 09:29:49 +0800 -Subject: [PATCH 01/14] block/qcow2: do free crypto_opts in qcow2_close() - -'crypto_opts' forgot to free in qcow2_close(), this patch fix the bellow leak stack: - -Direct leak of 24 byte(s) in 1 object(s) allocated from: - #0 0x7f0edd81f970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970) - #1 0x7f0edc6d149d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d) - #2 0x55d7eaede63d in qobject_input_start_struct /mnt/sdb/qemu-new/qemu_test/qemu/qapi/qobject-input-visitor.c:295 - #3 0x55d7eaed78b8 in visit_start_struct /mnt/sdb/qemu-new/qemu_test/qemu/qapi/qapi-visit-core.c:49 - #4 0x55d7eaf5140b in visit_type_QCryptoBlockOpenOptions qapi/qapi-visit-crypto.c:290 - #5 0x55d7eae43af3 in block_crypto_open_opts_init /mnt/sdb/qemu-new/qemu_test/qemu/block/crypto.c:163 - #6 0x55d7eacd2924 in qcow2_update_options_prepare /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1148 - #7 0x55d7eacd33f7 in qcow2_update_options /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1232 - #8 0x55d7eacd9680 in qcow2_do_open /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1512 - #9 0x55d7eacdc55e in qcow2_open_entry /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1792 - #10 0x55d7eacdc8fe in qcow2_open /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:1819 - #11 0x55d7eac3742d in bdrv_open_driver /mnt/sdb/qemu-new/qemu_test/qemu/block.c:1317 - #12 0x55d7eac3e990 in bdrv_open_common /mnt/sdb/qemu-new/qemu_test/qemu/block.c:1575 - #13 0x55d7eac4442c in bdrv_open_inherit /mnt/sdb/qemu-new/qemu_test/qemu/block.c:3126 - #14 0x55d7eac45c3f in bdrv_open /mnt/sdb/qemu-new/qemu_test/qemu/block.c:3219 - #15 0x55d7ead8e8a4 in blk_new_open /mnt/sdb/qemu-new/qemu_test/qemu/block/block-backend.c:397 - #16 0x55d7eacde74c in qcow2_co_create /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:3534 - #17 0x55d7eacdfa6d in qcow2_co_create_opts /mnt/sdb/qemu-new/qemu_test/qemu/block/qcow2.c:3668 - #18 0x55d7eac1c678 in bdrv_create_co_entry /mnt/sdb/qemu-new/qemu_test/qemu/block.c:485 - #19 0x55d7eb0024d2 in coroutine_trampoline /mnt/sdb/qemu-new/qemu_test/qemu/util/coroutine-ucontext.c:115 - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan -Reviewed-by: Max Reitz -Message-Id: <20200227012950.12256-2-pannengyuan@huawei.com> -Signed-off-by: Max Reitz -Signed-off-by: Peng Liang ---- - block/qcow2.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/block/qcow2.c b/block/qcow2.c -index 1909df6e1d24..27c54b9905aa 100644 ---- a/block/qcow2.c -+++ b/block/qcow2.c -@@ -2408,6 +2408,7 @@ static void qcow2_close(BlockDriverState *bs) - - qcrypto_block_free(s->crypto); - s->crypto = NULL; -+ qapi_free_QCryptoBlockOpenOptions(s->crypto_opts); - - g_free(s->unknown_header_fields); - cleanup_unknown_header_ext(bs); --- -2.26.2 - diff --git a/block-qcow2-threads-fix-qcow2_decompress.patch b/block-qcow2-threads-fix-qcow2_decompress.patch deleted file mode 100644 index d2fd9ee74fc5b57fb57ee1f655763895f1fe4356..0000000000000000000000000000000000000000 --- a/block-qcow2-threads-fix-qcow2_decompress.patch +++ /dev/null @@ -1,75 +0,0 @@ -From a583b6b616b086d3fdce93e255d24ab2c865efd3 Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Mon, 2 Mar 2020 18:09:30 +0300 -Subject: [PATCH 03/14] block/qcow2-threads: fix qcow2_decompress -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -On success path we return what inflate() returns instead of 0. And it -most probably works for Z_STREAM_END as it is positive, but is -definitely broken for Z_BUF_ERROR. - -While being here, switch to errno return code, to be closer to -qcow2_compress API (and usual expectations). - -Revert condition in if to be more positive. Drop dead initialization of -ret. - -Cc: qemu-stable@nongnu.org # v4.0 -Fixes: 341926ab83e2b -Signed-off-by: Vladimir Sementsov-Ogievskiy -Message-Id: <20200302150930.16218-1-vsementsov@virtuozzo.com> -Reviewed-by: Alberto Garcia -Reviewed-by: Ján Tomko -Signed-off-by: Max Reitz -Signed-off-by: Peng Liang ---- - block/qcow2-threads.c | 12 +++++++----- - 1 file changed, 7 insertions(+), 5 deletions(-) - -diff --git a/block/qcow2-threads.c b/block/qcow2-threads.c -index 3b1e63fe414d..449cd3c0a1f4 100644 ---- a/block/qcow2-threads.c -+++ b/block/qcow2-threads.c -@@ -128,12 +128,12 @@ static ssize_t qcow2_compress(void *dest, size_t dest_size, - * @src - source buffer, @src_size bytes - * - * Returns: 0 on success -- * -1 on fail -+ * -EIO on fail - */ - static ssize_t qcow2_decompress(void *dest, size_t dest_size, - const void *src, size_t src_size) - { -- int ret = 0; -+ int ret; - z_stream strm; - - memset(&strm, 0, sizeof(strm)); -@@ -144,17 +144,19 @@ static ssize_t qcow2_decompress(void *dest, size_t dest_size, - - ret = inflateInit2(&strm, -12); - if (ret != Z_OK) { -- return -1; -+ return -EIO; - } - - ret = inflate(&strm, Z_FINISH); -- if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) || strm.avail_out != 0) { -+ if ((ret == Z_STREAM_END || ret == Z_BUF_ERROR) && strm.avail_out == 0) { - /* - * We approve Z_BUF_ERROR because we need @dest buffer to be filled, but - * @src buffer may be processed partly (because in qcow2 we know size of - * compressed data with precision of one sector) - */ -- ret = -1; -+ ret = 0; -+ } else { -+ ret = -EIO; - } - - inflateEnd(&strm); --- -2.26.2 - diff --git a/block-snapshot-Restrict-set-of-snapshot-nodes.patch b/block-snapshot-Restrict-set-of-snapshot-nodes.patch deleted file mode 100644 index c29f30adc897f5b60bf8004b7f317b6e6257bf3a..0000000000000000000000000000000000000000 --- a/block-snapshot-Restrict-set-of-snapshot-nodes.patch +++ /dev/null @@ -1,124 +0,0 @@ -From 7a8aa6c734bb1c2927ad0cc1d10bcacb53cf4ae3 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 17 Sep 2019 12:26:23 +0200 -Subject: [PATCH] block/snapshot: Restrict set of snapshot nodes - -Nodes involved in internal snapshots were those that were returned by -bdrv_next(), inserted and not read-only. bdrv_next() in turn returns all -nodes that are either the root node of a BlockBackend or monitor-owned -nodes. - -With the typical -drive use, this worked well enough. However, in the -typical -blockdev case, the user defines one node per option, making all -nodes monitor-owned nodes. This includes protocol nodes etc. which often -are not snapshottable, so "savevm" only returns an error. - -Change the conditions so that internal snapshot still include all nodes -that have a BlockBackend attached (we definitely want to snapshot -anything attached to a guest device and probably also the built-in NBD -server; snapshotting block job BlockBackends is more of an accident, but -a preexisting one), but other monitor-owned nodes are only included if -they have no parents. - -This makes internal snapshots usable again with typical -blockdev -configurations. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Kevin Wolf -Reviewed-by: Eric Blake -Reviewed-by: Peter Krempa -Tested-by: Peter Krempa -(cherry picked from commit 05f4aced658a02b02d3e89a6c7a2281008fcf26c) -Signed-off-by: Michael Roth ---- - block/snapshot.c | 26 +++++++++++++++++++------- - 1 file changed, 19 insertions(+), 7 deletions(-) - -diff --git a/block/snapshot.c b/block/snapshot.c -index f2f48f926a..8081616ae9 100644 ---- a/block/snapshot.c -+++ b/block/snapshot.c -@@ -31,6 +31,7 @@ - #include "qapi/qmp/qerror.h" - #include "qapi/qmp/qstring.h" - #include "qemu/option.h" -+#include "sysemu/block-backend.h" - - QemuOptsList internal_snapshot_opts = { - .name = "snapshot", -@@ -384,6 +385,16 @@ int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs, - return ret; - } - -+static bool bdrv_all_snapshots_includes_bs(BlockDriverState *bs) -+{ -+ if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) { -+ return false; -+ } -+ -+ /* Include all nodes that are either in use by a BlockBackend, or that -+ * aren't attached to any node, but owned by the monitor. */ -+ return bdrv_has_blk(bs) || QLIST_EMPTY(&bs->parents); -+} - - /* Group operations. All block drivers are involved. - * These functions will properly handle dataplane (take aio_context_acquire -@@ -399,7 +410,7 @@ bool bdrv_all_can_snapshot(BlockDriverState **first_bad_bs) - AioContext *ctx = bdrv_get_aio_context(bs); - - aio_context_acquire(ctx); -- if (bdrv_is_inserted(bs) && !bdrv_is_read_only(bs)) { -+ if (bdrv_all_snapshots_includes_bs(bs)) { - ok = bdrv_can_snapshot(bs); - } - aio_context_release(ctx); -@@ -426,8 +437,9 @@ int bdrv_all_delete_snapshot(const char *name, BlockDriverState **first_bad_bs, - AioContext *ctx = bdrv_get_aio_context(bs); - - aio_context_acquire(ctx); -- if (bdrv_can_snapshot(bs) && -- bdrv_snapshot_find(bs, snapshot, name) >= 0) { -+ if (bdrv_all_snapshots_includes_bs(bs) && -+ bdrv_snapshot_find(bs, snapshot, name) >= 0) -+ { - ret = bdrv_snapshot_delete(bs, snapshot->id_str, - snapshot->name, err); - } -@@ -455,7 +467,7 @@ int bdrv_all_goto_snapshot(const char *name, BlockDriverState **first_bad_bs, - AioContext *ctx = bdrv_get_aio_context(bs); - - aio_context_acquire(ctx); -- if (bdrv_can_snapshot(bs)) { -+ if (bdrv_all_snapshots_includes_bs(bs)) { - ret = bdrv_snapshot_goto(bs, name, errp); - } - aio_context_release(ctx); -@@ -481,7 +493,7 @@ int bdrv_all_find_snapshot(const char *name, BlockDriverState **first_bad_bs) - AioContext *ctx = bdrv_get_aio_context(bs); - - aio_context_acquire(ctx); -- if (bdrv_can_snapshot(bs)) { -+ if (bdrv_all_snapshots_includes_bs(bs)) { - err = bdrv_snapshot_find(bs, &sn, name); - } - aio_context_release(ctx); -@@ -512,7 +524,7 @@ int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn, - if (bs == vm_state_bs) { - sn->vm_state_size = vm_state_size; - err = bdrv_snapshot_create(bs, sn); -- } else if (bdrv_can_snapshot(bs)) { -+ } else if (bdrv_all_snapshots_includes_bs(bs)) { - sn->vm_state_size = 0; - err = bdrv_snapshot_create(bs, sn); - } -@@ -538,7 +550,7 @@ BlockDriverState *bdrv_all_find_vmstate_bs(void) - bool found; - - aio_context_acquire(ctx); -- found = bdrv_can_snapshot(bs); -+ found = bdrv_all_snapshots_includes_bs(bs) && bdrv_can_snapshot(bs); - aio_context_release(ctx); - - if (found) { --- -2.23.0 diff --git a/block-vvfat-Fix-bad-printf-format-specifiers.patch b/block-vvfat-Fix-bad-printf-format-specifiers.patch deleted file mode 100644 index 597b9782683778c799e3192fd66d27eb230eee8e..0000000000000000000000000000000000000000 --- a/block-vvfat-Fix-bad-printf-format-specifiers.patch +++ /dev/null @@ -1,77 +0,0 @@ -From c9a4e85610bffe1803648c431e4cff4539a42323 Mon Sep 17 00:00:00 2001 -From: AlexChen -Date: Tue, 3 Nov 2020 17:42:56 +0800 -Subject: [PATCH] block/vvfat: Fix bad printf format specifiers - -We should use printf format specifier "%u" instead of "%d" for -argument of type "unsigned int". -In addition, fix two error format problems found by checkpatch.pl: -ERROR: space required after that ',' (ctx:VxV) -+ fprintf(stderr,"%s attributes=0x%02x begin=%u size=%d\n", - ^ -ERROR: line over 90 characters -+ fprintf(stderr, "%d, %s (%u, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action); - -Reported-by: Euler Robot -Signed-off-by: Alex Chen -Message-Id: <5FA12620.6030705@huawei.com> -Signed-off-by: Kevin Wolf -(cherry-picked from commit c9eb2f3e38) ---- - block/vvfat.c | 12 +++++++----- - 1 file changed, 7 insertions(+), 5 deletions(-) - -diff --git a/block/vvfat.c b/block/vvfat.c -index f6c28805dd..5dc8d6eb4c 100644 ---- a/block/vvfat.c -+++ b/block/vvfat.c -@@ -1453,7 +1453,7 @@ static void print_direntry(const direntry_t* direntry) - for(i=0;i<11;i++) - ADD_CHAR(direntry->name[i]); - buffer[j] = 0; -- fprintf(stderr,"%s attributes=0x%02x begin=%d size=%d\n", -+ fprintf(stderr, "%s attributes=0x%02x begin=%u size=%u\n", - buffer, - direntry->attributes, - begin_of_direntry(direntry),le32_to_cpu(direntry->size)); -@@ -1462,7 +1462,7 @@ static void print_direntry(const direntry_t* direntry) - - static void print_mapping(const mapping_t* mapping) - { -- fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, " -+ fprintf(stderr, "mapping (%p): begin, end = %u, %u, dir_index = %u, " - "first_mapping_index = %d, name = %s, mode = 0x%x, " , - mapping, mapping->begin, mapping->end, mapping->dir_index, - mapping->first_mapping_index, mapping->path, mapping->mode); -@@ -1470,7 +1470,7 @@ static void print_mapping(const mapping_t* mapping) - if (mapping->mode & MODE_DIRECTORY) - fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index); - else -- fprintf(stderr, "offset = %d\n", mapping->info.file.offset); -+ fprintf(stderr, "offset = %u\n", mapping->info.file.offset); - } - #endif - -@@ -1604,7 +1604,7 @@ typedef struct commit_t { - static void clear_commits(BDRVVVFATState* s) - { - int i; --DLOG(fprintf(stderr, "clear_commits (%d commits)\n", s->commits.next)); -+DLOG(fprintf(stderr, "clear_commits (%u commits)\n", s->commits.next)); - for (i = 0; i < s->commits.next; i++) { - commit_t* commit = array_get(&(s->commits), i); - assert(commit->path || commit->action == ACTION_WRITEOUT); -@@ -2660,7 +2660,9 @@ static int handle_renames_and_mkdirs(BDRVVVFATState* s) - fprintf(stderr, "handle_renames\n"); - for (i = 0; i < s->commits.next; i++) { - commit_t* commit = array_get(&(s->commits), i); -- fprintf(stderr, "%d, %s (%d, %d)\n", i, commit->path ? commit->path : "(null)", commit->param.rename.cluster, commit->action); -+ fprintf(stderr, "%d, %s (%u, %d)\n", i, -+ commit->path ? commit->path : "(null)", -+ commit->param.rename.cluster, commit->action); - } - #endif - --- -2.27.0 - diff --git a/blockdev-Return-bs-to-the-proper-context-on-snapshot.patch b/blockdev-Return-bs-to-the-proper-context-on-snapshot.patch deleted file mode 100644 index a232c7450689ae13c12e215803a7d1a2bca4c158..0000000000000000000000000000000000000000 --- a/blockdev-Return-bs-to-the-proper-context-on-snapshot.patch +++ /dev/null @@ -1,93 +0,0 @@ -From dc6b61f12750b3ab5a3965af2ec758750389233d Mon Sep 17 00:00:00 2001 -From: Sergio Lopez -Date: Wed, 8 Jan 2020 15:31:37 +0100 -Subject: [PATCH] blockdev: Return bs to the proper context on snapshot abort - -external_snapshot_abort() calls to bdrv_set_backing_hd(), which -returns state->old_bs to the main AioContext, as it's intended to be -used then the BDS is going to be released. As that's not the case when -aborting an external snapshot, return it to the AioContext it was -before the call. - -This issue can be triggered by issuing a transaction with two actions, -a proper blockdev-snapshot-sync and a bogus one, so the second will -trigger a transaction abort. This results in a crash with an stack -trace like this one: - - #0 0x00007fa1048b28df in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 - #1 0x00007fa10489ccf5 in __GI_abort () at abort.c:79 - #2 0x00007fa10489cbc9 in __assert_fail_base - (fmt=0x7fa104a03300 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x5572240b44d8 "bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs)", file=0x557224014d30 "block.c", line=2240, function=) at assert.c:92 - #3 0x00007fa1048aae96 in __GI___assert_fail - (assertion=assertion@entry=0x5572240b44d8 "bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs)", file=file@entry=0x557224014d30 "block.c", line=line@entry=2240, function=function@entry=0x5572240b5d60 <__PRETTY_FUNCTION__.31620> "bdrv_replace_child_noperm") at assert.c:101 - #4 0x0000557223e631f8 in bdrv_replace_child_noperm (child=0x557225b9c980, new_bs=new_bs@entry=0x557225c42e40) at block.c:2240 - #5 0x0000557223e68be7 in bdrv_replace_node (from=0x557226951a60, to=0x557225c42e40, errp=0x5572247d6138 ) at block.c:4196 - #6 0x0000557223d069c4 in external_snapshot_abort (common=0x557225d7e170) at blockdev.c:1731 - #7 0x0000557223d069c4 in external_snapshot_abort (common=0x557225d7e170) at blockdev.c:1717 - #8 0x0000557223d09013 in qmp_transaction (dev_list=, has_props=, props=0x557225cc7d70, errp=errp@entry=0x7ffe704c0c98) at blockdev.c:2360 - #9 0x0000557223e32085 in qmp_marshal_transaction (args=, ret=, errp=0x7ffe704c0d08) at qapi/qapi-commands-transaction.c:44 - #10 0x0000557223ee798c in do_qmp_dispatch (errp=0x7ffe704c0d00, allow_oob=, request=, cmds=0x5572247d3cc0 ) at qapi/qmp-dispatch.c:132 - #11 0x0000557223ee798c in qmp_dispatch (cmds=0x5572247d3cc0 , request=, allow_oob=) at qapi/qmp-dispatch.c:175 - #12 0x0000557223e06141 in monitor_qmp_dispatch (mon=0x557225c69ff0, req=) at monitor/qmp.c:120 - #13 0x0000557223e0678a in monitor_qmp_bh_dispatcher (data=) at monitor/qmp.c:209 - #14 0x0000557223f2f366 in aio_bh_call (bh=0x557225b9dc60) at util/async.c:117 - #15 0x0000557223f2f366 in aio_bh_poll (ctx=ctx@entry=0x557225b9c840) at util/async.c:117 - #16 0x0000557223f32754 in aio_dispatch (ctx=0x557225b9c840) at util/aio-posix.c:459 - #17 0x0000557223f2f242 in aio_ctx_dispatch (source=, callback=, user_data=) at util/async.c:260 - #18 0x00007fa10913467d in g_main_dispatch (context=0x557225c28e80) at gmain.c:3176 - #19 0x00007fa10913467d in g_main_context_dispatch (context=context@entry=0x557225c28e80) at gmain.c:3829 - #20 0x0000557223f31808 in glib_pollfds_poll () at util/main-loop.c:219 - #21 0x0000557223f31808 in os_host_main_loop_wait (timeout=) at util/main-loop.c:242 - #22 0x0000557223f31808 in main_loop_wait (nonblocking=) at util/main-loop.c:518 - #23 0x0000557223d13201 in main_loop () at vl.c:1828 - #24 0x0000557223bbfb82 in main (argc=, argv=, envp=) at vl.c:4504 - -RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1779036 -Signed-off-by: Sergio Lopez -Signed-off-by: Kevin Wolf ---- - blockdev.c | 21 +++++++++++++++++++++ - 1 file changed, 21 insertions(+) - -diff --git a/blockdev.c b/blockdev.c -index 5088541591..79112be2e6 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -1774,6 +1774,8 @@ static void external_snapshot_abort(BlkActionState *common) - if (state->new_bs) { - if (state->overlay_appended) { - AioContext *aio_context; -+ AioContext *tmp_context; -+ int ret; - - aio_context = bdrv_get_aio_context(state->old_bs); - aio_context_acquire(aio_context); -@@ -1781,6 +1783,25 @@ static void external_snapshot_abort(BlkActionState *common) - bdrv_ref(state->old_bs); /* we can't let bdrv_set_backind_hd() - close state->old_bs; we need it */ - bdrv_set_backing_hd(state->new_bs, NULL, &error_abort); -+ -+ /* -+ * The call to bdrv_set_backing_hd() above returns state->old_bs to -+ * the main AioContext. As we're still going to be using it, return -+ * it to the AioContext it was before. -+ */ -+ tmp_context = bdrv_get_aio_context(state->old_bs); -+ if (aio_context != tmp_context) { -+ aio_context_release(aio_context); -+ aio_context_acquire(tmp_context); -+ -+ ret = bdrv_try_set_aio_context(state->old_bs, -+ aio_context, NULL); -+ assert(ret == 0); -+ -+ aio_context_release(tmp_context); -+ aio_context_acquire(aio_context); -+ } -+ - bdrv_replace_node(state->new_bs, state->old_bs, &error_abort); - bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_bs */ - --- -2.27.0 - diff --git a/blockdev-backup-utilize-do_backup_common.patch b/blockdev-backup-utilize-do_backup_common.patch deleted file mode 100644 index 6827b221978c2646d97f15e62b42b8eb34282bea..0000000000000000000000000000000000000000 --- a/blockdev-backup-utilize-do_backup_common.patch +++ /dev/null @@ -1,105 +0,0 @@ -From e5456acf2332efd0ed6106eb13cf24e6bca1ee64 Mon Sep 17 00:00:00 2001 -From: John Snow -Date: Mon, 29 Jul 2019 16:35:52 -0400 -Subject: [PATCH] blockdev-backup: utilize do_backup_common - -Signed-off-by: John Snow -Reviewed-by: Max Reitz -Message-id: 20190709232550.10724-4-jsnow@redhat.com -Signed-off-by: John Snow ---- - blockdev.c | 65 +++++------------------------------------------------- - 1 file changed, 6 insertions(+), 59 deletions(-) - -diff --git a/blockdev.c b/blockdev.c -index a29838a1c8..aa15ed1f00 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -3668,78 +3668,25 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn, - { - BlockDriverState *bs; - BlockDriverState *target_bs; -- Error *local_err = NULL; -- BdrvDirtyBitmap *bmap = NULL; - AioContext *aio_context; -- BlockJob *job = NULL; -- int job_flags = JOB_DEFAULT; -- int ret; -- -- if (!backup->has_speed) { -- backup->speed = 0; -- } -- if (!backup->has_on_source_error) { -- backup->on_source_error = BLOCKDEV_ON_ERROR_REPORT; -- } -- if (!backup->has_on_target_error) { -- backup->on_target_error = BLOCKDEV_ON_ERROR_REPORT; -- } -- if (!backup->has_job_id) { -- backup->job_id = NULL; -- } -- if (!backup->has_auto_finalize) { -- backup->auto_finalize = true; -- } -- if (!backup->has_auto_dismiss) { -- backup->auto_dismiss = true; -- } -- if (!backup->has_compress) { -- backup->compress = false; -- } -+ BlockJob *job; - - bs = bdrv_lookup_bs(backup->device, backup->device, errp); - if (!bs) { - return NULL; - } - -- aio_context = bdrv_get_aio_context(bs); -- aio_context_acquire(aio_context); -- - target_bs = bdrv_lookup_bs(backup->target, backup->target, errp); - if (!target_bs) { -- goto out; -+ return NULL; - } - -- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp); -- if (ret < 0) { -- goto out; -- } -+ aio_context = bdrv_get_aio_context(bs); -+ aio_context_acquire(aio_context); - -- if (backup->has_bitmap) { -- bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap); -- if (!bmap) { -- error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap); -- goto out; -- } -- if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) { -- goto out; -- } -- } -+ job = do_backup_common(qapi_BlockdevBackup_base(backup), -+ bs, target_bs, aio_context, txn, errp); - -- if (!backup->auto_finalize) { -- job_flags |= JOB_MANUAL_FINALIZE; -- } -- if (!backup->auto_dismiss) { -- job_flags |= JOB_MANUAL_DISMISS; -- } -- job = backup_job_create(backup->job_id, bs, target_bs, backup->speed, -- backup->sync, bmap, backup->compress, -- backup->on_source_error, backup->on_target_error, -- job_flags, NULL, NULL, txn, &local_err); -- if (local_err != NULL) { -- error_propagate(errp, local_err); -- } --out: - aio_context_release(aio_context); - return job; - } --- -2.27.0 - diff --git a/blockdev-fix-coding-style-issues-in-drive_backup_pre.patch b/blockdev-fix-coding-style-issues-in-drive_backup_pre.patch deleted file mode 100644 index e915b05a415c2e2fc76ac0e58be7cc819f457533..0000000000000000000000000000000000000000 --- a/blockdev-fix-coding-style-issues-in-drive_backup_pre.patch +++ /dev/null @@ -1,44 +0,0 @@ -From ffbf1e237d0311512c411e195278e69d710fb9cf Mon Sep 17 00:00:00 2001 -From: Sergio Lopez -Date: Wed, 8 Jan 2020 15:31:31 +0100 -Subject: [PATCH] blockdev: fix coding style issues in drive_backup_prepare - -Fix a couple of minor coding style issues in drive_backup_prepare. - -Signed-off-by: Sergio Lopez -Reviewed-by: Max Reitz -Reviewed-by: Kevin Wolf -Signed-off-by: Kevin Wolf ---- - blockdev.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/blockdev.c b/blockdev.c -index 4435795b6d..99b1cafb8f 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -3597,7 +3597,7 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, - - if (!backup->has_format) { - backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ? -- NULL : (char*) bs->drv->format_name; -+ NULL : (char *) bs->drv->format_name; - } - - /* Early check to avoid creating target */ -@@ -3607,8 +3607,10 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, - - flags = bs->open_flags | BDRV_O_RDWR; - -- /* See if we have a backing HD we can use to create our new image -- * on top of. */ -+ /* -+ * See if we have a backing HD we can use to create our new image -+ * on top of. -+ */ - if (backup->sync == MIRROR_SYNC_MODE_TOP) { - source = backing_bs(bs); - if (!source) { --- -2.27.0 - diff --git a/blockdev-honor-bdrv_try_set_aio_context-context-requ.patch b/blockdev-honor-bdrv_try_set_aio_context-context-requ.patch deleted file mode 100644 index 970057179e504e1961c766d0a68107816c750721..0000000000000000000000000000000000000000 --- a/blockdev-honor-bdrv_try_set_aio_context-context-requ.patch +++ /dev/null @@ -1,191 +0,0 @@ -From 64c6b3b911f65c19f3a235c8394f5db894c1ee6a Mon Sep 17 00:00:00 2001 -From: Sergio Lopez -Date: Wed, 8 Jan 2020 15:31:34 +0100 -Subject: [PATCH] blockdev: honor bdrv_try_set_aio_context() context - requirements - -bdrv_try_set_aio_context() requires that the old context is held, and -the new context is not held. Fix all the occurrences where it's not -done this way. - -Suggested-by: Max Reitz -Signed-off-by: Sergio Lopez -Signed-off-by: Kevin Wolf ---- - blockdev.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++------- - 1 file changed, 60 insertions(+), 8 deletions(-) - -diff --git a/blockdev.c b/blockdev.c -index d3309c205a..5088541591 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -1578,6 +1578,7 @@ static void external_snapshot_prepare(BlkActionState *common, - DO_UPCAST(ExternalSnapshotState, common, common); - TransactionAction *action = common->action; - AioContext *aio_context; -+ AioContext *old_context; - int ret; - - /* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar -@@ -1718,7 +1719,16 @@ static void external_snapshot_prepare(BlkActionState *common, - goto out; - } - -+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */ -+ old_context = bdrv_get_aio_context(state->new_bs); -+ aio_context_release(aio_context); -+ aio_context_acquire(old_context); -+ - ret = bdrv_try_set_aio_context(state->new_bs, aio_context, errp); -+ -+ aio_context_release(old_context); -+ aio_context_acquire(aio_context); -+ - if (ret < 0) { - goto out; - } -@@ -1818,11 +1828,13 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp) - BlockDriverState *target_bs; - BlockDriverState *source = NULL; - AioContext *aio_context; -+ AioContext *old_context; - QDict *options; - Error *local_err = NULL; - int flags; - int64_t size; - bool set_backing_hd = false; -+ int ret; - - assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP); - backup = common->action->u.drive_backup.data; -@@ -1911,6 +1923,21 @@ static void drive_backup_prepare(BlkActionState *common, Error **errp) - goto out; - } - -+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */ -+ old_context = bdrv_get_aio_context(target_bs); -+ aio_context_release(aio_context); -+ aio_context_acquire(old_context); -+ -+ ret = bdrv_try_set_aio_context(target_bs, aio_context, errp); -+ if (ret < 0) { -+ bdrv_unref(target_bs); -+ aio_context_release(old_context); -+ return; -+ } -+ -+ aio_context_release(old_context); -+ aio_context_acquire(aio_context); -+ - if (set_backing_hd) { - bdrv_set_backing_hd(target_bs, source, &local_err); - if (local_err) { -@@ -1990,6 +2017,8 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp) - BlockDriverState *bs; - BlockDriverState *target_bs; - AioContext *aio_context; -+ AioContext *old_context; -+ int ret; - - assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP); - backup = common->action->u.blockdev_backup.data; -@@ -2004,7 +2033,18 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp) - return; - } - -+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */ - aio_context = bdrv_get_aio_context(bs); -+ old_context = bdrv_get_aio_context(target_bs); -+ aio_context_acquire(old_context); -+ -+ ret = bdrv_try_set_aio_context(target_bs, aio_context, errp); -+ if (ret < 0) { -+ aio_context_release(old_context); -+ return; -+ } -+ -+ aio_context_release(old_context); - aio_context_acquire(aio_context); - state->bs = bs; - -@@ -3562,7 +3602,6 @@ static BlockJob *do_backup_common(BackupCommon *backup, - BlockJob *job = NULL; - BdrvDirtyBitmap *bmap = NULL; - int job_flags = JOB_DEFAULT; -- int ret; - - if (!backup->has_speed) { - backup->speed = 0; -@@ -3586,11 +3625,6 @@ static BlockJob *do_backup_common(BackupCommon *backup, - backup->compress = false; - } - -- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp); -- if (ret < 0) { -- return NULL; -- } -- - if ((backup->sync == MIRROR_SYNC_MODE_BITMAP) || - (backup->sync == MIRROR_SYNC_MODE_INCREMENTAL)) { - /* done before desugaring 'incremental' to print the right message */ -@@ -3802,6 +3836,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) - BlockDriverState *bs; - BlockDriverState *source, *target_bs; - AioContext *aio_context; -+ AioContext *old_context; - BlockMirrorBackingMode backing_mode; - Error *local_err = NULL; - QDict *options = NULL; -@@ -3914,12 +3949,22 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) - (arg->mode == NEW_IMAGE_MODE_EXISTING || - !bdrv_has_zero_init(target_bs))); - -+ -+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */ -+ old_context = bdrv_get_aio_context(target_bs); -+ aio_context_release(aio_context); -+ aio_context_acquire(old_context); -+ - ret = bdrv_try_set_aio_context(target_bs, aio_context, errp); - if (ret < 0) { - bdrv_unref(target_bs); -- goto out; -+ aio_context_release(old_context); -+ return; - } - -+ aio_context_release(old_context); -+ aio_context_acquire(aio_context); -+ - blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs, - arg->has_replaces, arg->replaces, arg->sync, - backing_mode, zero_target, -@@ -3961,6 +4006,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id, - BlockDriverState *bs; - BlockDriverState *target_bs; - AioContext *aio_context; -+ AioContext *old_context; - BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN; - Error *local_err = NULL; - bool zero_target; -@@ -3978,10 +4024,16 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id, - - zero_target = (sync == MIRROR_SYNC_MODE_FULL); - -+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */ -+ old_context = bdrv_get_aio_context(target_bs); - aio_context = bdrv_get_aio_context(bs); -- aio_context_acquire(aio_context); -+ aio_context_acquire(old_context); - - ret = bdrv_try_set_aio_context(target_bs, aio_context, errp); -+ -+ aio_context_release(old_context); -+ aio_context_acquire(aio_context); -+ - if (ret < 0) { - goto out; - } --- -2.27.0 - diff --git a/blockdev-unify-qmp_blockdev_backup-and-blockdev-back.patch b/blockdev-unify-qmp_blockdev_backup-and-blockdev-back.patch deleted file mode 100644 index 84e29fffabed38135f24a1e83cbe12538481dbac..0000000000000000000000000000000000000000 --- a/blockdev-unify-qmp_blockdev_backup-and-blockdev-back.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 6d89e4923e9c341975dbfdd2bae153ba367a1b79 Mon Sep 17 00:00:00 2001 -From: Sergio Lopez -Date: Wed, 8 Jan 2020 15:31:33 +0100 -Subject: [PATCH] blockdev: unify qmp_blockdev_backup and blockdev-backup - transaction paths - -Issuing a blockdev-backup from qmp_blockdev_backup takes a slightly -different path than when it's issued from a transaction. In the code, -this is manifested as some redundancy between do_blockdev_backup() and -blockdev_backup_prepare(). - -This change unifies both paths, merging do_blockdev_backup() and -blockdev_backup_prepare(), and changing qmp_blockdev_backup() to -create a transaction instead of calling do_backup_common() direcly. - -As a side-effect, now qmp_blockdev_backup() is executed inside a -drained section, as it happens when creating a blockdev-backup -transaction. This change is visible from the user's perspective, as -the job gets paused and immediately resumed before starting the actual -work. - -Signed-off-by: Sergio Lopez -Reviewed-by: Max Reitz -Reviewed-by: Kevin Wolf -Signed-off-by: Kevin Wolf ---- - blockdev.c | 60 ++++++++++++------------------------------------------ - 1 file changed, 13 insertions(+), 47 deletions(-) - -diff --git a/blockdev.c b/blockdev.c -index 7016054688..d3309c205a 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -1983,16 +1983,13 @@ typedef struct BlockdevBackupState { - BlockJob *job; - } BlockdevBackupState; - --static BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn, -- Error **errp); -- - static void blockdev_backup_prepare(BlkActionState *common, Error **errp) - { - BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common); - BlockdevBackup *backup; -- BlockDriverState *bs, *target; -+ BlockDriverState *bs; -+ BlockDriverState *target_bs; - AioContext *aio_context; -- Error *local_err = NULL; - - assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP); - backup = common->action->u.blockdev_backup.data; -@@ -2002,8 +1999,8 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp) - return; - } - -- target = bdrv_lookup_bs(backup->target, backup->target, errp); -- if (!target) { -+ target_bs = bdrv_lookup_bs(backup->target, backup->target, errp); -+ if (!target_bs) { - return; - } - -@@ -2014,13 +2011,10 @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp) - /* Paired with .clean() */ - bdrv_drained_begin(state->bs); - -- state->job = do_blockdev_backup(backup, common->block_job_txn, &local_err); -- if (local_err) { -- error_propagate(errp, local_err); -- goto out; -- } -+ state->job = do_backup_common(qapi_BlockdevBackup_base(backup), -+ bs, target_bs, aio_context, -+ common->block_job_txn, errp); - --out: - aio_context_release(aio_context); - } - -@@ -3672,41 +3666,13 @@ XDbgBlockGraph *qmp_x_debug_query_block_graph(Error **errp) - return bdrv_get_xdbg_block_graph(errp); - } - --BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn, -- Error **errp) -+void qmp_blockdev_backup(BlockdevBackup *backup, Error **errp) - { -- BlockDriverState *bs; -- BlockDriverState *target_bs; -- AioContext *aio_context; -- BlockJob *job; -- -- bs = bdrv_lookup_bs(backup->device, backup->device, errp); -- if (!bs) { -- return NULL; -- } -- -- target_bs = bdrv_lookup_bs(backup->target, backup->target, errp); -- if (!target_bs) { -- return NULL; -- } -- -- aio_context = bdrv_get_aio_context(bs); -- aio_context_acquire(aio_context); -- -- job = do_backup_common(qapi_BlockdevBackup_base(backup), -- bs, target_bs, aio_context, txn, errp); -- -- aio_context_release(aio_context); -- return job; --} -- --void qmp_blockdev_backup(BlockdevBackup *arg, Error **errp) --{ -- BlockJob *job; -- job = do_blockdev_backup(arg, NULL, errp); -- if (job) { -- job_start(&job->job); -- } -+ TransactionAction action = { -+ .type = TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP, -+ .u.blockdev_backup.data = backup, -+ }; -+ blockdev_do_action(&action, errp); - } - - /* Parameter check and block job starting for drive mirroring. --- -2.27.0 - diff --git a/blockdev-unify-qmp_drive_backup-and-drive-backup-tra.patch b/blockdev-unify-qmp_drive_backup-and-drive-backup-tra.patch deleted file mode 100644 index aefa05e921b7d66a09995716f8176367817d434c..0000000000000000000000000000000000000000 --- a/blockdev-unify-qmp_drive_backup-and-drive-backup-tra.patch +++ /dev/null @@ -1,406 +0,0 @@ -From 952f7f53cdd4320d1a0328481fa578dd199eb1ce Mon Sep 17 00:00:00 2001 -From: Sergio Lopez -Date: Wed, 8 Jan 2020 15:31:32 +0100 -Subject: [PATCH] blockdev: unify qmp_drive_backup and drive-backup transaction - paths - -Issuing a drive-backup from qmp_drive_backup takes a slightly -different path than when it's issued from a transaction. In the code, -this is manifested as some redundancy between do_drive_backup() and -drive_backup_prepare(). - -This change unifies both paths, merging do_drive_backup() and -drive_backup_prepare(), and changing qmp_drive_backup() to create a -transaction instead of calling do_backup_common() direcly. - -As a side-effect, now qmp_drive_backup() is executed inside a drained -section, as it happens when creating a drive-backup transaction. This -change is visible from the user's perspective, as the job gets paused -and immediately resumed before starting the actual work. - -Also fix tests 141, 185 and 219 to cope with the extra -JOB_STATUS_CHANGE lines. - -Signed-off-by: Sergio Lopez -Reviewed-by: Kevin Wolf -Signed-off-by: Kevin Wolf ---- - blockdev.c | 224 +++++++++++++++++-------------------- - tests/qemu-iotests/141.out | 2 + - tests/qemu-iotests/185.out | 2 + - tests/qemu-iotests/219 | 7 +- - tests/qemu-iotests/219.out | 8 ++ - 5 files changed, 117 insertions(+), 126 deletions(-) - -diff --git a/blockdev.c b/blockdev.c -index 99b1cafb8f..7016054688 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -1804,39 +1804,128 @@ typedef struct DriveBackupState { - BlockJob *job; - } DriveBackupState; - --static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, -- Error **errp); -+static BlockJob *do_backup_common(BackupCommon *backup, -+ BlockDriverState *bs, -+ BlockDriverState *target_bs, -+ AioContext *aio_context, -+ JobTxn *txn, Error **errp); - - static void drive_backup_prepare(BlkActionState *common, Error **errp) - { - DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common); -- BlockDriverState *bs; - DriveBackup *backup; -+ BlockDriverState *bs; -+ BlockDriverState *target_bs; -+ BlockDriverState *source = NULL; - AioContext *aio_context; -+ QDict *options; - Error *local_err = NULL; -+ int flags; -+ int64_t size; -+ bool set_backing_hd = false; - - assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP); - backup = common->action->u.drive_backup.data; - -+ if (!backup->has_mode) { -+ backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; -+ } -+ - bs = bdrv_lookup_bs(backup->device, backup->device, errp); - if (!bs) { - return; - } - -+ if (!bs->drv) { -+ error_setg(errp, "Device has no medium"); -+ return; -+ } -+ - aio_context = bdrv_get_aio_context(bs); - aio_context_acquire(aio_context); - - /* Paired with .clean() */ - bdrv_drained_begin(bs); - -- state->bs = bs; -+ if (!backup->has_format) { -+ backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ? -+ NULL : (char *) bs->drv->format_name; -+ } -+ -+ /* Early check to avoid creating target */ -+ if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) { -+ goto out; -+ } -+ -+ flags = bs->open_flags | BDRV_O_RDWR; -+ -+ /* -+ * See if we have a backing HD we can use to create our new image -+ * on top of. -+ */ -+ if (backup->sync == MIRROR_SYNC_MODE_TOP) { -+ source = backing_bs(bs); -+ if (!source) { -+ backup->sync = MIRROR_SYNC_MODE_FULL; -+ } -+ } -+ if (backup->sync == MIRROR_SYNC_MODE_NONE) { -+ source = bs; -+ flags |= BDRV_O_NO_BACKING; -+ set_backing_hd = true; -+ } -+ -+ size = bdrv_getlength(bs); -+ if (size < 0) { -+ error_setg_errno(errp, -size, "bdrv_getlength failed"); -+ goto out; -+ } -+ -+ if (backup->mode != NEW_IMAGE_MODE_EXISTING) { -+ assert(backup->format); -+ if (source) { -+ bdrv_refresh_filename(source); -+ bdrv_img_create(backup->target, backup->format, source->filename, -+ source->drv->format_name, NULL, -+ size, flags, false, &local_err); -+ } else { -+ bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL, -+ size, flags, false, &local_err); -+ } -+ } - -- state->job = do_drive_backup(backup, common->block_job_txn, &local_err); - if (local_err) { - error_propagate(errp, local_err); - goto out; - } - -+ options = qdict_new(); -+ qdict_put_str(options, "discard", "unmap"); -+ qdict_put_str(options, "detect-zeroes", "unmap"); -+ if (backup->format) { -+ qdict_put_str(options, "driver", backup->format); -+ } -+ -+ target_bs = bdrv_open(backup->target, NULL, options, flags, errp); -+ if (!target_bs) { -+ goto out; -+ } -+ -+ if (set_backing_hd) { -+ bdrv_set_backing_hd(target_bs, source, &local_err); -+ if (local_err) { -+ goto unref; -+ } -+ } -+ -+ state->bs = bs; -+ -+ state->job = do_backup_common(qapi_DriveBackup_base(backup), -+ bs, target_bs, aio_context, -+ common->block_job_txn, errp); -+ -+unref: -+ bdrv_unref(target_bs); - out: - aio_context_release(aio_context); - } -@@ -3564,126 +3653,13 @@ static BlockJob *do_backup_common(BackupCommon *backup, - return job; - } - --static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, -- Error **errp) --{ -- BlockDriverState *bs; -- BlockDriverState *target_bs; -- BlockDriverState *source = NULL; -- BlockJob *job = NULL; -- AioContext *aio_context; -- QDict *options; -- Error *local_err = NULL; -- int flags; -- int64_t size; -- bool set_backing_hd = false; -- -- if (!backup->has_mode) { -- backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; -- } -- -- bs = bdrv_lookup_bs(backup->device, backup->device, errp); -- if (!bs) { -- return NULL; -- } -- -- if (!bs->drv) { -- error_setg(errp, "Device has no medium"); -- return NULL; -- } -- -- aio_context = bdrv_get_aio_context(bs); -- aio_context_acquire(aio_context); -- -- if (!backup->has_format) { -- backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ? -- NULL : (char *) bs->drv->format_name; -- } -- -- /* Early check to avoid creating target */ -- if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) { -- goto out; -- } -- -- flags = bs->open_flags | BDRV_O_RDWR; -- -- /* -- * See if we have a backing HD we can use to create our new image -- * on top of. -- */ -- if (backup->sync == MIRROR_SYNC_MODE_TOP) { -- source = backing_bs(bs); -- if (!source) { -- backup->sync = MIRROR_SYNC_MODE_FULL; -- } -- } -- if (backup->sync == MIRROR_SYNC_MODE_NONE) { -- source = bs; -- flags |= BDRV_O_NO_BACKING; -- set_backing_hd = true; -- } -- -- size = bdrv_getlength(bs); -- if (size < 0) { -- error_setg_errno(errp, -size, "bdrv_getlength failed"); -- goto out; -- } -- -- if (backup->mode != NEW_IMAGE_MODE_EXISTING) { -- assert(backup->format); -- if (source) { -- bdrv_refresh_filename(source); -- bdrv_img_create(backup->target, backup->format, source->filename, -- source->drv->format_name, NULL, -- size, flags, false, &local_err); -- } else { -- bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL, -- size, flags, false, &local_err); -- } -- } -- -- if (local_err) { -- error_propagate(errp, local_err); -- goto out; -- } -- -- options = qdict_new(); -- qdict_put_str(options, "discard", "unmap"); -- qdict_put_str(options, "detect-zeroes", "unmap"); -- if (backup->format) { -- qdict_put_str(options, "driver", backup->format); -- } -- -- target_bs = bdrv_open(backup->target, NULL, options, flags, errp); -- if (!target_bs) { -- goto out; -- } -- -- if (set_backing_hd) { -- bdrv_set_backing_hd(target_bs, source, &local_err); -- if (local_err) { -- goto unref; -- } -- } -- -- job = do_backup_common(qapi_DriveBackup_base(backup), -- bs, target_bs, aio_context, txn, errp); -- --unref: -- bdrv_unref(target_bs); --out: -- aio_context_release(aio_context); -- return job; --} -- --void qmp_drive_backup(DriveBackup *arg, Error **errp) -+void qmp_drive_backup(DriveBackup *backup, Error **errp) - { -- -- BlockJob *job; -- job = do_drive_backup(arg, NULL, errp); -- if (job) { -- job_start(&job->job); -- } -+ TransactionAction action = { -+ .type = TRANSACTION_ACTION_KIND_DRIVE_BACKUP, -+ .u.drive_backup.data = backup, -+ }; -+ blockdev_do_action(&action, errp); - } - - BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp) -diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out -index 4d71d9dcae..07e0ec66d7 100644 ---- a/tests/qemu-iotests/141.out -+++ b/tests/qemu-iotests/141.out -@@ -10,6 +10,8 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m. - Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT - {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} - {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} -+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "job0"}} -+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} - {"return": {}} - {"error": {"class": "GenericError", "desc": "Node drv0 is in use"}} - {"return": {}} -diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out -index ddfbf3c765..a233be7f58 100644 ---- a/tests/qemu-iotests/185.out -+++ b/tests/qemu-iotests/185.out -@@ -51,6 +51,8 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 l - Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 - {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}} - {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} -+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}} -+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} - {"return": {}} - {"return": {}} - {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} -diff --git a/tests/qemu-iotests/219 b/tests/qemu-iotests/219 -index e0c51662c0..655f54d881 100755 ---- a/tests/qemu-iotests/219 -+++ b/tests/qemu-iotests/219 -@@ -63,7 +63,7 @@ def test_pause_resume(vm): - # logged immediately - iotests.log(vm.qmp('query-jobs')) - --def test_job_lifecycle(vm, job, job_args, has_ready=False): -+def test_job_lifecycle(vm, job, job_args, has_ready=False, is_mirror=False): - global img_size - - iotests.log('') -@@ -135,6 +135,9 @@ def test_job_lifecycle(vm, job, job_args, has_ready=False): - iotests.log('Waiting for PENDING state...') - iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE'))) - iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE'))) -+ if is_mirror: -+ iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE'))) -+ iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE'))) - - if not job_args.get('auto-finalize', True): - # PENDING state: -@@ -218,7 +221,7 @@ with iotests.FilePath('disk.img') as disk_path, \ - - for auto_finalize in [True, False]: - for auto_dismiss in [True, False]: -- test_job_lifecycle(vm, 'drive-backup', job_args={ -+ test_job_lifecycle(vm, 'drive-backup', is_mirror=True, job_args={ - 'device': 'drive0-node', - 'target': copy_path, - 'sync': 'full', -diff --git a/tests/qemu-iotests/219.out b/tests/qemu-iotests/219.out -index 8ebd3fee60..0ea5d0b9d5 100644 ---- a/tests/qemu-iotests/219.out -+++ b/tests/qemu-iotests/219.out -@@ -135,6 +135,8 @@ Pause/resume in RUNNING - {"return": {}} - - Waiting for PENDING state... -+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} -+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} - {"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} - {"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} - {"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} -@@ -186,6 +188,8 @@ Pause/resume in RUNNING - {"return": {}} - - Waiting for PENDING state... -+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} -+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} - {"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} - {"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} - {"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} -@@ -245,6 +249,8 @@ Pause/resume in RUNNING - {"return": {}} - - Waiting for PENDING state... -+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} -+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} - {"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} - {"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} - {"return": [{"current-progress": 4194304, "id": "job0", "status": "pending", "total-progress": 4194304, "type": "backup"}]} -@@ -304,6 +310,8 @@ Pause/resume in RUNNING - {"return": {}} - - Waiting for PENDING state... -+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} -+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} - {"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} - {"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} - {"return": [{"current-progress": 4194304, "id": "job0", "status": "pending", "total-progress": 4194304, "type": "backup"}]} --- -2.27.0 - diff --git a/blockjob-Fix-crash-with-IOthread-when-block-commit-a.patch b/blockjob-Fix-crash-with-IOthread-when-block-commit-a.patch deleted file mode 100644 index 2efef7276e0463b863265039dccdc0afd3aee834..0000000000000000000000000000000000000000 --- a/blockjob-Fix-crash-with-IOthread-when-block-commit-a.patch +++ /dev/null @@ -1,114 +0,0 @@ -From e37cda3452309d147f1f7aec3c74249001e3db0c Mon Sep 17 00:00:00 2001 -From: Michael Qiu -Date: Wed, 12 May 2021 21:54:37 +0800 -Subject: [PATCH] blockjob: Fix crash with IOthread when block commit after - snapshot - -Currently, if guest has workloads, IO thread will acquire aio_context -lock before do io_submit, it leads to segmentfault when do block commit -after snapshot. Just like below: - -Program received signal SIGSEGV, Segmentation fault. - -[Switching to Thread 0x7f7c7d91f700 (LWP 99907)] -0x00005576d0f65aab in bdrv_mirror_top_pwritev at ../block/mirror.c:1437 -1437 ../block/mirror.c: No such file or directory. -(gdb) p s->job -$17 = (MirrorBlockJob *) 0x0 -(gdb) p s->stop -$18 = false - -Call trace of IO thread: -0 0x00005576d0f65aab in bdrv_mirror_top_pwritev at ../block/mirror.c:1437 -1 0x00005576d0f7f3ab in bdrv_driver_pwritev at ../block/io.c:1174 -2 0x00005576d0f8139d in bdrv_aligned_pwritev at ../block/io.c:1988 -3 0x00005576d0f81b65 in bdrv_co_pwritev_part at ../block/io.c:2156 -4 0x00005576d0f8e6b7 in blk_do_pwritev_part at ../block/block-backend.c:1260 -5 0x00005576d0f8e84d in blk_aio_write_entry at ../block/block-backend.c:1476 -... - -Switch to qemu main thread: -0 0x00007f903be704ed in __lll_lock_wait at -/lib/../lib64/libpthread.so.0 -1 0x00007f903be6bde6 in _L_lock_941 at /lib/../lib64/libpthread.so.0 -2 0x00007f903be6bcdf in pthread_mutex_lock at -/lib/../lib64/libpthread.so.0 -3 0x0000564b21456889 in qemu_mutex_lock_impl at -../util/qemu-thread-posix.c:79 -4 0x0000564b213af8a5 in block_job_add_bdrv at ../blockjob.c:224 -5 0x0000564b213b00ad in block_job_create at ../blockjob.c:440 -6 0x0000564b21357c0a in mirror_start_job at ../block/mirror.c:1622 -7 0x0000564b2135a9af in commit_active_start at ../block/mirror.c:1867 -8 0x0000564b2133d132 in qmp_block_commit at ../blockdev.c:2768 -9 0x0000564b2141fef3 in qmp_marshal_block_commit at -qapi/qapi-commands-block-core.c:346 -10 0x0000564b214503c9 in do_qmp_dispatch_bh at -../qapi/qmp-dispatch.c:110 -11 0x0000564b21451996 in aio_bh_poll at ../util/async.c:164 -12 0x0000564b2146018e in aio_dispatch at ../util/aio-posix.c:381 -13 0x0000564b2145187e in aio_ctx_dispatch at ../util/async.c:306 -14 0x00007f9040239049 in g_main_context_dispatch at -/lib/../lib64/libglib-2.0.so.0 -15 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:232 -16 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:255 -17 0x0000564b21447368 in main_loop_wait at ../util/main-loop.c:531 -18 0x0000564b212304e1 in qemu_main_loop at ../softmmu/runstate.c:721 -19 0x0000564b20f7975e in main at ../softmmu/main.c:50 - -In IO thread when do bdrv_mirror_top_pwritev, the job is NULL, and stop field -is false, this means the MirrorBDSOpaque "s" object has not been initialized -yet, and this object is initialized by block_job_create(), but the initialize -process is stuck in acquiring the lock. - -In this situation, IO thread come to bdrv_mirror_top_pwritev(),which means that -mirror-top node is already inserted into block graph, but its bs->opaque->job -is not initialized. - -The root cause is that qemu main thread do release/acquire when hold the lock, -at the same time, IO thread get the lock after release stage, and the crash -occured. - -Actually, in this situation, job->job.aio_context will not equal to -qemu_get_aio_context(), and will be the same as bs->aio_context, -thus, no need to release the lock, becasue bdrv_root_attach_child() -will not change the context. - -This patch fix this issue. - -Fixes: 132ada80 "block: Adjust AioContexts when attaching nodes" - -Signed-off-by: Michael Qiu -Message-Id: <20210203024059.52683-1-08005325@163.com> -Signed-off-by: Kevin Wolf ---- - blockjob.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/blockjob.c b/blockjob.c -index 74abb97bfd..72865a4a6e 100644 ---- a/blockjob.c -+++ b/blockjob.c -@@ -223,14 +223,18 @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs, - uint64_t perm, uint64_t shared_perm, Error **errp) - { - BdrvChild *c; -+ bool need_context_ops; - - bdrv_ref(bs); -- if (job->job.aio_context != qemu_get_aio_context()) { -+ -+ need_context_ops = bdrv_get_aio_context(bs) != job->job.aio_context; -+ -+ if (need_context_ops && job->job.aio_context != qemu_get_aio_context()) { - aio_context_release(job->job.aio_context); - } - c = bdrv_root_attach_child(bs, name, &child_job, job->job.aio_context, - perm, shared_perm, job, errp); -- if (job->job.aio_context != qemu_get_aio_context()) { -+ if (need_context_ops && job->job.aio_context != qemu_get_aio_context()) { - aio_context_acquire(job->job.aio_context); - } - if (c == NULL) { --- -2.27.0 - diff --git a/blockjob-update-nodes-head-while-removing-all-bdrv.patch b/blockjob-update-nodes-head-while-removing-all-bdrv.patch deleted file mode 100644 index 36cedc77f7d38b124263a6f5d09e5f1dc97de5b8..0000000000000000000000000000000000000000 --- a/blockjob-update-nodes-head-while-removing-all-bdrv.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 86b0f4022bb43b16979ba5300e8d40a1e6d44b79 Mon Sep 17 00:00:00 2001 -From: Sergio Lopez -Date: Wed, 11 Sep 2019 12:03:16 +0200 -Subject: [PATCH] blockjob: update nodes head while removing all bdrv - -block_job_remove_all_bdrv() iterates through job->nodes, calling -bdrv_root_unref_child() for each entry. The call to the latter may -reach child_job_[can_]set_aio_ctx(), which will also attempt to -traverse job->nodes, potentially finding entries that where freed -on previous iterations. - -To avoid this situation, update job->nodes head on each iteration to -ensure that already freed entries are no longer linked to the list. - -RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1746631 -Signed-off-by: Sergio Lopez -Cc: qemu-stable@nongnu.org -Signed-off-by: Max Reitz -Message-id: 20190911100316.32282-1-mreitz@redhat.com -Reviewed-by: Sergio Lopez -Signed-off-by: Max Reitz -(cherry picked from commit d876bf676f5e7c6aa9ac64555e48cba8734ecb2f) -Signed-off-by: Michael Roth ---- - blockjob.c | 17 +++++++++++++---- - 1 file changed, 13 insertions(+), 4 deletions(-) - -diff --git a/blockjob.c b/blockjob.c -index 20b7f557da..74abb97bfd 100644 ---- a/blockjob.c -+++ b/blockjob.c -@@ -186,14 +186,23 @@ static const BdrvChildRole child_job = { - - void block_job_remove_all_bdrv(BlockJob *job) - { -- GSList *l; -- for (l = job->nodes; l; l = l->next) { -+ /* -+ * bdrv_root_unref_child() may reach child_job_[can_]set_aio_ctx(), -+ * which will also traverse job->nodes, so consume the list one by -+ * one to make sure that such a concurrent access does not attempt -+ * to process an already freed BdrvChild. -+ */ -+ while (job->nodes) { -+ GSList *l = job->nodes; - BdrvChild *c = l->data; -+ -+ job->nodes = l->next; -+ - bdrv_op_unblock_all(c->bs, job->blocker); - bdrv_root_unref_child(c); -+ -+ g_slist_free_1(l); - } -- g_slist_free(job->nodes); -- job->nodes = NULL; - } - - bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs) --- -2.23.0 diff --git a/bootp-check-bootp_input-buffer-size.patch b/bootp-check-bootp_input-buffer-size.patch deleted file mode 100644 index 3c4829eb123bc2a850da3660d22b93b641b6e73f..0000000000000000000000000000000000000000 --- a/bootp-check-bootp_input-buffer-size.patch +++ /dev/null @@ -1,36 +0,0 @@ -From ab454ca5f45a842b2517a0f4eb786b6ea3019d5a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Fri, 4 Jun 2021 16:15:14 +0400 -Subject: [PATCH 3/6] bootp: check bootp_input buffer size -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fixes: CVE-2021-3592 -Fixes: https://gitlab.freedesktop.org/slirp/libslirp/-/issues/44 - -Signed-off-by: Marc-André Lureau -Signed-off-by: imxcc ---- - slirp/src/bootp.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/slirp/src/bootp.c b/slirp/src/bootp.c -index 57543271..57891871 100644 ---- a/slirp/src/bootp.c -+++ b/slirp/src/bootp.c -@@ -366,9 +366,9 @@ udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); - - void bootp_input(struct mbuf *m) - { -- struct bootp_t *bp = mtod(m, struct bootp_t *); -+ struct bootp_t *bp = mtod_check(m, sizeof(struct bootp_t)); - -- if (bp->bp_op == BOOTP_REQUEST) { -+ if (bp && bp->bp_op == BOOTP_REQUEST) { - bootp_reply(m->slirp, bp, m_end(m)); - } - } --- -2.27.0 - diff --git a/bootp-limit-vendor-specific-area-to-input-packet-mem.patch b/bootp-limit-vendor-specific-area-to-input-packet-mem.patch deleted file mode 100644 index 07fe5cfd429f37a224d8910cecd7690c537d84c6..0000000000000000000000000000000000000000 --- a/bootp-limit-vendor-specific-area-to-input-packet-mem.patch +++ /dev/null @@ -1,161 +0,0 @@ -From 3369988416bd98e97dc3d0400af165c0d9e536e0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Fri, 4 Jun 2021 19:25:28 +0400 -Subject: [PATCH 2/6] bootp: limit vendor-specific area to input packet memory - buffer -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -sizeof(bootp_t) currently holds DHCP_OPT_LEN. Remove this optional field -from the structure, to help with the following patch checking for -minimal header size. Modify the bootp_reply() function to take the -buffer boundaries and avoiding potential buffer overflow. - -Related to CVE-2021-3592. - -https://gitlab.freedesktop.org/slirp/libslirp/-/issues/44 - -Signed-off-by: Marc-André Lureau -Signed-off-by: imxcc ---- - slirp/src/bootp.c | 26 +++++++++++++++----------- - slirp/src/bootp.h | 2 +- - slirp/src/mbuf.c | 5 +++++ - slirp/src/mbuf.h | 1 + - 4 files changed, 22 insertions(+), 12 deletions(-) - -diff --git a/slirp/src/bootp.c b/slirp/src/bootp.c -index 3f9ce255..57543271 100644 ---- a/slirp/src/bootp.c -+++ b/slirp/src/bootp.c -@@ -92,21 +92,22 @@ found: - return bc; - } - --static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, -+static void dhcp_decode(const struct bootp_t *bp, -+ const uint8_t *bp_end, -+ int *pmsg_type, - struct in_addr *preq_addr) - { -- const uint8_t *p, *p_end; -+ const uint8_t *p; - int len, tag; - - *pmsg_type = 0; - preq_addr->s_addr = htonl(0L); - - p = bp->bp_vend; -- p_end = p + DHCP_OPT_LEN; - if (memcmp(p, rfc1533_cookie, 4) != 0) - return; - p += 4; -- while (p < p_end) { -+ while (p < bp_end) { - tag = p[0]; - if (tag == RFC1533_PAD) { - p++; -@@ -114,10 +115,10 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, - break; - } else { - p++; -- if (p >= p_end) -+ if (p >= bp_end) - break; - len = *p++; -- if (p + len > p_end) { -+ if (p + len > bp_end) { - break; - } - DPRINTF("dhcp: tag=%d len=%d\n", tag, len); -@@ -144,7 +145,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, - } - } - --static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) -+static void bootp_reply(Slirp *slirp, -+ const struct bootp_t *bp, -+ const uint8_t *bp_end) - { - BOOTPClient *bc = NULL; - struct mbuf *m; -@@ -157,7 +160,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) - uint8_t client_ethaddr[ETH_ALEN]; - - /* extract exact DHCP msg type */ -- dhcp_decode(bp, &dhcp_msg_type, &preq_addr); -+ dhcp_decode(bp, bp_end, &dhcp_msg_type, &preq_addr); - DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type); - if (preq_addr.s_addr != htonl(0L)) - DPRINTF(" req_addr=%08" PRIx32 "\n", ntohl(preq_addr.s_addr)); -@@ -179,9 +182,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) - return; - } - m->m_data += IF_MAXLINKHDR; -+ m_inc(m, sizeof(struct bootp_t) + DHCP_OPT_LEN); - rbp = (struct bootp_t *)m->m_data; - m->m_data += sizeof(struct udpiphdr); -- memset(rbp, 0, sizeof(struct bootp_t)); -+ memset(rbp, 0, sizeof(struct bootp_t) + DHCP_OPT_LEN); - - if (dhcp_msg_type == DHCPDISCOVER) { - if (preq_addr.s_addr != htonl(0L)) { -@@ -235,7 +239,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) - rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */ - - q = rbp->bp_vend; -- end = (uint8_t *)&rbp[1]; -+ end = rbp->bp_vend + DHCP_OPT_LEN; - memcpy(q, rfc1533_cookie, 4); - q += 4; - -@@ -365,6 +369,6 @@ void bootp_input(struct mbuf *m) - struct bootp_t *bp = mtod(m, struct bootp_t *); - - if (bp->bp_op == BOOTP_REQUEST) { -- bootp_reply(m->slirp, bp); -+ bootp_reply(m->slirp, bp, m_end(m)); - } - } -diff --git a/slirp/src/bootp.h b/slirp/src/bootp.h -index 03ece9bf..0d20a944 100644 ---- a/slirp/src/bootp.h -+++ b/slirp/src/bootp.h -@@ -114,7 +114,7 @@ struct bootp_t { - uint8_t bp_hwaddr[16]; - uint8_t bp_sname[64]; - uint8_t bp_file[128]; -- uint8_t bp_vend[DHCP_OPT_LEN]; -+ uint8_t bp_vend[]; - }; - - typedef struct { -diff --git a/slirp/src/mbuf.c b/slirp/src/mbuf.c -index 6d0653ed..7db07c08 100644 ---- a/slirp/src/mbuf.c -+++ b/slirp/src/mbuf.c -@@ -233,3 +233,8 @@ void *mtod_check(struct mbuf *m, size_t len) - - return NULL; - } -+ -+void *m_end(struct mbuf *m) -+{ -+ return m->m_data + m->m_len; -+} -diff --git a/slirp/src/mbuf.h b/slirp/src/mbuf.h -index 2015e323..a9752a36 100644 ---- a/slirp/src/mbuf.h -+++ b/slirp/src/mbuf.h -@@ -119,6 +119,7 @@ void m_adj(struct mbuf *, int); - int m_copy(struct mbuf *, struct mbuf *, int, int); - struct mbuf *dtom(Slirp *, void *); - void *mtod_check(struct mbuf *, size_t len); -+void *m_end(struct mbuf *); - - static inline void ifs_init(struct mbuf *ifm) - { --- -2.27.0 - diff --git a/bt-use-size_t-type-for-length-parameters-instead-of-.patch b/bt-use-size_t-type-for-length-parameters-instead-of-.patch deleted file mode 100644 index 2005979aec4f4401b512bd0ea72d6c12493f5ea1..0000000000000000000000000000000000000000 --- a/bt-use-size_t-type-for-length-parameters-instead-of-.patch +++ /dev/null @@ -1,794 +0,0 @@ -From f9ab92373813cfccd31f29c0d963232f65cb5f88 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Fri, 22 May 2020 12:22:26 +0800 -Subject: [PATCH] bt: use size_t type for length parameters instead of int - -From: Prasad J Pandit - -The length parameter values are not negative, thus use an unsigned -type 'size_t' for them. Many routines pass 'len' values to memcpy(3) -calls. If it was negative, it could lead to memory corruption issues. -Add check to avoid it. - -Reported-by: Arash TC -Signed-off-by: Prasad J Pandit - -diff --git a/bt-host.c b/bt-host.c -index 2f8f631..b73a44d 100644 ---- a/bt-host.c -+++ b/bt-host.c -@@ -43,7 +43,7 @@ struct bt_host_hci_s { - }; - - static void bt_host_send(struct HCIInfo *hci, -- int type, const uint8_t *data, int len) -+ int type, const uint8_t *data, size_t len) - { - struct bt_host_hci_s *s = (struct bt_host_hci_s *) hci; - uint8_t pkt = type; -@@ -63,17 +63,17 @@ static void bt_host_send(struct HCIInfo *hci, - } - } - --static void bt_host_cmd(struct HCIInfo *hci, const uint8_t *data, int len) -+static void bt_host_cmd(struct HCIInfo *hci, const uint8_t *data, size_t len) - { - bt_host_send(hci, HCI_COMMAND_PKT, data, len); - } - --static void bt_host_acl(struct HCIInfo *hci, const uint8_t *data, int len) -+static void bt_host_acl(struct HCIInfo *hci, const uint8_t *data, size_t len) - { - bt_host_send(hci, HCI_ACLDATA_PKT, data, len); - } - --static void bt_host_sco(struct HCIInfo *hci, const uint8_t *data, int len) -+static void bt_host_sco(struct HCIInfo *hci, const uint8_t *data, size_t len) - { - bt_host_send(hci, HCI_SCODATA_PKT, data, len); - } -diff --git a/bt-vhci.c b/bt-vhci.c -index 886e146..32ef1c5 100644 ---- a/bt-vhci.c -+++ b/bt-vhci.c -@@ -89,7 +89,7 @@ static void vhci_read(void *opaque) - } - - static void vhci_host_send(void *opaque, -- int type, const uint8_t *data, int len) -+ int type, const uint8_t *data, size_t len) - { - struct bt_vhci_s *s = (struct bt_vhci_s *) opaque; - #if 0 -@@ -112,6 +112,7 @@ static void vhci_host_send(void *opaque, - static uint8_t buf[4096]; - - buf[0] = type; -+ assert(len < sizeof(buf)); - memcpy(buf + 1, data, len); - - while (write(s->fd, buf, len + 1) < 0) -@@ -124,13 +125,13 @@ static void vhci_host_send(void *opaque, - } - - static void vhci_out_hci_packet_event(void *opaque, -- const uint8_t *data, int len) -+ const uint8_t *data, size_t len) - { - vhci_host_send(opaque, HCI_EVENT_PKT, data, len); - } - - static void vhci_out_hci_packet_acl(void *opaque, -- const uint8_t *data, int len) -+ const uint8_t *data, size_t len) - { - vhci_host_send(opaque, HCI_ACLDATA_PKT, data, len); - } -diff --git a/hw/bt/core.c b/hw/bt/core.c -index dfb196e..f548b3d 100644 ---- a/hw/bt/core.c -+++ b/hw/bt/core.c -@@ -44,7 +44,7 @@ static void bt_dummy_lmp_disconnect_master(struct bt_link_s *link) - } - - static void bt_dummy_lmp_acl_resp(struct bt_link_s *link, -- const uint8_t *data, int start, int len) -+ const uint8_t *data, int start, size_t len) - { - error_report("%s: stray ACL response PDU, fixme", __func__); - exit(-1); -diff --git a/hw/bt/hci-csr.c b/hw/bt/hci-csr.c -index 3d60654..f7a74c0 100644 ---- a/hw/bt/hci-csr.c -+++ b/hw/bt/hci-csr.c -@@ -103,7 +103,7 @@ static inline void csrhci_fifo_wake(struct csrhci_s *s) - } - - #define csrhci_out_packetz(s, len) memset(csrhci_out_packet(s, len), 0, len) --static uint8_t *csrhci_out_packet(struct csrhci_s *s, int len) -+static uint8_t *csrhci_out_packet(struct csrhci_s *s, size_t len) - { - int off = s->out_start + s->out_len; - -@@ -112,14 +112,14 @@ static uint8_t *csrhci_out_packet(struct csrhci_s *s, int len) - - if (off < FIFO_LEN) { - if (off + len > FIFO_LEN && (s->out_size = off + len) > FIFO_LEN * 2) { -- error_report("%s: can't alloc %i bytes", __func__, len); -+ error_report("%s: can't alloc %zu bytes", __func__, len); - exit(-1); - } - return s->outfifo + off; - } - - if (s->out_len > s->out_size) { -- error_report("%s: can't alloc %i bytes", __func__, len); -+ error_report("%s: can't alloc %zu bytes", __func__, len); - exit(-1); - } - -@@ -127,7 +127,7 @@ static uint8_t *csrhci_out_packet(struct csrhci_s *s, int len) - } - - static inline uint8_t *csrhci_out_packet_csr(struct csrhci_s *s, -- int type, int len) -+ int type, size_t len) - { - uint8_t *ret = csrhci_out_packetz(s, len + 2); - -@@ -138,7 +138,7 @@ static inline uint8_t *csrhci_out_packet_csr(struct csrhci_s *s, - } - - static inline uint8_t *csrhci_out_packet_event(struct csrhci_s *s, -- int evt, int len) -+ int evt, size_t len) - { - uint8_t *ret = csrhci_out_packetz(s, - len + 1 + sizeof(struct hci_event_hdr)); -@@ -151,7 +151,7 @@ static inline uint8_t *csrhci_out_packet_event(struct csrhci_s *s, - } - - static void csrhci_in_packet_vendor(struct csrhci_s *s, int ocf, -- uint8_t *data, int len) -+ uint8_t *data, size_t len) - { - int offset; - uint8_t *rpkt; -@@ -320,18 +320,18 @@ static int csrhci_write(struct Chardev *chr, - struct csrhci_s *s = (struct csrhci_s *)chr; - int total = 0; - -- if (!s->enable) -+ if (!s->enable || len <= 0) - return 0; - - for (;;) { - int cnt = MIN(len, s->in_needed - s->in_len); -- if (cnt) { -- memcpy(s->inpkt + s->in_len, buf, cnt); -- s->in_len += cnt; -- buf += cnt; -- len -= cnt; -- total += cnt; -- } -+ assert(cnt > 0); -+ -+ memcpy(s->inpkt + s->in_len, buf, cnt); -+ s->in_len += cnt; -+ buf += cnt; -+ len -= cnt; -+ total += cnt; - - if (s->in_len < s->in_needed) { - break; -@@ -363,7 +363,7 @@ static int csrhci_write(struct Chardev *chr, - } - - static void csrhci_out_hci_packet_event(void *opaque, -- const uint8_t *data, int len) -+ const uint8_t *data, size_t len) - { - struct csrhci_s *s = (struct csrhci_s *) opaque; - uint8_t *pkt = csrhci_out_packet(s, (len + 2) & ~1); /* Align */ -@@ -375,7 +375,7 @@ static void csrhci_out_hci_packet_event(void *opaque, - } - - static void csrhci_out_hci_packet_acl(void *opaque, -- const uint8_t *data, int len) -+ const uint8_t *data, size_t len) - { - struct csrhci_s *s = (struct csrhci_s *) opaque; - uint8_t *pkt = csrhci_out_packet(s, (len + 2) & ~1); /* Align */ -diff --git a/hw/bt/hci.c b/hw/bt/hci.c -index c7958f6..9c4f957 100644 ---- a/hw/bt/hci.c -+++ b/hw/bt/hci.c -@@ -31,7 +31,7 @@ - - struct bt_hci_s { - uint8_t *(*evt_packet)(void *opaque); -- void (*evt_submit)(void *opaque, int len); -+ void (*evt_submit)(void *opaque, size_t len); - void *opaque; - uint8_t evt_buf[256]; - -@@ -61,7 +61,7 @@ struct bt_hci_s { - struct bt_hci_master_link_s { - struct bt_link_s *link; - void (*lmp_acl_data)(struct bt_link_s *link, -- const uint8_t *data, int start, int len); -+ const uint8_t *data, int start, size_t len); - QEMUTimer *acl_mode_timer; - } handle[HCI_HANDLES_MAX]; - uint32_t role_bmp; -@@ -433,7 +433,7 @@ static const uint8_t bt_event_reserved_mask[8] = { - }; - - --static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len) -+static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, size_t len) - { - } - -@@ -451,13 +451,13 @@ struct HCIInfo null_hci = { - - - static inline uint8_t *bt_hci_event_start(struct bt_hci_s *hci, -- int evt, int len) -+ int evt, size_t len) - { - uint8_t *packet, mask; - int mask_byte; - - if (len > 255) { -- error_report("%s: HCI event params too long (%ib)", __func__, len); -+ error_report("%s: HCI event params too long (%zub)", __func__, len); - exit(-1); - } - -@@ -474,7 +474,7 @@ static inline uint8_t *bt_hci_event_start(struct bt_hci_s *hci, - } - - static inline void bt_hci_event(struct bt_hci_s *hci, int evt, -- void *params, int len) -+ void *params, size_t len) - { - uint8_t *packet = bt_hci_event_start(hci, evt, len); - -@@ -499,7 +499,7 @@ static inline void bt_hci_event_status(struct bt_hci_s *hci, int status) - } - - static inline void bt_hci_event_complete(struct bt_hci_s *hci, -- void *ret, int len) -+ void *ret, size_t len) - { - uint8_t *packet = bt_hci_event_start(hci, EVT_CMD_COMPLETE, - len + EVT_CMD_COMPLETE_SIZE); -@@ -1476,7 +1476,7 @@ static inline void bt_hci_event_num_comp_pkts(struct bt_hci_s *hci, - } - - static void bt_submit_hci(struct HCIInfo *info, -- const uint8_t *data, int length) -+ const uint8_t *data, size_t length) - { - struct bt_hci_s *hci = hci_from_info(info); - uint16_t cmd; -@@ -1970,7 +1970,7 @@ static void bt_submit_hci(struct HCIInfo *info, - break; - - short_hci: -- error_report("%s: HCI packet too short (%iB)", __func__, length); -+ error_report("%s: HCI packet too short (%zuB)", __func__, length); - bt_hci_event_status(hci, HCI_INVALID_PARAMETERS); - break; - } -@@ -1981,7 +1981,7 @@ static void bt_submit_hci(struct HCIInfo *info, - * know that a packet contained the last fragment of the SDU when the next - * SDU starts. */ - static inline void bt_hci_lmp_acl_data(struct bt_hci_s *hci, uint16_t handle, -- const uint8_t *data, int start, int len) -+ const uint8_t *data, int start, size_t len) - { - struct hci_acl_hdr *pkt = (void *) hci->acl_buf; - -@@ -1989,7 +1989,7 @@ static inline void bt_hci_lmp_acl_data(struct bt_hci_s *hci, uint16_t handle, - /* TODO: avoid memcpy'ing */ - - if (len + HCI_ACL_HDR_SIZE > sizeof(hci->acl_buf)) { -- error_report("%s: can't take ACL packets %i bytes long", -+ error_report("%s: can't take ACL packets %zu bytes long", - __func__, len); - return; - } -@@ -2003,7 +2003,7 @@ static inline void bt_hci_lmp_acl_data(struct bt_hci_s *hci, uint16_t handle, - } - - static void bt_hci_lmp_acl_data_slave(struct bt_link_s *btlink, -- const uint8_t *data, int start, int len) -+ const uint8_t *data, int start, size_t len) - { - struct bt_hci_link_s *link = (struct bt_hci_link_s *) btlink; - -@@ -2012,14 +2012,14 @@ static void bt_hci_lmp_acl_data_slave(struct bt_link_s *btlink, - } - - static void bt_hci_lmp_acl_data_host(struct bt_link_s *link, -- const uint8_t *data, int start, int len) -+ const uint8_t *data, int start, size_t len) - { - bt_hci_lmp_acl_data(hci_from_device(link->host), - link->handle, data, start, len); - } - - static void bt_submit_acl(struct HCIInfo *info, -- const uint8_t *data, int length) -+ const uint8_t *data, size_t length) - { - struct bt_hci_s *hci = hci_from_info(info); - uint16_t handle; -@@ -2027,7 +2027,7 @@ static void bt_submit_acl(struct HCIInfo *info, - struct bt_link_s *link; - - if (length < HCI_ACL_HDR_SIZE) { -- error_report("%s: ACL packet too short (%iB)", __func__, length); -+ error_report("%s: ACL packet too short (%zuB)", __func__, length); - return; - } - -@@ -2045,7 +2045,7 @@ static void bt_submit_acl(struct HCIInfo *info, - handle &= ~HCI_HANDLE_OFFSET; - - if (datalen > length) { -- error_report("%s: ACL packet too short (%iB < %iB)", -+ error_report("%s: ACL packet too short (%zuB < %iB)", - __func__, length, datalen); - return; - } -@@ -2087,7 +2087,7 @@ static void bt_submit_acl(struct HCIInfo *info, - } - - static void bt_submit_sco(struct HCIInfo *info, -- const uint8_t *data, int length) -+ const uint8_t *data, size_t length) - { - struct bt_hci_s *hci = hci_from_info(info); - uint16_t handle; -@@ -2106,7 +2106,7 @@ static void bt_submit_sco(struct HCIInfo *info, - } - - if (datalen > length) { -- error_report("%s: SCO packet too short (%iB < %iB)", -+ error_report("%s: SCO packet too short (%zuB < %iB)", - __func__, length, datalen); - return; - } -@@ -2127,7 +2127,7 @@ static uint8_t *bt_hci_evt_packet(void *opaque) - return s->evt_buf; - } - --static void bt_hci_evt_submit(void *opaque, int len) -+static void bt_hci_evt_submit(void *opaque, size_t len) - { - /* TODO: notify upper layer */ - struct bt_hci_s *s = opaque; -diff --git a/hw/bt/hid.c b/hw/bt/hid.c -index 066ca99..fe15434 100644 ---- a/hw/bt/hid.c -+++ b/hw/bt/hid.c -@@ -95,7 +95,7 @@ struct bt_hid_device_s { - int data_type; - int intr_state; - struct { -- int len; -+ size_t len; - uint8_t buffer[1024]; - } dataother, datain, dataout, feature, intrdataout; - enum { -@@ -168,7 +168,7 @@ static void bt_hid_disconnect(struct bt_hid_device_s *s) - } - - static void bt_hid_send_data(struct bt_l2cap_conn_params_s *ch, int type, -- const uint8_t *data, int len) -+ const uint8_t *data, size_t len) - { - uint8_t *pkt, hdr = (BT_DATA << 4) | type; - int plen; -@@ -189,7 +189,7 @@ static void bt_hid_send_data(struct bt_l2cap_conn_params_s *ch, int type, - } - - static void bt_hid_control_transaction(struct bt_hid_device_s *s, -- const uint8_t *data, int len) -+ const uint8_t *data, size_t len) - { - uint8_t type, parameter; - int rlen, ret = -1; -@@ -361,7 +361,7 @@ static void bt_hid_control_transaction(struct bt_hid_device_s *s, - bt_hid_send_handshake(s, ret); - } - --static void bt_hid_control_sdu(void *opaque, const uint8_t *data, int len) -+static void bt_hid_control_sdu(void *opaque, const uint8_t *data, size_t len) - { - struct bt_hid_device_s *hid = opaque; - -@@ -387,7 +387,7 @@ static void bt_hid_datain(HIDState *hs) - hid->datain.buffer, hid->datain.len); - } - --static void bt_hid_interrupt_sdu(void *opaque, const uint8_t *data, int len) -+static void bt_hid_interrupt_sdu(void *opaque, const uint8_t *data, size_t len) - { - struct bt_hid_device_s *hid = opaque; - -diff --git a/hw/bt/l2cap.c b/hw/bt/l2cap.c -index d67098a..2f70a03 100644 ---- a/hw/bt/l2cap.c -+++ b/hw/bt/l2cap.c -@@ -31,10 +31,10 @@ struct l2cap_instance_s { - int role; - - uint8_t frame_in[65535 + L2CAP_HDR_SIZE] __attribute__ ((aligned (4))); -- int frame_in_len; -+ uint32_t frame_in_len; - - uint8_t frame_out[65535 + L2CAP_HDR_SIZE] __attribute__ ((aligned (4))); -- int frame_out_len; -+ uint32_t frame_out_len; - - /* Signalling channel timers. They exist per-request but we can make - * sure we have no more than one outstanding request at any time. */ -@@ -48,7 +48,7 @@ struct l2cap_instance_s { - struct bt_l2cap_conn_params_s params; - - void (*frame_in)(struct l2cap_chan_s *chan, uint16_t cid, -- const l2cap_hdr *hdr, int len); -+ const l2cap_hdr *hdr, size_t len); - int mps; - int min_mtu; - -@@ -67,7 +67,7 @@ struct l2cap_instance_s { - - /* Only flow-controlled, connection-oriented channels */ - uint8_t sdu[65536]; /* TODO: dynamically allocate */ -- int len_cur, len_total; -+ uint32_t len_cur, len_total; - int rexmit; - int monitor_timeout; - QEMUTimer *monitor_timer; -@@ -139,7 +139,7 @@ static const uint16_t l2cap_fcs16_table[256] = { - 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040, - }; - --static uint16_t l2cap_fcs16(const uint8_t *message, int len) -+static uint16_t l2cap_fcs16(const uint8_t *message, size_t len) - { - uint16_t fcs = 0x0000; - -@@ -185,7 +185,7 @@ static void l2cap_monitor_timer_update(struct l2cap_chan_s *ch) - } - - static void l2cap_command_reject(struct l2cap_instance_s *l2cap, int id, -- uint16_t reason, const void *data, int plen) -+ uint16_t reason, const void *data, size_t plen) - { - uint8_t *pkt; - l2cap_cmd_hdr *hdr; -@@ -246,7 +246,7 @@ static void l2cap_connection_response(struct l2cap_instance_s *l2cap, - } - - static void l2cap_configuration_request(struct l2cap_instance_s *l2cap, -- int dcid, int flag, const uint8_t *data, int len) -+ int dcid, int flag, const uint8_t *data, size_t len) - { - uint8_t *pkt; - l2cap_cmd_hdr *hdr; -@@ -274,7 +274,7 @@ static void l2cap_configuration_request(struct l2cap_instance_s *l2cap, - } - - static void l2cap_configuration_response(struct l2cap_instance_s *l2cap, -- int scid, int flag, int result, const uint8_t *data, int len) -+ int scid, int flag, int result, const uint8_t *data, size_t len) - { - uint8_t *pkt; - l2cap_cmd_hdr *hdr; -@@ -321,7 +321,7 @@ static void l2cap_disconnection_response(struct l2cap_instance_s *l2cap, - } - - static void l2cap_echo_response(struct l2cap_instance_s *l2cap, -- const uint8_t *data, int len) -+ const uint8_t *data, size_t len) - { - uint8_t *pkt; - l2cap_cmd_hdr *hdr; -@@ -342,7 +342,7 @@ static void l2cap_echo_response(struct l2cap_instance_s *l2cap, - } - - static void l2cap_info_response(struct l2cap_instance_s *l2cap, int type, -- int result, const uint8_t *data, int len) -+ int result, const uint8_t *data, size_t len) - { - uint8_t *pkt; - l2cap_cmd_hdr *hdr; -@@ -365,16 +365,18 @@ static void l2cap_info_response(struct l2cap_instance_s *l2cap, int type, - l2cap->signalling_ch.params.sdu_submit(&l2cap->signalling_ch.params); - } - --static uint8_t *l2cap_bframe_out(struct bt_l2cap_conn_params_s *parm, int len); -+static uint8_t *l2cap_bframe_out(struct bt_l2cap_conn_params_s *parm, -+ size_t len); - static void l2cap_bframe_submit(struct bt_l2cap_conn_params_s *parms); - #if 0 --static uint8_t *l2cap_iframe_out(struct bt_l2cap_conn_params_s *parm, int len); -+static uint8_t *l2cap_iframe_out(struct bt_l2cap_conn_params_s *parm, -+ size_t len); - static void l2cap_iframe_submit(struct bt_l2cap_conn_params_s *parm); - #endif - static void l2cap_bframe_in(struct l2cap_chan_s *ch, uint16_t cid, -- const l2cap_hdr *hdr, int len); -+ const l2cap_hdr *hdr, size_t len); - static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid, -- const l2cap_hdr *hdr, int len); -+ const l2cap_hdr *hdr, size_t len); - - static int l2cap_cid_new(struct l2cap_instance_s *l2cap) - { -@@ -498,7 +500,7 @@ static void l2cap_channel_config_req_event(struct l2cap_instance_s *l2cap, - - static int l2cap_channel_config(struct l2cap_instance_s *l2cap, - struct l2cap_chan_s *ch, int flag, -- const uint8_t *data, int len) -+ const uint8_t *data, size_t len) - { - l2cap_conf_opt *opt; - l2cap_conf_opt_qos *qos; -@@ -683,7 +685,7 @@ static int l2cap_channel_config(struct l2cap_instance_s *l2cap, - } - - static void l2cap_channel_config_req_msg(struct l2cap_instance_s *l2cap, -- int flag, int cid, const uint8_t *data, int len) -+ int flag, int cid, const uint8_t *data, size_t len) - { - struct l2cap_chan_s *ch; - -@@ -715,7 +717,7 @@ static void l2cap_channel_config_req_msg(struct l2cap_instance_s *l2cap, - } - - static int l2cap_channel_config_rsp_msg(struct l2cap_instance_s *l2cap, -- int result, int flag, int cid, const uint8_t *data, int len) -+ int result, int flag, int cid, const uint8_t *data, size_t len) - { - struct l2cap_chan_s *ch; - -@@ -783,7 +785,7 @@ static void l2cap_info(struct l2cap_instance_s *l2cap, int type) - } - - static void l2cap_command(struct l2cap_instance_s *l2cap, int code, int id, -- const uint8_t *params, int len) -+ const uint8_t *params, size_t len) - { - int err; - -@@ -938,7 +940,7 @@ static void l2cap_rexmit_enable(struct l2cap_chan_s *ch, int enable) - } - - /* Command frame SDU */ --static void l2cap_cframe_in(void *opaque, const uint8_t *data, int len) -+static void l2cap_cframe_in(void *opaque, const uint8_t *data, size_t len) - { - struct l2cap_instance_s *l2cap = opaque; - const l2cap_cmd_hdr *hdr; -@@ -966,7 +968,7 @@ static void l2cap_cframe_in(void *opaque, const uint8_t *data, int len) - } - - /* Group frame SDU */ --static void l2cap_gframe_in(void *opaque, const uint8_t *data, int len) -+static void l2cap_gframe_in(void *opaque, const uint8_t *data, size_t len) - { - } - -@@ -977,7 +979,7 @@ static void l2cap_sframe_in(struct l2cap_chan_s *ch, uint16_t ctrl) - - /* Basic L2CAP mode Information frame */ - static void l2cap_bframe_in(struct l2cap_chan_s *ch, uint16_t cid, -- const l2cap_hdr *hdr, int len) -+ const l2cap_hdr *hdr, size_t len) - { - /* We have a full SDU, no further processing */ - ch->params.sdu_in(ch->params.opaque, hdr->data, len); -@@ -985,7 +987,7 @@ static void l2cap_bframe_in(struct l2cap_chan_s *ch, uint16_t cid, - - /* Flow Control and Retransmission mode frame */ - static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid, -- const l2cap_hdr *hdr, int len) -+ const l2cap_hdr *hdr, size_t len) - { - uint16_t fcs = lduw_le_p(hdr->data + len - 2); - -@@ -1076,7 +1078,7 @@ static void l2cap_frame_in(struct l2cap_instance_s *l2cap, - - /* "Recombination" */ - static void l2cap_pdu_in(struct l2cap_instance_s *l2cap, -- const uint8_t *data, int len) -+ const uint8_t *data, size_t len) - { - const l2cap_hdr *hdr = (void *) l2cap->frame_in; - -@@ -1123,7 +1125,7 @@ static inline void l2cap_pdu_submit(struct l2cap_instance_s *l2cap) - (l2cap->link, l2cap->frame_out, 1, l2cap->frame_out_len); - } - --static uint8_t *l2cap_bframe_out(struct bt_l2cap_conn_params_s *parm, int len) -+static uint8_t *l2cap_bframe_out(struct bt_l2cap_conn_params_s *parm, size_t len) - { - struct l2cap_chan_s *chan = (struct l2cap_chan_s *) parm; - -@@ -1146,7 +1148,7 @@ static void l2cap_bframe_submit(struct bt_l2cap_conn_params_s *parms) - - #if 0 - /* Stub: Only used if an emulated device requests outgoing flow control */ --static uint8_t *l2cap_iframe_out(struct bt_l2cap_conn_params_s *parm, int len) -+static uint8_t *l2cap_iframe_out(struct bt_l2cap_conn_params_s *parm, size_t len) - { - struct l2cap_chan_s *chan = (struct l2cap_chan_s *) parm; - -@@ -1291,7 +1293,7 @@ static void l2cap_lmp_disconnect_slave(struct bt_link_s *link) - } - - static void l2cap_lmp_acl_data_slave(struct bt_link_s *link, -- const uint8_t *data, int start, int len) -+ const uint8_t *data, int start, size_t len) - { - struct slave_l2cap_instance_s *l2cap = - (struct slave_l2cap_instance_s *) link; -@@ -1304,7 +1306,7 @@ static void l2cap_lmp_acl_data_slave(struct bt_link_s *link, - - /* Stub */ - static void l2cap_lmp_acl_data_host(struct bt_link_s *link, -- const uint8_t *data, int start, int len) -+ const uint8_t *data, int start, size_t len) - { - struct bt_l2cap_device_s *dev = (struct bt_l2cap_device_s *) link->host; - struct l2cap_instance_s *l2cap = -diff --git a/hw/bt/sdp.c b/hw/bt/sdp.c -index 2860d76..6bfb174 100644 ---- a/hw/bt/sdp.c -+++ b/hw/bt/sdp.c -@@ -496,7 +496,7 @@ static ssize_t sdp_svc_search_attr_get(struct bt_l2cap_sdp_state_s *sdp, - return end + 2; - } - --static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, int len) -+static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, size_t len) - { - struct bt_l2cap_sdp_state_s *sdp = opaque; - enum bt_sdp_cmd pdu_id; -@@ -506,7 +506,7 @@ static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, int len) - int rsp_len = 0; - - if (len < 5) { -- error_report("%s: short SDP PDU (%iB).", __func__, len); -+ error_report("%s: short SDP PDU (%zuB).", __func__, len); - return; - } - -@@ -517,7 +517,7 @@ static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, int len) - len -= 5; - - if (len != plen) { -- error_report("%s: wrong SDP PDU length (%iB != %iB).", -+ error_report("%s: wrong SDP PDU length (%iB != %zuB).", - __func__, plen, len); - err = SDP_INVALID_PDU_SIZE; - goto respond; -diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c -index 670ba32..240a901 100644 ---- a/hw/usb/dev-bluetooth.c -+++ b/hw/usb/dev-bluetooth.c -@@ -265,7 +265,7 @@ static void usb_bt_fifo_reset(struct usb_hci_in_fifo_s *fifo) - } - - static void usb_bt_fifo_enqueue(struct usb_hci_in_fifo_s *fifo, -- const uint8_t *data, int len) -+ const uint8_t *data, size_t len) - { - int off = fifo->dstart + fifo->dlen; - uint8_t *buf; -@@ -274,13 +274,13 @@ static void usb_bt_fifo_enqueue(struct usb_hci_in_fifo_s *fifo, - if (off <= DFIFO_LEN_MASK) { - if (off + len > DFIFO_LEN_MASK + 1 && - (fifo->dsize = off + len) > (DFIFO_LEN_MASK + 1) * 2) { -- fprintf(stderr, "%s: can't alloc %i bytes\n", __func__, len); -+ fprintf(stderr, "%s: can't alloc %zu bytes\n", __func__, len); - exit(-1); - } - buf = fifo->data + off; - } else { - if (fifo->dlen > fifo->dsize) { -- fprintf(stderr, "%s: can't alloc %i bytes\n", __func__, len); -+ fprintf(stderr, "%s: can't alloc %zu bytes\n", __func__, len); - exit(-1); - } - buf = fifo->data + off - fifo->dsize; -@@ -319,7 +319,7 @@ static inline void usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo, - - static inline void usb_bt_fifo_out_enqueue(struct USBBtState *s, - struct usb_hci_out_fifo_s *fifo, -- void (*send)(struct HCIInfo *, const uint8_t *, int), -+ void (*send)(struct HCIInfo *, const uint8_t *, size_t), - int (*complete)(const uint8_t *, int), - USBPacket *p) - { -@@ -478,7 +478,7 @@ static void usb_bt_handle_data(USBDevice *dev, USBPacket *p) - } - - static void usb_bt_out_hci_packet_event(void *opaque, -- const uint8_t *data, int len) -+ const uint8_t *data, size_t len) - { - struct USBBtState *s = (struct USBBtState *) opaque; - -@@ -489,7 +489,7 @@ static void usb_bt_out_hci_packet_event(void *opaque, - } - - static void usb_bt_out_hci_packet_acl(void *opaque, -- const uint8_t *data, int len) -+ const uint8_t *data, size_t len) - { - struct USBBtState *s = (struct USBBtState *) opaque; - -diff --git a/include/hw/bt.h b/include/hw/bt.h -index b5e11d4..bc362aa 100644 ---- a/include/hw/bt.h -+++ b/include/hw/bt.h -@@ -94,9 +94,9 @@ struct bt_device_s { - void (*lmp_disconnect_master)(struct bt_link_s *link); - void (*lmp_disconnect_slave)(struct bt_link_s *link); - void (*lmp_acl_data)(struct bt_link_s *link, const uint8_t *data, -- int start, int len); -+ int start, size_t len); - void (*lmp_acl_resp)(struct bt_link_s *link, const uint8_t *data, -- int start, int len); -+ int start, size_t len); - void (*lmp_mode_change)(struct bt_link_s *link); - - void (*handle_destroy)(struct bt_device_s *device); -@@ -148,12 +148,12 @@ struct bt_l2cap_device_s { - - struct bt_l2cap_conn_params_s { - /* Input */ -- uint8_t *(*sdu_out)(struct bt_l2cap_conn_params_s *chan, int len); -+ uint8_t *(*sdu_out)(struct bt_l2cap_conn_params_s *chan, size_t len); - void (*sdu_submit)(struct bt_l2cap_conn_params_s *chan); - int remote_mtu; - /* Output */ - void *opaque; -- void (*sdu_in)(void *opaque, const uint8_t *data, int len); -+ void (*sdu_in)(void *opaque, const uint8_t *data, size_t len); - void (*close)(void *opaque); - }; - -diff --git a/include/sysemu/bt.h b/include/sysemu/bt.h -index 2fd8c0f..df8fb63 100644 ---- a/include/sysemu/bt.h -+++ b/include/sysemu/bt.h -@@ -5,12 +5,12 @@ - - typedef struct HCIInfo { - int (*bdaddr_set)(struct HCIInfo *hci, const uint8_t *bd_addr); -- void (*cmd_send)(struct HCIInfo *hci, const uint8_t *data, int len); -- void (*sco_send)(struct HCIInfo *hci, const uint8_t *data, int len); -- void (*acl_send)(struct HCIInfo *hci, const uint8_t *data, int len); -+ void (*cmd_send)(struct HCIInfo *hci, const uint8_t *data, size_t len); -+ void (*sco_send)(struct HCIInfo *hci, const uint8_t *data, size_t len); -+ void (*acl_send)(struct HCIInfo *hci, const uint8_t *data, size_t len); - void *opaque; -- void (*evt_recv)(void *opaque, const uint8_t *data, int len); -- void (*acl_recv)(void *opaque, const uint8_t *data, int len); -+ void (*evt_recv)(void *opaque, const uint8_t *data, size_t len); -+ void (*acl_recv)(void *opaque, const uint8_t *data, size_t len); - } HCIInfo; - - /* bt-host.c */ --- -1.8.3.1 - diff --git a/bugfix-Use-gicr_typer-in-arm_gicv3_icc_reset.patch b/bugfix-Use-gicr_typer-in-arm_gicv3_icc_reset.patch deleted file mode 100644 index e714cb10bef351cd6ed6df71d08f3666df879ed5..0000000000000000000000000000000000000000 --- a/bugfix-Use-gicr_typer-in-arm_gicv3_icc_reset.patch +++ /dev/null @@ -1,44 +0,0 @@ -From b9e4a4ff6f3292927adb1463777c86cd4063a6ef Mon Sep 17 00:00:00 2001 -From: Keqian Zhu -Date: Sat, 18 Apr 2020 12:10:11 +0800 -Subject: [PATCH] bugfix: Use gicr_typer in arm_gicv3_icc_reset - -The KVM_VGIC_ATTR macro expect the second parameter as gicr_typer, -of which high 32bit is constructed by mp_affinity. For most case, -the high 32bit of mp_affinity is zero, so it will always access the -ICC_CTLR_EL1 of CPU0. - -Signed-off-by: Keqian Zhu ---- - hw/intc/arm_gicv3_kvm.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c -index d9c72f85be..b1e74147ba 100644 ---- a/hw/intc/arm_gicv3_kvm.c -+++ b/hw/intc/arm_gicv3_kvm.c -@@ -661,13 +661,11 @@ static void kvm_arm_gicv3_get(GICv3State *s) - - static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri) - { -- ARMCPU *cpu; - GICv3State *s; - GICv3CPUState *c; - - c = (GICv3CPUState *)env->gicv3state; - s = c->gic; -- cpu = ARM_CPU(c->cpu); - - c->icc_pmr_el1 = 0; - c->icc_bpr[GICV3_G0] = GIC_MIN_BPR; -@@ -684,7 +682,7 @@ static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri) - - /* Initialize to actual HW supported configuration */ - kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, -- KVM_VGIC_ATTR(ICC_CTLR_EL1, cpu->mp_affinity), -+ KVM_VGIC_ATTR(ICC_CTLR_EL1, c->gicr_typer), - &c->icc_ctlr_el1[GICV3_NS], false, &error_abort); - - c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS]; --- -2.19.1 diff --git a/bugfix-fix-eventfds-may-double-free-when-vm_id-reuse.patch b/bugfix-fix-eventfds-may-double-free-when-vm_id-reuse.patch new file mode 100644 index 0000000000000000000000000000000000000000..5802835732b041606945c051bc2a5c5917ebb282 --- /dev/null +++ b/bugfix-fix-eventfds-may-double-free-when-vm_id-reuse.patch @@ -0,0 +1,48 @@ +From 02a17066ac3dfb5e53b72b15a80643154990191b Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Thu, 10 Feb 2022 21:50:28 +0800 +Subject: [PATCH] bugfix: fix eventfds may double free when vm_id reused in + ivshmem + +As the ivshmem Server-Client Protol describes, when a +client disconnects from the server, server sends disconnect +notifications to the other clients. And the other clients +will free the eventfds of the disconnected client according +to the client ID. If the client ID is reused, the eventfds +may be double freed. + +It will be solved by setting eventfds to NULL after freeing +and allocating memory for it when it's used. + +Signed-off-by: Peng Liang +Signed-off-by: jiangdongxu +--- + hw/misc/ivshmem.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c +index 1ba4a98377..05f06ed6cf 100644 +--- a/hw/misc/ivshmem.c ++++ b/hw/misc/ivshmem.c +@@ -400,6 +400,7 @@ static void close_peer_eventfds(IVShmemState *s, int posn) + } + + g_free(s->peers[posn].eventfds); ++ s->peers[posn].eventfds = NULL; + s->peers[posn].nb_eventfds = 0; + } + +@@ -530,6 +531,10 @@ static void process_msg_connect(IVShmemState *s, uint16_t posn, int fd, + close(fd); + return; + } ++ if (peer->eventfds == NULL) { ++ peer->eventfds = g_new0(EventNotifier, s->vectors); ++ peer->nb_eventfds = 0; ++ } + vector = peer->nb_eventfds++; + + IVSHMEM_DPRINTF("eventfds[%d][%d] = %d\n", posn, vector, fd); +-- +2.27.0 + diff --git a/bugfix-fix-mmio-information-leak-and-ehci-vm-escape-.patch b/bugfix-fix-mmio-information-leak-and-ehci-vm-escape-.patch new file mode 100644 index 0000000000000000000000000000000000000000..f463c6b4b060133576134775c5c5c5ddcd400d92 --- /dev/null +++ b/bugfix-fix-mmio-information-leak-and-ehci-vm-escape-.patch @@ -0,0 +1,67 @@ +From f14ea0bd2596f94ad926009411b8ffda9c2c2cda Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Thu, 10 Feb 2022 22:42:23 +0800 +Subject: [PATCH] bugfix: fix mmio information leak and ehci vm escape 0-day + vulnerability + +Signed-off-by: Yutao Ai +Signed-off-by: jiangdongxu +--- + hw/usb/core.c | 20 ++++++++++++++++++-- + hw/usb/hcd-ehci.c | 2 ++ + 2 files changed, 20 insertions(+), 2 deletions(-) + +diff --git a/hw/usb/core.c b/hw/usb/core.c +index 51b36126ca..a62826e051 100644 +--- a/hw/usb/core.c ++++ b/hw/usb/core.c +@@ -206,7 +206,15 @@ static void do_token_in(USBDevice *s, USBPacket *p) + + case SETUP_STATE_DATA: + if (s->setup_buf[0] & USB_DIR_IN) { +- int len = s->setup_len - s->setup_index; ++ int len; ++ if (s->setup_len > sizeof(s->data_buf)) { ++ fprintf(stderr, ++ "usb_generic_handle_packet: ctrl buffer too small do_token_in(%d > %zu)\n", ++ s->setup_len, sizeof(s->data_buf)); ++ p->status = USB_RET_STALL; ++ return; ++ } ++ len = s->setup_len - s->setup_index; + if (len > p->iov.size) { + len = p->iov.size; + } +@@ -244,7 +252,15 @@ static void do_token_out(USBDevice *s, USBPacket *p) + + case SETUP_STATE_DATA: + if (!(s->setup_buf[0] & USB_DIR_IN)) { +- int len = s->setup_len - s->setup_index; ++ int len; ++ if (s->setup_len > sizeof(s->data_buf)) { ++ fprintf(stderr, ++ "usb_generic_handle_packet: ctrl buffer too small do_token_out(%d > %zu)\n", ++ s->setup_len, sizeof(s->data_buf)); ++ p->status = USB_RET_STALL; ++ return; ++ } ++ len = s->setup_len - s->setup_index; + if (len > p->iov.size) { + len = p->iov.size; + } +diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c +index 6caa7ac6c2..1415107315 100644 +--- a/hw/usb/hcd-ehci.c ++++ b/hw/usb/hcd-ehci.c +@@ -612,6 +612,8 @@ static void ehci_free_queue(EHCIQueue *q, const char *warn) + ehci_trace_guest_bug(q->ehci, warn); + } + QTAILQ_REMOVE(head, q, next); ++ memset(q, 0, sizeof(*q)); ++ *(volatile char *)q = *(volatile char *)q; + g_free(q); + } + +-- +2.27.0 + diff --git a/bugfix-fix-possible-memory-leak.patch b/bugfix-fix-possible-memory-leak.patch new file mode 100644 index 0000000000000000000000000000000000000000..3e6a611ed470f6d0acdbbaa2889bcbd90c089353 --- /dev/null +++ b/bugfix-fix-possible-memory-leak.patch @@ -0,0 +1,97 @@ +From 03e7e232a323c45205d3c6ecb7d8e52e7209d9eb Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Thu, 10 Feb 2022 22:12:50 +0800 +Subject: [PATCH] bugfix: fix possible memory leak + +Signed-off-by: caojinhua +Signed-off-by: jiangdongxu +--- + migration/savevm.c | 2 ++ + qga/main.c | 18 +++++++++++++----- + 2 files changed, 15 insertions(+), 5 deletions(-) + +diff --git a/migration/savevm.c b/migration/savevm.c +index d59e976d50..803cd9004d 100644 +--- a/migration/savevm.c ++++ b/migration/savevm.c +@@ -1427,6 +1427,7 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f, + ret = vmstate_save(f, se, vmdesc); + if (ret) { + qemu_file_set_error(f, ret); ++ json_writer_free(vmdesc); + return ret; + } + trace_savevm_section_end(se->idstr, se->section_id, 0); +@@ -1443,6 +1444,7 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f, + error_report("%s: bdrv_inactivate_all() failed (%d)", + __func__, ret); + qemu_file_set_error(f, ret); ++ json_writer_free(vmdesc); + return ret; + } + } +diff --git a/qga/main.c b/qga/main.c +index 15fd3a4149..6f09a689ac 100644 +--- a/qga/main.c ++++ b/qga/main.c +@@ -1283,7 +1283,7 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation) + if (g_mkdir_with_parents(config->state_dir, S_IRWXU) == -1) { + g_critical("unable to create (an ancestor of) the state directory" + " '%s': %s", config->state_dir, strerror(errno)); +- return NULL; ++ goto failed; + } + #endif + +@@ -1308,7 +1308,7 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation) + if (!log_file) { + g_critical("unable to open specified log file: %s", + strerror(errno)); +- return NULL; ++ goto failed; + } + s->log_file = log_file; + } +@@ -1319,7 +1319,7 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation) + s->pstate_filepath, + ga_is_frozen(s))) { + g_critical("failed to load persistent state"); +- return NULL; ++ goto failed; + } + + config->blacklist = ga_command_blacklist_init(config->blacklist); +@@ -1340,7 +1340,7 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation) + #ifndef _WIN32 + if (!register_signal_handlers()) { + g_critical("failed to register signal handlers"); +- return NULL; ++ goto failed; + } + #endif + +@@ -1353,12 +1353,20 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation) + s->wakeup_event = CreateEvent(NULL, TRUE, FALSE, TEXT("WakeUp")); + if (s->wakeup_event == NULL) { + g_critical("CreateEvent failed"); +- return NULL; ++ goto failed; + } + #endif + + ga_state = s; + return s; ++failed: ++ g_free(s->pstate_filepath); ++ g_free(s->state_filepath_isfrozen); ++ if (s->log_file) { ++ fclose(s->log_file); ++ } ++ g_free(s); ++ return NULL; + } + + static void cleanup_agent(GAState *s) +-- +2.27.0 + diff --git a/bugfix-fix-some-illegal-memory-access-and-memory-lea.patch b/bugfix-fix-some-illegal-memory-access-and-memory-lea.patch new file mode 100644 index 0000000000000000000000000000000000000000..48c7970efa46bf78c772159cae0c501ff997ae1a --- /dev/null +++ b/bugfix-fix-some-illegal-memory-access-and-memory-lea.patch @@ -0,0 +1,53 @@ +From 0a0a490c805fadc7191489277e77fbf9688b39ab Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Thu, 10 Feb 2022 21:32:37 +0800 +Subject: [PATCH] bugfix: fix some illegal memory access and memory leak + +Signed-off-by: yuxiating +Signed-off-by: jiangdongxu +--- + contrib/elf2dmp/main.c | 1 + + hw/display/cirrus_vga.c | 2 +- + util/range.c | 1 + + 3 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c +index 20b477d582..3f0d1eb709 100644 +--- a/contrib/elf2dmp/main.c ++++ b/contrib/elf2dmp/main.c +@@ -125,6 +125,7 @@ static KDDEBUGGER_DATA64 *get_kdbg(uint64_t KernBase, struct pdb_reader *pdb, + + if (va_space_rw(vs, KdDebuggerDataBlock, kdbg, kdbg_hdr.Size, 0)) { + eprintf("Failed to extract entire KDBG\n"); ++ free(kdbg); + return NULL; + } + +diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c +index fdca6ca659..c66ed801ef 100644 +--- a/hw/display/cirrus_vga.c ++++ b/hw/display/cirrus_vga.c +@@ -834,7 +834,7 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s) + word alignment, so we keep them for the next line */ + /* XXX: keep alignment to speed up transfer */ + end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; +- copy_count = s->cirrus_srcptr_end - end_ptr; ++ copy_count = MIN(s->cirrus_srcptr_end - end_ptr, CIRRUS_BLTBUFSIZE); + memmove(s->cirrus_bltbuf, end_ptr, copy_count); + s->cirrus_srcptr = s->cirrus_bltbuf + copy_count; + s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; +diff --git a/util/range.c b/util/range.c +index 098d9d2dc0..83d1a6c302 100644 +--- a/util/range.c ++++ b/util/range.c +@@ -65,6 +65,7 @@ GList *range_list_insert(GList *list, Range *data) + range_extend(l->data, l->next->data); + g_free(l->next->data); + new_l = g_list_delete_link(list, l->next); ++ l->next = NULL; + assert(new_l == list); + } + +-- +2.27.0 + diff --git a/bugfix-irq-Avoid-covering-object-refcount-of-qemu_ir.patch b/bugfix-irq-Avoid-covering-object-refcount-of-qemu_ir.patch new file mode 100644 index 0000000000000000000000000000000000000000..5a329c7f1d4ed1472e22909b75bcd56cd92b32a0 --- /dev/null +++ b/bugfix-irq-Avoid-covering-object-refcount-of-qemu_ir.patch @@ -0,0 +1,32 @@ +From 32353a7838f9ff38c5bd768252a79bd8e485658b Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Mon, 27 Jul 2020 20:39:07 +0800 +Subject: [PATCH] bugfix: irq: Avoid covering object refcount of qemu_irq + +Avoid covering object refcount of qemu_irq, otherwise it may causes +memory leak. + +Signed-off-by: Keqian Zhu +--- + hw/core/irq.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/hw/core/irq.c b/hw/core/irq.c +index 8a9cbdd556..700a6373d8 100644 +--- a/hw/core/irq.c ++++ b/hw/core/irq.c +@@ -126,7 +126,10 @@ void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n) + int i; + qemu_irq *old_irqs = qemu_allocate_irqs(NULL, NULL, n); + for (i = 0; i < n; i++) { +- *old_irqs[i] = *gpio_in[i]; ++ old_irqs[i]->handler = gpio_in[i]->handler; ++ old_irqs[i]->opaque = gpio_in[i]->opaque; ++ old_irqs[i]->n = gpio_in[i]->n; ++ + gpio_in[i]->handler = handler; + gpio_in[i]->opaque = &old_irqs[i]; + } +-- +2.27.0 + diff --git a/build-smt-processor-structure-to-support-smt-topolog.patch b/build-smt-processor-structure-to-support-smt-topolog.patch deleted file mode 100644 index ed01d38bb17dd4931a1f23b5a21127a2c5dd0425..0000000000000000000000000000000000000000 --- a/build-smt-processor-structure-to-support-smt-topolog.patch +++ /dev/null @@ -1,104 +0,0 @@ -From af8740502815be450709e88df44ad322da2b071f Mon Sep 17 00:00:00 2001 -From: Henglong Fan -Date: Tue, 18 Aug 2020 21:42:33 +0800 -Subject: [PATCH] build smt processor structure to support smt topology - -if vcpu support smt, create new smt hierarchy according to -Processor Properties Topology Table(PPTT) in acpi spec 6.3. -Threads sharing a core must be grouped under a unique Processor -hierarchy node structure for each group of threads - -Signed-off-by: Henglong Fan ---- - hw/acpi/aml-build.c | 40 ++++++++++++++++++++++++++++++++-------- - 1 file changed, 32 insertions(+), 8 deletions(-) - -diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c -index 74e95005..8a3b51c8 100644 ---- a/hw/acpi/aml-build.c -+++ b/hw/acpi/aml-build.c -@@ -53,7 +53,7 @@ static void build_append_array(GArray *array, GArray *val) - } - - /* -- * ACPI 6.2 Processor Properties Topology Table (PPTT) -+ * ACPI 6.3 Processor Properties Topology Table (PPTT) - */ - #ifdef __aarch64__ - static void build_cache_head(GArray *tbl, uint32_t next_level) -@@ -126,7 +126,7 @@ static void build_arm_socket_hierarchy(GArray *tbl, - build_append_int_noprefix(tbl, offset, 4); - } - --static void build_arm_cpu_hierarchy(GArray *tbl, -+static void build_arm_core_hierarchy(GArray *tbl, - struct offset_status *offset, uint32_t id) - { - if (!offset) { -@@ -144,18 +144,35 @@ static void build_arm_cpu_hierarchy(GArray *tbl, - build_append_int_noprefix(tbl, offset->l2_offset, 4); - } - -+static void build_arm_smt_hierarchy(GArray *tbl, -+ uint32_t offset, uint32_t id) -+{ -+ if (!offset) { -+ return; -+ } -+ build_append_byte(tbl, 0); /* Type 0 - processor */ -+ build_append_byte(tbl, 20); /* Length, add private resources */ -+ build_append_int_noprefix(tbl, 0, 2); /* Reserved */ -+ build_append_int_noprefix(tbl, 14, 4); /* Valid id*/ -+ build_append_int_noprefix(tbl, offset, 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; -+ int uid = 0, socket; -+ uint32_t core_offset; - struct offset_status offset; - const MachineState *ms = MACHINE(qdev_get_machine()); - unsigned int smp_cores = ms->smp.cores; -+ unsigned int smp_sockets = ms->smp.cpus / (smp_cores * ms->smp.threads); - - acpi_data_push(table_data, sizeof(AcpiTableHeader)); - -- for (socket = 0; cpus < possible_cpus; socket++) { -- int core; -+ for (socket = 0; socket < smp_sockets; socket++) { -+ int core,thread; - uint32_t l3_offset = table_data->len - pptt_start; - build_cache_hierarchy(table_data, 0, ARM_L3_CACHE); - -@@ -169,14 +186,21 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, int possible_cpus) - 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++; -+ core_offset = table_data->len - pptt_start; -+ if (ms->smp.threads <= 1) { -+ build_arm_core_hierarchy(table_data, &offset, uid++); -+ } else { -+ build_arm_core_hierarchy(table_data, &offset, core); -+ for (thread = 0; thread < ms->smp.threads; thread++) { -+ build_arm_smt_hierarchy(table_data, core_offset, uid++); -+ } -+ } - } - } - - build_header(linker, table_data, - (void *)(table_data->data + pptt_start), "PPTT", -- table_data->len - pptt_start, 1, NULL, NULL); -+ table_data->len - pptt_start, 2, NULL, NULL); - } - - #else --- -2.23.0 - diff --git a/char-fix-use-after-free-with-dup-chardev-reconnect.patch b/char-fix-use-after-free-with-dup-chardev-reconnect.patch deleted file mode 100644 index fd81015a18beced443caef903d0ec1f2a1fd8850..0000000000000000000000000000000000000000 --- a/char-fix-use-after-free-with-dup-chardev-reconnect.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 902a8192600ff81681a162509e23bf95619d1f04 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Mon, 20 Apr 2020 13:20:12 +0200 -Subject: [PATCH] char: fix use-after-free with dup chardev & reconnect -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -With a reconnect socket, qemu_char_open() will start a background -thread. It should keep a reference on the chardev. - -Fixes invalid read: -READ of size 8 at 0x6040000ac858 thread T7 - #0 0x5555598d37b8 in unix_connect_saddr /home/elmarco/src/qq/util/qemu-sockets.c:954 - #1 0x5555598d4751 in socket_connect /home/elmarco/src/qq/util/qemu-sockets.c:1109 - #2 0x555559707c34 in qio_channel_socket_connect_sync /home/elmarco/src/qq/io/channel-socket.c:145 - #3 0x5555596adebb in tcp_chr_connect_client_task /home/elmarco/src/qq/chardev/char-socket.c:1104 - #4 0x555559723d55 in qio_task_thread_worker /home/elmarco/src/qq/io/task.c:123 - #5 0x5555598a6731 in qemu_thread_start /home/elmarco/src/qq/util/qemu-thread-posix.c:519 - #6 0x7ffff40d4431 in start_thread (/lib64/libpthread.so.0+0x9431) - #7 0x7ffff40029d2 in __clone (/lib64/libc.so.6+0x1019d2) - -Signed-off-by: Marc-André Lureau -Reviewed-by: Daniel P. Berrangé -Message-Id: <20200420112012.567284-1-marcandre.lureau@redhat.com> -Signed-off-by: Zhenyu Ye ---- - chardev/char-socket.c | 3 ++- - tests/test-char.c | 53 ++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 54 insertions(+), 2 deletions(-) - -diff --git a/chardev/char-socket.c b/chardev/char-socket.c -index 7ca5d97a..701b62f9 100644 ---- a/chardev/char-socket.c -+++ b/chardev/char-socket.c -@@ -1118,7 +1118,8 @@ static void tcp_chr_connect_client_async(Chardev *chr) - */ - s->connect_task = qio_task_new(OBJECT(sioc), - qemu_chr_socket_connected, -- chr, NULL); -+ object_ref(OBJECT(chr)), -+ (GDestroyNotify)object_unref); - qio_task_run_in_thread(s->connect_task, - tcp_chr_connect_client_task, - s->addr, -diff --git a/tests/test-char.c b/tests/test-char.c -index f9440cdc..0e4069fb 100644 ---- a/tests/test-char.c -+++ b/tests/test-char.c -@@ -871,6 +871,53 @@ typedef struct { - } CharSocketClientTestConfig; - - -+static void char_socket_client_dupid_test(gconstpointer opaque) -+{ -+ const CharSocketClientTestConfig *config = opaque; -+ QIOChannelSocket *ioc; -+ char *optstr; -+ Chardev *chr1, *chr2; -+ SocketAddress *addr; -+ QemuOpts *opts; -+ Error *local_err = NULL; -+ -+ /* -+ * Setup a listener socket and determine get its address -+ * so we know the TCP port for the client later -+ */ -+ ioc = qio_channel_socket_new(); -+ g_assert_nonnull(ioc); -+ qio_channel_socket_listen_sync(ioc, config->addr, &error_abort); -+ addr = qio_channel_socket_get_local_address(ioc, &error_abort); -+ g_assert_nonnull(addr); -+ -+ /* -+ * Populate the chardev address based on what the server -+ * is actually listening on -+ */ -+ optstr = char_socket_addr_to_opt_str(addr, -+ config->fd_pass, -+ config->reconnect, -+ false); -+ -+ opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"), -+ optstr, true); -+ g_assert_nonnull(opts); -+ chr1 = qemu_chr_new_from_opts(opts, NULL, &error_abort); -+ g_assert_nonnull(chr1); -+ -+ chr2 = qemu_chr_new_from_opts(opts, NULL, &local_err); -+ g_assert_null(chr2); -+ error_free_or_abort(&local_err); -+ -+ object_unref(OBJECT(ioc)); -+ qemu_opts_del(opts); -+ object_unparent(OBJECT(chr1)); -+ qapi_free_SocketAddress(addr); -+ g_free(optstr); -+} -+ -+ - static void char_socket_client_test(gconstpointer opaque) - { - const CharSocketClientTestConfig *config = opaque; -@@ -1425,6 +1472,8 @@ int main(int argc, char **argv) - { addr, NULL, false, true }; \ - CharSocketClientTestConfig client6 ## name = \ - { addr, NULL, true, true }; \ -+ CharSocketClientTestConfig client7 ## name = \ -+ { addr, ",reconnect=1", false, false }; \ - g_test_add_data_func("/char/socket/client/mainloop/" # name, \ - &client1 ##name, char_socket_client_test); \ - g_test_add_data_func("/char/socket/client/wait-conn/" # name, \ -@@ -1436,7 +1485,9 @@ int main(int argc, char **argv) - g_test_add_data_func("/char/socket/client/mainloop-fdpass/" # name, \ - &client5 ##name, char_socket_client_test); \ - g_test_add_data_func("/char/socket/client/wait-conn-fdpass/" # name, \ -- &client6 ##name, char_socket_client_test) -+ &client6 ##name, char_socket_client_test); \ -+ g_test_add_data_func("/char/socket/client/dupid-reconnect/" # name, \ -+ &client7 ##name, char_socket_client_dupid_test) - - SOCKET_SERVER_TEST(tcp, &tcpaddr); - SOCKET_CLIENT_TEST(tcp, &tcpaddr); --- -2.22.0.windows.1 - diff --git a/chardev-tcp-Fix-error-message-double-free-error.patch b/chardev-tcp-Fix-error-message-double-free-error.patch deleted file mode 100644 index 175ddfe2dea85111016d162aa0cd95d79a49a492..0000000000000000000000000000000000000000 --- a/chardev-tcp-Fix-error-message-double-free-error.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 4488ab4700d344b049ddef808a64eda4b5867902 Mon Sep 17 00:00:00 2001 -From: lichun -Date: Mon, 22 Jun 2020 05:30:17 +0800 -Subject: [PATCH 06/11] chardev/tcp: Fix error message double free error - -Errors are already freed by error_report_err, so we only need to call -error_free when that function is not called. - -Cc: qemu-stable@nongnu.org -Signed-off-by: lichun -Message-Id: <20200621213017.17978-1-lichun@ruijie.com.cn> -Reviewed-by: Markus Armbruster -[Commit message improved, cc: qemu-stable] -Signed-off-by: Markus Armbruster -Signed-off-by: BiaoXiang Ye ---- - chardev/char-socket.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/chardev/char-socket.c b/chardev/char-socket.c -index 701b62f9..9b06c8aa 100644 ---- a/chardev/char-socket.c -+++ b/chardev/char-socket.c -@@ -141,6 +141,8 @@ static void check_report_connect_error(Chardev *chr, - error_report("Unable to connect character device %s: %s", - chr->label, error_get_pretty(err)); - s->connect_err_reported = true; -+ } else { -+ error_free(err); - } - qemu_chr_socket_restart_timer(chr); - } -@@ -1074,7 +1076,6 @@ static void qemu_chr_socket_connected(QIOTask *task, void *opaque) - if (qio_task_propagate_error(task, &err)) { - tcp_chr_change_state(s, TCP_CHARDEV_STATE_DISCONNECTED); - check_report_connect_error(chr, err); -- error_free(err); - goto cleanup; - } - --- -2.27.0.dirty - diff --git a/colo-compare-Fix-memory-leak-in-packet_enqueue.patch b/colo-compare-Fix-memory-leak-in-packet_enqueue.patch deleted file mode 100644 index ca5e43c49a6ad18fa7c6d204c1eabfac7ed6ddd5..0000000000000000000000000000000000000000 --- a/colo-compare-Fix-memory-leak-in-packet_enqueue.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 19afb1431bd730a1e4e09e3c0835c35572517268 Mon Sep 17 00:00:00 2001 -From: Derek Su -Date: Fri, 22 May 2020 15:53:57 +0800 -Subject: [PATCH 07/11] colo-compare: Fix memory leak in packet_enqueue() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The patch is to fix the "pkt" memory leak in packet_enqueue(). -The allocated "pkt" needs to be freed if the colo compare -primary or secondary queue is too big. - -Replace the error_report of full queue with a trace event. - -Signed-off-by: Derek Su -Reviewed-by: Zhang Chen -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Zhang Chen -Signed-off-by: Jason Wang -Signed-off-by: BiaoXiang Ye ---- - net/colo-compare.c | 23 +++++++++++++++-------- - net/trace-events | 1 + - 2 files changed, 16 insertions(+), 8 deletions(-) - -diff --git a/net/colo-compare.c b/net/colo-compare.c -index 7ee17f2c..3168407e 100644 ---- a/net/colo-compare.c -+++ b/net/colo-compare.c -@@ -120,6 +120,10 @@ enum { - SECONDARY_IN, - }; - -+static const char *colo_mode[] = { -+ [PRIMARY_IN] = "primary", -+ [SECONDARY_IN] = "secondary", -+}; - - static int compare_chr_send(CompareState *s, - const uint8_t *buf, -@@ -215,6 +219,7 @@ static int packet_enqueue(CompareState *s, int mode, Connection **con) - ConnectionKey key; - Packet *pkt = NULL; - Connection *conn; -+ int ret; - - if (mode == PRIMARY_IN) { - pkt = packet_new(s->pri_rs.buf, -@@ -243,16 +248,18 @@ static int packet_enqueue(CompareState *s, int mode, Connection **con) - } - - if (mode == PRIMARY_IN) { -- if (!colo_insert_packet(&conn->primary_list, pkt, &conn->pack)) { -- error_report("colo compare primary queue size too big," -- "drop packet"); -- } -+ ret = colo_insert_packet(&conn->primary_list, pkt, &conn->pack); - } else { -- if (!colo_insert_packet(&conn->secondary_list, pkt, &conn->sack)) { -- error_report("colo compare secondary queue size too big," -- "drop packet"); -- } -+ ret = colo_insert_packet(&conn->secondary_list, pkt, &conn->sack); - } -+ -+ if (!ret) { -+ trace_colo_compare_drop_packet(colo_mode[mode], -+ "queue size too big, drop packet"); -+ packet_destroy(pkt, NULL); -+ pkt = NULL; -+ } -+ - *con = conn; - - return 0; -diff --git a/net/trace-events b/net/trace-events -index ac570564..a9995387 100644 ---- a/net/trace-events -+++ b/net/trace-events -@@ -12,6 +12,7 @@ colo_proxy_main(const char *chr) ": %s" - - # colo-compare.c - colo_compare_main(const char *chr) ": %s" -+colo_compare_drop_packet(const char *queue, const char *chr) ": %s: %s" - colo_compare_udp_miscompare(const char *sta, int size) ": %s = %d" - colo_compare_icmp_miscompare(const char *sta, int size) ": %s = %d" - colo_compare_ip_info(int psize, const char *sta, const char *stb, int ssize, const char *stc, const char *std) "ppkt size = %d, ip_src = %s, ip_dst = %s, spkt size = %d, ip_src = %s, ip_dst = %s" --- -2.27.0.dirty - diff --git a/configure-Enable-test-and-libs-for-zstd.patch b/configure-Enable-test-and-libs-for-zstd.patch deleted file mode 100644 index bf900cf343d4d77c997d203ffcd12a8dc6c434fb..0000000000000000000000000000000000000000 --- a/configure-Enable-test-and-libs-for-zstd.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 5a79ccd388ee09dc1db93d26791d1e4a6b2ced47 Mon Sep 17 00:00:00 2001 -From: Juan Quintela -Date: Wed, 3 Feb 2021 17:33:44 +0800 -Subject: [PATCH] configure: Enable test and libs for zstd - -configure: Enable test and libs for zstd -Add it to several build systems to make testing good. - -Signed-off-by: Juan Quintela -Reviewed-by: Dr. David Alan Gilbert - -Signed-off-by: Jiajie Li ---- - .gitlab-ci.yml | 1 + - .travis.yml | 1 + - configure | 30 ++++++++++++++++++++++++++++++ - 3 files changed, 32 insertions(+) - -diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml -index c63bf2f822..3d9b7f9262 100644 ---- a/.gitlab-ci.yml -+++ b/.gitlab-ci.yml -@@ -16,6 +16,7 @@ build-system2: - script: - - apt-get install -y -qq libsdl2-dev libgcrypt-dev libbrlapi-dev libaio-dev - libfdt-dev liblzo2-dev librdmacm-dev libibverbs-dev libibumad-dev -+ libzstd-dev - - ./configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu - microblaze-softmmu mips-softmmu riscv32-softmmu s390x-softmmu sh4-softmmu - sparc64-softmmu x86_64-softmmu xtensa-softmmu nios2-softmmu or1k-softmmu" -diff --git a/.travis.yml b/.travis.yml -index caf0a1f8fa..f3fe04fba9 100644 ---- a/.travis.yml -+++ b/.travis.yml -@@ -35,6 +35,7 @@ addons: - - liburcu-dev - - libusb-1.0-0-dev - - libvte-2.91-dev -+ - libzstd-dev - - sparse - - uuid-dev - - gcovr -diff --git a/configure b/configure -index 714e7fb6a1..577533e9ed 100755 ---- a/configure -+++ b/configure -@@ -446,6 +446,7 @@ lzo="" - snappy="" - bzip2="" - lzfse="" -+zstd="" - guest_agent="" - guest_agent_with_vss="no" - guest_agent_ntddscsi="no" -@@ -1358,6 +1359,10 @@ for opt do - ;; - --disable-lzfse) lzfse="no" - ;; -+ --disable-zstd) zstd="no" -+ ;; -+ --enable-zstd) zstd="yes" -+ ;; - --enable-guest-agent) guest_agent="yes" - ;; - --disable-guest-agent) guest_agent="no" -@@ -1812,6 +1817,8 @@ disabled with --disable-FEATURE, default is enabled if available: - (for reading bzip2-compressed dmg images) - lzfse support of lzfse compression library - (for reading lzfse-compressed dmg images) -+ zstd support for zstd compression library -+ (for migration compression) - seccomp seccomp support - coroutine-pool coroutine freelist (better performance) - glusterfs GlusterFS backend -@@ -2407,6 +2414,24 @@ EOF - fi - fi - -+########################################## -+# zstd check -+ -+if test "$zstd" != "no" ; then -+ if $pkg_config --exist libzstd ; then -+ zstd_cflags="$($pkg_config --cflags libzstd)" -+ zstd_libs="$($pkg_config --libs libzstd)" -+ LIBS="$zstd_libs $LIBS" -+ QEMU_CFLAGS="$QEMU_CFLAGS $zstd_cflags" -+ zstd="yes" -+ else -+ if test "$zstd" = "yes" ; then -+ feature_not_found "libzstd" "Install libzstd devel" -+ fi -+ zstd="no" -+ fi -+fi -+ - ########################################## - # libseccomp check - -@@ -6460,6 +6485,7 @@ echo "lzo support $lzo" - echo "snappy support $snappy" - echo "bzip2 support $bzip2" - echo "lzfse support $lzfse" -+echo "zstd support $zstd" - echo "NUMA host support $numa" - echo "libxml2 $libxml2" - echo "tcmalloc support $tcmalloc" -@@ -7024,6 +7050,10 @@ if test "$lzfse" = "yes" ; then - echo "LZFSE_LIBS=-llzfse" >> $config_host_mak - fi - -+if test "$zstd" = "yes" ; then -+ echo "CONFIG_ZSTD=y" >> $config_host_mak -+fi -+ - if test "$libiscsi" = "yes" ; then - echo "CONFIG_LIBISCSI=m" >> $config_host_mak - echo "LIBISCSI_CFLAGS=$libiscsi_cflags" >> $config_host_mak --- -2.27.0 - diff --git a/contrib-libvhost-user-Protect-slave-fd-with-mutex.patch b/contrib-libvhost-user-Protect-slave-fd-with-mutex.patch deleted file mode 100644 index 44fc4283ca652bb9743c186b2127f073e32b5043..0000000000000000000000000000000000000000 --- a/contrib-libvhost-user-Protect-slave-fd-with-mutex.patch +++ /dev/null @@ -1,121 +0,0 @@ -From f076af734a5964c3e48b2d223130f855b86f40e5 Mon Sep 17 00:00:00 2001 -From: "Dr. David Alan Gilbert" -Date: Fri, 1 Mar 2019 11:18:30 +0000 -Subject: [PATCH] contrib/libvhost-user: Protect slave fd with mutex -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In future patches we'll be performing commands on the slave-fd driven -by commands on queues, since those queues will be driven by individual -threads we need to make sure they don't attempt to use the slave-fd -for multiple commands in parallel. - -Signed-off-by: Dr. David Alan Gilbert -Reviewed-by: Daniel P. Berrangé -Signed-off-by: Dr. David Alan Gilbert ---- - contrib/libvhost-user/libvhost-user.c | 24 ++++++++++++++++++++---- - contrib/libvhost-user/libvhost-user.h | 3 +++ - 2 files changed, 23 insertions(+), 4 deletions(-) - -diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c -index cb5f5770e4..fb75837032 100644 ---- a/contrib/libvhost-user/libvhost-user.c -+++ b/contrib/libvhost-user/libvhost-user.c -@@ -387,26 +387,37 @@ vu_send_reply(VuDev *dev, int conn_fd, VhostUserMsg *vmsg) - return vu_message_write(dev, conn_fd, vmsg); - } - -+/* -+ * Processes a reply on the slave channel. -+ * Entered with slave_mutex held and releases it before exit. -+ * Returns true on success. -+ */ - static bool - vu_process_message_reply(VuDev *dev, const VhostUserMsg *vmsg) - { - VhostUserMsg msg_reply; -+ bool result = false; - - if ((vmsg->flags & VHOST_USER_NEED_REPLY_MASK) == 0) { -- return true; -+ result = true; -+ goto out; - } - - if (!vu_message_read(dev, dev->slave_fd, &msg_reply)) { -- return false; -+ goto out; - } - - if (msg_reply.request != vmsg->request) { - DPRINT("Received unexpected msg type. Expected %d received %d", - vmsg->request, msg_reply.request); -- return false; -+ goto out; - } - -- return msg_reply.payload.u64 == 0; -+ result = msg_reply.payload.u64 == 0; -+ -+out: -+ pthread_mutex_unlock(&dev->slave_mutex); -+ return result; - } - - /* Kick the log_call_fd if required. */ -@@ -1102,10 +1113,13 @@ bool vu_set_queue_host_notifier(VuDev *dev, VuVirtq *vq, int fd, - return false; - } - -+ pthread_mutex_lock(&dev->slave_mutex); - if (!vu_message_write(dev, dev->slave_fd, &vmsg)) { -+ pthread_mutex_unlock(&dev->slave_mutex); - return false; - } - -+ /* Also unlocks the slave_mutex */ - return vu_process_message_reply(dev, &vmsg); - } - -@@ -1625,6 +1639,7 @@ vu_deinit(VuDev *dev) - close(dev->slave_fd); - dev->slave_fd = -1; - } -+ pthread_mutex_destroy(&dev->slave_mutex); - - if (dev->sock != -1) { - close(dev->sock); -@@ -1660,6 +1675,7 @@ vu_init(VuDev *dev, - dev->remove_watch = remove_watch; - dev->iface = iface; - dev->log_call_fd = -1; -+ pthread_mutex_init(&dev->slave_mutex, NULL); - dev->slave_fd = -1; - dev->max_queues = max_queues; - -diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h -index 46b600799b..1844b6f8d4 100644 ---- a/contrib/libvhost-user/libvhost-user.h -+++ b/contrib/libvhost-user/libvhost-user.h -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include "standard-headers/linux/virtio_ring.h" - - /* Based on qemu/hw/virtio/vhost-user.c */ -@@ -355,6 +356,8 @@ struct VuDev { - VuVirtq *vq; - VuDevInflightInfo inflight_info; - int log_call_fd; -+ /* Must be held while using slave_fd */ -+ pthread_mutex_t slave_mutex; - int slave_fd; - uint64_t log_size; - uint8_t *log_table; --- -2.27.0 - diff --git a/coro-support-live-patch-for-libcare.patch b/coro-support-live-patch-for-libcare.patch new file mode 100644 index 0000000000000000000000000000000000000000..5e287eb8965a7dceae982963097dc196874f3347 --- /dev/null +++ b/coro-support-live-patch-for-libcare.patch @@ -0,0 +1,120 @@ +From 2135fe8e9c4d459d3f06babf3bfd71b5387b0214 Mon Sep 17 00:00:00 2001 +From: jiang-dawei15 +Date: Tue, 15 Mar 2022 10:28:34 +0800 +Subject: [PATCH] coro: support live patch for libcare + +Description: +For coroutine live patch, we need find all coroutines stack and check them +before patching. There is no structure to manage all coroutines in qemu. So we +add a list which contain all running coroutines to accelerate libcare live +patch. +--- + include/qemu/coroutine_int.h | 3 ++- + util/coroutine-ucontext.c | 52 ++++++++++++++++++++++++++++++++++++ + util/qemu-coroutine.c | 4 +++ + 3 files changed, 58 insertions(+), 1 deletion(-) + +diff --git a/include/qemu/coroutine_int.h b/include/qemu/coroutine_int.h +index 1da148552f..11b550a0fc 100644 +--- a/include/qemu/coroutine_int.h ++++ b/include/qemu/coroutine_int.h +@@ -73,5 +73,6 @@ Coroutine *qemu_coroutine_new(void); + void qemu_coroutine_delete(Coroutine *co); + CoroutineAction qemu_coroutine_switch(Coroutine *from, Coroutine *to, + CoroutineAction action); +- ++void qemu_coroutine_info_add(const Coroutine *co_); ++void qemu_coroutine_info_delete(const Coroutine *co_); + #endif +diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c +index 904b375192..23ab7cdf74 100644 +--- a/util/coroutine-ucontext.c ++++ b/util/coroutine-ucontext.c +@@ -79,6 +79,19 @@ union cc_arg { + int i[2]; + }; + ++/** ++ * coroutines list for libcare ++ */ ++struct CoroutineInformation { ++ sigjmp_buf *env; ++ QLIST_ENTRY(CoroutineInformation) next; ++}; ++ ++static QemuMutex coro_mtx; ++QLIST_HEAD(, CoroutineInformation) coro_info_list = QLIST_HEAD_INITIALIZER(pool); ++int coro_env_offset = offsetof(struct CoroutineInformation, env); ++int coro_next_offset = offsetof(struct CoroutineInformation, next); ++ + /* + * QEMU_ALWAYS_INLINE only does so if __OPTIMIZE__, so we cannot use it. + * always_inline is required to avoid TSan runtime fatal errors. +@@ -330,3 +343,42 @@ bool qemu_in_coroutine(void) + { + return current && current->caller; + } ++ ++static void __attribute__((constructor)) coro_mutex_init(void) ++{ ++ qemu_mutex_init(&coro_mtx); ++} ++ ++void qemu_coroutine_info_add(const Coroutine *co_) ++{ ++ CoroutineUContext *co; ++ struct CoroutineInformation *coro_info; ++ ++ /* save coroutine env to coro_info_list */ ++ co = DO_UPCAST(CoroutineUContext, base, co_); ++ coro_info = g_malloc0(sizeof(struct CoroutineInformation)); ++ coro_info->env = &co->env; ++ ++ qemu_mutex_lock(&coro_mtx); ++ QLIST_INSERT_HEAD(&coro_info_list, coro_info, next); ++ qemu_mutex_unlock(&coro_mtx); ++} ++ ++void qemu_coroutine_info_delete(const Coroutine *co_) ++{ ++ CoroutineUContext *co; ++ struct CoroutineInformation *coro_info; ++ ++ /* Remove relative coroutine env info from coro_info_list */ ++ co = DO_UPCAST(CoroutineUContext, base, co_); ++ ++ qemu_mutex_lock(&coro_mtx); ++ QLIST_FOREACH(coro_info, &coro_info_list, next) { ++ if (coro_info->env == &co->env) { ++ QLIST_REMOVE(coro_info, next); ++ g_free(coro_info); ++ break; ++ } ++ } ++ qemu_mutex_unlock(&coro_mtx); ++} +diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c +index b9586d6929..9c81336d8e 100644 +--- a/util/qemu-coroutine.c ++++ b/util/qemu-coroutine.c +@@ -75,6 +75,8 @@ Coroutine *qemu_coroutine_create(CoroutineEntry *entry, void *opaque) + co = qemu_coroutine_new(); + } + ++ qemu_coroutine_info_add(co); ++ + co->entry = entry; + co->entry_arg = opaque; + QSIMPLEQ_INIT(&co->co_queue_wakeup); +@@ -85,6 +87,8 @@ static void coroutine_delete(Coroutine *co) + { + co->caller = NULL; + ++ qemu_coroutine_info_delete(co); ++ + if (CONFIG_COROUTINE_POOL) { + if (release_pool_size < POOL_BATCH_SIZE * 2) { + QSLIST_INSERT_HEAD_ATOMIC(&release_pool, co, pool_next); +-- +2.27.0 + diff --git a/coroutine-Add-qemu_co_mutex_assert_locked.patch b/coroutine-Add-qemu_co_mutex_assert_locked.patch deleted file mode 100644 index fb1f2589f3edd987f0311288d049951c726ddeb8..0000000000000000000000000000000000000000 --- a/coroutine-Add-qemu_co_mutex_assert_locked.patch +++ /dev/null @@ -1,50 +0,0 @@ -From e9bb3d942e268a19e03fc5d404586d2ed1564282 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Thu, 24 Oct 2019 16:26:57 +0200 -Subject: [PATCH] coroutine: Add qemu_co_mutex_assert_locked() - -Some functions require that the caller holds a certain CoMutex for them -to operate correctly. Add a function so that they can assert the lock is -really held. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Kevin Wolf -Tested-by: Michael Weiser -Reviewed-by: Michael Weiser -Reviewed-by: Vladimir Sementsov-Ogievskiy -Reviewed-by: Denis V. Lunev -Reviewed-by: Max Reitz -(cherry picked from commit 944f3d5dd216fcd8cb007eddd4f82dced0a15b3d) -Signed-off-by: Michael Roth ---- - include/qemu/coroutine.h | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - -diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h -index 9801e7f5a4..f4843b5f59 100644 ---- a/include/qemu/coroutine.h -+++ b/include/qemu/coroutine.h -@@ -167,6 +167,21 @@ void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex); - */ - void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex); - -+/** -+ * Assert that the current coroutine holds @mutex. -+ */ -+static inline coroutine_fn void qemu_co_mutex_assert_locked(CoMutex *mutex) -+{ -+ /* -+ * mutex->holder doesn't need any synchronisation if the assertion holds -+ * true because the mutex protects it. If it doesn't hold true, we still -+ * don't mind if another thread takes or releases mutex behind our back, -+ * because the condition will be false no matter whether we read NULL or -+ * the pointer for any other coroutine. -+ */ -+ assert(atomic_read(&mutex->locked) && -+ mutex->holder == qemu_coroutine_self()); -+} - - /** - * CoQueues are a mechanism to queue coroutines in order to continue executing --- -2.23.0 diff --git a/cpu-add-Cortex-A72-processor-kvm-target-support.patch b/cpu-add-Cortex-A72-processor-kvm-target-support.patch index a310c37de95cb5fac446418afcd1efe3650180af..9a83a8d560cde00b49675184bb86c780c0a33691 100644 --- a/cpu-add-Cortex-A72-processor-kvm-target-support.patch +++ b/cpu-add-Cortex-A72-processor-kvm-target-support.patch @@ -1,39 +1,32 @@ -From 4304d1de2c790ac75ed2f5984c4a3a2760c08fff Mon Sep 17 00:00:00 2001 +From f0da7fa5230b5f771570b2c12288e4a56a20dd97 Mon Sep 17 00:00:00 2001 From: Xu Yandong -Date: Mon, 23 Sep 2019 14:35:25 +0800 +Date: Tue, 8 Feb 2022 22:18:55 +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 +Signed-off-by: Mingwang Li --- - target/arm/cpu64.c | 2 +- + target/arm/cpu64.c | 1 + target/arm/kvm-consts.h | 3 +++ - 2 files changed, 4 insertions(+), 1 deletion(-) + 2 files changed, 4 insertions(+) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index e408f50d..afbfd1ec 100644 +index aaca79f7c3..556b6f3691 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c -@@ -212,6 +212,7 @@ static void aarch64_a72_initfn(Object *obj) +@@ -202,6 +202,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, + set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h -index aad28258..b7dac596 100644 +index 580f1c1fee..5f1311ade7 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); @@ -45,14 +38,14 @@ index aad28258..b7dac596 100644 /* 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); +@@ -141,6 +143,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); + + #define CP_REG_ARM64 0x6000000000000000ULL + #define CP_REG_ARM_COPROC_MASK 0x000000000FFF0000 -- -2.23.0 +2.27.0 diff --git a/cpu-add-Kunpeng-920-cpu-support.patch b/cpu-add-Kunpeng-920-cpu-support.patch index 74e27645ac18a07c00a04283f428bec515cf259e..5e24be91c6cf13417cb239f561c60bd4704c0711 100644 --- a/cpu-add-Kunpeng-920-cpu-support.patch +++ b/cpu-add-Kunpeng-920-cpu-support.patch @@ -1,66 +1,68 @@ -From 70063948181062161a341a8738a53708d8ed0a0b Mon Sep 17 00:00:00 2001 +From 8ebab06c4824626ab4d7204133cd1e7b9c67f468 Mon Sep 17 00:00:00 2001 From: Xu Yandong -Date: Wed, 28 Aug 2019 01:36:21 -0400 +Date: Tue, 8 Feb 2022 21:36:22 +0800 Subject: [PATCH] cpu: add Kunpeng-920 cpu support -Add the Kunpeng-920 CPU model. +Add the Kunpeng-920 CPU model Signed-off-by: Xu Yandong +Signed-off-by: Mingwang Li --- 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 +index 30da05dfe0..a4a35584e9 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -179,6 +179,7 @@ static const char *valid_cpus[] = { +@@ -201,6 +201,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-920"), + ARM_CPU_TYPE_NAME("a64fx"), 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 +index 019edc66c9..aaca79f7c3 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c -@@ -258,6 +258,26 @@ static void aarch64_a72_initfn(Object *obj) +@@ -248,6 +248,26 @@ static void aarch64_a72_initfn(Object *obj) define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo); } - + +static void aarch64_kunpeng_920_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + + /* + * Hisilicon Kunpeng-920 CPU is similar to cortex-a72, -+ * so first initialize cpu data as cortex-a72 CPU, -+ * and then update the special registers. ++ * so first initialize cpu data as cortex-a72, ++ * and then update the special register. + */ + aarch64_a72_initfn(obj); + + cpu->midr = 0x480fd010; + cpu->ctr = 0x84448004; + cpu->isar.id_aa64pfr0 = 0x11001111; -+ cpu->id_aa64dfr0 = 0x110305408; ++ cpu->isar.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) + void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { -@@ -388,6 +408,7 @@ static const ARMCPUInfo aarch64_cpus[] = { + /* +@@ -892,6 +912,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-920", .initfn = aarch64_kunpeng_920_initfn }, ++ { .name = "Kunpeng-920", .initfn = aarch64_kunpeng_920_initfn}, + { .name = "a64fx", .initfn = aarch64_a64fx_initfn }, { .name = "max", .initfn = aarch64_max_initfn }, - { .name = NULL } }; --- -2.19.1 +-- +2.27.0 + diff --git a/cpu-features-fix-bug-for-memory-leakage.patch b/cpu-features-fix-bug-for-memory-leakage.patch new file mode 100644 index 0000000000000000000000000000000000000000..cb7010440d9d395acd9bb0bc9792de279a4d4088 --- /dev/null +++ b/cpu-features-fix-bug-for-memory-leakage.patch @@ -0,0 +1,25 @@ +From 12706113392018fd7aa6471a3cbada62f0180539 Mon Sep 17 00:00:00 2001 +From: Chuan Zheng +Date: Wed, 9 Feb 2022 12:51:19 +0800 +Subject: [PATCH 13/15] cpu/features: fix bug for memory leakage + +strList hash not free after used, Fix it. +--- + target/i386/cpu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index aa9e636800..b9690e3250 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -4752,6 +4752,7 @@ static void x86_cpu_get_unavailable_features(Object *obj, Visitor *v, + + x86_cpu_list_feature_names(xc->filtered_features, &result); + visit_type_strList(v, "unavailable-features", &result, errp); ++ qapi_free_strList(result); + } + + /* Check for missing features that may prevent the CPU class from +-- +2.27.0 + diff --git a/cpu-parse-feature-to-avoid-failure.patch b/cpu-parse-feature-to-avoid-failure.patch index 78178bfa3dd2a9dd1413dd3c12bbc8e6ed6d2869..4ae42d904b815b115399e9560f3e456de96c712f 100644 --- a/cpu-parse-feature-to-avoid-failure.patch +++ b/cpu-parse-feature-to-avoid-failure.patch @@ -1,35 +1,28 @@ -From ba1ca232cfa2ca273c610beda40bee2143f11964 Mon Sep 17 00:00:00 2001 +From ef83cde8dd2c9b404527354489b14d2bd238733d Mon Sep 17 00:00:00 2001 From: Xu Yandong -Date: Tue, 3 Sep 2019 16:27:39 +0800 +Date: Tue, 8 Feb 2022 20:48:17 +0800 Subject: [PATCH] cpu: parse +/- feature to avoid failure -To avoid cpu feature parse failuer, +/- feature is added. +To avoid cpu feature parse failure, +/- feature is added. Signed-off-by: Xu Yandong +Signed-off-by: Mingwang Li --- - target/arm/cpu64.c | 38 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 38 insertions(+) + target/arm/cpu64.c | 37 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 37 insertions(+) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index 0d492877..6ce87ce0 100644 +index 15245a60a8..019edc66c9 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) +@@ -933,10 +933,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) ++ Error **errp ) +{ + char *featurestr; + char *val; @@ -67,9 +60,9 @@ index 0d492877..6ce87ce0 100644 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; + cc->gdb_num_core_regs = 34; -- -2.19.1 +2.27.0 diff --git a/cris-do-not-leak-struct-cris_disasm_data.patch b/cris-do-not-leak-struct-cris_disasm_data.patch deleted file mode 100644 index fa7623fe1878eca815805e853d64ff9b2d8a88a3..0000000000000000000000000000000000000000 --- a/cris-do-not-leak-struct-cris_disasm_data.patch +++ /dev/null @@ -1,139 +0,0 @@ -From d0586065e67b5df2611f4cf61eb791d48b78ff77 Mon Sep 17 00:00:00 2001 -From: lizhengui -Date: Wed, 9 Sep 2020 14:42:59 +0800 -Subject: [PATCH] cris: do not leak struct cris_disasm_data - -Use a stack-allocated struct to avoid a memory leak. - -Signed-off-by: Paolo Bonzini ---- - disas/cris.c | 65 ++++++++++++++++++++++++++++------------------------ - 1 file changed, 35 insertions(+), 30 deletions(-) - -diff --git a/disas/cris.c b/disas/cris.c -index 2f43c9b2..f3ff44ba 100644 ---- a/disas/cris.c -+++ b/disas/cris.c -@@ -1294,24 +1294,17 @@ static int cris_constraint - /* Parse disassembler options and store state in info. FIXME: For the - time being, we abuse static variables. */ - --static bfd_boolean --cris_parse_disassembler_options (disassemble_info *info, -+static void -+cris_parse_disassembler_options (struct cris_disasm_data *disdata, -+ char *disassembler_options, - enum cris_disass_family distype) - { -- struct cris_disasm_data *disdata; -- -- info->private_data = calloc (1, sizeof (struct cris_disasm_data)); -- disdata = (struct cris_disasm_data *) info->private_data; -- if (disdata == NULL) -- return false; -- - /* Default true. */ - disdata->trace_case -- = (info->disassembler_options == NULL -- || (strcmp (info->disassembler_options, "nocase") != 0)); -+ = (disassembler_options == NULL -+ || (strcmp (disassembler_options, "nocase") != 0)); - - disdata->distype = distype; -- return true; - } - - static const struct cris_spec_reg * -@@ -2736,9 +2729,11 @@ static int - print_insn_cris_with_register_prefix (bfd_vma vma, - disassemble_info *info) - { -- if (info->private_data == NULL -- && !cris_parse_disassembler_options (info, cris_dis_v0_v10)) -- return -1; -+ struct cris_disasm_data disdata; -+ info->private_data = &disdata; -+ cris_parse_disassembler_options (&disdata, info->disassembler_options, -+ cris_dis_v0_v10); -+ - return print_insn_cris_generic (vma, info, true); - } - /* Disassemble, prefixing register names with `$'. CRIS v32. */ -@@ -2747,9 +2742,11 @@ static int - print_insn_crisv32_with_register_prefix (bfd_vma vma, - disassemble_info *info) - { -- if (info->private_data == NULL -- && !cris_parse_disassembler_options (info, cris_dis_v32)) -- return -1; -+ struct cris_disasm_data disdata; -+ info->private_data = &disdata; -+ cris_parse_disassembler_options (&disdata, info->disassembler_options, -+ cris_dis_v32); -+ - return print_insn_cris_generic (vma, info, true); - } - -@@ -2761,9 +2758,11 @@ static int - print_insn_crisv10_v32_with_register_prefix (bfd_vma vma, - disassemble_info *info) - { -- if (info->private_data == NULL -- && !cris_parse_disassembler_options (info, cris_dis_common_v10_v32)) -- return -1; -+ struct cris_disasm_data disdata; -+ info->private_data = &disdata; -+ cris_parse_disassembler_options (&disdata, info->disassembler_options, -+ cris_dis_common_v10_v32); -+ - return print_insn_cris_generic (vma, info, true); - } - -@@ -2773,9 +2772,11 @@ static int - print_insn_cris_without_register_prefix (bfd_vma vma, - disassemble_info *info) - { -- if (info->private_data == NULL -- && !cris_parse_disassembler_options (info, cris_dis_v0_v10)) -- return -1; -+ struct cris_disasm_data disdata; -+ info->private_data = &disdata; -+ cris_parse_disassembler_options (&disdata, info->disassembler_options, -+ cris_dis_v0_v10); -+ - return print_insn_cris_generic (vma, info, false); - } - -@@ -2785,9 +2786,11 @@ static int - print_insn_crisv32_without_register_prefix (bfd_vma vma, - disassemble_info *info) - { -- if (info->private_data == NULL -- && !cris_parse_disassembler_options (info, cris_dis_v32)) -- return -1; -+ struct cris_disasm_data disdata; -+ info->private_data = &disdata; -+ cris_parse_disassembler_options (&disdata, info->disassembler_options, -+ cris_dis_v32); -+ - return print_insn_cris_generic (vma, info, false); - } - -@@ -2798,9 +2801,11 @@ static int - print_insn_crisv10_v32_without_register_prefix (bfd_vma vma, - disassemble_info *info) - { -- if (info->private_data == NULL -- && !cris_parse_disassembler_options (info, cris_dis_common_v10_v32)) -- return -1; -+ struct cris_disasm_data disdata; -+ info->private_data = &disdata; -+ cris_parse_disassembler_options (&disdata, info->disassembler_options, -+ cris_dis_common_v10_v32); -+ - return print_insn_cris_generic (vma, info, false); - } - #endif --- -2.19.1 - diff --git a/crypto-add-support-for-gcrypt-s-native-XTS-impl.patch b/crypto-add-support-for-gcrypt-s-native-XTS-impl.patch deleted file mode 100644 index d204f017b830d15bb9609570e39fb11e34676203..0000000000000000000000000000000000000000 --- a/crypto-add-support-for-gcrypt-s-native-XTS-impl.patch +++ /dev/null @@ -1,346 +0,0 @@ -From 84352558eec97cfb0e4517fbb53d75d9f15cbcf9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= -Date: Mon, 14 Oct 2019 17:28:27 +0100 -Subject: [PATCH] crypto: add support for gcrypt's native XTS impl -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Libgcrypt 1.8.0 added support for the XTS mode. Use this because long -term we wish to delete QEMU's XTS impl to avoid carrying private crypto -algorithm impls. - -As an added benefit, using this improves performance from 531 MB/sec to -670 MB/sec, since we are avoiding several layers of function call -indirection. - -This is even more noticable with the gcrypt builds in Fedora or RHEL-8 -which have a non-upstream patch for FIPS mode which does mutex locking. -This is catastrophic for encryption performance with small block sizes, -meaning this patch improves encryption from 240 MB/sec to 670 MB/sec. - -Reviewed-by: Philippe Mathieu-Daudé -Reviewed-by: Stefano Garzarella -Signed-off-by: Daniel P. Berrangé ---- - configure | 22 ++++++++++ - crypto/Makefile.objs | 2 +- - crypto/cipher-gcrypt.c | 97 ++++++++++++++++++++++++++++-------------- - tests/Makefile.include | 2 +- - 4 files changed, 88 insertions(+), 35 deletions(-) - -diff --git a/configure b/configure -index 5dcaac3b95..a88cdd5109 100755 ---- a/configure -+++ b/configure -@@ -476,6 +476,8 @@ nettle="" - nettle_xts="no" - gcrypt="" - gcrypt_hmac="no" -+gcrypt_xts="no" -+qemu_private_xts="yes" - auth_pam="" - vte="" - virglrenderer="" -@@ -2974,6 +2976,18 @@ EOF - if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then - gcrypt_hmac=yes - fi -+ cat > $TMPC << EOF -+#include -+int main(void) { -+ gcry_cipher_hd_t handle; -+ gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_XTS, 0); -+ return 0; -+} -+EOF -+ if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then -+ gcrypt_xts=yes -+ qemu_private_xts=no -+ fi - elif test "$gcrypt" = "yes"; then - feature_not_found "gcrypt" "Install gcrypt devel >= 1.5.0" - else -@@ -6404,6 +6418,11 @@ echo "VTE support $vte $(echo_version $vte $vteversion)" - echo "TLS priority $tls_priority" - echo "GNUTLS support $gnutls" - echo "libgcrypt $gcrypt" -+if test "$gcrypt" = "yes" -+then -+ echo " hmac $gcrypt_hmac" -+ echo " XTS $gcrypt_xts" -+fi - echo "nettle $nettle $(echo_version $nettle $nettle_version)" - if test "$nettle" = "yes" - then -@@ -6889,6 +6908,9 @@ if test "$nettle" = "yes" ; then - echo "CONFIG_NETTLE=y" >> $config_host_mak - echo "CONFIG_NETTLE_VERSION_MAJOR=${nettle_version%%.*}" >> $config_host_mak - fi -+if test "$qemu_private_xts" = "yes" ; then -+ echo "CONFIG_QEMU_PRIVATE_XTS=y" >> $config_host_mak -+fi - if test "$tasn1" = "yes" ; then - echo "CONFIG_TASN1=y" >> $config_host_mak - fi -diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs -index 7fe2fa9da2..cdb01f9de9 100644 ---- a/crypto/Makefile.objs -+++ b/crypto/Makefile.objs -@@ -31,7 +31,7 @@ crypto-obj-y += ivgen-essiv.o - crypto-obj-y += ivgen-plain.o - crypto-obj-y += ivgen-plain64.o - crypto-obj-y += afsplit.o --crypto-obj-y += xts.o -+crypto-obj-$(CONFIG_QEMU_PRIVATE_XTS) += xts.o - crypto-obj-y += block.o - crypto-obj-y += block-qcow.o - crypto-obj-y += block-luks.o -diff --git a/crypto/cipher-gcrypt.c b/crypto/cipher-gcrypt.c -index 5cece9b244..2864099527 100644 ---- a/crypto/cipher-gcrypt.c -+++ b/crypto/cipher-gcrypt.c -@@ -19,7 +19,9 @@ - */ - - #include "qemu/osdep.h" -+#ifdef CONFIG_QEMU_PRIVATE_XTS - #include "crypto/xts.h" -+#endif - #include "cipherpriv.h" - - #include -@@ -59,10 +61,12 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, - typedef struct QCryptoCipherGcrypt QCryptoCipherGcrypt; - struct QCryptoCipherGcrypt { - gcry_cipher_hd_t handle; -- gcry_cipher_hd_t tweakhandle; - size_t blocksize; -+#ifdef CONFIG_QEMU_PRIVATE_XTS -+ gcry_cipher_hd_t tweakhandle; - /* Initialization vector or Counter */ - uint8_t *iv; -+#endif - }; - - static void -@@ -74,10 +78,12 @@ qcrypto_gcrypt_cipher_free_ctx(QCryptoCipherGcrypt *ctx, - } - - gcry_cipher_close(ctx->handle); -+#ifdef CONFIG_QEMU_PRIVATE_XTS - if (mode == QCRYPTO_CIPHER_MODE_XTS) { - gcry_cipher_close(ctx->tweakhandle); - } - g_free(ctx->iv); -+#endif - g_free(ctx); - } - -@@ -94,8 +100,14 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, - - switch (mode) { - case QCRYPTO_CIPHER_MODE_ECB: -+ gcrymode = GCRY_CIPHER_MODE_ECB; -+ break; - case QCRYPTO_CIPHER_MODE_XTS: -+#ifdef CONFIG_QEMU_PRIVATE_XTS - gcrymode = GCRY_CIPHER_MODE_ECB; -+#else -+ gcrymode = GCRY_CIPHER_MODE_XTS; -+#endif - break; - case QCRYPTO_CIPHER_MODE_CBC: - gcrymode = GCRY_CIPHER_MODE_CBC; -@@ -172,6 +184,7 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, - gcry_strerror(err)); - goto error; - } -+#ifdef CONFIG_QEMU_PRIVATE_XTS - if (mode == QCRYPTO_CIPHER_MODE_XTS) { - err = gcry_cipher_open(&ctx->tweakhandle, gcryalg, gcrymode, 0); - if (err != 0) { -@@ -180,6 +193,7 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, - goto error; - } - } -+#endif - - if (alg == QCRYPTO_CIPHER_ALG_DES_RFB) { - /* We're using standard DES cipher from gcrypt, so we need -@@ -191,6 +205,7 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, - g_free(rfbkey); - ctx->blocksize = 8; - } else { -+#ifdef CONFIG_QEMU_PRIVATE_XTS - if (mode == QCRYPTO_CIPHER_MODE_XTS) { - nkey /= 2; - err = gcry_cipher_setkey(ctx->handle, key, nkey); -@@ -201,8 +216,11 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, - } - err = gcry_cipher_setkey(ctx->tweakhandle, key + nkey, nkey); - } else { -+#endif - err = gcry_cipher_setkey(ctx->handle, key, nkey); -+#ifdef CONFIG_QEMU_PRIVATE_XTS - } -+#endif - if (err != 0) { - error_setg(errp, "Cannot set key: %s", - gcry_strerror(err)); -@@ -228,6 +246,7 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, - } - } - -+#ifdef CONFIG_QEMU_PRIVATE_XTS - if (mode == QCRYPTO_CIPHER_MODE_XTS) { - if (ctx->blocksize != XTS_BLOCK_SIZE) { - error_setg(errp, -@@ -237,6 +256,7 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, - } - ctx->iv = g_new0(uint8_t, ctx->blocksize); - } -+#endif - - return ctx; - -@@ -253,6 +273,7 @@ qcrypto_gcrypt_cipher_ctx_free(QCryptoCipher *cipher) - } - - -+#ifdef CONFIG_QEMU_PRIVATE_XTS - static void qcrypto_gcrypt_xts_encrypt(const void *ctx, - size_t length, - uint8_t *dst, -@@ -272,6 +293,7 @@ static void qcrypto_gcrypt_xts_decrypt(const void *ctx, - err = gcry_cipher_decrypt((gcry_cipher_hd_t)ctx, dst, length, src, length); - g_assert(err == 0); - } -+#endif - - static int - qcrypto_gcrypt_cipher_encrypt(QCryptoCipher *cipher, -@@ -289,20 +311,23 @@ qcrypto_gcrypt_cipher_encrypt(QCryptoCipher *cipher, - return -1; - } - -+#ifdef CONFIG_QEMU_PRIVATE_XTS - if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) { - xts_encrypt(ctx->handle, ctx->tweakhandle, - qcrypto_gcrypt_xts_encrypt, - qcrypto_gcrypt_xts_decrypt, - ctx->iv, len, out, in); -- } else { -- err = gcry_cipher_encrypt(ctx->handle, -- out, len, -- in, len); -- if (err != 0) { -- error_setg(errp, "Cannot encrypt data: %s", -- gcry_strerror(err)); -- return -1; -- } -+ return 0; -+ } -+#endif -+ -+ err = gcry_cipher_encrypt(ctx->handle, -+ out, len, -+ in, len); -+ if (err != 0) { -+ error_setg(errp, "Cannot encrypt data: %s", -+ gcry_strerror(err)); -+ return -1; - } - - return 0; -@@ -325,20 +350,23 @@ qcrypto_gcrypt_cipher_decrypt(QCryptoCipher *cipher, - return -1; - } - -+#ifdef CONFIG_QEMU_PRIVATE_XTS - if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) { - xts_decrypt(ctx->handle, ctx->tweakhandle, - qcrypto_gcrypt_xts_encrypt, - qcrypto_gcrypt_xts_decrypt, - ctx->iv, len, out, in); -- } else { -- err = gcry_cipher_decrypt(ctx->handle, -- out, len, -- in, len); -- if (err != 0) { -- error_setg(errp, "Cannot decrypt data: %s", -- gcry_strerror(err)); -- return -1; -- } -+ return 0; -+ } -+#endif -+ -+ err = gcry_cipher_decrypt(ctx->handle, -+ out, len, -+ in, len); -+ if (err != 0) { -+ error_setg(errp, "Cannot decrypt data: %s", -+ gcry_strerror(err)); -+ return -1; - } - - return 0; -@@ -358,24 +386,27 @@ qcrypto_gcrypt_cipher_setiv(QCryptoCipher *cipher, - return -1; - } - -+#ifdef CONFIG_QEMU_PRIVATE_XTS - if (ctx->iv) { - memcpy(ctx->iv, iv, niv); -- } else { -- if (cipher->mode == QCRYPTO_CIPHER_MODE_CTR) { -- err = gcry_cipher_setctr(ctx->handle, iv, niv); -- if (err != 0) { -- error_setg(errp, "Cannot set Counter: %s", -+ return 0; -+ } -+#endif -+ -+ if (cipher->mode == QCRYPTO_CIPHER_MODE_CTR) { -+ err = gcry_cipher_setctr(ctx->handle, iv, niv); -+ if (err != 0) { -+ error_setg(errp, "Cannot set Counter: %s", - gcry_strerror(err)); -- return -1; -- } -- } else { -- gcry_cipher_reset(ctx->handle); -- err = gcry_cipher_setiv(ctx->handle, iv, niv); -- if (err != 0) { -- error_setg(errp, "Cannot set IV: %s", -+ return -1; -+ } -+ } else { -+ gcry_cipher_reset(ctx->handle); -+ err = gcry_cipher_setiv(ctx->handle, iv, niv); -+ if (err != 0) { -+ error_setg(errp, "Cannot set IV: %s", - gcry_strerror(err)); -- return -1; -- } -+ return -1; - } - } - -diff --git a/tests/Makefile.include b/tests/Makefile.include -index d6de4e1042..3be60ab999 100644 ---- a/tests/Makefile.include -+++ b/tests/Makefile.include -@@ -132,7 +132,7 @@ check-unit-y += tests/test-base64$(EXESUF) - check-unit-$(call land,$(CONFIG_BLOCK),$(if $(CONFIG_NETTLE),y,$(CONFIG_GCRYPT))) += tests/test-crypto-pbkdf$(EXESUF) - check-unit-$(CONFIG_BLOCK) += tests/test-crypto-ivgen$(EXESUF) - check-unit-$(CONFIG_BLOCK) += tests/test-crypto-afsplit$(EXESUF) --check-unit-$(CONFIG_BLOCK) += tests/test-crypto-xts$(EXESUF) -+check-unit-$(if $(CONFIG_BLOCK),$(CONFIG_QEMU_PRIVATE_XTS)) += tests/test-crypto-xts$(EXESUF) - check-unit-$(CONFIG_BLOCK) += tests/test-crypto-block$(EXESUF) - check-unit-y += tests/test-logging$(EXESUF) - check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_REPLICATION)) += tests/test-replication$(EXESUF) --- -2.27.0 - diff --git a/crypto-add-support-for-nettle-s-native-XTS-impl.patch b/crypto-add-support-for-nettle-s-native-XTS-impl.patch deleted file mode 100644 index 5aed7d626edf019c94c64939f35357274e39136a..0000000000000000000000000000000000000000 --- a/crypto-add-support-for-nettle-s-native-XTS-impl.patch +++ /dev/null @@ -1,126 +0,0 @@ -From c4db6fcb2c45b800cd46e088f8265ccc0631b6fc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= -Date: Mon, 14 Oct 2019 17:28:27 +0100 -Subject: [PATCH] crypto: add support for nettle's native XTS impl -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Nettle 3.5.0 will add support for the XTS mode. Use this because long -term we wish to delete QEMU's XTS impl to avoid carrying private crypto -algorithm impls. - -Unfortunately this degrades nettle performance from 612 MB/s to 568 MB/s -as nettle's XTS impl isn't so well optimized yet. - -Reviewed-by: Philippe Mathieu-Daudé -Reviewed-by: Stefano Garzarella -Signed-off-by: Daniel P. Berrangé ---- - configure | 18 ++++++++++++++++++ - crypto/cipher-nettle.c | 18 ++++++++++++++++++ - 2 files changed, 36 insertions(+) - -diff --git a/configure b/configure -index 577533e9ed..5dcaac3b95 100755 ---- a/configure -+++ b/configure -@@ -473,6 +473,7 @@ gtk_gl="no" - tls_priority="NORMAL" - gnutls="" - nettle="" -+nettle_xts="no" - gcrypt="" - gcrypt_hmac="no" - auth_pam="" -@@ -2918,6 +2919,19 @@ if test "$nettle" != "no"; then - pass="yes" - fi - fi -+ if test "$pass" = "yes" -+ then -+ cat > $TMPC << EOF -+#include -+int main(void) { -+ return 0; -+} -+EOF -+ if compile_prog "$nettle_cflags" "$nettle_libs" ; then -+ nettle_xts=yes -+ qemu_private_xts=no -+ fi -+ fi - if test "$pass" = "no" && test "$nettle" = "yes"; then - feature_not_found "nettle" "Install nettle devel >= 2.7.1" - else -@@ -6391,6 +6405,10 @@ echo "TLS priority $tls_priority" - echo "GNUTLS support $gnutls" - echo "libgcrypt $gcrypt" - echo "nettle $nettle $(echo_version $nettle $nettle_version)" -+if test "$nettle" = "yes" -+then -+ echo " XTS $nettle_xts" -+fi - echo "libtasn1 $tasn1" - echo "PAM $auth_pam" - echo "iconv support $iconv" -diff --git a/crypto/cipher-nettle.c b/crypto/cipher-nettle.c -index d7411bb8ff..7e9a4cc199 100644 ---- a/crypto/cipher-nettle.c -+++ b/crypto/cipher-nettle.c -@@ -19,7 +19,9 @@ - */ - - #include "qemu/osdep.h" -+#ifdef CONFIG_QEMU_PRIVATE_XTS - #include "crypto/xts.h" -+#endif - #include "cipherpriv.h" - - #include -@@ -30,6 +32,9 @@ - #include - #include - #include -+#ifndef CONFIG_QEMU_PRIVATE_XTS -+#include -+#endif - - typedef void (*QCryptoCipherNettleFuncWrapper)(const void *ctx, - size_t length, -@@ -626,9 +631,15 @@ qcrypto_nettle_cipher_encrypt(QCryptoCipher *cipher, - break; - - case QCRYPTO_CIPHER_MODE_XTS: -+#ifdef CONFIG_QEMU_PRIVATE_XTS - xts_encrypt(ctx->ctx, ctx->ctx_tweak, - ctx->alg_encrypt_wrapper, ctx->alg_encrypt_wrapper, - ctx->iv, len, out, in); -+#else -+ xts_encrypt_message(ctx->ctx, ctx->ctx_tweak, -+ ctx->alg_encrypt_native, -+ ctx->iv, len, out, in); -+#endif - break; - - case QCRYPTO_CIPHER_MODE_CTR: -@@ -673,9 +684,16 @@ qcrypto_nettle_cipher_decrypt(QCryptoCipher *cipher, - break; - - case QCRYPTO_CIPHER_MODE_XTS: -+#ifdef CONFIG_QEMU_PRIVATE_XTS - xts_decrypt(ctx->ctx, ctx->ctx_tweak, - ctx->alg_encrypt_wrapper, ctx->alg_decrypt_wrapper, - ctx->iv, len, out, in); -+#else -+ xts_decrypt_message(ctx->ctx, ctx->ctx_tweak, -+ ctx->alg_decrypt_native, -+ ctx->alg_encrypt_native, -+ ctx->iv, len, out, in); -+#endif - break; - case QCRYPTO_CIPHER_MODE_CTR: - ctr_crypt(ctx->ctx, ctx->alg_encrypt_native, --- -2.27.0 - diff --git a/delete-the-in-tpm.txt.patch b/delete-the-in-tpm.txt.patch deleted file mode 100644 index 01ce3ace541aca115bccd47100f5dbd954643764..0000000000000000000000000000000000000000 --- a/delete-the-in-tpm.txt.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 3020ae141ef40f06b17eb0f16d2a3c6d5872ff89 Mon Sep 17 00:00:00 2001 -From: jiangfangjie -Date: Wed, 29 Jul 2020 08:45:50 +0000 -Subject: [PATCH 05/19] delete the in tpm.txt - -Signed-off-by: jiangfangjie ---- - docs/specs/tpm.txt | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/docs/specs/tpm.txt b/docs/specs/tpm.txt -index 5d8c26b1..9c8cca04 100644 ---- a/docs/specs/tpm.txt -+++ b/docs/specs/tpm.txt -@@ -89,7 +89,7 @@ TPM upon reboot. The PPI specification defines the operation requests and the - actions the firmware has to take. The system administrator passes the operation - request number to the firmware through an ACPI interface which writes this - number to a memory location that the firmware knows. Upon reboot, the firmware --finds the number and sends commands to the the TPM. The firmware writes the TPM -+finds the number and sends commands to the TPM. The firmware writes the TPM - result code and the operation request number to a memory location that ACPI can - read from and pass the result on to the administrator. - --- -2.23.0 - diff --git a/display-bochs-display-fix-memory-leak.patch b/display-bochs-display-fix-memory-leak.patch deleted file mode 100644 index 4dd3aa61c2b2b1026e0065c708ead4aeb79b3c21..0000000000000000000000000000000000000000 --- a/display-bochs-display-fix-memory-leak.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 7edca67dc630e31043644e87ede2e05e504f845b Mon Sep 17 00:00:00 2001 -From: Cameron Esfahani -Date: Tue, 10 Dec 2019 13:27:54 -0800 -Subject: [PATCH 1/8] display/bochs-display: fix memory leak -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fix memory leak in bochs_display_update(). Leaks 304 bytes per frame. - -Fixes: 33ebad54056 -Signed-off-by: Cameron Esfahani -Message-Id: -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Gerd Hoffmann ---- - hw/display/bochs-display.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/hw/display/bochs-display.c b/hw/display/bochs-display.c -index 8e83b51..b601b2f 100644 ---- a/hw/display/bochs-display.c -+++ b/hw/display/bochs-display.c -@@ -251,6 +251,8 @@ static void bochs_display_update(void *opaque) - dpy_gfx_update(s->con, 0, ys, - mode.width, y - ys); - } -+ -+ g_free(snap); - } - } - --- -1.8.3.1 - diff --git a/dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch b/dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch deleted file mode 100644 index c61c9fd848c4e1d68baa778388c8440a8d28ec32..0000000000000000000000000000000000000000 --- a/dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch +++ /dev/null @@ -1,79 +0,0 @@ -From fbde196c30e4797a51bda046ba514b187963d4ba Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 29 Jul 2019 23:34:16 +0200 -Subject: [PATCH] dma-helpers: ensure AIO callback is invoked after - cancellation - -dma_aio_cancel unschedules the BH if there is one, which corresponds -to the reschedule_dma case of dma_blk_cb. This can stall the DMA -permanently, because dma_complete will never get invoked and therefore -nobody will ever invoke the original AIO callback in dbs->common.cb. - -Fix this by invoking the callback (which is ensured to happen after -a bdrv_aio_cancel_async, or done manually in the dbs->bh case), and -add assertions to check that the DMA state machine is indeed waiting -for dma_complete or reschedule_dma, but never both. - -Reported-by: John Snow -Signed-off-by: Paolo Bonzini -Message-id: 20190729213416.1972-1-pbonzini@redhat.com -Signed-off-by: John Snow -(cherry picked from commit 539343c0a47e19d5dd64d846d64d084d9793681f) -Signed-off-by: Michael Roth ---- - dma-helpers.c | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - -diff --git a/dma-helpers.c b/dma-helpers.c -index 2d7e02d35e..d3871dc61e 100644 ---- a/dma-helpers.c -+++ b/dma-helpers.c -@@ -90,6 +90,7 @@ static void reschedule_dma(void *opaque) - { - DMAAIOCB *dbs = (DMAAIOCB *)opaque; - -+ assert(!dbs->acb && dbs->bh); - qemu_bh_delete(dbs->bh); - dbs->bh = NULL; - dma_blk_cb(dbs, 0); -@@ -111,15 +112,12 @@ static void dma_complete(DMAAIOCB *dbs, int ret) - { - trace_dma_complete(dbs, ret, dbs->common.cb); - -+ assert(!dbs->acb && !dbs->bh); - dma_blk_unmap(dbs); - if (dbs->common.cb) { - dbs->common.cb(dbs->common.opaque, ret); - } - qemu_iovec_destroy(&dbs->iov); -- if (dbs->bh) { -- qemu_bh_delete(dbs->bh); -- dbs->bh = NULL; -- } - qemu_aio_unref(dbs); - } - -@@ -179,14 +177,21 @@ static void dma_aio_cancel(BlockAIOCB *acb) - - trace_dma_aio_cancel(dbs); - -+ assert(!(dbs->acb && dbs->bh)); - if (dbs->acb) { -+ /* This will invoke dma_blk_cb. */ - blk_aio_cancel_async(dbs->acb); -+ return; - } -+ - if (dbs->bh) { - cpu_unregister_map_client(dbs->bh); - qemu_bh_delete(dbs->bh); - dbs->bh = NULL; - } -+ if (dbs->common.cb) { -+ dbs->common.cb(dbs->common.opaque, -ECANCELED); -+ } - } - - static AioContext *dma_get_aio_context(BlockAIOCB *acb) --- -2.23.0 diff --git a/doc-Update-multi-thread-compression-doc.patch b/doc-Update-multi-thread-compression-doc.patch index 33ef835acaf040ed3a404b6f0314a9e5c4af0673..d020d23bb07bd6ec16f5e6470b760c72b33f6275 100644 --- a/doc-Update-multi-thread-compression-doc.patch +++ b/doc-Update-multi-thread-compression-doc.patch @@ -1,10 +1,11 @@ -From 642df85795097017e9370a9721f702cbec50c173 Mon Sep 17 00:00:00 2001 -From: Zeyu Jin +From 213bd45d2c5337f10216c69c13f0438dd40c58d8 Mon Sep 17 00:00:00 2001 +From: Chuan Zheng Date: Sat, 30 Jan 2021 16:36:47 +0800 -Subject: [PATCH] doc: Update multi-thread compression doc +Subject: [PATCH 14/14] doc: Update multi-thread compression doc Modify the doc to fit the previous changes. +Signed-off-by: Chuan Zheng Signed-off-by: Zeyu Jin Signed-off-by: Ying Fang --- diff --git a/docs-specs-Add-ACPI-GED-documentation.patch b/docs-specs-Add-ACPI-GED-documentation.patch deleted file mode 100644 index 46e8c17483ba33af2b75e954233c3cbdc5c7cddc..0000000000000000000000000000000000000000 --- a/docs-specs-Add-ACPI-GED-documentation.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 9c1752703fb8a5b70985cf4c9caabc3388c5953b Mon Sep 17 00:00:00 2001 -From: Shameer Kolothum -Date: Wed, 18 Sep 2019 14:06:31 +0100 -Subject: [PATCH] docs/specs: Add ACPI GED documentation - -Documents basic concepts of ACPI Generic Event device(GED) -and interface between QEMU and the ACPI BIOS. - -Signed-off-by: Shameer Kolothum -Reviewed-by: Eric Auger -Message-Id: <20190918130633.4872-10-shameerali.kolothum.thodi@huawei.com> -Acked-by: Peter Maydell -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin ---- - docs/specs/acpi_hw_reduced_hotplug.rst | 70 ++++++++++++++++++++++++++ - docs/specs/index.rst | 1 + - 2 files changed, 71 insertions(+) - create mode 100644 docs/specs/acpi_hw_reduced_hotplug.rst - -diff --git a/docs/specs/acpi_hw_reduced_hotplug.rst b/docs/specs/acpi_hw_reduced_hotplug.rst -new file mode 100644 -index 0000000000..911a98255b ---- /dev/null -+++ b/docs/specs/acpi_hw_reduced_hotplug.rst -@@ -0,0 +1,70 @@ -+================================================== -+QEMU and ACPI BIOS Generic Event Device interface -+================================================== -+ -+The ACPI *Generic Event Device* (GED) is a HW reduced platform -+specific device introduced in ACPI v6.1 that handles all platform -+events, including the hotplug ones. GED is modelled as a device -+in the namespace with a _HID defined to be ACPI0013. This document -+describes the interface between QEMU and the ACPI BIOS. -+ -+GED allows HW reduced platforms to handle interrupts in ACPI ASL -+statements. It follows a very similar approach to the _EVT method -+from GPIO events. All interrupts are listed in _CRS and the handler -+is written in _EVT method. However, the QEMU implementation uses a -+single interrupt for the GED device, relying on an IO memory region -+to communicate the type of device affected by the interrupt. This way, -+we can support up to 32 events with a unique interrupt. -+ -+**Here is an example,** -+ -+:: -+ -+ Device (\_SB.GED) -+ { -+ Name (_HID, "ACPI0013") -+ Name (_UID, Zero) -+ Name (_CRS, ResourceTemplate () -+ { -+ Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, ) -+ { -+ 0x00000029, -+ } -+ }) -+ OperationRegion (EREG, SystemMemory, 0x09080000, 0x04) -+ Field (EREG, DWordAcc, NoLock, WriteAsZeros) -+ { -+ ESEL, 32 -+ } -+ Method (_EVT, 1, Serialized) -+ { -+ Local0 = ESEL // ESEL = IO memory region which specifies the -+ // device type. -+ If (((Local0 & One) == One)) -+ { -+ MethodEvent1() -+ } -+ If ((Local0 & 0x2) == 0x2) -+ { -+ MethodEvent2() -+ } -+ ... -+ } -+ } -+ -+GED IO interface (4 byte access) -+-------------------------------- -+**read access:** -+ -+:: -+ -+ [0x0-0x3] Event selector bit field (32 bit) set by QEMU. -+ -+ bits: -+ 0: Memory hotplug event -+ 1: System power down event -+ 2-31: Reserved -+ -+**write_access:** -+ -+Nothing is expected to be written into GED IO memory -diff --git a/docs/specs/index.rst b/docs/specs/index.rst -index 40adb97c5e..984ba44029 100644 ---- a/docs/specs/index.rst -+++ b/docs/specs/index.rst -@@ -12,3 +12,4 @@ Contents: - - ppc-xive - ppc-spapr-xive -+ acpi_hw_reduced_hotplug --- -2.19.1 diff --git a/docs-specs-tpm-Document-TPM_TIS-sysbus-device-for-AR.patch b/docs-specs-tpm-Document-TPM_TIS-sysbus-device-for-AR.patch deleted file mode 100644 index f0be64a937fd5b1f78c54f5f74854f388c023786..0000000000000000000000000000000000000000 --- a/docs-specs-tpm-Document-TPM_TIS-sysbus-device-for-AR.patch +++ /dev/null @@ -1,66 +0,0 @@ -From dd7f6cc3bcd71681920e3530f2c53041c812c5d3 Mon Sep 17 00:00:00 2001 -From: Eric Auger -Date: Thu, 5 Mar 2020 17:51:46 +0100 -Subject: [PATCH 16/19] docs/specs/tpm: Document TPM_TIS sysbus device for ARM - -Update the documentation with recent changes related to the -sysbus TPM_TIS device addition and add the command line -to be used with arm VIRT. - -Signed-off-by: Eric Auger -Reviewed-by: Stefan Berger -Message-id: 20200305165149.618-8-eric.auger@redhat.com -Signed-off-by: Stefan Berger -Signed-off-by: jiangfangjie ---- - docs/specs/tpm.rst | 25 ++++++++++++++++++++++++- - 1 file changed, 24 insertions(+), 1 deletion(-) - -diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst -index 2bdf637f..da9eb39c 100644 ---- a/docs/specs/tpm.rst -+++ b/docs/specs/tpm.rst -@@ -18,9 +18,15 @@ The TIS interface makes a memory mapped IO region in the area - 0xfed40000-0xfed44fff available to the guest operating system. - - QEMU files related to TPM TIS interface: -- - ``hw/tpm/tpm_tis.c`` -+ - ``hw/tpm/tpm_tis_common.c`` -+ - ``hw/tpm/tpm_tis_isa.c`` -+ - ``hw/tpm/tpm_tis_sysbus.c`` - - ``hw/tpm/tpm_tis.h`` - -+Both an ISA device and a sysbus device are available. The former is -+used with pc/q35 machine while the latter can be instantiated in the -+ARM virt machine. -+ - CRB interface - ------------- - -@@ -325,6 +331,23 @@ In case a pSeries machine is emulated, use the following command line: - -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,id=virtio-disk0 \ - -drive file=test.img,format=raw,if=none,id=drive-virtio-disk0 - -+In case an ARM virt machine is emulated, use the following command line: -+ -+.. code-block:: console -+ -+ qemu-system-aarch64 -machine virt,gic-version=3,accel=kvm \ -+ -cpu host -m 4G \ -+ -nographic -no-acpi \ -+ -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ -+ -tpmdev emulator,id=tpm0,chardev=chrtpm \ -+ -device tpm-tis-device,tpmdev=tpm0 \ -+ -device virtio-blk-pci,drive=drv0 \ -+ -drive format=qcow2,file=hda.qcow2,if=none,id=drv0 \ -+ -drive if=pflash,format=raw,file=flash0.img,readonly \ -+ -drive if=pflash,format=raw,file=flash1.img -+ -+ On ARM, ACPI boot with TPM is not yet supported. -+ - In case SeaBIOS is used as firmware, it should show the TPM menu item - after entering the menu with 'ESC'. - --- -2.23.0 - diff --git a/docs-specs-tpm-reST-ify-TPM-documentation.patch b/docs-specs-tpm-reST-ify-TPM-documentation.patch deleted file mode 100644 index d4648994bde2fc4b68ce49f28f4a612f53e65551..0000000000000000000000000000000000000000 --- a/docs-specs-tpm-reST-ify-TPM-documentation.patch +++ /dev/null @@ -1,993 +0,0 @@ -From 5d1865496ca39f08142a0c1eb2c9b14ec1ec9140 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Tue, 21 Jan 2020 10:29:35 -0500 -Subject: [PATCH 09/19] docs/specs/tpm: reST-ify TPM documentation -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Marc-André Lureau -Reviewed-by: Stefan Berger -Message-Id: <20200121152935.649898-7-stefanb@linux.ibm.com> -Signed-off-by: David Gibson -Signed-off-by: jiangfangjie ---- - docs/specs/index.rst | 1 + - docs/specs/tpm.rst | 503 +++++++++++++++++++++++++++++++++++++++++++ - docs/specs/tpm.txt | 445 -------------------------------------- - 3 files changed, 504 insertions(+), 445 deletions(-) - create mode 100644 docs/specs/tpm.rst - delete mode 100644 docs/specs/tpm.txt - -diff --git a/docs/specs/index.rst b/docs/specs/index.rst -index 984ba440..de46a8b5 100644 ---- a/docs/specs/index.rst -+++ b/docs/specs/index.rst -@@ -13,3 +13,4 @@ Contents: - ppc-xive - ppc-spapr-xive - acpi_hw_reduced_hotplug -+ tpm -diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst -new file mode 100644 -index 00000000..2bdf637f ---- /dev/null -+++ b/docs/specs/tpm.rst -@@ -0,0 +1,503 @@ -+=============== -+QEMU TPM Device -+=============== -+ -+Guest-side hardware interface -+============================= -+ -+TIS interface -+------------- -+ -+The QEMU TPM emulation implements a TPM TIS hardware interface -+following the Trusted Computing Group's specification "TCG PC Client -+Specific TPM Interface Specification (TIS)", Specification Version -+1.3, 21 March 2013. (see the `TIS specification`_, or a later version -+of it). -+ -+The TIS interface makes a memory mapped IO region in the area -+0xfed40000-0xfed44fff available to the guest operating system. -+ -+QEMU files related to TPM TIS interface: -+ - ``hw/tpm/tpm_tis.c`` -+ - ``hw/tpm/tpm_tis.h`` -+ -+CRB interface -+------------- -+ -+QEMU also implements a TPM CRB interface following the Trusted -+Computing Group's specification "TCG PC Client Platform TPM Profile -+(PTP) Specification", Family "2.0", Level 00 Revision 01.03 v22, May -+22, 2017. (see the `CRB specification`_, or a later version of it) -+ -+The CRB interface makes a memory mapped IO region in the area -+0xfed40000-0xfed40fff (1 locality) available to the guest -+operating system. -+ -+QEMU files related to TPM CRB interface: -+ - ``hw/tpm/tpm_crb.c`` -+ -+SPAPR interface -+--------------- -+ -+pSeries (ppc64) machines offer a tpm-spapr device model. -+ -+QEMU files related to the SPAPR interface: -+ - ``hw/tpm/tpm_spapr.c`` -+ -+fw_cfg interface -+================ -+ -+The bios/firmware may read the ``"etc/tpm/config"`` fw_cfg entry for -+configuring the guest appropriately. -+ -+The entry of 6 bytes has the following content, in little-endian: -+ -+.. code-block:: c -+ -+ #define TPM_VERSION_UNSPEC 0 -+ #define TPM_VERSION_1_2 1 -+ #define TPM_VERSION_2_0 2 -+ -+ #define TPM_PPI_VERSION_NONE 0 -+ #define TPM_PPI_VERSION_1_30 1 -+ -+ struct FwCfgTPMConfig { -+ uint32_t tpmppi_address; /* PPI memory location */ -+ uint8_t tpm_version; /* TPM version */ -+ uint8_t tpmppi_version; /* PPI version */ -+ }; -+ -+ACPI interface -+============== -+ -+The TPM device is defined with ACPI ID "PNP0C31". QEMU builds a SSDT -+and passes it into the guest through the fw_cfg device. The device -+description contains the base address of the TIS interface 0xfed40000 -+and the size of the MMIO area (0x5000). In case a TPM2 is used by -+QEMU, a TPM2 ACPI table is also provided. The device is described to -+be used in polling mode rather than interrupt mode primarily because -+no unused IRQ could be found. -+ -+To support measurement logs to be written by the firmware, -+e.g. SeaBIOS, a TCPA table is implemented. This table provides a 64kb -+buffer where the firmware can write its log into. For TPM 2 only a -+more recent version of the TPM2 table provides support for -+measurements logs and a TCPA table does not need to be created. -+ -+The TCPA and TPM2 ACPI tables follow the Trusted Computing Group -+specification "TCG ACPI Specification" Family "1.2" and "2.0", Level -+00 Revision 00.37. (see the `ACPI specification`_, or a later version -+of it) -+ -+ACPI PPI Interface -+------------------ -+ -+QEMU supports the Physical Presence Interface (PPI) for TPM 1.2 and -+TPM 2. This interface requires ACPI and firmware support. (see the -+`PPI specification`_) -+ -+PPI enables a system administrator (root) to request a modification to -+the TPM upon reboot. The PPI specification defines the operation -+requests and the actions the firmware has to take. The system -+administrator passes the operation request number to the firmware -+through an ACPI interface which writes this number to a memory -+location that the firmware knows. Upon reboot, the firmware finds the -+number and sends commands to the TPM. The firmware writes the TPM -+result code and the operation request number to a memory location that -+ACPI can read from and pass the result on to the administrator. -+ -+The PPI specification defines a set of mandatory and optional -+operations for the firmware to implement. The ACPI interface also -+allows an administrator to list the supported operations. In QEMU the -+ACPI code is generated by QEMU, yet the firmware needs to implement -+support on a per-operations basis, and different firmwares may support -+a different subset. Therefore, QEMU introduces the virtual memory -+device for PPI where the firmware can indicate which operations it -+supports and ACPI can enable the ones that are supported and disable -+all others. This interface lies in main memory and has the following -+layout: -+ -+ +-------------+--------+--------+-------------------------------------------+ -+ | Field | Length | Offset | Description | -+ +=============+========+========+===========================================+ -+ | ``func`` | 0x100 | 0x000 | Firmware sets values for each supported | -+ | | | | operation. See defined values below. | -+ +-------------+--------+--------+-------------------------------------------+ -+ | ``ppin`` | 0x1 | 0x100 | SMI interrupt to use. Set by firmware. | -+ | | | | Not supported. | -+ +-------------+--------+--------+-------------------------------------------+ -+ | ``ppip`` | 0x4 | 0x101 | ACPI function index to pass to SMM code. | -+ | | | | Set by ACPI. Not supported. | -+ +-------------+--------+--------+-------------------------------------------+ -+ | ``pprp`` | 0x4 | 0x105 | Result of last executed operation. Set by | -+ | | | | firmware. See function index 5 for values.| -+ +-------------+--------+--------+-------------------------------------------+ -+ | ``pprq`` | 0x4 | 0x109 | Operation request number to execute. See | -+ | | | | 'Physical Presence Interface Operation | -+ | | | | Summary' tables in specs. Set by ACPI. | -+ +-------------+--------+--------+-------------------------------------------+ -+ | ``pprm`` | 0x4 | 0x10d | Operation request optional parameter. | -+ | | | | Values depend on operation. Set by ACPI. | -+ +-------------+--------+--------+-------------------------------------------+ -+ | ``lppr`` | 0x4 | 0x111 | Last executed operation request number. | -+ | | | | Copied from pprq field by firmware. | -+ +-------------+--------+--------+-------------------------------------------+ -+ | ``fret`` | 0x4 | 0x115 | Result code from SMM function. | -+ | | | | Not supported. | -+ +-------------+--------+--------+-------------------------------------------+ -+ | ``res1`` | 0x40 | 0x119 | Reserved for future use | -+ +-------------+--------+--------+-------------------------------------------+ -+ |``next_step``| 0x1 | 0x159 | Operation to execute after reboot by | -+ | | | | firmware. Used by firmware. | -+ +-------------+--------+--------+-------------------------------------------+ -+ | ``movv`` | 0x1 | 0x15a | Memory overwrite variable | -+ +-------------+--------+--------+-------------------------------------------+ -+ -+The following values are supported for the ``func`` field. They -+correspond to the values used by ACPI function index 8. -+ -+ +----------+-------------------------------------------------------------+ -+ | Value | Description | -+ +==========+=============================================================+ -+ | 0 | Operation is not implemented. | -+ +----------+-------------------------------------------------------------+ -+ | 1 | Operation is only accessible through firmware. | -+ +----------+-------------------------------------------------------------+ -+ | 2 | Operation is blocked for OS by firmware configuration. | -+ +----------+-------------------------------------------------------------+ -+ | 3 | Operation is allowed and physically present user required. | -+ +----------+-------------------------------------------------------------+ -+ | 4 | Operation is allowed and physically present user is not | -+ | | required. | -+ +----------+-------------------------------------------------------------+ -+ -+The location of the table is given by the fw_cfg ``tpmppi_address`` -+field. The PPI memory region size is 0x400 (``TPM_PPI_ADDR_SIZE``) to -+leave enough room for future updates. -+ -+QEMU files related to TPM ACPI tables: -+ - ``hw/i386/acpi-build.c`` -+ - ``include/hw/acpi/tpm.h`` -+ -+TPM backend devices -+=================== -+ -+The TPM implementation is split into two parts, frontend and -+backend. The frontend part is the hardware interface, such as the TPM -+TIS interface described earlier, and the other part is the TPM backend -+interface. The backend interfaces implement the interaction with a TPM -+device, which may be a physical or an emulated device. The split -+between the front- and backend devices allows a frontend to be -+connected with any available backend. This enables the TIS interface -+to be used with the passthrough backend or the swtpm backend. -+ -+QEMU files related to TPM backends: -+ - ``backends/tpm.c`` -+ - ``include/sysemu/tpm_backend.h`` -+ - ``include/sysemu/tpm_backend_int.h`` -+ -+The QEMU TPM passthrough device -+------------------------------- -+ -+In case QEMU is run on Linux as the host operating system it is -+possible to make the hardware TPM device available to a single QEMU -+guest. In this case the user must make sure that no other program is -+using the device, e.g., /dev/tpm0, before trying to start QEMU with -+it. -+ -+The passthrough driver uses the host's TPM device for sending TPM -+commands and receiving responses from. Besides that it accesses the -+TPM device's sysfs entry for support of command cancellation. Since -+none of the state of a hardware TPM can be migrated between hosts, -+virtual machine migration is disabled when the TPM passthrough driver -+is used. -+ -+Since the host's TPM device will already be initialized by the host's -+firmware, certain commands, e.g. ``TPM_Startup()``, sent by the -+virtual firmware for device initialization, will fail. In this case -+the firmware should not use the TPM. -+ -+Sharing the device with the host is generally not a recommended usage -+scenario for a TPM device. The primary reason for this is that two -+operating systems can then access the device's single set of -+resources, such as platform configuration registers -+(PCRs). Applications or kernel security subsystems, such as the Linux -+Integrity Measurement Architecture (IMA), are not expecting to share -+PCRs. -+ -+QEMU files related to the TPM passthrough device: -+ - ``hw/tpm/tpm_passthrough.c`` -+ - ``hw/tpm/tpm_util.c`` -+ - ``hw/tpm/tpm_util.h`` -+ -+ -+Command line to start QEMU with the TPM passthrough device using the host's -+hardware TPM ``/dev/tpm0``: -+ -+.. code-block:: console -+ -+ qemu-system-x86_64 -display sdl -accel kvm \ -+ -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ -+ -tpmdev passthrough,id=tpm0,path=/dev/tpm0 \ -+ -device tpm-tis,tpmdev=tpm0 test.img -+ -+ -+The following commands should result in similar output inside the VM -+with a Linux kernel that either has the TPM TIS driver built-in or -+available as a module: -+ -+.. code-block:: console -+ -+ # dmesg | grep -i tpm -+ [ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1) -+ -+ # dmesg | grep TCPA -+ [ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \ -+ BXPCTCPA 0000001 BXPC 00000001) -+ -+ # ls -l /dev/tpm* -+ crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0 -+ -+ # find /sys/devices/ | grep pcrs$ | xargs cat -+ PCR-00: 35 4E 3B CE 23 9F 38 59 ... -+ ... -+ PCR-23: 00 00 00 00 00 00 00 00 ... -+ -+The QEMU TPM emulator device -+---------------------------- -+ -+The TPM emulator device uses an external TPM emulator called 'swtpm' -+for sending TPM commands to and receiving responses from. The swtpm -+program must have been started before trying to access it through the -+TPM emulator with QEMU. -+ -+The TPM emulator implements a command channel for transferring TPM -+commands and responses as well as a control channel over which control -+commands can be sent. (see the `SWTPM protocol`_ specification) -+ -+The control channel serves the purpose of resetting, initializing, and -+migrating the TPM state, among other things. -+ -+The swtpm program behaves like a hardware TPM and therefore needs to -+be initialized by the firmware running inside the QEMU virtual -+machine. One necessary step for initializing the device is to send -+the TPM_Startup command to it. SeaBIOS, for example, has been -+instrumented to initialize a TPM 1.2 or TPM 2 device using this -+command. -+ -+QEMU files related to the TPM emulator device: -+ - ``hw/tpm/tpm_emulator.c`` -+ - ``hw/tpm/tpm_util.c`` -+ - ``hw/tpm/tpm_util.h`` -+ -+The following commands start the swtpm with a UnixIO control channel over -+a socket interface. They do not need to be run as root. -+ -+.. code-block:: console -+ -+ mkdir /tmp/mytpm1 -+ swtpm socket --tpmstate dir=/tmp/mytpm1 \ -+ --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ -+ --log level=20 -+ -+Command line to start QEMU with the TPM emulator device communicating -+with the swtpm (x86): -+ -+.. code-block:: console -+ -+ qemu-system-x86_64 -display sdl -accel kvm \ -+ -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ -+ -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ -+ -tpmdev emulator,id=tpm0,chardev=chrtpm \ -+ -device tpm-tis,tpmdev=tpm0 test.img -+ -+In case a pSeries machine is emulated, use the following command line: -+ -+.. code-block:: console -+ -+ qemu-system-ppc64 -display sdl -machine pseries,accel=kvm \ -+ -m 1024 -bios slof.bin -boot menu=on \ -+ -nodefaults -device VGA -device pci-ohci -device usb-kbd \ -+ -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ -+ -tpmdev emulator,id=tpm0,chardev=chrtpm \ -+ -device tpm-spapr,tpmdev=tpm0 \ -+ -device spapr-vscsi,id=scsi0,reg=0x00002000 \ -+ -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,id=virtio-disk0 \ -+ -drive file=test.img,format=raw,if=none,id=drive-virtio-disk0 -+ -+In case SeaBIOS is used as firmware, it should show the TPM menu item -+after entering the menu with 'ESC'. -+ -+.. code-block:: console -+ -+ Select boot device: -+ 1. DVD/CD [ata1-0: QEMU DVD-ROM ATAPI-4 DVD/CD] -+ [...] -+ 5. Legacy option rom -+ -+ t. TPM Configuration -+ -+The following commands should result in similar output inside the VM -+with a Linux kernel that either has the TPM TIS driver built-in or -+available as a module: -+ -+.. code-block:: console -+ -+ # dmesg | grep -i tpm -+ [ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1) -+ -+ # dmesg | grep TCPA -+ [ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \ -+ BXPCTCPA 0000001 BXPC 00000001) -+ -+ # ls -l /dev/tpm* -+ crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0 -+ -+ # find /sys/devices/ | grep pcrs$ | xargs cat -+ PCR-00: 35 4E 3B CE 23 9F 38 59 ... -+ ... -+ PCR-23: 00 00 00 00 00 00 00 00 ... -+ -+Migration with the TPM emulator -+=============================== -+ -+The TPM emulator supports the following types of virtual machine -+migration: -+ -+- VM save / restore (migration into a file) -+- Network migration -+- Snapshotting (migration into storage like QoW2 or QED) -+ -+The following command sequences can be used to test VM save / restore. -+ -+In a 1st terminal start an instance of a swtpm using the following command: -+ -+.. code-block:: console -+ -+ mkdir /tmp/mytpm1 -+ swtpm socket --tpmstate dir=/tmp/mytpm1 \ -+ --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ -+ --log level=20 --tpm2 -+ -+In a 2nd terminal start the VM: -+ -+.. code-block:: console -+ -+ qemu-system-x86_64 -display sdl -accel kvm \ -+ -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ -+ -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ -+ -tpmdev emulator,id=tpm0,chardev=chrtpm \ -+ -device tpm-tis,tpmdev=tpm0 \ -+ -monitor stdio \ -+ test.img -+ -+Verify that the attached TPM is working as expected using applications -+inside the VM. -+ -+To store the state of the VM use the following command in the QEMU -+monitor in the 2nd terminal: -+ -+.. code-block:: console -+ -+ (qemu) migrate "exec:cat > testvm.bin" -+ (qemu) quit -+ -+At this point a file called ``testvm.bin`` should exists and the swtpm -+and QEMU processes should have ended. -+ -+To test 'VM restore' you have to start the swtpm with the same -+parameters as before. If previously a TPM 2 [--tpm2] was saved, --tpm2 -+must now be passed again on the command line. -+ -+In the 1st terminal restart the swtpm with the same command line as -+before: -+ -+.. code-block:: console -+ -+ swtpm socket --tpmstate dir=/tmp/mytpm1 \ -+ --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ -+ --log level=20 --tpm2 -+ -+In the 2nd terminal restore the state of the VM using the additional -+'-incoming' option. -+ -+.. code-block:: console -+ -+ qemu-system-x86_64 -display sdl -accel kvm \ -+ -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ -+ -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ -+ -tpmdev emulator,id=tpm0,chardev=chrtpm \ -+ -device tpm-tis,tpmdev=tpm0 \ -+ -incoming "exec:cat < testvm.bin" \ -+ test.img -+ -+Troubleshooting migration -+------------------------- -+ -+There are several reasons why migration may fail. In case of problems, -+please ensure that the command lines adhere to the following rules -+and, if possible, that identical versions of QEMU and swtpm are used -+at all times. -+ -+VM save and restore: -+ -+ - QEMU command line parameters should be identical apart from the -+ '-incoming' option on VM restore -+ -+ - swtpm command line parameters should be identical -+ -+VM migration to 'localhost': -+ -+ - QEMU command line parameters should be identical apart from the -+ '-incoming' option on the destination side -+ -+ - swtpm command line parameters should point to two different -+ directories on the source and destination swtpm (--tpmstate dir=...) -+ (especially if different versions of libtpms were to be used on the -+ same machine). -+ -+VM migration across the network: -+ -+ - QEMU command line parameters should be identical apart from the -+ '-incoming' option on the destination side -+ -+ - swtpm command line parameters should be identical -+ -+VM Snapshotting: -+ - QEMU command line parameters should be identical -+ -+ - swtpm command line parameters should be identical -+ -+ -+Besides that, migration failure reasons on the swtpm level may include -+the following: -+ -+ - the versions of the swtpm on the source and destination sides are -+ incompatible -+ -+ - downgrading of TPM state may not be supported -+ -+ - the source and destination libtpms were compiled with different -+ compile-time options and the destination side refuses to accept the -+ state -+ -+ - different migration keys are used on the source and destination side -+ and the destination side cannot decrypt the migrated state -+ (swtpm ... --migration-key ... ) -+ -+ -+.. _TIS specification: -+ https://trustedcomputinggroup.org/pc-client-work-group-pc-client-specific-tpm-interface-specification-tis/ -+ -+.. _CRB specification: -+ https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/ -+ -+ -+.. _ACPI specification: -+ https://trustedcomputinggroup.org/tcg-acpi-specification/ -+ -+.. _PPI specification: -+ https://trustedcomputinggroup.org/resource/tcg-physical-presence-interface-specification/ -+ -+.. _SWTPM protocol: -+ https://github.com/stefanberger/swtpm/blob/master/man/man3/swtpm_ioctls.pod -diff --git a/docs/specs/tpm.txt b/docs/specs/tpm.txt -deleted file mode 100644 -index 9c3e67d8..00000000 ---- a/docs/specs/tpm.txt -+++ /dev/null -@@ -1,445 +0,0 @@ --QEMU TPM Device --=============== -- --= Guest-side Hardware Interface = -- --The QEMU TPM emulation implements a TPM TIS hardware interface following the --Trusted Computing Group's specification "TCG PC Client Specific TPM Interface --Specification (TIS)", Specification Version 1.3, 21 March 2013. This --specification, or a later version of it, can be accessed from the following --URL: -- --https://trustedcomputinggroup.org/pc-client-work-group-pc-client-specific-tpm-interface-specification-tis/ -- --The TIS interface makes a memory mapped IO region in the area 0xfed40000 - --0xfed44fff available to the guest operating system. -- -- --QEMU files related to TPM TIS interface: -- - hw/tpm/tpm_tis.c -- - hw/tpm/tpm_tis.h -- -- --QEMU also implements a TPM CRB interface following the Trusted Computing --Group's specification "TCG PC Client Platform TPM Profile (PTP) --Specification", Family "2.0", Level 00 Revision 01.03 v22, May 22, 2017. --This specification, or a later version of it, can be accessed from the --following URL: -- --https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/ -- --The CRB interface makes a memory mapped IO region in the area 0xfed40000 - --0xfed40fff (1 locality) available to the guest operating system. -- --QEMU files related to TPM CRB interface: -- - hw/tpm/tpm_crb.c -- -- --pSeries (ppc64) machines offer a tpm-spapr device model. -- --QEMU files related to the SPAPR interface: -- - hw/tpm/tpm_spapr.c -- --= fw_cfg interface = -- --The bios/firmware may read the "etc/tpm/config" fw_cfg entry for --configuring the guest appropriately. -- --The entry of 6 bytes has the following content, in little-endian: -- -- #define TPM_VERSION_UNSPEC 0 -- #define TPM_VERSION_1_2 1 -- #define TPM_VERSION_2_0 2 -- -- #define TPM_PPI_VERSION_NONE 0 -- #define TPM_PPI_VERSION_1_30 1 -- -- struct FwCfgTPMConfig { -- uint32_t tpmppi_address; /* PPI memory location */ -- uint8_t tpm_version; /* TPM version */ -- uint8_t tpmppi_version; /* PPI version */ -- }; -- --= ACPI Interface = -- --The TPM device is defined with ACPI ID "PNP0C31". QEMU builds a SSDT and passes --it into the guest through the fw_cfg device. The device description contains --the base address of the TIS interface 0xfed40000 and the size of the MMIO area --(0x5000). In case a TPM2 is used by QEMU, a TPM2 ACPI table is also provided. --The device is described to be used in polling mode rather than interrupt mode --primarily because no unused IRQ could be found. -- --To support measurement logs to be written by the firmware, e.g. SeaBIOS, a TCPA --table is implemented. This table provides a 64kb buffer where the firmware can --write its log into. For TPM 2 only a more recent version of the TPM2 table --provides support for measurements logs and a TCPA table does not need to be --created. -- --The TCPA and TPM2 ACPI tables follow the Trusted Computing Group specification --"TCG ACPI Specification" Family "1.2" and "2.0", Level 00 Revision 00.37. This --specification, or a later version of it, can be accessed from the following --URL: -- --https://trustedcomputinggroup.org/tcg-acpi-specification/ -- --== ACPI PPI Interface == -- --QEMU supports the Physical Presence Interface (PPI) for TPM 1.2 and TPM 2. This --interface requires ACPI and firmware support. The specification can be found at --the following URL: -- --https://trustedcomputinggroup.org/resource/tcg-physical-presence-interface-specification/ -- --PPI enables a system administrator (root) to request a modification to the --TPM upon reboot. The PPI specification defines the operation requests and the --actions the firmware has to take. The system administrator passes the operation --request number to the firmware through an ACPI interface which writes this --number to a memory location that the firmware knows. Upon reboot, the firmware --finds the number and sends commands to the TPM. The firmware writes the TPM --result code and the operation request number to a memory location that ACPI can --read from and pass the result on to the administrator. -- --The PPI specification defines a set of mandatory and optional operations for --the firmware to implement. The ACPI interface also allows an administrator to --list the supported operations. In QEMU the ACPI code is generated by QEMU, yet --the firmware needs to implement support on a per-operations basis, and --different firmwares may support a different subset. Therefore, QEMU introduces --the virtual memory device for PPI where the firmware can indicate which --operations it supports and ACPI can enable the ones that are supported and --disable all others. This interface lies in main memory and has the following --layout: -- -- +----------+--------+--------+-------------------------------------------+ -- | Field | Length | Offset | Description | -- +----------+--------+--------+-------------------------------------------+ -- | func | 0x100 | 0x000 | Firmware sets values for each supported | -- | | | | operation. See defined values below. | -- +----------+--------+--------+-------------------------------------------+ -- | ppin | 0x1 | 0x100 | SMI interrupt to use. Set by firmware. | -- | | | | Not supported. | -- +----------+--------+--------+-------------------------------------------+ -- | ppip | 0x4 | 0x101 | ACPI function index to pass to SMM code. | -- | | | | Set by ACPI. Not supported. | -- +----------+--------+--------+-------------------------------------------+ -- | pprp | 0x4 | 0x105 | Result of last executed operation. Set by | -- | | | | firmware. See function index 5 for values.| -- +----------+--------+--------+-------------------------------------------+ -- | pprq | 0x4 | 0x109 | Operation request number to execute. See | -- | | | | 'Physical Presence Interface Operation | -- | | | | Summary' tables in specs. Set by ACPI. | -- +----------+--------+--------+-------------------------------------------+ -- | pprm | 0x4 | 0x10d | Operation request optional parameter. | -- | | | | Values depend on operation. Set by ACPI. | -- +----------+--------+--------+-------------------------------------------+ -- | lppr | 0x4 | 0x111 | Last executed operation request number. | -- | | | | Copied from pprq field by firmware. | -- +----------+--------+--------+-------------------------------------------+ -- | fret | 0x4 | 0x115 | Result code from SMM function. | -- | | | | Not supported. | -- +----------+--------+--------+-------------------------------------------+ -- | res1 | 0x40 | 0x119 | Reserved for future use | -- +----------+--------+--------+-------------------------------------------+ -- | next_step| 0x1 | 0x159 | Operation to execute after reboot by | -- | | | | firmware. Used by firmware. | -- +----------+--------+--------+-------------------------------------------+ -- | movv | 0x1 | 0x15a | Memory overwrite variable | -- +----------+--------+--------+-------------------------------------------+ -- -- The following values are supported for the 'func' field. They correspond -- to the values used by ACPI function index 8. -- -- +----------+-------------------------------------------------------------+ -- | value | Description | -- +----------+-------------------------------------------------------------+ -- | 0 | Operation is not implemented. | -- +----------+-------------------------------------------------------------+ -- | 1 | Operation is only accessible through firmware. | -- +----------+-------------------------------------------------------------+ -- | 2 | Operation is blocked for OS by firmware configuration. | -- +----------+-------------------------------------------------------------+ -- | 3 | Operation is allowed and physically present user required. | -- +----------+-------------------------------------------------------------+ -- | 4 | Operation is allowed and physically present user is not | -- | | required. | -- +----------+-------------------------------------------------------------+ -- --The location of the table is given by the fw_cfg tpmppi_address field. --The PPI memory region size is 0x400 (TPM_PPI_ADDR_SIZE) to leave --enough room for future updates. -- -- --QEMU files related to TPM ACPI tables: -- - hw/i386/acpi-build.c -- - include/hw/acpi/tpm.h -- -- --= TPM backend devices = -- --The TPM implementation is split into two parts, frontend and backend. The --frontend part is the hardware interface, such as the TPM TIS interface --described earlier, and the other part is the TPM backend interface. The backend --interfaces implement the interaction with a TPM device, which may be a physical --or an emulated device. The split between the front- and backend devices allows --a frontend to be connected with any available backend. This enables the TIS --interface to be used with the passthrough backend or the (future) swtpm backend. -- -- --QEMU files related to TPM backends: -- - backends/tpm.c -- - include/sysemu/tpm_backend.h -- - include/sysemu/tpm_backend_int.h -- -- --== The QEMU TPM passthrough device == -- --In case QEMU is run on Linux as the host operating system it is possible to --make the hardware TPM device available to a single QEMU guest. In this case the --user must make sure that no other program is using the device, e.g., /dev/tpm0, --before trying to start QEMU with it. -- --The passthrough driver uses the host's TPM device for sending TPM commands --and receiving responses from. Besides that it accesses the TPM device's sysfs --entry for support of command cancellation. Since none of the state of a --hardware TPM can be migrated between hosts, virtual machine migration is --disabled when the TPM passthrough driver is used. -- --Since the host's TPM device will already be initialized by the host's firmware, --certain commands, e.g. TPM_Startup(), sent by the virtual firmware for device --initialization, will fail. In this case the firmware should not use the TPM. -- --Sharing the device with the host is generally not a recommended usage scenario --for a TPM device. The primary reason for this is that two operating systems can --then access the device's single set of resources, such as platform configuration --registers (PCRs). Applications or kernel security subsystems, such as the --Linux Integrity Measurement Architecture (IMA), are not expecting to share PCRs. -- -- --QEMU files related to the TPM passthrough device: -- - hw/tpm/tpm_passthrough.c -- - hw/tpm/tpm_util.c -- - hw/tpm/tpm_util.h -- -- --Command line to start QEMU with the TPM passthrough device using the host's --hardware TPM /dev/tpm0: -- --qemu-system-x86_64 -display sdl -accel kvm \ -- -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ -- -tpmdev passthrough,id=tpm0,path=/dev/tpm0 \ -- -device tpm-tis,tpmdev=tpm0 test.img -- --The following commands should result in similar output inside the VM with a --Linux kernel that either has the TPM TIS driver built-in or available as a --module: -- --#> dmesg | grep -i tpm --[ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1) -- --#> dmesg | grep TCPA --[ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \ -- BXPCTCPA 0000001 BXPC 00000001) -- --#> ls -l /dev/tpm* --crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0 -- --#> find /sys/devices/ | grep pcrs$ | xargs cat --PCR-00: 35 4E 3B CE 23 9F 38 59 ... --... --PCR-23: 00 00 00 00 00 00 00 00 ... -- -- --== The QEMU TPM emulator device == -- --The TPM emulator device uses an external TPM emulator called 'swtpm' for --sending TPM commands to and receiving responses from. The swtpm program --must have been started before trying to access it through the TPM emulator --with QEMU. -- --The TPM emulator implements a command channel for transferring TPM commands --and responses as well as a control channel over which control commands can --be sent. The specification for the control channel can be found here: -- --https://github.com/stefanberger/swtpm/blob/master/man/man3/swtpm_ioctls.pod -- -- --The control channel serves the purpose of resetting, initializing, and --migrating the TPM state, among other things. -- --The swtpm program behaves like a hardware TPM and therefore needs to be --initialized by the firmware running inside the QEMU virtual machine. --One necessary step for initializing the device is to send the TPM_Startup --command to it. SeaBIOS, for example, has been instrumented to initialize --a TPM 1.2 or TPM 2 device using this command. -- -- --QEMU files related to the TPM emulator device: -- - hw/tpm/tpm_emulator.c -- - hw/tpm/tpm_util.c -- - hw/tpm/tpm_util.h -- -- --The following commands start the swtpm with a UnixIO control channel over --a socket interface. They do not need to be run as root. -- --mkdir /tmp/mytpm1 --swtpm socket --tpmstate dir=/tmp/mytpm1 \ -- --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ -- --log level=20 -- --Command line to start QEMU with the TPM emulator device communicating with --the swtpm (x86): -- --qemu-system-x86_64 -display sdl -accel kvm \ -- -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ -- -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ -- -tpmdev emulator,id=tpm0,chardev=chrtpm \ -- -device tpm-tis,tpmdev=tpm0 test.img -- --In case a pSeries machine is emulated, use the following command line: -- --qemu-system-ppc64 -display sdl -machine pseries,accel=kvm \ -- -m 1024 -bios slof.bin -boot menu=on \ -- -nodefaults -device VGA -device pci-ohci -device usb-kbd \ -- -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ -- -tpmdev emulator,id=tpm0,chardev=chrtpm \ -- -device tpm-spapr,tpmdev=tpm0 \ -- -device spapr-vscsi,id=scsi0,reg=0x00002000 \ -- -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,id=virtio-disk0 \ -- -drive file=test.img,format=raw,if=none,id=drive-virtio-disk0 -- -- --In case SeaBIOS is used as firmware, it should show the TPM menu item --after entering the menu with 'ESC'. -- --Select boot device: --1. DVD/CD [ata1-0: QEMU DVD-ROM ATAPI-4 DVD/CD] --[...] --5. Legacy option rom -- --t. TPM Configuration -- -- --The following commands should result in similar output inside the VM with a --Linux kernel that either has the TPM TIS driver built-in or available as a --module: -- --#> dmesg | grep -i tpm --[ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1) -- --#> dmesg | grep TCPA --[ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \ -- BXPCTCPA 0000001 BXPC 00000001) -- --#> ls -l /dev/tpm* --crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0 -- --#> find /sys/devices/ | grep pcrs$ | xargs cat --PCR-00: 35 4E 3B CE 23 9F 38 59 ... --... --PCR-23: 00 00 00 00 00 00 00 00 ... -- -- --=== Migration with the TPM emulator === -- --The TPM emulator supports the following types of virtual machine migration: -- --- VM save / restore (migration into a file) --- Network migration --- Snapshotting (migration into storage like QoW2 or QED) -- --The following command sequences can be used to test VM save / restore. -- -- --In a 1st terminal start an instance of a swtpm using the following command: -- --mkdir /tmp/mytpm1 --swtpm socket --tpmstate dir=/tmp/mytpm1 \ -- --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ -- --log level=20 --tpm2 -- --In a 2nd terminal start the VM: -- --qemu-system-x86_64 -display sdl -accel kvm \ -- -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ -- -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ -- -tpmdev emulator,id=tpm0,chardev=chrtpm \ -- -device tpm-tis,tpmdev=tpm0 \ -- -monitor stdio \ -- test.img -- --Verify that the attached TPM is working as expected using applications inside --the VM. -- --To store the state of the VM use the following command in the QEMU monitor in --the 2nd terminal: -- --(qemu) migrate "exec:cat > testvm.bin" --(qemu) quit -- --At this point a file called 'testvm.bin' should exists and the swtpm and QEMU --processes should have ended. -- --To test 'VM restore' you have to start the swtpm with the same parameters --as before. If previously a TPM 2 [--tpm2] was saved, --tpm2 must now be --passed again on the command line. -- --In the 1st terminal restart the swtpm with the same command line as before: -- --swtpm socket --tpmstate dir=/tmp/mytpm1 \ -- --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ -- --log level=20 --tpm2 -- --In the 2nd terminal restore the state of the VM using the additional --'-incoming' option. -- --qemu-system-x86_64 -display sdl -accel kvm \ -- -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ -- -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ -- -tpmdev emulator,id=tpm0,chardev=chrtpm \ -- -device tpm-tis,tpmdev=tpm0 \ -- -incoming "exec:cat < testvm.bin" \ -- test.img -- -- --Troubleshooting migration: -- --There are several reasons why migration may fail. In case of problems, --please ensure that the command lines adhere to the following rules and, --if possible, that identical versions of QEMU and swtpm are used at all --times. -- --VM save and restore: -- - QEMU command line parameters should be identical apart from the -- '-incoming' option on VM restore -- - swtpm command line parameters should be identical -- --VM migration to 'localhost': -- - QEMU command line parameters should be identical apart from the -- '-incoming' option on the destination side -- - swtpm command line parameters should point to two different -- directories on the source and destination swtpm (--tpmstate dir=...) -- (especially if different versions of libtpms were to be used on the -- same machine). -- --VM migration across the network: -- - QEMU command line parameters should be identical apart from the -- '-incoming' option on the destination side -- - swtpm command line parameters should be identical -- --VM Snapshotting: -- - QEMU command line parameters should be identical -- - swtpm command line parameters should be identical -- -- --Besides that, migration failure reasons on the swtpm level may include --the following: -- -- - the versions of the swtpm on the source and destination sides are -- incompatible -- - downgrading of TPM state may not be supported -- - the source and destination libtpms were compiled with different -- compile-time options and the destination side refuses to accept the -- state -- - different migration keys are used on the source and destination side -- and the destination side cannot decrypt the migrated state -- (swtpm ... --migration-key ... ) --- -2.23.0 - diff --git a/drive-backup-create-do_backup_common.patch b/drive-backup-create-do_backup_common.patch deleted file mode 100644 index cccbc2e967c1529f5072ac64cbad1f6de3c3aee1..0000000000000000000000000000000000000000 --- a/drive-backup-create-do_backup_common.patch +++ /dev/null @@ -1,163 +0,0 @@ -From 98dcfbd5ee53f3be705df7acf37e8706533f494f Mon Sep 17 00:00:00 2001 -From: John Snow -Date: Mon, 29 Jul 2019 16:35:52 -0400 -Subject: [PATCH] drive-backup: create do_backup_common - -Create a common core that comprises the actual meat of what the backup API -boundary needs to do, and then switch drive-backup to use it. - -Signed-off-by: John Snow -Reviewed-by: Max Reitz -Message-id: 20190709232550.10724-3-jsnow@redhat.com -Signed-off-by: John Snow ---- - blockdev.c | 102 ++++++++++++++++++++++++++++++----------------------- - 1 file changed, 57 insertions(+), 45 deletions(-) - -diff --git a/blockdev.c b/blockdev.c -index 99c92b96d2..a29838a1c8 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -3469,20 +3469,16 @@ out: - aio_context_release(aio_context); - } - --static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, -- Error **errp) -+/* Common QMP interface for drive-backup and blockdev-backup */ -+static BlockJob *do_backup_common(BackupCommon *backup, -+ BlockDriverState *bs, -+ BlockDriverState *target_bs, -+ AioContext *aio_context, -+ JobTxn *txn, Error **errp) - { -- BlockDriverState *bs; -- BlockDriverState *target_bs; -- BlockDriverState *source = NULL; - BlockJob *job = NULL; - BdrvDirtyBitmap *bmap = NULL; -- AioContext *aio_context; -- QDict *options = NULL; -- Error *local_err = NULL; -- int flags, job_flags = JOB_DEFAULT; -- int64_t size; -- bool set_backing_hd = false; -+ int job_flags = JOB_DEFAULT; - int ret; - - if (!backup->has_speed) { -@@ -3494,9 +3490,6 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, - if (!backup->has_on_target_error) { - backup->on_target_error = BLOCKDEV_ON_ERROR_REPORT; - } -- if (!backup->has_mode) { -- backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; -- } - if (!backup->has_job_id) { - backup->job_id = NULL; - } -@@ -3510,6 +3503,54 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, - backup->compress = false; - } - -+ ret = bdrv_try_set_aio_context(target_bs, aio_context, errp); -+ if (ret < 0) { -+ return NULL; -+ } -+ -+ if (backup->has_bitmap) { -+ bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap); -+ if (!bmap) { -+ error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap); -+ return NULL; -+ } -+ if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) { -+ return NULL; -+ } -+ } -+ -+ if (!backup->auto_finalize) { -+ job_flags |= JOB_MANUAL_FINALIZE; -+ } -+ if (!backup->auto_dismiss) { -+ job_flags |= JOB_MANUAL_DISMISS; -+ } -+ -+ job = backup_job_create(backup->job_id, bs, target_bs, backup->speed, -+ backup->sync, bmap, backup->compress, -+ backup->on_source_error, backup->on_target_error, -+ job_flags, NULL, NULL, txn, errp); -+ return job; -+} -+ -+static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, -+ Error **errp) -+{ -+ BlockDriverState *bs; -+ BlockDriverState *target_bs; -+ BlockDriverState *source = NULL; -+ BlockJob *job = NULL; -+ AioContext *aio_context; -+ QDict *options = NULL; -+ Error *local_err = NULL; -+ int flags; -+ int64_t size; -+ bool set_backing_hd = false; -+ -+ if (!backup->has_mode) { -+ backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; -+ } -+ - bs = bdrv_lookup_bs(backup->device, backup->device, errp); - if (!bs) { - return NULL; -@@ -3585,12 +3626,6 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, - goto out; - } - -- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp); -- if (ret < 0) { -- bdrv_unref(target_bs); -- goto out; -- } -- - if (set_backing_hd) { - bdrv_set_backing_hd(target_bs, source, &local_err); - if (local_err) { -@@ -3598,31 +3633,8 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn, - } - } - -- if (backup->has_bitmap) { -- bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap); -- if (!bmap) { -- error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap); -- goto unref; -- } -- if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) { -- goto unref; -- } -- } -- if (!backup->auto_finalize) { -- job_flags |= JOB_MANUAL_FINALIZE; -- } -- if (!backup->auto_dismiss) { -- job_flags |= JOB_MANUAL_DISMISS; -- } -- -- job = backup_job_create(backup->job_id, bs, target_bs, backup->speed, -- backup->sync, bmap, backup->compress, -- backup->on_source_error, backup->on_target_error, -- job_flags, NULL, NULL, txn, &local_err); -- if (local_err != NULL) { -- error_propagate(errp, local_err); -- goto unref; -- } -+ job = do_backup_common(qapi_DriveBackup_base(backup), -+ bs, target_bs, aio_context, txn, errp); - - unref: - bdrv_unref(target_bs); --- -2.27.0 - diff --git a/ehci-fix-queue-dev-null-ptr-dereference.patch b/ehci-fix-queue-dev-null-ptr-dereference.patch deleted file mode 100644 index 18114e984199f44d7689e939152ed160d6dc0292..0000000000000000000000000000000000000000 --- a/ehci-fix-queue-dev-null-ptr-dereference.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 901ac0dee4b17890db815d143a8efeeac5d105f7 Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -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 -Signed-off-by: Gerd Hoffmann -Tested-by: Guenter Roeck -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 - diff --git a/elf2dmp-Fix-memory-leak-on-main-error-paths.patch b/elf2dmp-Fix-memory-leak-on-main-error-paths.patch deleted file mode 100644 index 219cec31e799c1f32912a717982740f08c70a3c0..0000000000000000000000000000000000000000 --- a/elf2dmp-Fix-memory-leak-on-main-error-paths.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 1f63f8c20a4cb7b752981ef07b2614bbea828b30 Mon Sep 17 00:00:00 2001 -From: AlexChen -Date: Wed, 26 Aug 2020 18:15:53 +0800 -Subject: [PATCH] elf2dmp: Fix memory leak on main() error paths - -The 'kdgb' is allocating memory in get_kdbg(), but it is not freed -in both fill_header() and fill_context() failed branches, fix it. - -Signed-off-by: AlexChen -Reviewed-by: Li Qiang -Reviewed-by: Viktor Prutyanov -Reviewed-by: Thomas Huth -Message-Id: <5F463659.8080101@huawei.com> -Signed-off-by: Laurent Vivier -(cherry-picked from commit 885538fdc9) ---- - contrib/elf2dmp/main.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c -index 9a2dbc2902..ac746e49e0 100644 ---- a/contrib/elf2dmp/main.c -+++ b/contrib/elf2dmp/main.c -@@ -568,12 +568,12 @@ int main(int argc, char *argv[]) - if (fill_header(&header, &ps, &vs, KdDebuggerDataBlock, kdbg, - KdVersionBlock, qemu_elf.state_nr)) { - err = 1; -- goto out_pdb; -+ goto out_kdbg; - } - - if (fill_context(kdbg, &vs, &qemu_elf)) { - err = 1; -- goto out_pdb; -+ goto out_kdbg; - } - - if (write_dump(&ps, &header, argv[2])) { --- -2.27.0 - diff --git a/es1370-check-total-frame-count-against-current-frame.patch b/es1370-check-total-frame-count-against-current-frame.patch deleted file mode 100644 index fb1e7a7cdfa6f8046b6aa2ebb270b557dcae14a5..0000000000000000000000000000000000000000 --- a/es1370-check-total-frame-count-against-current-frame.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 22bbf1a90ac11fe30e1665c09f9ad904683b6ddc Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Fri, 15 May 2020 01:36:08 +0530 -Subject: [PATCH 1/9] es1370: check total frame count against current frame - -A guest user may set channel frame count via es1370_write() -such that, in es1370_transfer_audio(), total frame count -'size' is lesser than the number of frames that are processed -'cnt'. - - int cnt = d->frame_cnt >> 16; - int size = d->frame_cnt & 0xffff; - -if (size < cnt), it results in incorrect calculations leading -to OOB access issue(s). Add check to avoid it. - -Reported-by: Ren Ding -Reported-by: Hanqing Zhao -Signed-off-by: Prasad J Pandit -Message-id: 20200514200608.1744203-1-ppandit@redhat.com -Signed-off-by: Gerd Hoffmann ---- - hw/audio/es1370.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c -index 260c142b70..eff7d03ae1 100644 ---- a/hw/audio/es1370.c -+++ b/hw/audio/es1370.c -@@ -643,6 +643,9 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel, - int csc_bytes = (csc + 1) << d->shift; - int cnt = d->frame_cnt >> 16; - int size = d->frame_cnt & 0xffff; -+ if (size < cnt) { -+ return; -+ } - int left = ((size - cnt + 1) << 2) + d->leftover; - int transferred = 0; - int temp = audio_MIN (max, audio_MIN (left, csc_bytes)); -@@ -651,7 +654,7 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel, - addr += (cnt << 2) + d->leftover; - - if (index == ADC_CHANNEL) { -- while (temp) { -+ while (temp > 0) { - int acquired, to_copy; - - to_copy = audio_MIN ((size_t) temp, sizeof (tmpbuf)); -@@ -669,7 +672,7 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel, - else { - SWVoiceOut *voice = s->dac_voice[index]; - -- while (temp) { -+ while (temp > 0) { - int copied, to_copy; - - to_copy = audio_MIN ((size_t) temp, sizeof (tmpbuf)); --- -2.25.1 - diff --git a/exec-set-map-length-to-zero-when-returning-NULL.patch b/exec-set-map-length-to-zero-when-returning-NULL.patch deleted file mode 100644 index 64c918e8d9de6eb3dd357c955d75488ff5f11c48..0000000000000000000000000000000000000000 --- a/exec-set-map-length-to-zero-when-returning-NULL.patch +++ /dev/null @@ -1,54 +0,0 @@ -From a1a9d6f908b21878daa7868313243c30b7a90fcf Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Tue, 26 May 2020 16:47:43 +0530 -Subject: [PATCH 2/9] exec: set map length to zero when returning NULL -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When mapping physical memory into host's virtual address space, -'address_space_map' may return NULL if BounceBuffer is in_use. -Set and return '*plen = 0' to avoid later NULL pointer dereference. - -Reported-by: Alexander Bulekov -Fixes: https://bugs.launchpad.net/qemu/+bug/1878259 -Suggested-by: Paolo Bonzini -Suggested-by: Peter Maydell -Signed-off-by: Prasad J Pandit -Message-Id: <20200526111743.428367-1-ppandit@redhat.com> -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Paolo Bonzini ---- - exec.c | 1 + - include/exec/memory.h | 3 ++- - 2 files changed, 3 insertions(+), 1 deletion(-) - -diff --git a/exec.c b/exec.c -index 3e78de3b8f..85c6d80353 100644 ---- a/exec.c -+++ b/exec.c -@@ -3739,6 +3739,7 @@ void *address_space_map(AddressSpace *as, - if (!memory_access_is_direct(mr, is_write)) { - if (atomic_xchg(&bounce.in_use, true)) { - rcu_read_unlock(); -+ *plen = 0; - return NULL; - } - /* Avoid unbounded allocations */ -diff --git a/include/exec/memory.h b/include/exec/memory.h -index 611a89122d..dca8184277 100644 ---- a/include/exec/memory.h -+++ b/include/exec/memory.h -@@ -2064,7 +2064,8 @@ bool address_space_access_valid(AddressSpace *as, hwaddr addr, hwaddr len, - /* address_space_map: map a physical memory region into a host virtual address - * - * May map a subset of the requested range, given by and returned in @plen. -- * May return %NULL if resources needed to perform the mapping are exhausted. -+ * May return %NULL and set *@plen to zero(0), if resources needed to perform -+ * the mapping are exhausted. - * Use only for reads OR writes - not for read-modify-write operations. - * Use cpu_register_map_client() to know when retrying the map operation is - * likely to succeed. --- -2.25.1 - diff --git a/feature-Add-log-for-each-modules.patch b/feature-Add-log-for-each-modules.patch new file mode 100644 index 0000000000000000000000000000000000000000..62d2f1ad4960d4eca4d464d88a7d5c3b894a59e6 --- /dev/null +++ b/feature-Add-log-for-each-modules.patch @@ -0,0 +1,262 @@ +From 1a0b974a0aaff667a76972403c28c66416c2947b Mon Sep 17 00:00:00 2001 +From: "wangxinxin.wang@huawei.com" +Date: Tue, 27 Jun 2017 17:42:23 +0800 +Subject: [PATCH 2/3] feature: Add log for each modules + +add log for each modules. + +Signed-off-by: miaoyubo +Signed-off-by: Jingyi Wang +--- + accel/kvm/kvm-all.c | 5 ++++- + hw/char/virtio-serial-bus.c | 5 +++++ + hw/pci/pci.c | 1 + + hw/usb/bus.c | 6 ++++++ + hw/usb/host-libusb.c | 5 +++++ + hw/virtio/virtio-scsi-pci.c | 3 +++ + monitor/monitor.c | 1 + + monitor/qmp-cmds.c | 3 +++ + os-posix.c | 1 + + qapi/qmp-dispatch.c | 15 +++++++++++++++ + softmmu/qdev-monitor.c | 5 +++++ + 11 files changed, 49 insertions(+), 1 deletion(-) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index b128d311c2..8a98446b7c 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -1751,7 +1751,10 @@ void kvm_irqchip_commit_routes(KVMState *s) + s->irq_routes->flags = 0; + trace_kvm_irqchip_commit_routes(); + ret = kvm_vm_ioctl(s, KVM_SET_GSI_ROUTING, s->irq_routes); +- assert(ret == 0); ++ if (ret < 0) { ++ error_report("Set GSI routing failed: %m"); ++ abort(); ++ } + } + + static void kvm_add_routing_entry(KVMState *s, +diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c +index f01ec2137c..edb7a44ee9 100644 +--- a/hw/char/virtio-serial-bus.c ++++ b/hw/char/virtio-serial-bus.c +@@ -257,6 +257,8 @@ static size_t send_control_event(VirtIOSerial *vser, uint32_t port_id, + virtio_stw_p(vdev, &cpkt.value, value); + + trace_virtio_serial_send_control_event(port_id, event, value); ++ qemu_log("virtio serial port %d send control message" ++ " event = %d, value = %d\n", port_id, event, value); + return send_control_msg(vser, &cpkt, sizeof(cpkt)); + } + +@@ -364,6 +366,9 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len) + cpkt.value = virtio_lduw_p(vdev, &gcpkt->value); + + trace_virtio_serial_handle_control_message(cpkt.event, cpkt.value); ++ qemu_log("virtio serial port '%u' handle control message" ++ " event = %d, value = %d\n", ++ virtio_ldl_p(vdev, &gcpkt->id), cpkt.event, cpkt.value); + + if (cpkt.event == VIRTIO_CONSOLE_DEVICE_READY) { + if (!cpkt.value) { +diff --git a/hw/pci/pci.c b/hw/pci/pci.c +index 850735fc46..0743dc7c42 100644 +--- a/hw/pci/pci.c ++++ b/hw/pci/pci.c +@@ -2411,6 +2411,7 @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, + } else { + snprintf(name, sizeof(name), "%s.rom", object_get_typename(OBJECT(pdev))); + } ++ qemu_log("add rom file: %s\n", name); + pdev->has_rom = true; + memory_region_init_rom(&pdev->rom, OBJECT(pdev), name, pdev->romsize, &error_fatal); + ptr = memory_region_get_ram_ptr(&pdev->rom); +diff --git a/hw/usb/bus.c b/hw/usb/bus.c +index 92d6ed5626..20cd9b6e6f 100644 +--- a/hw/usb/bus.c ++++ b/hw/usb/bus.c +@@ -536,6 +536,10 @@ void usb_check_attach(USBDevice *dev, Error **errp) + bus->qbus.name, port->path, portspeed); + return; + } ++ ++ qemu_log("attach usb device \"%s\" (%s speed) to VM bus \"%s\", " ++ "port \"%s\" (%s speed)\n", dev->product_desc, devspeed, ++ bus->qbus.name, port->path, portspeed); + } + + void usb_device_attach(USBDevice *dev, Error **errp) +@@ -564,6 +568,8 @@ int usb_device_detach(USBDevice *dev) + + usb_detach(port); + dev->attached = false; ++ qemu_log("detach usb device \"%s\" from VM bus \"%s\", port \"%s\"\n", ++ dev->product_desc, bus->qbus.name, port->path); + return 0; + } + +diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c +index 8f521ad586..3394b04f50 100644 +--- a/hw/usb/host-libusb.c ++++ b/hw/usb/host-libusb.c +@@ -992,6 +992,8 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd) + + rc = libusb_open(dev, &s->dh); + if (rc != 0) { ++ qemu_log("libusb open usb device bus %d, device %d failed\n", ++ bus_num, addr); + goto fail; + } + } else { +@@ -1019,6 +1021,7 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd) + + libusb_get_device_descriptor(dev, &s->ddesc); + usb_host_get_port(s->dev, s->port, sizeof(s->port)); ++ qemu_log("open a host usb device on bus %d, device %d\n", bus_num, addr); + + usb_ep_init(udev); + usb_host_ep_update(s); +@@ -1146,6 +1149,8 @@ static int usb_host_close(USBHostDevice *s) + usb_device_detach(udev); + } + ++ qemu_log("begin to reset the usb device, bus : %d, device : %d\n", ++ s->bus_num, s->addr); + usb_host_release_interfaces(s); + libusb_reset_device(s->dh); + usb_host_attach_kernel(s); +diff --git a/hw/virtio/virtio-scsi-pci.c b/hw/virtio/virtio-scsi-pci.c +index 97fab74236..498f9e2c98 100644 +--- a/hw/virtio/virtio-scsi-pci.c ++++ b/hw/virtio/virtio-scsi-pci.c +@@ -18,6 +18,7 @@ + #include "hw/qdev-properties.h" + #include "hw/virtio/virtio-scsi.h" + #include "qemu/module.h" ++#include "qemu/log.h" + #include "virtio-pci.h" + #include "qom/object.h" + +@@ -51,6 +52,8 @@ static void virtio_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) + VirtIOSCSIConf *conf = &dev->vdev.parent_obj.conf; + char *bus_name; + ++ qemu_log("virtio scsi HBA %s begin to initialize.\n", ++ !proxy->id ? "NULL" : proxy->id); + if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) { + conf->num_queues = + virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED); +diff --git a/monitor/monitor.c b/monitor/monitor.c +index 621e79eb66..28206bedc4 100644 +--- a/monitor/monitor.c ++++ b/monitor/monitor.c +@@ -23,6 +23,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/log.h" + #include "monitor-internal.h" + #include "qapi/error.h" + #include "qapi/opts-visitor.h" +diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c +index 98868cee03..d71beace6a 100644 +--- a/monitor/qmp-cmds.c ++++ b/monitor/qmp-cmds.c +@@ -21,6 +21,7 @@ + #include "sysemu/sysemu.h" + #include "qemu/config-file.h" + #include "qemu/uuid.h" ++#include "qemu/log.h" + #include "chardev/char.h" + #include "ui/qemu-spice.h" + #include "ui/console.h" +@@ -150,8 +151,10 @@ void qmp_cont(Error **errp) + } + + if (runstate_check(RUN_STATE_INMIGRATE)) { ++ qemu_log("qmp cont is received in migration\n"); + autostart = 1; + } else { ++ qemu_log("qmp cont is received and vm is started\n"); + vm_start(); + } + } +diff --git a/os-posix.c b/os-posix.c +index ae6c9f2a5e..306c442bc8 100644 +--- a/os-posix.c ++++ b/os-posix.c +@@ -322,6 +322,7 @@ int os_mlock(void) + #ifdef HAVE_MLOCKALL + int ret = 0; + ++ qemu_log("do mlockall\n"); + ret = mlockall(MCL_CURRENT | MCL_FUTURE); + if (ret < 0) { + error_report("mlockall: %s", strerror(errno)); +diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c +index bb005594d3..392ddb097c 100644 +--- a/qapi/qmp-dispatch.c ++++ b/qapi/qmp-dispatch.c +@@ -26,6 +26,7 @@ + #include "qemu/coroutine.h" + #include "qemu/main-loop.h" + #include "qemu/log.h" ++#include "qapi/qmp/qstring.h" + + Visitor *qobject_input_visitor_new_qmp(QObject *obj) + { +@@ -221,6 +222,20 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, + + assert(!(oob && qemu_in_coroutine())); + assert(monitor_cur() == NULL); ++ ++ json = qobject_to_json(QOBJECT(args)); ++ if (json) { ++ if ((strcmp(command, "query-block-jobs") != 0) ++ && (strcmp(command, "query-migrate") != 0) ++ && (strcmp(command, "query-blockstats") != 0) ++ && (strcmp(command, "query-balloon") != 0) ++ && (strcmp(command, "set_password") != 0)) { ++ qemu_log("qmp_cmd_name: %s, arguments: %s\n", ++ command, json->str); ++ } ++ g_string_free(json, true); ++ } ++ + if (!!(cmd->options & QCO_COROUTINE) == qemu_in_coroutine()) { + monitor_set_cur(qemu_coroutine_self(), cur_mon); + cmd->fn(args, &ret, &err); +diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c +index 4a20f5dbd7..05e1d88d99 100644 +--- a/softmmu/qdev-monitor.c ++++ b/softmmu/qdev-monitor.c +@@ -636,6 +636,7 @@ DeviceState *qdev_device_add_from_qdict(const QDict *opts, + if (path != NULL) { + bus = qbus_find(path, errp); + if (!bus) { ++ qemu_log("can not find bus for %s\n", driver); + return NULL; + } + if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) { +@@ -706,6 +707,8 @@ DeviceState *qdev_device_add_from_qdict(const QDict *opts, + object_set_properties_from_keyval(&dev->parent_obj, dev->opts, from_json, + errp); + if (*errp) { ++ qemu_log("the bus %s -driver %s set property failed\n", ++ bus ? bus->name : "None", driver); + goto err_del_dev; + } + qemu_log("add qdev %s:%s success\n", driver, dev->id ? dev->id : "none"); +@@ -730,6 +733,8 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) + + ret = qdev_device_add_from_qdict(qdict, false, errp); + if (ret) { ++ qemu_log("add qdev %s:%s success\n", qemu_opt_get(opts, "driver"), ++ qemu_opts_id(opts) ? qemu_opts_id(opts) : "none"); + qemu_opts_del(opts); + } + qobject_unref(qdict); +-- +2.30.0 + diff --git a/feature-Add-logs-for-vm-start-and-destroy.patch b/feature-Add-logs-for-vm-start-and-destroy.patch new file mode 100644 index 0000000000000000000000000000000000000000..0b6484d4c3f8186eb1f3863ffc34f3a46f3858bc --- /dev/null +++ b/feature-Add-logs-for-vm-start-and-destroy.patch @@ -0,0 +1,157 @@ +From afbf800fa1f5e104a5edf116db4956289990ebe1 Mon Sep 17 00:00:00 2001 +From: "wangxinxin.wang@huawei.com" +Date: Thu, 22 Jun 2017 08:30:04 +0800 +Subject: [PATCH 3/3] feature: Add logs for vm start and destroy + +Add QEMU_LOG for vm start and destroy + +Signed-off-by: miaoyubo +Signed-off-by: Jingyi Wang +--- + hw/acpi/core.c | 4 ++++ + hw/core/reset.c | 2 ++ + softmmu/main.c | 2 ++ + softmmu/runstate.c | 2 ++ + softmmu/vl.c | 6 ++++++ + 5 files changed, 16 insertions(+) + +diff --git a/hw/acpi/core.c b/hw/acpi/core.c +index 1e004d0078..eb631caa91 100644 +--- a/hw/acpi/core.c ++++ b/hw/acpi/core.c +@@ -24,6 +24,7 @@ + #include "hw/acpi/acpi.h" + #include "hw/nvram/fw_cfg.h" + #include "qemu/config-file.h" ++#include "qemu/log.h" + #include "qapi/error.h" + #include "qapi/opts-visitor.h" + #include "qapi/qapi-events-run-state.h" +@@ -560,13 +561,16 @@ static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val) + uint16_t sus_typ = (val >> 10) & 7; + switch (sus_typ) { + case 0: /* soft power off */ ++ qemu_log("VM will be soft power off\n"); + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + break; + case 1: ++ qemu_log("VM will be suspend state\n"); + qemu_system_suspend_request(); + break; + default: + if (sus_typ == ar->pm1.cnt.s4_val) { /* S4 request */ ++ qemu_log("VM will be S4 state\n"); + qapi_event_send_suspend_disk(); + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + } +diff --git a/hw/core/reset.c b/hw/core/reset.c +index 9c477f2bf5..e923723d38 100644 +--- a/hw/core/reset.c ++++ b/hw/core/reset.c +@@ -25,6 +25,7 @@ + + #include "qemu/osdep.h" + #include "qemu/queue.h" ++#include "qemu/log.h" + #include "sysemu/reset.h" + + /* reset/shutdown handler */ +@@ -64,6 +65,7 @@ void qemu_devices_reset(void) + { + QEMUResetEntry *re, *nre; + ++ qemu_log("reset all devices\n"); + /* reset all devices */ + QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) { + re->func(re->opaque); +diff --git a/softmmu/main.c b/softmmu/main.c +index 639c67ff48..0acb41bd30 100644 +--- a/softmmu/main.c ++++ b/softmmu/main.c +@@ -23,6 +23,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/log.h" + #include "qemu-common.h" + #include "sysemu/sysemu.h" + +@@ -47,6 +48,7 @@ int main(int argc, char **argv) + int main(int argc, char **argv, char **envp) + { + qemu_init(argc, argv, envp); ++ qemu_log("qemu enter main_loop\n"); + qemu_main_loop(); + qemu_cleanup(); + +diff --git a/softmmu/runstate.c b/softmmu/runstate.c +index 5736d908db..52fc3b7d6f 100644 +--- a/softmmu/runstate.c ++++ b/softmmu/runstate.c +@@ -708,9 +708,11 @@ static bool main_loop_should_exit(void) + } + if (qemu_powerdown_requested()) { + qemu_system_powerdown(); ++ qemu_log("domain is power down by outside operation\n"); + } + if (qemu_vmstop_requested(&r)) { + vm_stop(r); ++ qemu_log("domain is stopped by outside operation\n"); + } + return false; + } +diff --git a/softmmu/vl.c b/softmmu/vl.c +index d9e4c619d3..d8996f3d6e 100644 +--- a/softmmu/vl.c ++++ b/softmmu/vl.c +@@ -26,6 +26,7 @@ + #include "qemu-common.h" + #include "qemu/datadir.h" + #include "qemu/units.h" ++#include "qemu/log.h" + #include "exec/cpu-common.h" + #include "hw/qdev-properties.h" + #include "qapi/compat-policy.h" +@@ -2680,6 +2681,7 @@ static void qemu_create_cli_devices(void) + } + + /* init generic devices */ ++ qemu_log("device init start\n"); + rom_set_order_override(FW_CFG_ORDER_OVERRIDE_DEVICE); + qemu_opts_foreach(qemu_find_opts("device"), + device_init_func, NULL, &error_fatal); +@@ -2819,6 +2821,7 @@ void qemu_init(int argc, char **argv, char **envp) + + qemu_init_subsystems(); + ++ qemu_log("qemu pid is %d, options parsing start\n", getpid()); + /* first pass of option parsing */ + optind = 1; + while (optind < argc) { +@@ -3027,6 +3030,7 @@ void qemu_init(int argc, char **argv, char **envp) + exit(0); + break; + case QEMU_OPTION_m: ++ qemu_log("memory options parse start\n"); + opts = qemu_opts_parse_noisily(qemu_find_opts("memory"), + optarg, true); + if (!opts) { +@@ -3744,6 +3748,7 @@ void qemu_init(int argc, char **argv, char **envp) + */ + + machine_class = MACHINE_GET_CLASS(current_machine); ++ qemu_log("configure accelerator %s start\n", machine_class->name); + if (!qtest_enabled() && machine_class->deprecation_reason) { + error_report("Machine type '%s' is deprecated: %s", + machine_class->name, machine_class->deprecation_reason); +@@ -3757,6 +3762,7 @@ void qemu_init(int argc, char **argv, char **envp) + + qemu_create_late_backends(); + ++ qemu_log("machine init start\n"); + /* parse features once if machine provides default cpu_type */ + current_machine->cpu_type = machine_class->default_cpu_type; + if (cpu_option) { +-- +2.30.0 + diff --git a/file-posix-Fix-leaked-fd-in-raw_open_common-error-pa.patch b/file-posix-Fix-leaked-fd-in-raw_open_common-error-pa.patch deleted file mode 100644 index 28c1e3bc6837063888bb8c862fb1e629f70de8be..0000000000000000000000000000000000000000 --- a/file-posix-Fix-leaked-fd-in-raw_open_common-error-pa.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 94be73a20d42482cdf30115e672c36af2fe9068d Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Fri, 17 Jul 2020 12:54:26 +0200 -Subject: [PATCH 5/5] file-posix: Fix leaked fd in raw_open_common() error path - -Signed-off-by: Kevin Wolf -Message-Id: <20200717105426.51134-4-kwolf@redhat.com> -Reviewed-by: Max Reitz -Signed-off-by: Kevin Wolf -Signed-off-by: Zhenyu Ye ---- - block/file-posix.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/block/file-posix.c b/block/file-posix.c -index 2184aa98..1259bf58 100644 ---- a/block/file-posix.c -+++ b/block/file-posix.c -@@ -671,6 +671,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, - bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK; - ret = 0; - fail: -+ if (ret < 0 && s->fd != -1) { -+ qemu_close(s->fd); -+ } - if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) { - unlink(filename); - } --- -2.22.0.windows.1 - diff --git a/file-posix-Handle-undetectable-alignment.patch b/file-posix-Handle-undetectable-alignment.patch deleted file mode 100644 index 87a97dc4fdd67b160b89726f2ec9425d868df325..0000000000000000000000000000000000000000 --- a/file-posix-Handle-undetectable-alignment.patch +++ /dev/null @@ -1,158 +0,0 @@ -From b4bbef6714a45ffd7b4a57e5a0522c7006f504a6 Mon Sep 17 00:00:00 2001 -From: Nir Soffer -Date: Tue, 13 Aug 2019 21:21:03 +0300 -Subject: [PATCH] file-posix: Handle undetectable alignment - -In some cases buf_align or request_alignment cannot be detected: - -1. With Gluster, buf_align cannot be detected since the actual I/O is - done on Gluster server, and qemu buffer alignment does not matter. - Since we don't have alignment requirement, buf_align=1 is the best - value. - -2. With local XFS filesystem, buf_align cannot be detected if reading - from unallocated area. In this we must align the buffer, but we don't - know what is the correct size. Using the wrong alignment results in - I/O error. - -3. With Gluster backed by XFS, request_alignment cannot be detected if - reading from unallocated area. In this case we need to use the - correct alignment, and failing to do so results in I/O errors. - -4. With NFS, the server does not use direct I/O, so both buf_align cannot - be detected. In this case we don't need any alignment so we can use - buf_align=1 and request_alignment=1. - -These cases seems to work when storage sector size is 512 bytes, because -the current code starts checking align=512. If the check succeeds -because alignment cannot be detected we use 512. But this does not work -for storage with 4k sector size. - -To determine if we can detect the alignment, we probe first with -align=1. If probing succeeds, maybe there are no alignment requirement -(cases 1, 4) or we are probing unallocated area (cases 2, 3). Since we -don't have any way to tell, we treat this as undetectable alignment. If -probing with align=1 fails with EINVAL, but probing with one of the -expected alignments succeeds, we know that we found a working alignment. - -Practically the alignment requirements are the same for buffer -alignment, buffer length, and offset in file. So in case we cannot -detect buf_align, we can use request alignment. If we cannot detect -request alignment, we can fallback to a safe value. To use this logic, -we probe first request alignment instead of buf_align. - -Here is a table showing the behaviour with current code (the value in -parenthesis is the optimal value). - -Case Sector buf_align (opt) request_alignment (opt) result -====================================================================== -1 512 512 (1) 512 (512) OK -1 4096 512 (1) 4096 (4096) FAIL ----------------------------------------------------------------------- -2 512 512 (512) 512 (512) OK -2 4096 512 (4096) 4096 (4096) FAIL ----------------------------------------------------------------------- -3 512 512 (1) 512 (512) OK -3 4096 512 (1) 512 (4096) FAIL ----------------------------------------------------------------------- -4 512 512 (1) 512 (1) OK -4 4096 512 (1) 512 (1) OK - -Same cases with this change: - -Case Sector buf_align (opt) request_alignment (opt) result -====================================================================== -1 512 512 (1) 512 (512) OK -1 4096 4096 (1) 4096 (4096) OK ----------------------------------------------------------------------- -2 512 512 (512) 512 (512) OK -2 4096 4096 (4096) 4096 (4096) OK ----------------------------------------------------------------------- -3 512 4096 (1) 4096 (512) OK -3 4096 4096 (1) 4096 (4096) OK ----------------------------------------------------------------------- -4 512 4096 (1) 4096 (1) OK -4 4096 4096 (1) 4096 (1) OK - -I tested that provisioning VMs and copying disks on local XFS and -Gluster with 4k bytes sector size work now, resolving bugs [1],[2]. -I tested also on XFS, NFS, Gluster with 512 bytes sector size. - -[1] https://bugzilla.redhat.com/1737256 -[2] https://bugzilla.redhat.com/1738657 - -Signed-off-by: Nir Soffer -Signed-off-by: Kevin Wolf - -(cherry picked from commit a6b257a08e3d72219f03e461a52152672fec0612) - -Signed-off-by: Michael Roth ---- - block/file-posix.c | 36 +++++++++++++++++++++++++----------- - 1 file changed, 25 insertions(+), 11 deletions(-) - -diff --git a/block/file-posix.c b/block/file-posix.c -index c185f34..d5065c6 100644 ---- a/block/file-posix.c -+++ b/block/file-posix.c -@@ -321,6 +321,7 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp) - BDRVRawState *s = bs->opaque; - char *buf; - size_t max_align = MAX(MAX_BLOCKSIZE, getpagesize()); -+ size_t alignments[] = {1, 512, 1024, 2048, 4096}; - - /* For SCSI generic devices the alignment is not really used. - With buffered I/O, we don't have any restrictions. */ -@@ -347,25 +348,38 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp) - } - #endif - -- /* If we could not get the sizes so far, we can only guess them */ -- if (!s->buf_align) { -+ /* -+ * If we could not get the sizes so far, we can only guess them. First try -+ * to detect request alignment, since it is more likely to succeed. Then -+ * try to detect buf_align, which cannot be detected in some cases (e.g. -+ * Gluster). If buf_align cannot be detected, we fallback to the value of -+ * request_alignment. -+ */ -+ -+ if (!bs->bl.request_alignment) { -+ int i; - size_t align; -- buf = qemu_memalign(max_align, 2 * max_align); -- for (align = 512; align <= max_align; align <<= 1) { -- if (raw_is_io_aligned(fd, buf + align, max_align)) { -- s->buf_align = align; -+ buf = qemu_memalign(max_align, max_align); -+ for (i = 0; i < ARRAY_SIZE(alignments); i++) { -+ align = alignments[i]; -+ if (raw_is_io_aligned(fd, buf, align)) { -+ /* Fallback to safe value. */ -+ bs->bl.request_alignment = (align != 1) ? align : max_align; - break; - } - } - qemu_vfree(buf); - } - -- if (!bs->bl.request_alignment) { -+ if (!s->buf_align) { -+ int i; - size_t align; -- buf = qemu_memalign(s->buf_align, max_align); -- for (align = 512; align <= max_align; align <<= 1) { -- if (raw_is_io_aligned(fd, buf, align)) { -- bs->bl.request_alignment = align; -+ buf = qemu_memalign(max_align, 2 * max_align); -+ for (i = 0; i < ARRAY_SIZE(alignments); i++) { -+ align = alignments[i]; -+ if (raw_is_io_aligned(fd, buf + align, max_align)) { -+ /* Fallback to request_aligment. */ -+ s->buf_align = (align != 1) ? align : bs->bl.request_alignment; - break; - } - } --- -1.8.3.1 - diff --git a/fix-cve-2020-35504.patch b/fix-cve-2020-35504.patch deleted file mode 100644 index bf03fb5f56ee23b70d2931c956d1e91e89af3d3c..0000000000000000000000000000000000000000 --- a/fix-cve-2020-35504.patch +++ /dev/null @@ -1,30 +0,0 @@ -From dc8416b55d69e70912acd2364494a490b02e3198 Mon Sep 17 00:00:00 2001 -From: imxcc -Date: Mon, 21 Jun 2021 17:15:39 +0800 -Subject: [PATCH] fix cve-2020-35504 - -esp: always check current_req is not NULL before use in DMA callbacks - -Signed-off-by: Mark Cave-Ayland -Signed-off-by: imxcc ---- - hw/scsi/esp.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c -index 7508d035ca..d1f13b350e 100644 ---- a/hw/scsi/esp.c -+++ b/hw/scsi/esp.c -@@ -253,6 +253,9 @@ static void esp_do_dma(ESPState *s) - s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len); - return; - } -+ if (!s->current_req) { -+ return; -+ } - if (s->async_len == 0) { - /* Defer until data is available. */ - return; --- -2.27.0 - diff --git a/fix-cve-2020-35505.patch b/fix-cve-2020-35505.patch deleted file mode 100644 index eb639d926d70554b3663e5dd96105367090a2ba1..0000000000000000000000000000000000000000 --- a/fix-cve-2020-35505.patch +++ /dev/null @@ -1,46 +0,0 @@ -From a1c9b6747da5f3d2815a0c186473dc76d9e4f682 Mon Sep 17 00:00:00 2001 -From: imxcc -Date: Mon, 21 Jun 2021 17:20:55 +0800 -Subject: [PATCH] fix cve-2020-35505 - -esp: ensure cmdfifo is not empty and current_dev is non-NULL - -Signed-off-by: Mark Cave-Ayland -Signed-off-by: imxcc ---- - hw/scsi/esp.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c -index d1f13b350e..db6bed4f00 100644 ---- a/hw/scsi/esp.c -+++ b/hw/scsi/esp.c -@@ -79,6 +79,7 @@ void esp_request_cancelled(SCSIRequest *req) - scsi_req_unref(s->current_req); - s->current_req = NULL; - s->current_dev = NULL; -+ s->async_len = 0; - } - } - -@@ -113,7 +114,6 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t buflen) - if (s->current_req) { - /* Started a new command before the old one finished. Cancel it. */ - scsi_req_cancel(s->current_req); -- s->async_len = 0; - } - - s->current_dev = scsi_device_find(&s->bus, 0, target, 0); -@@ -136,6 +136,9 @@ static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid) - - trace_esp_do_busid_cmd(busid); - lun = busid & 7; -+ if (!s->current_dev) { -+ return; -+ } - current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, lun); - s->current_req = scsi_req_new(current_lun, 0, lun, buf, s); - datalen = scsi_req_enqueue(s->current_req); --- -2.27.0 - diff --git a/fix-vhost_user_blk_watch-crash.patch b/fix-vhost_user_blk_watch-crash.patch deleted file mode 100644 index 905cbe3c2542b7d59f8d69da720bf0639a4be9bb..0000000000000000000000000000000000000000 --- a/fix-vhost_user_blk_watch-crash.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 0b77995819a596f96c621697643e83624126e668 Mon Sep 17 00:00:00 2001 -From: Li Feng -Date: Mon, 23 Mar 2020 13:29:24 +0800 -Subject: [PATCH 13/14] fix vhost_user_blk_watch crash - -the G_IO_HUP is watched in tcp_chr_connect, and the callback -vhost_user_blk_watch is not needed, because tcp_chr_hup is registered as -callback. And it will close the tcp link. - -Signed-off-by: Li Feng -Message-Id: <20200323052924.29286-1-fengli@smartx.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Signed-off-by: Peng Liang ---- - hw/block/vhost-user-blk.c | 19 ------------------- - include/hw/virtio/vhost-user-blk.h | 1 - - 2 files changed, 20 deletions(-) - -diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c -index 85bc4017e7e9..dc66f8a5febd 100644 ---- a/hw/block/vhost-user-blk.c -+++ b/hw/block/vhost-user-blk.c -@@ -346,18 +346,6 @@ static void vhost_user_blk_disconnect(DeviceState *dev) - vhost_dev_cleanup(&s->dev); - } - --static gboolean vhost_user_blk_watch(GIOChannel *chan, GIOCondition cond, -- void *opaque) --{ -- DeviceState *dev = opaque; -- VirtIODevice *vdev = VIRTIO_DEVICE(dev); -- VHostUserBlk *s = VHOST_USER_BLK(vdev); -- -- qemu_chr_fe_disconnect(&s->chardev); -- -- return true; --} -- - static void vhost_user_blk_event(void *opaque, int event) - { - DeviceState *dev = opaque; -@@ -370,15 +358,9 @@ static void vhost_user_blk_event(void *opaque, int event) - qemu_chr_fe_disconnect(&s->chardev); - return; - } -- s->watch = qemu_chr_fe_add_watch(&s->chardev, G_IO_HUP, -- vhost_user_blk_watch, dev); - break; - case CHR_EVENT_CLOSED: - vhost_user_blk_disconnect(dev); -- if (s->watch) { -- g_source_remove(s->watch); -- s->watch = 0; -- } - break; - } - } -@@ -419,7 +401,6 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp) - - s->inflight = g_new0(struct vhost_inflight, 1); - s->vqs = g_new(struct vhost_virtqueue, s->num_queues); -- s->watch = 0; - s->connected = false; - - qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, vhost_user_blk_event, -diff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-user-blk.h -index 8dbf11c6f071..ad9b742a644c 100644 ---- a/include/hw/virtio/vhost-user-blk.h -+++ b/include/hw/virtio/vhost-user-blk.h -@@ -38,7 +38,6 @@ typedef struct VHostUserBlk { - struct vhost_inflight *inflight; - VhostUserState vhost_user; - struct vhost_virtqueue *vqs; -- guint watch; - bool connected; - } VHostUserBlk; - --- -2.26.2 - diff --git a/freeclock-add-qmp-command-to-get-time-offset-of-vm-i.patch b/freeclock-add-qmp-command-to-get-time-offset-of-vm-i.patch new file mode 100644 index 0000000000000000000000000000000000000000..e16b514e4f0d8db9fe55a393ed1c9ce434228334 --- /dev/null +++ b/freeclock-add-qmp-command-to-get-time-offset-of-vm-i.patch @@ -0,0 +1,125 @@ +From 124d427a1fdae2d1eeed433093ec4ab78b81237e Mon Sep 17 00:00:00 2001 +From: "shenghualong@huawei.com" +Date: Thu, 10 Feb 2022 11:11:37 +0800 +Subject: [PATCH] freeclock: add qmp command to get time offset of vm in + seconds + +When setting the system time in VM, a RTC_CHANGE event will be reported. +However, if libvirt is restarted while the event is be reporting, the +event will be lost and we will get the old time (not the time we set in +VM) after rebooting the VM. + +We save the delta time in QEMU and add a rtc-date-diff qmp to get the +delta time so that libvirt can get the latest time in VM according to +the qmp after libvirt is restarted. + +Signed-off-by: Peng Liang +Signed-off-by: zhangxinhao +--- + include/qemu-common.h | 4 +++- + monitor/qmp-cmds.c | 5 +++++ + qapi/misc.json | 9 +++++++++ + qapi/pragma.json | 3 ++- + softmmu/rtc.c | 13 ++++++++++++- + 5 files changed, 31 insertions(+), 3 deletions(-) + +diff --git a/include/qemu-common.h b/include/qemu-common.h +index 73bcf763ed..9ed8832152 100644 +--- a/include/qemu-common.h ++++ b/include/qemu-common.h +@@ -27,7 +27,9 @@ int qemu_main(int argc, char **argv, char **envp); + #endif + + void qemu_get_timedate(struct tm *tm, int offset); +-int qemu_timedate_diff(struct tm *tm); ++time_t qemu_timedate_diff(struct tm *tm); ++time_t get_rtc_date_diff(void); ++void set_rtc_date_diff(time_t diff); + + void *qemu_oom_check(void *ptr); + +diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c +index 343353e27a..98868cee03 100644 +--- a/monitor/qmp-cmds.c ++++ b/monitor/qmp-cmds.c +@@ -466,3 +466,8 @@ HumanReadableText *qmp_x_query_irq(Error **errp) + + return human_readable_text_from_str(buf); + } ++ ++int64_t qmp_query_rtc_date_diff(Error **errp) ++{ ++ return get_rtc_date_diff(); ++} +diff --git a/qapi/misc.json b/qapi/misc.json +index 358548abe1..5b6d653682 100644 +--- a/qapi/misc.json ++++ b/qapi/misc.json +@@ -527,3 +527,12 @@ + 'data': { '*option': 'str' }, + 'returns': ['CommandLineOptionInfo'], + 'allow-preconfig': true } ++ ++## ++# @query-rtc-date-diff: ++# ++# get vm's time offset ++# ++# Since: 2.8 ++## ++{ 'command': 'query-rtc-date-diff', 'returns': 'int64' } +diff --git a/qapi/pragma.json b/qapi/pragma.json +index 3bc0335d1f..b37f6de445 100644 +--- a/qapi/pragma.json ++++ b/qapi/pragma.json +@@ -26,7 +26,8 @@ + 'qom-get', + 'query-tpm-models', + 'query-tpm-types', +- 'ringbuf-read' ], ++ 'ringbuf-read', ++ 'query-rtc-date-diff' ], + # Externally visible types whose member names may use uppercase + 'member-name-exceptions': [ # visible in: + 'ACPISlotType', # query-acpi-ospm-status +diff --git a/softmmu/rtc.c b/softmmu/rtc.c +index 5632684fc9..57bb8bba7c 100644 +--- a/softmmu/rtc.c ++++ b/softmmu/rtc.c +@@ -43,6 +43,7 @@ static time_t rtc_ref_start_datetime; + static int rtc_realtime_clock_offset; /* used only with QEMU_CLOCK_REALTIME */ + static int rtc_host_datetime_offset = -1; /* valid & used only with + RTC_BASE_DATETIME */ ++static time_t rtc_date_diff = 0; + QEMUClockType rtc_clock; + /***********************************************************/ + /* RTC reference time/date access */ +@@ -84,7 +85,7 @@ void qemu_get_timedate(struct tm *tm, int offset) + } + } + +-int qemu_timedate_diff(struct tm *tm) ++time_t qemu_timedate_diff(struct tm *tm) + { + time_t seconds; + +@@ -107,6 +108,16 @@ int qemu_timedate_diff(struct tm *tm) + return seconds - qemu_ref_timedate(QEMU_CLOCK_HOST); + } + ++time_t get_rtc_date_diff(void) ++{ ++ return rtc_date_diff; ++} ++ ++void set_rtc_date_diff(time_t diff) ++{ ++ rtc_date_diff = diff; ++} ++ + static void configure_rtc_base_datetime(const char *startdate) + { + time_t rtc_start_datetime; +-- +2.27.0 + diff --git a/freeclock-set-rtc_date_diff-for-X86.patch b/freeclock-set-rtc_date_diff-for-X86.patch new file mode 100644 index 0000000000000000000000000000000000000000..bb81b33449af932142f1781a949b4d6edc2e9f1d --- /dev/null +++ b/freeclock-set-rtc_date_diff-for-X86.patch @@ -0,0 +1,30 @@ +From 3d0846d864384be3d08a54ca6e2ce247a5cee952 Mon Sep 17 00:00:00 2001 +From: l00500761 +Date: Thu, 10 Feb 2022 14:25:30 +0800 +Subject: [PATCH] freeclock: set rtc_date_diff for X86 + +Set rtc_date_diff in mc146818rtc. + +Signed-off-by: l00500761 +Signed-off-by: zhangxinhao +--- + hw/rtc/mc146818rtc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c +index 4fbafddb22..af1df9aaeb 100644 +--- a/hw/rtc/mc146818rtc.c ++++ b/hw/rtc/mc146818rtc.c +@@ -616,7 +616,8 @@ static void rtc_set_time(RTCState *s) + s->base_rtc = mktimegm(&tm); + s->last_update = qemu_clock_get_ns(rtc_clock); + +- qapi_event_send_rtc_change(qemu_timedate_diff(&tm)); ++ set_rtc_date_diff(qemu_timedate_diff(&tm)); ++ qapi_event_send_rtc_change(get_rtc_date_diff()); + } + + static void rtc_set_cmos(RTCState *s, const struct tm *tm) +-- +2.27.0 + diff --git a/freeclock-set-rtc_date_diff-for-arm.patch b/freeclock-set-rtc_date_diff-for-arm.patch new file mode 100644 index 0000000000000000000000000000000000000000..6156fe13bd9406dcc0d38d37d8005c5ea6dada45 --- /dev/null +++ b/freeclock-set-rtc_date_diff-for-arm.patch @@ -0,0 +1,30 @@ +From 1e6bae1d13302594b6e63d88e8627fa477966cf4 Mon Sep 17 00:00:00 2001 +From: "shenghualong@huawei.com" +Date: Thu, 10 Feb 2022 14:23:28 +0800 +Subject: [PATCH] freeclock: set rtc_date_diff for arm + +Set rtc_date_diff in pl031. + +Signed-off-by: Peng Liang +Signed-off-by: zhangxinhao +--- + hw/rtc/pl031.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/rtc/pl031.c b/hw/rtc/pl031.c +index e7ced90b02..da8b061e91 100644 +--- a/hw/rtc/pl031.c ++++ b/hw/rtc/pl031.c +@@ -143,7 +143,8 @@ static void pl031_write(void * opaque, hwaddr offset, + s->tick_offset += value - pl031_get_count(s); + + qemu_get_timedate(&tm, s->tick_offset); +- qapi_event_send_rtc_change(qemu_timedate_diff(&tm)); ++ set_rtc_date_diff(qemu_timedate_diff(&tm)); ++ qapi_event_send_rtc_change(get_rtc_date_diff()); + + pl031_set_alarm(s); + break; +-- +2.27.0 + diff --git a/hbitmap-handle-set-reset-with-zero-length.patch b/hbitmap-handle-set-reset-with-zero-length.patch deleted file mode 100644 index b346a970d8594e2fae6a730c8c66370dc66af0da..0000000000000000000000000000000000000000 --- a/hbitmap-handle-set-reset-with-zero-length.patch +++ /dev/null @@ -1,50 +0,0 @@ -From c0b35d87de345bd3b59a44c604b247a0497f2fc0 Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Fri, 11 Oct 2019 12:07:07 +0300 -Subject: [PATCH] hbitmap: handle set/reset with zero length - -Passing zero length to these functions leads to unpredicted results. -Zero-length set/reset may occur in active-mirror, on zero-length write -(which is unlikely, but not guaranteed to never happen). - -Let's just do nothing on zero-length request. - -Signed-off-by: Vladimir Sementsov-Ogievskiy -Message-id: 20191011090711.19940-2-vsementsov@virtuozzo.com -Reviewed-by: Max Reitz -Cc: qemu-stable@nongnu.org -Signed-off-by: Max Reitz -(cherry picked from commit fed33bd175f663cc8c13f8a490a4f35a19756cfe) -Signed-off-by: Michael Roth ---- - util/hbitmap.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/util/hbitmap.c b/util/hbitmap.c -index 71c6ba2c52..c059313b9e 100644 ---- a/util/hbitmap.c -+++ b/util/hbitmap.c -@@ -387,6 +387,10 @@ void hbitmap_set(HBitmap *hb, uint64_t start, uint64_t count) - uint64_t first, n; - uint64_t last = start + count - 1; - -+ if (count == 0) { -+ return; -+ } -+ - trace_hbitmap_set(hb, start, count, - start >> hb->granularity, last >> hb->granularity); - -@@ -478,6 +482,10 @@ void hbitmap_reset(HBitmap *hb, uint64_t start, uint64_t count) - uint64_t last = start + count - 1; - uint64_t gran = 1ULL << hb->granularity; - -+ if (count == 0) { -+ return; -+ } -+ - assert(QEMU_IS_ALIGNED(start, gran)); - assert(QEMU_IS_ALIGNED(count, gran) || (start + count == hb->orig_size)); - --- -2.23.0 diff --git a/hmp-vnc-Fix-info-vnc-list-leak.patch b/hmp-vnc-Fix-info-vnc-list-leak.patch deleted file mode 100644 index ccc4e1db511a18c5da864a1d8b2732e9a4cd8a1f..0000000000000000000000000000000000000000 --- a/hmp-vnc-Fix-info-vnc-list-leak.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 6cb599f75b7844aefd7823ad97fc3bae70eff11f Mon Sep 17 00:00:00 2001 -From: "Dr. David Alan Gilbert" -Date: Mon, 23 Mar 2020 12:08:22 +0000 -Subject: [PATCH 06/14] hmp/vnc: Fix info vnc list leak - -We're iterating the list, and then freeing the iteration pointer rather -than the list head. - -Fixes: 0a9667ecdb6d ("hmp: Update info vnc") -Reported-by: Coverity (CID 1421932) -Signed-off-by: Dr. David Alan Gilbert -Message-Id: <20200323120822.51266-1-dgilbert@redhat.com> -Reviewed-by: Peter Maydell -Signed-off-by: Dr. David Alan Gilbert -Signed-off-by: Peng Liang ---- - monitor/hmp-cmds.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c -index 5ca3ebe94272..fc5d6b92c4b6 100644 ---- a/monitor/hmp-cmds.c -+++ b/monitor/hmp-cmds.c -@@ -745,10 +745,11 @@ static void hmp_info_vnc_servers(Monitor *mon, VncServerInfo2List *server) - - void hmp_info_vnc(Monitor *mon, const QDict *qdict) - { -- VncInfo2List *info2l; -+ VncInfo2List *info2l, *info2l_head; - Error *err = NULL; - - info2l = qmp_query_vnc_servers(&err); -+ info2l_head = info2l; - if (err) { - hmp_handle_error(mon, &err); - return; -@@ -777,7 +778,7 @@ void hmp_info_vnc(Monitor *mon, const QDict *qdict) - info2l = info2l->next; - } - -- qapi_free_VncInfo2List(info2l); -+ qapi_free_VncInfo2List(info2l_head); - - } - #endif --- -2.26.2 - diff --git a/hostmem-Fix-up-free-host_nodes-list-right-after-visi.patch b/hostmem-Fix-up-free-host_nodes-list-right-after-visi.patch deleted file mode 100644 index 0cbda2bf538fdf6eccab11faa319bc9a31be12f9..0000000000000000000000000000000000000000 --- a/hostmem-Fix-up-free-host_nodes-list-right-after-visi.patch +++ /dev/null @@ -1,61 +0,0 @@ -From f14505f7f91edbce738202a6f658806d1074116c Mon Sep 17 00:00:00 2001 -From: Keqian Zhu -Date: Fri, 11 Dec 2020 17:28:39 +0800 -Subject: [PATCH] hostmem: Fix up free host_nodes list right after visited - -In host_memory_backend_get_host_nodes, we build host_nodes -list and output it to v (a StringOutputVisitor) but forget -to free the list. This fixes the memory leak. - -The memory leak stack: - -Direct leak of 32 byte(s) in 2 object(s) allocated from: - #0 0xfffda30b3393 in __interceptor_calloc (/usr/lib64/libasan.so.4+0xd3393) - #1 0xfffda1d28b9b in g_malloc0 (/usr/lib64/libglib-2.0.so.0+0x58b9b) - #2 0xaaab05ca6e43 in host_memory_backend_get_host_nodes backends/hostmem.c:94 - #3 0xaaab061ddf83 in object_property_get_uint16List qom/object.c:1478 - #4 0xaaab05866513 in query_memdev hw/core/machine-qmp-cmds.c:312 - #5 0xaaab061d980b in do_object_child_foreach qom/object.c:1001 - #6 0xaaab0586779b in qmp_query_memdev hw/core/machine-qmp-cmds.c:328 - #7 0xaaab0615ed3f in qmp_marshal_query_memdev qapi/qapi-commands-machine.c:327 - #8 0xaaab0632d647 in do_qmp_dispatch qapi/qmp-dispatch.c:147 - #9 0xaaab0632d647 in qmp_dispatch qapi/qmp-dispatch.c:190 - #10 0xaaab0610f74b in monitor_qmp_dispatch monitor/qmp.c:120 - #11 0xaaab0611074b in monitor_qmp_bh_dispatcher monitor/qmp.c:209 - #12 0xaaab063caefb in aio_bh_poll util/async.c:117 - #13 0xaaab063d30fb in aio_dispatch util/aio-posix.c:459 - #14 0xaaab063cac8f in aio_ctx_dispatch util/async.c:268 - #15 0xfffda1d22a6b in g_main_context_dispatch (/usr/lib64/libglib-2.0.so.0+0x52a6b) - #16 0xaaab063d0e97 in glib_pollfds_poll util/main-loop.c:218 - #17 0xaaab063d0e97 in os_host_main_loop_wait util/main-loop.c:241 - #18 0xaaab063d0e97 in main_loop_wait util/main-loop.c:517 - #19 0xaaab05c8bfa7 in main_loop /root/rpmbuild/BUILD/qemu-4.1.0/vl.c:1791 - #20 0xaaab05713bc3 in main /root/rpmbuild/BUILD/qemu-4.1.0/vl.c:4473 - #21 0xfffda0a83ebf in __libc_start_main (/usr/lib64/libc.so.6+0x23ebf) - #22 0xaaab0571ed5f (aarch64-softmmu/qemu-system-aarch64+0x88ed5f) -SUMMARY: AddressSanitizer: 32 byte(s) leaked in 2 allocation(s). - -Fixes: 4cf1b76bf1e2 (hostmem: add properties for NUMA memory policy) -Reported-by: Euler Robot -Tested-by: Chen Qun -Reviewed-by: Igor Mammedov -Signed-off-by: Keqian Zhu ---- - backends/hostmem.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/backends/hostmem.c b/backends/hostmem.c -index 463102aa15..9e1b3a0afc 100644 ---- a/backends/hostmem.c -+++ b/backends/hostmem.c -@@ -108,6 +108,7 @@ host_memory_backend_get_host_nodes(Object *obj, Visitor *v, const char *name, - - ret: - visit_type_uint16List(v, name, &host_nodes, errp); -+ qapi_free_uint16List(host_nodes); - } - - static void --- -2.27.0 - diff --git a/hppa-fix-leak-from-g_strdup_printf.patch b/hppa-fix-leak-from-g_strdup_printf.patch deleted file mode 100644 index b04193e380fe58ef14e91cb56d162abc264dce9b..0000000000000000000000000000000000000000 --- a/hppa-fix-leak-from-g_strdup_printf.patch +++ /dev/null @@ -1,54 +0,0 @@ -From b7ef7e6fb5a2b08268f4b19c07c07abd4fbb2064 Mon Sep 17 00:00:00 2001 -From: lizhengui -Date: Wed, 9 Sep 2020 14:48:49 +0800 -Subject: [PATCH] hppa: fix leak from g_strdup_printf -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -memory_region_init_* takes care of copying the name into memory it owns. -Free it in the caller. - -Signed-off-by: Paolo Bonzini -Reviewed-by: Philippe Mathieu-Daudé ---- - hw/hppa/dino.c | 1 + - hw/hppa/machine.c | 4 +++- - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/hw/hppa/dino.c b/hw/hppa/dino.c -index e94614ab..ef923b49 100644 ---- a/hw/hppa/dino.c -+++ b/hw/hppa/dino.c -@@ -485,6 +485,7 @@ PCIBus *dino_init(MemoryRegion *addr_space, - memory_region_init_alias(&s->pci_mem_alias[i], OBJECT(s), - name, &s->pci_mem, addr, - DINO_MEM_CHUNK_SIZE); -+ g_free(name); - } - - /* Set up PCI view of memory: Bus master address space. */ -diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c -index 662838d8..9e25660e 100644 ---- a/hw/hppa/machine.c -+++ b/hw/hppa/machine.c -@@ -78,13 +78,15 @@ static void machine_hppa_init(MachineState *machine) - - /* Create CPUs. */ - for (i = 0; i < smp_cpus; i++) { -+ char *name = g_strdup_printf("cpu%ld-io-eir", i); - cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type)); - - cpu_region = g_new(MemoryRegion, 1); - memory_region_init_io(cpu_region, OBJECT(cpu[i]), &hppa_io_eir_ops, -- cpu[i], g_strdup_printf("cpu%ld-io-eir", i), 4); -+ cpu[i], name, 4); - memory_region_add_subregion(addr_space, CPU_HPA + i * 0x1000, - cpu_region); -+ g_free(name); - } - - /* Limit main memory. */ --- -2.19.1 - diff --git a/hugepages-hugepages-files-maybe-leftover.patch b/hugepages-hugepages-files-maybe-leftover.patch new file mode 100644 index 0000000000000000000000000000000000000000..611f1eace32aebf33917851b1a3833984efab124 --- /dev/null +++ b/hugepages-hugepages-files-maybe-leftover.patch @@ -0,0 +1,99 @@ +From 3cb1b0ce091998532a30793e3272925da4e6f3aa Mon Sep 17 00:00:00 2001 +From: Jiajie Li +Date: Mon, 7 Feb 2022 14:31:34 +0800 +Subject: [PATCH 1/2] hugepages: hugepages files maybe leftover + +Before qemu uses the hugepage memory directory /dev/hugepages/libvirt/qemu/xxx, +The directory may be deleted because of the destroy virtual machine. +Cause qemu to create files directly under /dev/hugepages/libvirt/qemu/. +After the file is created, the file is not cleaned up by unlink, +and when the virtual machine is destroyed, libvirt will only clean up +/dev/hugepages/libvirt/qemu/xxx directory. After creating the hugepage file, +execute unlink to clean up the file to fix the problem. + +Signed-off-by: Jinhua Cao +Signed-off-by: Jiajie Li +--- + include/qemu/mmap-alloc.h | 3 +++ + softmmu/physmem.c | 10 +++++++++- + util/mmap-alloc.c | 22 ++++++++++++++++++++++ + 3 files changed, 34 insertions(+), 1 deletion(-) + +diff --git a/include/qemu/mmap-alloc.h b/include/qemu/mmap-alloc.h +index 90d0eee705..707202e5be 100644 +--- a/include/qemu/mmap-alloc.h ++++ b/include/qemu/mmap-alloc.h +@@ -1,6 +1,9 @@ + #ifndef QEMU_MMAP_ALLOC_H + #define QEMU_MMAP_ALLOC_H + ++#define HUGETLBFS_MAGIC 0x958458f6 ++ ++size_t qemu_fd_getfiletype(int fd); + + size_t qemu_fd_getpagesize(int fd); + +diff --git a/softmmu/physmem.c b/softmmu/physmem.c +index 3524c04c2a..3b9a61448c 100644 +--- a/softmmu/physmem.c ++++ b/softmmu/physmem.c +@@ -1496,7 +1496,14 @@ static int file_ram_open(const char *path, + /* @path names a file that doesn't exist, create it */ + fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0644); + if (fd >= 0) { +- *created = true; ++ info_report("open %s success \n", path); ++ /* if fd file type is HUGETLBFS_MAGIC, unlink it, */ ++ /* in case to prevent residue after qemu killed */ ++ if (qemu_fd_getfiletype(fd) == HUGETLBFS_MAGIC) { ++ unlink(path); ++ } else { ++ *created = true; ++ } + break; + } + } else if (errno == EISDIR) { +@@ -1515,6 +1522,7 @@ static int file_ram_open(const char *path, + + fd = mkstemp(filename); + if (fd >= 0) { ++ info_report("mkstemp %s success \n", filename); + unlink(filename); + g_free(filename); + break; +diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c +index 893d864354..4993dd5bfa 100644 +--- a/util/mmap-alloc.c ++++ b/util/mmap-alloc.c +@@ -29,6 +29,28 @@ + #include + #endif + ++size_t qemu_fd_getfiletype(int fd) ++{ ++ struct statfs fs; ++ int ret; ++ ++ if (fd != -1) { ++ do { ++ ret = fstatfs(fd, &fs); ++ } while (ret != 0 && errno == EINTR); ++ ++ if (ret != 0) { ++ fprintf(stderr, "Couldn't fstatfs() fd: %s\n", ++ strerror(errno)); ++ return -1; ++ } ++ return fs.f_type; ++ } else { ++ fprintf(stderr, "fd is invalid \n"); ++ return -1; ++ } ++} ++ + size_t qemu_fd_getpagesize(int fd) + { + #ifdef CONFIG_LINUX +-- +2.27.0 + diff --git a/hw-acpi-Add-ACPI-Generic-Event-Device-Support.patch b/hw-acpi-Add-ACPI-Generic-Event-Device-Support.patch deleted file mode 100644 index dc57aa64dd12427afc1e59af0476206317065d1b..0000000000000000000000000000000000000000 --- a/hw-acpi-Add-ACPI-Generic-Event-Device-Support.patch +++ /dev/null @@ -1,478 +0,0 @@ -From b12d9edd0079d4ee136c25e95333918b0c6d3cd9 Mon Sep 17 00:00:00 2001 -From: Samuel Ortiz -Date: Wed, 18 Sep 2019 14:06:25 +0100 -Subject: [PATCH] hw/acpi: Add ACPI Generic Event Device Support - -The ACPI Generic Event Device (GED) is a hardware-reduced specific -device[ACPI v6.1 Section 5.6.9] that handles all platform events, -including the hotplug ones. This patch generates the AML code that -defines GEDs. - -Platforms need to specify their own GED Event bitmap to describe -what kind of events they want to support through GED. Also this -uses a a single interrupt for the GED device, relying on IO -memory region to communicate the type of device affected by the -interrupt. This way, we can support up to 32 events with a unique -interrupt. - -This supports only memory hotplug for now. - -Signed-off-by: Samuel Ortiz -Signed-off-by: Sebastien Boeuf -Signed-off-by: Shameer Kolothum -Reviewed-by: Eric Auger -Message-Id: <20190918130633.4872-4-shameerali.kolothum.thodi@huawei.com> -Acked-by: Peter Maydell -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Reviewed-by: Igor Mammedov ---- - hw/acpi/Kconfig | 4 + - hw/acpi/Makefile.objs | 1 + - hw/acpi/generic_event_device.c | 303 +++++++++++++++++++++++++ - include/hw/acpi/generic_event_device.h | 100 ++++++++ - 4 files changed, 408 insertions(+) - create mode 100644 hw/acpi/generic_event_device.c - create mode 100644 include/hw/acpi/generic_event_device.h - -diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig -index 7c59cf900b..12e3f1e86e 100644 ---- a/hw/acpi/Kconfig -+++ b/hw/acpi/Kconfig -@@ -31,3 +31,7 @@ config ACPI_VMGENID - bool - default y - depends on PC -+ -+config ACPI_HW_REDUCED -+ bool -+ depends on ACPI -diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs -index 1a720c381e..e4b5d101a4 100644 ---- a/hw/acpi/Makefile.objs -+++ b/hw/acpi/Makefile.objs -@@ -6,6 +6,7 @@ common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o - common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o - common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o - common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o -+common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o - common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o - - common-obj-y += acpi_interface.o -diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c -new file mode 100644 -index 0000000000..b94500b08d ---- /dev/null -+++ b/hw/acpi/generic_event_device.c -@@ -0,0 +1,303 @@ -+/* -+ * -+ * Copyright (c) 2018 Intel Corporation -+ * Copyright (c) 2019 Huawei Technologies R & D (UK) Ltd -+ * Written by Samuel Ortiz, Shameer Kolothum -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2 or later, as published by the Free Software Foundation. -+ */ -+ -+#include "qemu/osdep.h" -+#include "qapi/error.h" -+#include "exec/address-spaces.h" -+#include "hw/acpi/acpi.h" -+#include "hw/acpi/generic_event_device.h" -+#include "hw/irq.h" -+#include "hw/mem/pc-dimm.h" -+#include "hw/qdev-properties.h" -+#include "migration/vmstate.h" -+#include "qemu/error-report.h" -+ -+static const uint32_t ged_supported_events[] = { -+ ACPI_GED_MEM_HOTPLUG_EVT, -+}; -+ -+/* -+ * The ACPI Generic Event Device (GED) is a hardware-reduced specific -+ * device[ACPI v6.1 Section 5.6.9] that handles all platform events, -+ * including the hotplug ones. Platforms need to specify their own -+ * GED Event bitmap to describe what kind of events they want to support -+ * through GED. This routine uses a single interrupt for the GED device, -+ * relying on IO memory region to communicate the type of device -+ * affected by the interrupt. This way, we can support up to 32 events -+ * with a unique interrupt. -+ */ -+void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, -+ uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base) -+{ -+ AcpiGedState *s = ACPI_GED(hotplug_dev); -+ Aml *crs = aml_resource_template(); -+ Aml *evt, *field; -+ Aml *dev = aml_device("%s", name); -+ Aml *evt_sel = aml_local(0); -+ Aml *esel = aml_name(AML_GED_EVT_SEL); -+ -+ /* _CRS interrupt */ -+ aml_append(crs, aml_interrupt(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH, -+ AML_EXCLUSIVE, &ged_irq, 1)); -+ -+ aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0013"))); -+ aml_append(dev, aml_name_decl("_UID", aml_string(GED_DEVICE))); -+ aml_append(dev, aml_name_decl("_CRS", crs)); -+ -+ /* Append IO region */ -+ aml_append(dev, aml_operation_region(AML_GED_EVT_REG, rs, -+ aml_int(ged_base + ACPI_GED_EVT_SEL_OFFSET), -+ ACPI_GED_EVT_SEL_LEN)); -+ field = aml_field(AML_GED_EVT_REG, AML_DWORD_ACC, AML_NOLOCK, -+ AML_WRITE_AS_ZEROS); -+ aml_append(field, aml_named_field(AML_GED_EVT_SEL, -+ ACPI_GED_EVT_SEL_LEN * BITS_PER_BYTE)); -+ aml_append(dev, field); -+ -+ /* -+ * For each GED event we: -+ * - Add a conditional block for each event, inside a loop. -+ * - Call a method for each supported GED event type. -+ * -+ * The resulting ASL code looks like: -+ * -+ * Local0 = ESEL -+ * If ((Local0 & One) == One) -+ * { -+ * MethodEvent0() -+ * } -+ * -+ * If ((Local0 & 0x2) == 0x2) -+ * { -+ * MethodEvent1() -+ * } -+ * ... -+ */ -+ evt = aml_method("_EVT", 1, AML_SERIALIZED); -+ { -+ Aml *if_ctx; -+ uint32_t i; -+ uint32_t ged_events = ctpop32(s->ged_event_bitmap); -+ -+ /* Local0 = ESEL */ -+ aml_append(evt, aml_store(esel, evt_sel)); -+ -+ for (i = 0; i < ARRAY_SIZE(ged_supported_events) && ged_events; i++) { -+ uint32_t event = s->ged_event_bitmap & ged_supported_events[i]; -+ -+ if (!event) { -+ continue; -+ } -+ -+ if_ctx = aml_if(aml_equal(aml_and(evt_sel, aml_int(event), NULL), -+ aml_int(event))); -+ switch (event) { -+ case ACPI_GED_MEM_HOTPLUG_EVT: -+ aml_append(if_ctx, aml_call0(MEMORY_DEVICES_CONTAINER "." -+ MEMORY_SLOT_SCAN_METHOD)); -+ break; -+ default: -+ /* -+ * Please make sure all the events in ged_supported_events[] -+ * are handled above. -+ */ -+ g_assert_not_reached(); -+ } -+ -+ aml_append(evt, if_ctx); -+ ged_events--; -+ } -+ -+ if (ged_events) { -+ error_report("Unsupported events specified"); -+ abort(); -+ } -+ } -+ -+ /* Append _EVT method */ -+ aml_append(dev, evt); -+ -+ aml_append(table, dev); -+} -+ -+/* Memory read by the GED _EVT AML dynamic method */ -+static uint64_t ged_read(void *opaque, hwaddr addr, unsigned size) -+{ -+ uint64_t val = 0; -+ GEDState *ged_st = opaque; -+ -+ switch (addr) { -+ case ACPI_GED_EVT_SEL_OFFSET: -+ /* Read the selector value and reset it */ -+ val = ged_st->sel; -+ ged_st->sel = 0; -+ break; -+ default: -+ break; -+ } -+ -+ return val; -+} -+ -+/* Nothing is expected to be written to the GED memory region */ -+static void ged_write(void *opaque, hwaddr addr, uint64_t data, -+ unsigned int size) -+{ -+} -+ -+static const MemoryRegionOps ged_ops = { -+ .read = ged_read, -+ .write = ged_write, -+ .endianness = DEVICE_LITTLE_ENDIAN, -+ .valid = { -+ .min_access_size = 4, -+ .max_access_size = 4, -+ }, -+}; -+ -+static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ AcpiGedState *s = ACPI_GED(hotplug_dev); -+ -+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -+ acpi_memory_plug_cb(hotplug_dev, &s->memhp_state, dev, errp); -+ } else { -+ error_setg(errp, "virt: device plug request for unsupported device" -+ " type: %s", object_get_typename(OBJECT(dev))); -+ } -+} -+ -+static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) -+{ -+ AcpiGedState *s = ACPI_GED(adev); -+ GEDState *ged_st = &s->ged_state; -+ uint32_t sel; -+ -+ if (ev & ACPI_MEMORY_HOTPLUG_STATUS) { -+ sel = ACPI_GED_MEM_HOTPLUG_EVT; -+ } else { -+ /* Unknown event. Return without generating interrupt. */ -+ warn_report("GED: Unsupported event %d. No irq injected", ev); -+ return; -+ } -+ -+ /* -+ * Set the GED selector field to communicate the event type. -+ * This will be read by GED aml code to select the appropriate -+ * event method. -+ */ -+ ged_st->sel |= sel; -+ -+ /* Trigger the event by sending an interrupt to the guest. */ -+ qemu_irq_pulse(s->irq); -+} -+ -+static Property acpi_ged_properties[] = { -+ DEFINE_PROP_UINT32("ged-event", AcpiGedState, ged_event_bitmap, 0), -+ DEFINE_PROP_END_OF_LIST(), -+}; -+ -+static const VMStateDescription vmstate_memhp_state = { -+ .name = "acpi-ged/memhp", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .fields = (VMStateField[]) { -+ VMSTATE_MEMORY_HOTPLUG(memhp_state, AcpiGedState), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+static const VMStateDescription vmstate_ged_state = { -+ .name = "acpi-ged-state", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT32(sel, GEDState), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+static const VMStateDescription vmstate_acpi_ged = { -+ .name = "acpi-ged", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .fields = (VMStateField[]) { -+ VMSTATE_STRUCT(ged_state, AcpiGedState, 1, vmstate_ged_state, GEDState), -+ VMSTATE_END_OF_LIST(), -+ }, -+ .subsections = (const VMStateDescription * []) { -+ &vmstate_memhp_state, -+ NULL -+ } -+}; -+ -+static void acpi_ged_initfn(Object *obj) -+{ -+ DeviceState *dev = DEVICE(obj); -+ AcpiGedState *s = ACPI_GED(dev); -+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj); -+ GEDState *ged_st = &s->ged_state; -+ -+ memory_region_init_io(&ged_st->io, obj, &ged_ops, ged_st, -+ TYPE_ACPI_GED, ACPI_GED_EVT_SEL_LEN); -+ sysbus_init_mmio(sbd, &ged_st->io); -+ -+ sysbus_init_irq(sbd, &s->irq); -+ -+ s->memhp_state.is_enabled = true; -+ /* -+ * GED handles memory hotplug event and acpi-mem-hotplug -+ * memory region gets initialized here. Create an exclusive -+ * container for memory hotplug IO and expose it as GED sysbus -+ * MMIO so that boards can map it separately. -+ */ -+ memory_region_init(&s->container_memhp, OBJECT(dev), "memhp container", -+ MEMORY_HOTPLUG_IO_LEN); -+ sysbus_init_mmio(sbd, &s->container_memhp); -+ acpi_memory_hotplug_init(&s->container_memhp, OBJECT(dev), -+ &s->memhp_state, 0); -+} -+ -+static void acpi_ged_class_init(ObjectClass *class, void *data) -+{ -+ DeviceClass *dc = DEVICE_CLASS(class); -+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(class); -+ AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(class); -+ -+ dc->desc = "ACPI Generic Event Device"; -+ dc->props = acpi_ged_properties; -+ dc->vmsd = &vmstate_acpi_ged; -+ -+ hc->plug = acpi_ged_device_plug_cb; -+ -+ adevc->send_event = acpi_ged_send_event; -+} -+ -+static const TypeInfo acpi_ged_info = { -+ .name = TYPE_ACPI_GED, -+ .parent = TYPE_SYS_BUS_DEVICE, -+ .instance_size = sizeof(AcpiGedState), -+ .instance_init = acpi_ged_initfn, -+ .class_init = acpi_ged_class_init, -+ .interfaces = (InterfaceInfo[]) { -+ { TYPE_HOTPLUG_HANDLER }, -+ { TYPE_ACPI_DEVICE_IF }, -+ { } -+ } -+}; -+ -+static void acpi_ged_register_types(void) -+{ -+ type_register_static(&acpi_ged_info); -+} -+ -+type_init(acpi_ged_register_types) -diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h -new file mode 100644 -index 0000000000..2049e8d873 ---- /dev/null -+++ b/include/hw/acpi/generic_event_device.h -@@ -0,0 +1,100 @@ -+/* -+ * -+ * Copyright (c) 2018 Intel Corporation -+ * Copyright (c) 2019 Huawei Technologies R & D (UK) Ltd -+ * Written by Samuel Ortiz, Shameer Kolothum -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2 or later, as published by the Free Software Foundation. -+ * -+ * The ACPI Generic Event Device (GED) is a hardware-reduced specific -+ * device[ACPI v6.1 Section 5.6.9] that handles all platform events, -+ * including the hotplug ones. Generic Event Device allows platforms -+ * to handle interrupts in ACPI ASL statements. It follows a very -+ * similar approach like the _EVT method from GPIO events. All -+ * interrupts are listed in _CRS and the handler is written in _EVT -+ * method. Here, we use a single interrupt for the GED device, relying -+ * on IO memory region to communicate the type of device affected by -+ * the interrupt. This way, we can support up to 32 events with a -+ * unique interrupt. -+ * -+ * Here is an example. -+ * -+ * Device (\_SB.GED) -+ * { -+ * Name (_HID, "ACPI0013") -+ * Name (_UID, Zero) -+ * Name (_CRS, ResourceTemplate () -+ * { -+ * Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, ) -+ * { -+ * 0x00000029, -+ * } -+ * }) -+ * OperationRegion (EREG, SystemMemory, 0x09080000, 0x04) -+ * Field (EREG, DWordAcc, NoLock, WriteAsZeros) -+ * { -+ * ESEL, 32 -+ * } -+ * -+ * Method (_EVT, 1, Serialized) // _EVT: Event -+ * { -+ * Local0 = ESEL // ESEL = IO memory region which specifies the -+ * // device type. -+ * If (((Local0 & One) == One)) -+ * { -+ * MethodEvent1() -+ * } -+ * If ((Local0 & 0x2) == 0x2) -+ * { -+ * MethodEvent2() -+ * } -+ * ... -+ * } -+ * } -+ * -+ */ -+ -+#ifndef HW_ACPI_GED_H -+#define HW_ACPI_GED_H -+ -+#include "hw/sysbus.h" -+#include "hw/acpi/memory_hotplug.h" -+ -+#define TYPE_ACPI_GED "acpi-ged" -+#define ACPI_GED(obj) \ -+ OBJECT_CHECK(AcpiGedState, (obj), TYPE_ACPI_GED) -+ -+#define ACPI_GED_EVT_SEL_OFFSET 0x0 -+#define ACPI_GED_EVT_SEL_LEN 0x4 -+ -+#define GED_DEVICE "GED" -+#define AML_GED_EVT_REG "EREG" -+#define AML_GED_EVT_SEL "ESEL" -+ -+/* -+ * Platforms need to specify the GED event bitmap -+ * to describe what kind of events they want to support -+ * through GED. -+ */ -+#define ACPI_GED_MEM_HOTPLUG_EVT 0x1 -+ -+typedef struct GEDState { -+ MemoryRegion io; -+ uint32_t sel; -+} GEDState; -+ -+typedef struct AcpiGedState { -+ SysBusDevice parent_obj; -+ MemHotplugState memhp_state; -+ MemoryRegion container_memhp; -+ GEDState ged_state; -+ uint32_t ged_event_bitmap; -+ qemu_irq irq; -+} AcpiGedState; -+ -+void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev, -+ uint32_t ged_irq, AmlRegionSpace rs, hwaddr ged_base); -+ -+#endif --- -2.19.1 diff --git a/hw-acpi-Do-not-create-memory-hotplug-method-when-han.patch b/hw-acpi-Do-not-create-memory-hotplug-method-when-han.patch deleted file mode 100644 index 292687199fbe797b86b25ac2fb56063f7080a0f0..0000000000000000000000000000000000000000 --- a/hw-acpi-Do-not-create-memory-hotplug-method-when-han.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 7a08983315bf4d624966a89112259e2b4949de91 Mon Sep 17 00:00:00 2001 -From: Samuel Ortiz -Date: Wed, 18 Sep 2019 14:06:24 +0100 -Subject: [PATCH] hw/acpi: Do not create memory hotplug method when handler is - not defined - -With Hardware-reduced ACPI, the GED device will manage ACPI -hotplug entirely. As a consequence, make the memory specific -events AML generation optional. The code will only be added -when the method name is not NULL. - -Signed-off-by: Samuel Ortiz -Signed-off-by: Shameer Kolothum -Reviewed-by: Eric Auger -Reviewed-by: Igor Mammedov -Message-Id: <20190918130633.4872-3-shameerali.kolothum.thodi@huawei.com> -Acked-by: Peter Maydell -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin ---- - hw/acpi/memory_hotplug.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c -index 9a515c0484..8b30356c1a 100644 ---- a/hw/acpi/memory_hotplug.c -+++ b/hw/acpi/memory_hotplug.c -@@ -711,10 +711,12 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, - } - aml_append(table, dev_container); - -- method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED); -- aml_append(method, -- aml_call0(MEMORY_DEVICES_CONTAINER "." MEMORY_SLOT_SCAN_METHOD)); -- aml_append(table, method); -+ if (event_handler_method) { -+ method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED); -+ aml_append(method, aml_call0(MEMORY_DEVICES_CONTAINER "." -+ MEMORY_SLOT_SCAN_METHOD)); -+ aml_append(table, method); -+ } - - g_free(mhp_res_path); - } --- -2.19.1 diff --git a/hw-acpi-Make-ACPI-IO-address-space-configurable.patch b/hw-acpi-Make-ACPI-IO-address-space-configurable.patch deleted file mode 100644 index cdf597b51566400b17ddac3e27dc93cb65a61bd6..0000000000000000000000000000000000000000 --- a/hw-acpi-Make-ACPI-IO-address-space-configurable.patch +++ /dev/null @@ -1,196 +0,0 @@ -From 6cd7281c73ca462b2f27969f1e28f1afd3ebe82d Mon Sep 17 00:00:00 2001 -From: Shameer Kolothum -Date: Wed, 18 Sep 2019 14:06:23 +0100 -Subject: [PATCH] hw/acpi: Make ACPI IO address space configurable - -This is in preparation for adding support for ARM64 platforms -where it doesn't use port mapped IO for ACPI IO space. We are -making changes so that MMIO region can be accommodated -and board can pass the base address into the aml build function. - -Also move few MEMORY_* definitions to header so that other memory -hotplug event signalling mechanisms (eg. Generic Event Device on -HW-reduced acpi platforms) can use the same from their respective -event handler code. - -Signed-off-by: Shameer Kolothum -Reviewed-by: Eric Auger -Reviewed-by: Igor Mammedov -Message-Id: <20190918130633.4872-2-shameerali.kolothum.thodi@huawei.com> -Acked-by: Peter Maydell -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin ---- - hw/acpi/memory_hotplug.c | 33 ++++++++++++++------------------ - hw/i386/acpi-build.c | 7 ++++++- - hw/i386/pc.c | 3 +++ - include/hw/acpi/memory_hotplug.h | 9 +++++++-- - include/hw/i386/pc.h | 3 +++ - 5 files changed, 33 insertions(+), 22 deletions(-) - -diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c -index 297812d5f7..9a515c0484 100644 ---- a/hw/acpi/memory_hotplug.c -+++ b/hw/acpi/memory_hotplug.c -@@ -29,12 +29,7 @@ - #define MEMORY_SLOT_PROXIMITY_METHOD "MPXM" - #define MEMORY_SLOT_EJECT_METHOD "MEJ0" - #define MEMORY_SLOT_NOTIFY_METHOD "MTFY" --#define MEMORY_SLOT_SCAN_METHOD "MSCN" - #define MEMORY_HOTPLUG_DEVICE "MHPD" --#define MEMORY_HOTPLUG_IO_LEN 24 --#define MEMORY_DEVICES_CONTAINER "\\_SB.MHPC" -- --static uint16_t memhp_io_base; - - static ACPIOSTInfo *acpi_memory_device_status(int slot, MemStatus *mdev) - { -@@ -209,7 +204,7 @@ static const MemoryRegionOps acpi_memory_hotplug_ops = { - }; - - void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, -- MemHotplugState *state, uint16_t io_base) -+ MemHotplugState *state, hwaddr io_base) - { - MachineState *machine = MACHINE(qdev_get_machine()); - -@@ -218,12 +213,10 @@ void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, - return; - } - -- assert(!memhp_io_base); -- memhp_io_base = io_base; - state->devs = g_malloc0(sizeof(*state->devs) * state->dev_count); - memory_region_init_io(&state->io, owner, &acpi_memory_hotplug_ops, state, - "acpi-mem-hotplug", MEMORY_HOTPLUG_IO_LEN); -- memory_region_add_subregion(as, memhp_io_base, &state->io); -+ memory_region_add_subregion(as, io_base, &state->io); - } - - /** -@@ -342,7 +335,8 @@ const VMStateDescription vmstate_memory_hotplug = { - - void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, - const char *res_root, -- const char *event_handler_method) -+ const char *event_handler_method, -+ AmlRegionSpace rs, hwaddr memhp_io_base) - { - int i; - Aml *ifctx; -@@ -351,10 +345,6 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, - Aml *mem_ctrl_dev; - char *mhp_res_path; - -- if (!memhp_io_base) { -- return; -- } -- - mhp_res_path = g_strdup_printf("%s." MEMORY_HOTPLUG_DEVICE, res_root); - mem_ctrl_dev = aml_device("%s", mhp_res_path); - { -@@ -365,14 +355,19 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, - aml_name_decl("_UID", aml_string("Memory hotplug resources"))); - - crs = aml_resource_template(); -- aml_append(crs, -- aml_io(AML_DECODE16, memhp_io_base, memhp_io_base, 0, -- MEMORY_HOTPLUG_IO_LEN) -- ); -+ if (rs == AML_SYSTEM_IO) { -+ aml_append(crs, -+ aml_io(AML_DECODE16, memhp_io_base, memhp_io_base, 0, -+ MEMORY_HOTPLUG_IO_LEN) -+ ); -+ } else { -+ aml_append(crs, aml_memory32_fixed(memhp_io_base, -+ MEMORY_HOTPLUG_IO_LEN, AML_READ_WRITE)); -+ } - aml_append(mem_ctrl_dev, aml_name_decl("_CRS", crs)); - - aml_append(mem_ctrl_dev, aml_operation_region( -- MEMORY_HOTPLUG_IO_REGION, AML_SYSTEM_IO, -+ MEMORY_HOTPLUG_IO_REGION, rs, - aml_int(memhp_io_base), MEMORY_HOTPLUG_IO_LEN) - ); - -diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c -index f3fdfefcd5..749218561a 100644 ---- a/hw/i386/acpi-build.c -+++ b/hw/i386/acpi-build.c -@@ -1871,7 +1871,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, - build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base, - "\\_SB.PCI0", "\\_GPE._E02"); - } -- build_memory_hotplug_aml(dsdt, nr_mem, "\\_SB.PCI0", "\\_GPE._E03"); -+ -+ if (pcms->memhp_io_base && nr_mem) { -+ build_memory_hotplug_aml(dsdt, nr_mem, "\\_SB.PCI0", -+ "\\_GPE._E03", AML_SYSTEM_IO, -+ pcms->memhp_io_base); -+ } - - scope = aml_scope("_GPE"); - { -diff --git a/hw/i386/pc.c b/hw/i386/pc.c -index d011733ff7..8a914130b0 100644 ---- a/hw/i386/pc.c -+++ b/hw/i386/pc.c -@@ -1936,6 +1936,9 @@ void pc_memory_init(PCMachineState *pcms, - - /* Init default IOAPIC address space */ - pcms->ioapic_as = &address_space_memory; -+ -+ /* Init ACPI memory hotplug IO base address */ -+ pcms->memhp_io_base = ACPI_MEMORY_HOTPLUG_BASE; - } - - /* -diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h -index 77c65765d6..dfe9cf3fde 100644 ---- a/include/hw/acpi/memory_hotplug.h -+++ b/include/hw/acpi/memory_hotplug.h -@@ -5,6 +5,10 @@ - #include "hw/acpi/acpi.h" - #include "hw/acpi/aml-build.h" - -+#define MEMORY_SLOT_SCAN_METHOD "MSCN" -+#define MEMORY_DEVICES_CONTAINER "\\_SB.MHPC" -+#define MEMORY_HOTPLUG_IO_LEN 24 -+ - /** - * MemStatus: - * @is_removing: the memory device in slot has been requested to be ejected. -@@ -29,7 +33,7 @@ typedef struct MemHotplugState { - } MemHotplugState; - - void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, -- MemHotplugState *state, uint16_t io_base); -+ MemHotplugState *state, hwaddr io_base); - - void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st, - DeviceState *dev, Error **errp); -@@ -48,5 +52,6 @@ void acpi_memory_ospm_status(MemHotplugState *mem_st, ACPIOSTInfoList ***list); - - void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, - const char *res_root, -- const char *event_handler_method); -+ const char *event_handler_method, -+ AmlRegionSpace rs, hwaddr memhp_io_base); - #endif -diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h -index 859b64c51d..49b47535cf 100644 ---- a/include/hw/i386/pc.h -+++ b/include/hw/i386/pc.h -@@ -69,6 +69,9 @@ struct PCMachineState { - /* Address space used by IOAPIC device. All IOAPIC interrupts - * will be translated to MSI messages in the address space. */ - AddressSpace *ioapic_as; -+ -+ /* ACPI Memory hotplug IO base address */ -+ hwaddr memhp_io_base; - }; - - #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device" --- -2.19.1 diff --git a/hw-acpi-aml-build-Improve-scalability-of-PPTT-genera.patch b/hw-acpi-aml-build-Improve-scalability-of-PPTT-genera.patch new file mode 100644 index 0000000000000000000000000000000000000000..0525989485e8ce7ea6180b3d8b933ab70dfe74ef --- /dev/null +++ b/hw-acpi-aml-build-Improve-scalability-of-PPTT-genera.patch @@ -0,0 +1,113 @@ +From 66c935b435d90ef9c1ae4446c5edc07cbd8ba0ed Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Fri, 7 Jan 2022 16:32:29 +0800 +Subject: [PATCH 17/24] hw/acpi/aml-build: Improve scalability of PPTT + generation + +Use g_queue APIs to reduce the nested loops and code indentation +with the processor hierarchy levels increasing. Consenquently, +it's more scalable to add new topology level to build_pptt. + +No functional change intended. + +Signed-off-by: Yanan Wang +Reviewed-by: Andrew Jones +Message-id: 20220107083232.16256-4-wangyanan55@huawei.com +Signed-off-by: Peter Maydell +--- + hw/acpi/aml-build.c | 50 +++++++++++++++++++++++++++++---------------- + 1 file changed, 32 insertions(+), 18 deletions(-) + +diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c +index b3b3310df3..6aaedca2e5 100644 +--- a/hw/acpi/aml-build.c ++++ b/hw/acpi/aml-build.c +@@ -2001,7 +2001,10 @@ static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags, + void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + const char *oem_id, const char *oem_table_id) + { +- int pptt_start = table_data->len; ++ GQueue *list = g_queue_new(); ++ guint pptt_start = table_data->len; ++ guint parent_offset; ++ guint length, i; + int uid = 0; + int socket; + AcpiTable table = { .sig = "PPTT", .rev = 2, +@@ -2010,9 +2013,8 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + acpi_table_begin(&table, table_data); + + for (socket = 0; socket < ms->smp.sockets; socket++) { +- uint32_t socket_offset = table_data->len - pptt_start; +- int core; +- ++ g_queue_push_tail(list, ++ GUINT_TO_POINTER(table_data->len - pptt_start)); + build_processor_hierarchy_node( + table_data, + /* +@@ -2021,35 +2023,47 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + */ + (1 << 0), + 0, socket, NULL, 0); ++ } + +- for (core = 0; core < ms->smp.cores; core++) { +- uint32_t core_offset = table_data->len - pptt_start; +- int thread; ++ length = g_queue_get_length(list); ++ for (i = 0; i < length; i++) { ++ int core; + ++ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); ++ for (core = 0; core < ms->smp.cores; core++) { + if (ms->smp.threads > 1) { ++ g_queue_push_tail(list, ++ GUINT_TO_POINTER(table_data->len - pptt_start)); + build_processor_hierarchy_node( + table_data, + (0 << 0), /* not a physical package */ +- socket_offset, core, NULL, 0); +- +- for (thread = 0; thread < ms->smp.threads; thread++) { +- build_processor_hierarchy_node( +- table_data, +- (1 << 1) | /* ACPI Processor ID valid */ +- (1 << 2) | /* Processor is a Thread */ +- (1 << 3), /* Node is a Leaf */ +- core_offset, uid++, NULL, 0); +- } ++ parent_offset, core, NULL, 0); + } else { + build_processor_hierarchy_node( + table_data, + (1 << 1) | /* ACPI Processor ID valid */ + (1 << 3), /* Node is a Leaf */ +- socket_offset, uid++, NULL, 0); ++ parent_offset, uid++, NULL, 0); + } + } + } + ++ length = g_queue_get_length(list); ++ for (i = 0; i < length; i++) { ++ int thread; ++ ++ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); ++ for (thread = 0; thread < ms->smp.threads; thread++) { ++ build_processor_hierarchy_node( ++ table_data, ++ (1 << 1) | /* ACPI Processor ID valid */ ++ (1 << 2) | /* Processor is a Thread */ ++ (1 << 3), /* Node is a Leaf */ ++ parent_offset, uid++, NULL, 0); ++ } ++ } ++ ++ g_queue_free(list); + acpi_table_end(linker, &table); + } + +-- +2.27.0 + diff --git a/hw-acpi-aml-build-Support-cluster-level-in-PPTT-gene.patch b/hw-acpi-aml-build-Support-cluster-level-in-PPTT-gene.patch new file mode 100644 index 0000000000000000000000000000000000000000..17542a05a23ab3037961b1d4e970d9b1d32efd34 --- /dev/null +++ b/hw-acpi-aml-build-Support-cluster-level-in-PPTT-gene.patch @@ -0,0 +1,56 @@ +From 9c16924ba0a77c34246b69e8b1faee219f266445 Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Fri, 7 Jan 2022 16:32:31 +0800 +Subject: [PATCH 19/24] hw/acpi/aml-build: Support cluster level in PPTT + generation + +Support CPU cluster topology level in generation of ACPI +Processor Properties Topology Table (PPTT). + +Signed-off-by: Yanan Wang +Reviewed-by: Andrew Jones +Message-id: 20220107083232.16256-6-wangyanan55@huawei.com +Signed-off-by: Peter Maydell +--- + hw/acpi/aml-build.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c +index 6aaedca2e5..bb2cad63b5 100644 +--- a/hw/acpi/aml-build.c ++++ b/hw/acpi/aml-build.c +@@ -2001,6 +2001,7 @@ static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags, + void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + const char *oem_id, const char *oem_table_id) + { ++ MachineClass *mc = MACHINE_GET_CLASS(ms); + GQueue *list = g_queue_new(); + guint pptt_start = table_data->len; + guint parent_offset; +@@ -2025,6 +2026,23 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + 0, socket, NULL, 0); + } + ++ if (mc->smp_props.clusters_supported) { ++ length = g_queue_get_length(list); ++ for (i = 0; i < length; i++) { ++ int cluster; ++ ++ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); ++ for (cluster = 0; cluster < ms->smp.clusters; cluster++) { ++ g_queue_push_tail(list, ++ GUINT_TO_POINTER(table_data->len - pptt_start)); ++ build_processor_hierarchy_node( ++ table_data, ++ (0 << 0), /* not a physical package */ ++ parent_offset, cluster, NULL, 0); ++ } ++ } ++ } ++ + length = g_queue_get_length(list); + for (i = 0; i < length; i++) { + int core; +-- +2.27.0 + diff --git a/hw-arm-Factor-out-powerdown-notifier-from-GPIO.patch b/hw-arm-Factor-out-powerdown-notifier-from-GPIO.patch deleted file mode 100644 index f2c0f3900d05652a977be13df0babb8210c65b1b..0000000000000000000000000000000000000000 --- a/hw-arm-Factor-out-powerdown-notifier-from-GPIO.patch +++ /dev/null @@ -1,72 +0,0 @@ -From e6b1fd7bfbfe116e9d5df590f7069336c1eb1983 Mon Sep 17 00:00:00 2001 -From: Shameer Kolothum -Date: Wed, 18 Sep 2019 14:06:29 +0100 -Subject: [PATCH] hw/arm: Factor out powerdown notifier from GPIO - -This is in preparation of using GED device for -system_powerdown event. Make the powerdown notifier -registration independent of create_gpio() fn. - -Signed-off-by: Shameer Kolothum -Reviewed-by: Eric Auger -Reviewed-by: Igor Mammedov -Message-Id: <20190918130633.4872-8-shameerali.kolothum.thodi@huawei.com> -Acked-by: Peter Maydell -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin ---- - hw/arm/virt.c | 12 ++++-------- - include/hw/arm/virt.h | 1 + - 2 files changed, 5 insertions(+), 8 deletions(-) - -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index ab33cce4b3..aaefa5578e 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -910,10 +910,6 @@ static void virt_powerdown_req(Notifier *n, void *opaque) - qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); - } - --static Notifier virt_system_powerdown_notifier = { -- .notify = virt_powerdown_req --}; -- - static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) - { - char *nodename; -@@ -954,10 +950,6 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) - KEY_POWER); - qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff", - "gpios", phandle, 3, 0); -- -- /* connect powerdown request */ -- qemu_register_powerdown_notifier(&virt_system_powerdown_notifier); -- - g_free(nodename); - } - -@@ -1856,6 +1848,10 @@ static void machvirt_init(MachineState *machine) - vms->acpi_dev = create_acpi_ged(vms, pic); - } - -+ /* connect powerdown request */ -+ vms->powerdown_notifier.notify = virt_powerdown_req; -+ qemu_register_powerdown_notifier(&vms->powerdown_notifier); -+ - /* Create mmio transports, so the user can create virtio backends - * (which will be automatically plugged in to the transports). If - * no backend is created the transport will just sit harmlessly idle. -diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h -index 0350285136..dcceb9c615 100644 ---- a/include/hw/arm/virt.h -+++ b/include/hw/arm/virt.h -@@ -139,6 +139,7 @@ typedef struct { - int psci_conduit; - hwaddr highest_gpa; - DeviceState *acpi_dev; -+ Notifier powerdown_notifier; - } VirtMachineState; - - #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) --- -2.19.1 diff --git a/hw-arm-Use-GED-for-system_powerdown-event.patch b/hw-arm-Use-GED-for-system_powerdown-event.patch deleted file mode 100644 index 140f59a2c71da40f47a2edd2bd2dd529227c3ddc..0000000000000000000000000000000000000000 --- a/hw-arm-Use-GED-for-system_powerdown-event.patch +++ /dev/null @@ -1,167 +0,0 @@ -From 0b77f242b180f1ae40b9752999cef4894113df8e Mon Sep 17 00:00:00 2001 -From: Shameer Kolothum -Date: Wed, 18 Sep 2019 14:06:30 +0100 -Subject: [PATCH] hw/arm: Use GED for system_powerdown event - -For machines 4.2 or higher with ACPI boot use GED for system_powerdown -event instead of GPIO. Guest boot with DT still uses GPIO. - -Signed-off-by: Shameer Kolothum -Reviewed-by: Eric Auger -Reviewed-by: Igor Mammedov -Message-Id: <20190918130633.4872-9-shameerali.kolothum.thodi@huawei.com> -Acked-by: Peter Maydell -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin ---- - hw/acpi/generic_event_device.c | 8 ++++++++ - hw/arm/virt-acpi-build.c | 6 +++--- - hw/arm/virt.c | 18 ++++++++++++------ - include/hw/acpi/acpi_dev_interface.h | 1 + - include/hw/acpi/generic_event_device.h | 3 +++ - 5 files changed, 27 insertions(+), 9 deletions(-) - -diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c -index b94500b08d..9cee90cc70 100644 ---- a/hw/acpi/generic_event_device.c -+++ b/hw/acpi/generic_event_device.c -@@ -22,6 +22,7 @@ - - static const uint32_t ged_supported_events[] = { - ACPI_GED_MEM_HOTPLUG_EVT, -+ ACPI_GED_PWR_DOWN_EVT, - }; - - /* -@@ -104,6 +105,11 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev, - aml_append(if_ctx, aml_call0(MEMORY_DEVICES_CONTAINER "." - MEMORY_SLOT_SCAN_METHOD)); - break; -+ case ACPI_GED_PWR_DOWN_EVT: -+ aml_append(if_ctx, -+ aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE), -+ aml_int(0x80))); -+ break; - default: - /* - * Please make sure all the events in ged_supported_events[] -@@ -184,6 +190,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) - - if (ev & ACPI_MEMORY_HOTPLUG_STATUS) { - sel = ACPI_GED_MEM_HOTPLUG_EVT; -+ } else if (ev & ACPI_POWER_DOWN_STATUS) { -+ sel = ACPI_GED_PWR_DOWN_EVT; - } else { - /* Unknown event. Return without generating interrupt. */ - warn_report("GED: Unsupported event %d. No irq injected", ev); -diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c -index 9622994e50..f48733d9f2 100644 ---- a/hw/arm/virt-acpi-build.c -+++ b/hw/arm/virt-acpi-build.c -@@ -50,7 +50,6 @@ - #include "hw/acpi/acpi-defs.h" - - #define ARM_SPI_BASE 32 --#define ACPI_POWER_BUTTON_DEVICE "PWRB" - - static void acpi_dsdt_add_psd(Aml *dev, int cpus) - { -@@ -813,13 +812,14 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) - (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); - acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE), - vms->highmem, vms->highmem_ecam); -- acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], -- (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); - if (vms->acpi_dev) { - build_ged_aml(scope, "\\_SB."GED_DEVICE, - HOTPLUG_HANDLER(vms->acpi_dev), - irqmap[VIRT_ACPI_GED] + ARM_SPI_BASE, AML_SYSTEM_MEMORY, - memmap[VIRT_ACPI_GED].base); -+ } else { -+ acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], -+ (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); - } - - if (vms->acpi_dev) { -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index aaefa5578e..18321e522b 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -639,10 +639,10 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic) - DeviceState *dev; - MachineState *ms = MACHINE(vms); - int irq = vms->irqmap[VIRT_ACPI_GED]; -- uint32_t event = 0; -+ uint32_t event = ACPI_GED_PWR_DOWN_EVT; - - if (ms->ram_slots) { -- event = ACPI_GED_MEM_HOTPLUG_EVT; -+ event |= ACPI_GED_MEM_HOTPLUG_EVT; - } - - dev = qdev_create(NULL, TYPE_ACPI_GED); -@@ -906,8 +906,14 @@ static void create_rtc(const VirtMachineState *vms, qemu_irq *pic) - static DeviceState *gpio_key_dev; - static void virt_powerdown_req(Notifier *n, void *opaque) - { -- /* use gpio Pin 3 for power button event */ -- qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); -+ VirtMachineState *s = container_of(n, VirtMachineState, powerdown_notifier); -+ -+ if (s->acpi_dev) { -+ acpi_send_event(s->acpi_dev, ACPI_POWER_DOWN_STATUS); -+ } else { -+ /* use gpio Pin 3 for power button event */ -+ qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); -+ } - } - - static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) -@@ -1842,10 +1848,10 @@ static void machvirt_init(MachineState *machine) - - create_pcie(vms, pic); - -- create_gpio(vms, pic); -- - if (has_ged && aarch64 && firmware_loaded && acpi_enabled) { - vms->acpi_dev = create_acpi_ged(vms, pic); -+ } else { -+ create_gpio(vms, pic); - } - - /* connect powerdown request */ -diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h -index 43ff119179..adcb3a816c 100644 ---- a/include/hw/acpi/acpi_dev_interface.h -+++ b/include/hw/acpi/acpi_dev_interface.h -@@ -11,6 +11,7 @@ typedef enum { - ACPI_MEMORY_HOTPLUG_STATUS = 8, - ACPI_NVDIMM_HOTPLUG_STATUS = 16, - ACPI_VMGENID_CHANGE_STATUS = 32, -+ ACPI_POWER_DOWN_STATUS = 64, - } AcpiEventStatusBits; - - #define TYPE_ACPI_DEVICE_IF "acpi-device-interface" -diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h -index 2049e8d873..d157eac088 100644 ---- a/include/hw/acpi/generic_event_device.h -+++ b/include/hw/acpi/generic_event_device.h -@@ -62,6 +62,8 @@ - #include "hw/sysbus.h" - #include "hw/acpi/memory_hotplug.h" - -+#define ACPI_POWER_BUTTON_DEVICE "PWRB" -+ - #define TYPE_ACPI_GED "acpi-ged" - #define ACPI_GED(obj) \ - OBJECT_CHECK(AcpiGedState, (obj), TYPE_ACPI_GED) -@@ -79,6 +81,7 @@ - * through GED. - */ - #define ACPI_GED_MEM_HOTPLUG_EVT 0x1 -+#define ACPI_GED_PWR_DOWN_EVT 0x2 - - typedef struct GEDState { - MemoryRegion io; --- -2.19.1 diff --git a/hw-arm-acpi-enable-SHPC-native-hot-plug.patch b/hw-arm-acpi-enable-SHPC-native-hot-plug.patch deleted file mode 100644 index 2b2e530bb8e3555b4f9cf2a807b060ac62ccd9de..0000000000000000000000000000000000000000 --- a/hw-arm-acpi-enable-SHPC-native-hot-plug.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 1ad2e774f4fd3f720d5db07e86fe60df13f21a6d Mon Sep 17 00:00:00 2001 -From: Heyi Guo -Date: Mon, 9 Dec 2019 14:37:19 +0800 -Subject: [PATCH] hw/arm/acpi: enable SHPC native hot plug - -After the introduction of generic PCIe root port and PCIe-PCI bridge, -we will also have SHPC controller on ARM, so just enable SHPC native -hot plug. - -Also update tests/data/acpi/virt/DSDT* to pass "make check". - -Cc: Shannon Zhao -Cc: Peter Maydell -Cc: "Michael S. Tsirkin" -Cc: Igor Mammedov -Reviewed-by: Michael S. Tsirkin -Reviewed-by: Igor Mammedov -Signed-off-by: Heyi Guo -Message-id: 20191209063719.23086-3-guoheyi@huawei.com -Signed-off-by: Peter Maydell ---- - hw/arm/virt-acpi-build.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c -index 2cfac7b84f..588e7f2680 100644 ---- a/hw/arm/virt-acpi-build.c -+++ b/hw/arm/virt-acpi-build.c -@@ -347,7 +347,12 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, - aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3")); - aml_append(ifctx, aml_store(aml_name("CDW2"), aml_name("SUPP"))); - aml_append(ifctx, aml_store(aml_name("CDW3"), aml_name("CTRL"))); -- aml_append(ifctx, aml_store(aml_and(aml_name("CTRL"), aml_int(0x1D), NULL), -+ -+ /* -+ * Allow OS control for all 5 features: -+ * PCIeHotplug SHPCHotplug PME AER PCIeCapability. -+ */ -+ aml_append(ifctx, aml_store(aml_and(aml_name("CTRL"), aml_int(0x1F), NULL), - aml_name("CTRL"))); - - ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(0x1)))); --- -2.23.0 - diff --git a/hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch b/hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch index 95abd07e5a2b62acd14c1a45e61ce471707f173e..0055d3b37ec334de1912824a8c78e9d81321a6cd 100644 --- a/hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch +++ b/hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch @@ -1,4 +1,4 @@ -From de86ba0ff72a51b0c1cdbebf790869aea73ae9d3 Mon Sep 17 00:00:00 2001 +From 9dc22ff87eb61a8b2bcc5892961ec432986893c9 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Thu, 9 Apr 2020 09:31:22 +0800 Subject: [PATCH] hw/arm/boot: Add manually register and trigger of CPU reset @@ -17,13 +17,13 @@ Signed-off-by: Salil Mehta 4 files changed, 50 insertions(+) diff --git a/hw/arm/boot.c b/hw/arm/boot.c -index fc4e021a38..3ab9de6456 100644 +index 21024f7999..3d45de1772 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c -@@ -789,6 +789,24 @@ static void do_cpu_reset(void *opaque) +@@ -814,6 +814,24 @@ static void do_cpu_reset(void *opaque) } } - + +void cpu_hotplug_register_reset(int ncpu) +{ + CPUState *cpu_0 = qemu_get_cpu(0); @@ -46,13 +46,13 @@ index fc4e021a38..3ab9de6456 100644 * load_image_to_fw_cfg() - Load an image file into an fw_cfg entry identified * by key. diff --git a/hw/core/reset.c b/hw/core/reset.c -index 9c477f2bf5..0efaf2d76c 100644 +index e923723d38..314d332111 100644 --- a/hw/core/reset.c +++ b/hw/core/reset.c -@@ -47,6 +47,31 @@ void qemu_register_reset(QEMUResetHandler *func, void *opaque) +@@ -48,6 +48,31 @@ void qemu_register_reset(QEMUResetHandler *func, void *opaque) QTAILQ_INSERT_TAIL(&reset_handlers, re, entry); } - + +QEMUResetEntry *qemu_get_reset_entry(QEMUResetHandler *func, + void *opaque) +{ @@ -82,13 +82,13 @@ index 9c477f2bf5..0efaf2d76c 100644 { QEMUResetEntry *re; diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h -index c48cc4c2bc..9452ccd1fa 100644 +index ce2b48b88b..c3c4d3ea79 100644 --- a/include/hw/arm/boot.h +++ b/include/hw/arm/boot.h -@@ -118,6 +118,9 @@ struct arm_boot_info { +@@ -119,6 +119,9 @@ struct arm_boot_info { arm_endianness endianness; }; - + +void cpu_hotplug_register_reset(int ncpu); +void cpu_hotplug_reset_manually(int ncpu); + @@ -101,15 +101,16 @@ index 0b0d6d7598..f3ff26c637 100644 +++ b/include/sysemu/reset.h @@ -2,7 +2,11 @@ #define QEMU_SYSEMU_RESET_H - + typedef void QEMUResetHandler(void *opaque); +typedef struct QEMUResetEntry QEMUResetEntry; - + +QEMUResetEntry *qemu_get_reset_entry(QEMUResetHandler *func, void *opaque); +void qemu_register_reset_after(QEMUResetEntry *entry, + QEMUResetHandler *func, void *opaque); void qemu_register_reset(QEMUResetHandler *func, void *opaque); void qemu_unregister_reset(QEMUResetHandler *func, void *opaque); void qemu_devices_reset(void); --- -2.19.1 +-- +2.27.0 + diff --git a/hw-arm-boot.c-Set-NSACR.-CP11-CP10-for-NS-kernel-boo.patch b/hw-arm-boot.c-Set-NSACR.-CP11-CP10-for-NS-kernel-boo.patch deleted file mode 100644 index e7ca51a5deb7146de6d6b05aa1d8391b0c08adac..0000000000000000000000000000000000000000 --- a/hw-arm-boot.c-Set-NSACR.-CP11-CP10-for-NS-kernel-boo.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 220816989c1e3d490d293b8d7ac85dbc41a4c321 Mon Sep 17 00:00:00 2001 -From: Peter Maydell -Date: Fri, 20 Sep 2019 18:40:39 +0100 -Subject: [PATCH] hw/arm/boot.c: Set NSACR.{CP11,CP10} for NS kernel boots - -If we're booting a Linux kernel directly into Non-Secure -state on a CPU which has Secure state, then make sure we -set the NSACR CP11 and CP10 bits, so that Non-Secure is allowed -to access the FPU. Otherwise an AArch32 kernel will UNDEF as -soon as it tries to use the FPU. - -It used to not matter that we didn't do this until commit -fc1120a7f5f2d4b6, where we implemented actually honouring -these NSACR bits. - -The problem only exists for CPUs where EL3 is AArch32; the -equivalent AArch64 trap bits are in CPTR_EL3 and are "0 to -not trap, 1 to trap", so the reset value of the register -permits NS access, unlike NSACR. - -Fixes: fc1120a7f5 -Fixes: https://bugs.launchpad.net/qemu/+bug/1844597 -Cc: qemu-stable@nongnu.org -Signed-off-by: Peter Maydell -Reviewed-by: Richard Henderson -Message-id: 20190920174039.3916-1-peter.maydell@linaro.org -(cherry picked from commit ece628fcf69cbbd4b3efb6fbd203af07609467a2) -Signed-off-by: Michael Roth ---- - hw/arm/boot.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/hw/arm/boot.c b/hw/arm/boot.c -index c2b89b3bb9..fc4e021a38 100644 ---- a/hw/arm/boot.c -+++ b/hw/arm/boot.c -@@ -754,6 +754,8 @@ static void do_cpu_reset(void *opaque) - (cs != first_cpu || !info->secure_board_setup)) { - /* Linux expects non-secure state */ - env->cp15.scr_el3 |= SCR_NS; -+ /* Set NSACR.{CP11,CP10} so NS can access the FPU */ -+ env->cp15.nsacr |= 3 << 10; - } - } - --- -2.23.0 diff --git a/hw-arm-smmu-common-Allow-domain-invalidation-for-NH_.patch b/hw-arm-smmu-common-Allow-domain-invalidation-for-NH_.patch index 1824b8e4fd0fa31603df903bb640065c70858907..d92b5edd5a76cec878d9d7ddb1af9698360280b8 100644 --- a/hw-arm-smmu-common-Allow-domain-invalidation-for-NH_.patch +++ b/hw-arm-smmu-common-Allow-domain-invalidation-for-NH_.patch @@ -1,4 +1,4 @@ -From 8bf9d1dc67335c1fb921a56825f6bf198a568091 Mon Sep 17 00:00:00 2001 +From 876d18c962f0ead31d8458cd7ac19178be78455c Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Fri, 19 Mar 2021 12:22:48 -0400 Subject: [PATCH] hw/arm/smmu-common: Allow domain invalidation for @@ -17,16 +17,16 @@ Signed-off-by: Kunkun Jiang 1 file changed, 1 insertion(+) diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c -index 717d22bcbe..de9468d33f 100644 +index 3a1ecf81d6..2ec4222c93 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c -@@ -395,6 +395,7 @@ static void smmu_unmap_notifier_range(IOMMUNotifier *n) - entry.iova = n->start; - entry.perm = IOMMU_NONE; - entry.addr_mask = n->end - n->start; -+ entry.granularity = IOMMU_INV_GRAN_DOMAIN; +@@ -477,6 +477,7 @@ static void smmu_unmap_notifier_range(IOMMUNotifier *n) + event.entry.iova = n->start; + event.entry.perm = IOMMU_NONE; + event.entry.addr_mask = n->end - n->start; ++ event.entry.granularity = IOMMU_INV_GRAN_DOMAIN; - memory_region_notify_one(n, &entry); + memory_region_notify_iommu_one(n, &event); } -- 2.27.0 diff --git a/hw-arm-smmuv3-Advertise-MSI_TRANSLATE-attribute.patch b/hw-arm-smmuv3-Advertise-MSI_TRANSLATE-attribute.patch index 89f9292287246e65a25587df2da43f2765457312..e8d397824f80fff77c7260bfb4dcec67e410b250 100644 --- a/hw-arm-smmuv3-Advertise-MSI_TRANSLATE-attribute.patch +++ b/hw-arm-smmuv3-Advertise-MSI_TRANSLATE-attribute.patch @@ -1,4 +1,4 @@ -From bc602a4d1355774a0a44e8fbf6dd842049dd63f3 Mon Sep 17 00:00:00 2001 +From 5a759ab19d508361053e388694546216705d173b Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 28 Aug 2018 09:21:53 -0400 Subject: [PATCH] hw/arm/smmuv3: Advertise MSI_TRANSLATE attribute @@ -14,10 +14,10 @@ Signed-off-by: Kunkun Jiang 1 file changed, 3 insertions(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c -index 55eed5189e..83d59b6d28 100644 +index 9b87d16217..12f354a0d5 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c -@@ -1538,6 +1538,9 @@ static int smmuv3_get_attr(IOMMUMemoryRegion *iommu, +@@ -1596,6 +1596,9 @@ static int smmuv3_get_attr(IOMMUMemoryRegion *iommu, if (attr == IOMMU_ATTR_VFIO_NESTED) { *(bool *) data = true; return 0; diff --git a/hw-arm-smmuv3-Allow-MAP-notifiers.patch b/hw-arm-smmuv3-Allow-MAP-notifiers.patch index ec050121fcd57a2e942774ce76fceb8ed5039cf2..1d82532d1262f420e3d4bb39f27579d85f437026 100644 --- a/hw-arm-smmuv3-Allow-MAP-notifiers.patch +++ b/hw-arm-smmuv3-Allow-MAP-notifiers.patch @@ -1,4 +1,4 @@ -From 965729b4875f637dacdbf82960347beb65512d12 Mon Sep 17 00:00:00 2001 +From dc126664134989975ce9ab9e7d5d2c8916628bf6 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Wed, 18 Mar 2020 11:17:36 +0100 Subject: [PATCH] hw/arm/smmuv3: Allow MAP notifiers @@ -14,19 +14,19 @@ Signed-off-by: Kunkun Jiang 1 file changed, 8 deletions(-) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c -index 931d6eae57..c26fba118c 100644 +index 9aeb420428..45f21c53fe 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c -@@ -1563,14 +1563,6 @@ static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu, - SMMUv3State *s3 = sdev->smmu; - SMMUState *s = &(s3->smmu_state); +@@ -1628,14 +1628,6 @@ static int smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu, + return -EINVAL; + } - if (new & IOMMU_NOTIFIER_MAP) { -- int bus_num = pci_bus_num(sdev->bus); -- PCIDevice *pcidev = pci_find_device(sdev->bus, bus_num, sdev->devfn); -- -- warn_report("SMMUv3 does not support notification on MAP: " -- "device %s will not function properly", pcidev->name); +- error_setg(errp, +- "device %02x.%02x.%x requires iommu MAP notifier which is " +- "not currently supported", pci_bus_num(sdev->bus), +- PCI_SLOT(sdev->devfn), PCI_FUNC(sdev->devfn)); +- return -EINVAL; - } - if (old == IOMMU_NOTIFIER_NONE) { diff --git a/hw-arm-smmuv3-Fill-the-IOTLBEntry-arch_id-on-NH_VA-i.patch b/hw-arm-smmuv3-Fill-the-IOTLBEntry-arch_id-on-NH_VA-i.patch index 1f3425e7eddae1fee87d0cb8d86587f4e6011ee5..646a95bd19bab7b28a797433b0321edc45512657 100644 --- a/hw-arm-smmuv3-Fill-the-IOTLBEntry-arch_id-on-NH_VA-i.patch +++ b/hw-arm-smmuv3-Fill-the-IOTLBEntry-arch_id-on-NH_VA-i.patch @@ -1,4 +1,4 @@ -From 8108317641b3cb378bf1862dc3c0a73d1e0976ce Mon Sep 17 00:00:00 2001 +From dcda615b3d9b1acffee3d31d57974cc9e4bd0dee Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 4 Sep 2018 08:48:33 -0400 Subject: [PATCH] hw/arm/smmuv3: Fill the IOTLBEntry arch_id on NH_VA @@ -17,17 +17,17 @@ Signed-off-by: Kunkun Jiang 1 file changed, 2 insertions(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c -index f8e721f949..c6b950af35 100644 +index 3416f6a639..696c588f08 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c -@@ -824,6 +824,8 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, - entry.iova = iova; - entry.addr_mask = (1 << tt->granule_sz) - 1; - entry.perm = IOMMU_NONE; -+ entry.flags = IOMMU_INV_FLAGS_ARCHID; -+ entry.arch_id = asid; +@@ -833,6 +833,8 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, + event.entry.iova = iova; + event.entry.addr_mask = num_pages * (1 << granule) - 1; + event.entry.perm = IOMMU_NONE; ++ event.entry.flags = IOMMU_INV_FLAGS_ARCHID; ++ event.entry.arch_id = asid; - memory_region_notify_one(n, &entry); + memory_region_notify_iommu_one(n, &event); } -- 2.27.0 diff --git a/hw-arm-smmuv3-Fill-the-IOTLBEntry-leaf-field-on-NH_V.patch b/hw-arm-smmuv3-Fill-the-IOTLBEntry-leaf-field-on-NH_V.patch index febaffaa655ecbe70419d692e586e56b1561f330..f5f3db19ea9ca70944d1da3be402ce800226d08c 100644 --- a/hw-arm-smmuv3-Fill-the-IOTLBEntry-leaf-field-on-NH_V.patch +++ b/hw-arm-smmuv3-Fill-the-IOTLBEntry-leaf-field-on-NH_V.patch @@ -1,4 +1,4 @@ -From 6393ad5c1ba6a04b038d80ecc1e663ad91ed0d21 Mon Sep 17 00:00:00 2001 +From c219274b7b6a472d7340a4f72a052ba33ed19659 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 14 Mar 2019 09:55:13 -0400 Subject: [PATCH] hw/arm/smmuv3: Fill the IOTLBEntry leaf field on NH_VA @@ -12,70 +12,66 @@ penalties in nested mode. Signed-off-by: Eric Auger Signed-off-by: Kunkun Jiang --- - hw/arm/smmuv3.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) + hw/arm/smmuv3.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c -index c6b950af35..c1caa6bc3a 100644 +index 696c588f08..ad816e850c 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c -@@ -795,7 +795,7 @@ epilogue: +@@ -800,7 +800,7 @@ epilogue: static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, IOMMUNotifier *n, - int asid, -- dma_addr_t iova) -+ dma_addr_t iova, bool leaf) + int asid, dma_addr_t iova, +- uint8_t tg, uint64_t num_pages) ++ uint8_t tg, uint64_t num_pages, bool leaf) { SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu); - SMMUEventInfo event = {}; -@@ -826,6 +826,7 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, - entry.perm = IOMMU_NONE; - entry.flags = IOMMU_INV_FLAGS_ARCHID; - entry.arch_id = asid; -+ entry.leaf = leaf; + IOMMUTLBEvent event = {}; +@@ -835,6 +835,7 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, + event.entry.perm = IOMMU_NONE; + event.entry.flags = IOMMU_INV_FLAGS_ARCHID; + event.entry.arch_id = asid; ++ event.entry.leaf = leaf; - memory_region_notify_one(n, &entry); - } -@@ -854,7 +855,8 @@ static void smmuv3_notify_asid(IOMMUMemoryRegion *mr, + memory_region_notify_iommu_one(n, &event); } +@@ -866,7 +867,7 @@ static void smmuv3_notify_asid(IOMMUMemoryRegion *mr, - /* invalidate an asid/iova tuple in all mr's */ --static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova) -+static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova, -+ bool leaf) + /* invalidate an asid/iova range tuple in all mr's */ + static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova, +- uint8_t tg, uint64_t num_pages) ++ uint8_t tg, uint64_t num_pages, bool leaf) { SMMUDevice *sdev; -@@ -865,7 +867,7 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova) - trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova); +@@ -878,7 +879,7 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova, + tg, num_pages); IOMMU_NOTIFIER_FOREACH(n, mr) { -- smmuv3_notify_iova(mr, n, asid, iova); -+ smmuv3_notify_iova(mr, n, asid, iova, leaf); +- smmuv3_notify_iova(mr, n, asid, iova, tg, num_pages); ++ smmuv3_notify_iova(mr, n, asid, iova, tg, num_pages, leaf); } } } -@@ -1018,9 +1020,10 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) - { - dma_addr_t addr = CMD_ADDR(&cmd); - uint16_t vmid = CMD_VMID(&cmd); -+ bool leaf = CMD_LEAF(&cmd); +@@ -903,7 +904,7 @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd) - trace_smmuv3_cmdq_tlbi_nh_vaa(vmid, addr); -- smmuv3_inv_notifiers_iova(bs, -1, addr); -+ smmuv3_inv_notifiers_iova(bs, -1, addr, leaf); - smmu_iotlb_inv_all(bs); - break; - } -@@ -1032,7 +1035,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) - bool leaf = CMD_LEAF(&cmd); + if (!tg) { + trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, 1, ttl, leaf); +- smmuv3_inv_notifiers_iova(s, asid, addr, tg, 1); ++ smmuv3_inv_notifiers_iova(s, asid, addr, tg, 1, leaf); + smmu_iotlb_inv_iova(s, asid, addr, tg, 1, ttl); + return; + } +@@ -921,7 +922,7 @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd) - trace_smmuv3_cmdq_tlbi_nh_va(vmid, asid, addr, leaf); -- smmuv3_inv_notifiers_iova(bs, asid, addr); -+ smmuv3_inv_notifiers_iova(bs, asid, addr, leaf); - smmu_iotlb_inv_iova(bs, asid, addr); - break; - } + num_pages = (mask + 1) >> granule; + trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf); +- smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages); ++ smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages, leaf); + smmu_iotlb_inv_iova(s, asid, addr, tg, num_pages, ttl); + addr += mask + 1; + } -- 2.27.0 diff --git a/hw-arm-smmuv3-Implement-fault-injection.patch b/hw-arm-smmuv3-Implement-fault-injection.patch index 0260e28a05e7d30ec2b637eadb2251890c7e3701..5ecb6da751ece0b759505e47ea49e254234787ef 100644 --- a/hw-arm-smmuv3-Implement-fault-injection.patch +++ b/hw-arm-smmuv3-Implement-fault-injection.patch @@ -1,4 +1,4 @@ -From 55bfd18b7671c82705d83d543281add0afcda31f Mon Sep 17 00:00:00 2001 +From d31c754470b4b651d0e19c66738fbcc8fc6abf3c Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 13 Sep 2018 14:24:45 +0200 Subject: [PATCH] hw/arm/smmuv3: Implement fault injection @@ -14,10 +14,10 @@ Signed-off-by: Kunkun Jiang 1 file changed, 71 insertions(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c -index 3d2151857d..931d6eae57 100644 +index 58139f707d..9aeb420428 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c -@@ -1594,6 +1594,76 @@ static int smmuv3_get_attr(IOMMUMemoryRegion *iommu, +@@ -1660,6 +1660,76 @@ static int smmuv3_get_attr(IOMMUMemoryRegion *iommu, return -EINVAL; } @@ -94,7 +94,7 @@ index 3d2151857d..931d6eae57 100644 static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass, void *data) { -@@ -1602,6 +1672,7 @@ static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass, +@@ -1668,6 +1738,7 @@ static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass, imrc->translate = smmuv3_translate; imrc->notify_flag_changed = smmuv3_notify_flag_changed; imrc->get_attr = smmuv3_get_attr; diff --git a/hw-arm-smmuv3-Improve-stage1-ASID-invalidation.patch b/hw-arm-smmuv3-Improve-stage1-ASID-invalidation.patch index 10639e89f957b970b78f2c0de930ad8b92032d0f..505bec39045c01a65e90863f940dc28011f7b400 100644 --- a/hw-arm-smmuv3-Improve-stage1-ASID-invalidation.patch +++ b/hw-arm-smmuv3-Improve-stage1-ASID-invalidation.patch @@ -1,4 +1,4 @@ -From c0027c2e744c8ed99e937d3cbc88f400ab63a316 Mon Sep 17 00:00:00 2001 +From de53feaa37a267a21ed30a642e1e64c5fcfbc4a4 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Sun, 14 Feb 2021 12:30:57 -0500 Subject: [PATCH] hw/arm/smmuv3: Improve stage1 ASID invalidation @@ -17,16 +17,16 @@ do not support the new fields, like VHOST. Signed-off-by: Eric Auger Signed-off-by: Kunkun Jiang --- - hw/arm/smmuv3.c | 42 ++++++++++++++++++++++++++++++++++++++++-- + hw/arm/smmuv3.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- hw/arm/trace-events | 1 + - 2 files changed, 41 insertions(+), 2 deletions(-) + 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c -index 3b5723e1e1..0ef1ca376c 100644 +index 94e2c658f8..da5dac1ba5 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c -@@ -827,6 +827,29 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, - memory_region_notify_one(n, &entry); +@@ -836,6 +836,31 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, + memory_region_notify_iommu_one(n, &event); } +/** @@ -39,24 +39,26 @@ index 3b5723e1e1..0ef1ca376c 100644 +static void smmuv3_notify_asid(IOMMUMemoryRegion *mr, + IOMMUNotifier *n, int asid) +{ -+ IOMMUTLBEntry entry; ++ IOMMUTLBEvent event = {}; + -+ entry.target_as = &address_space_memory; -+ entry.perm = IOMMU_NONE; -+ entry.granularity = IOMMU_INV_GRAN_PASID; -+ entry.flags = IOMMU_INV_FLAGS_ARCHID; -+ entry.arch_id = asid; -+ entry.iova = n->start; -+ entry.addr_mask = n->end - n->start; ++ event.type = IOMMU_NOTIFIER_UNMAP; ++ event.entry.target_as = &address_space_memory; ++ event.entry.perm = IOMMU_NONE; ++ event.entry.granularity = IOMMU_INV_GRAN_PASID; ++ event.entry.flags = IOMMU_INV_FLAGS_ARCHID; ++ event.entry.arch_id = asid; ++ event.entry.iova = n->start; ++ event.entry.addr_mask = n->end - n->start; + -+ memory_region_notify_one(n, &entry); ++ memory_region_notify_iommu_one(n, &event); +} + - /* invalidate an asid/iova tuple in all mr's */ - static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova) - { -@@ -844,6 +867,22 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova) - } ++ + /* invalidate an asid/iova range tuple in all mr's */ + static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova, + uint8_t tg, uint64_t num_pages) +@@ -913,6 +938,22 @@ smmuv3_invalidate_ste(gpointer key, gpointer value, gpointer user_data) + return true; } +static void smmuv3_s1_asid_inval(SMMUState *s, uint16_t asid) @@ -78,7 +80,7 @@ index 3b5723e1e1..0ef1ca376c 100644 static int smmuv3_cmdq_consume(SMMUv3State *s) { SMMUState *bs = ARM_SMMU(s); -@@ -963,8 +1002,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) +@@ -1027,8 +1068,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) uint16_t asid = CMD_ASID(&cmd); trace_smmuv3_cmdq_tlbi_nh_asid(asid); @@ -89,17 +91,17 @@ index 3b5723e1e1..0ef1ca376c 100644 } case SMMU_CMD_TLBI_NH_ALL: diff --git a/hw/arm/trace-events b/hw/arm/trace-events -index 0acedcedc6..4512d20115 100644 +index 2dee296c8f..1447ad5a90 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events -@@ -44,6 +44,7 @@ smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t p - smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid %d (hits=%d, misses=%d, hit rate=%d)" - smmuv3_cmdq_tlbi_nh_va(int vmid, int asid, uint64_t addr, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" leaf=%d" - smmuv3_cmdq_tlbi_nh_vaa(int vmid, uint64_t addr) "vmid =%d addr=0x%"PRIx64 +@@ -46,6 +46,7 @@ smmuv3_cmdq_cfgi_cd(uint32_t sid) "sid=0x%x" + smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid=0x%x (hits=%d, misses=%d, hit rate=%d)" + smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid=0x%x (hits=%d, misses=%d, hit rate=%d)" + smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, uint8_t tg, uint64_t num_pages, uint8_t ttl, bool leaf) "vmid=%d asid=%d addr=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" ttl=%d leaf=%d" +smmuv3_s1_asid_inval(int asid) "asid=%d" smmuv3_cmdq_tlbi_nh(void) "" smmuv3_cmdq_tlbi_nh_asid(uint16_t asid) "asid=%d" - smmu_iotlb_cache_hit(uint16_t asid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache HIT asid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d" + smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x" -- 2.27.0 diff --git a/hw-arm-smmuv3-Pass-stage-1-configurations-to-the-hos.patch b/hw-arm-smmuv3-Pass-stage-1-configurations-to-the-hos.patch index a615b8664bd6b9c3603073bfd7ec0bb505e70ef8..012c5d0071dc9f1bce50e706958e55fb443230d2 100644 --- a/hw-arm-smmuv3-Pass-stage-1-configurations-to-the-hos.patch +++ b/hw-arm-smmuv3-Pass-stage-1-configurations-to-the-hos.patch @@ -1,4 +1,4 @@ -From d0a1ce3c46246b6ef5510ac1d5c18308417ed525 Mon Sep 17 00:00:00 2001 +From 2e5929ec2a35a7a227dc7ba70a557a84993a366d Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 9 Aug 2018 21:04:19 +0200 Subject: [PATCH] hw/arm/smmuv3: Pass stage 1 configurations to the host @@ -12,12 +12,25 @@ to the host and apply it at physical level. Signed-off-by: Eric Auger Signed-off-by: Kunkun Jiang --- - hw/arm/smmuv3.c | 77 +++++++++++++++++++++++++++++++++++---------- - hw/arm/trace-events | 2 +- - 2 files changed, 61 insertions(+), 18 deletions(-) + hw/arm/smmu-internal.h | 1 + + hw/arm/smmuv3.c | 71 ++++++++++++++++++++++++++++++++++++------ + hw/arm/trace-events | 1 + + 3 files changed, 64 insertions(+), 9 deletions(-) +diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h +index 2d75b31953..5ef8c598c6 100644 +--- a/hw/arm/smmu-internal.h ++++ b/hw/arm/smmu-internal.h +@@ -105,6 +105,7 @@ typedef struct SMMUIOTLBPageInvInfo { + } SMMUIOTLBPageInvInfo; + + typedef struct SMMUSIDRange { ++ SMMUState *state; + uint32_t start; + uint32_t end; + } SMMUSIDRange; diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c -index c1caa6bc3a..3d2151857d 100644 +index ad816e850c..58139f707d 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -16,6 +16,10 @@ @@ -29,9 +42,9 @@ index c1caa6bc3a..3d2151857d 100644 +#endif + #include "qemu/osdep.h" - #include "hw/boards.h" - #include "sysemu/sysemu.h" -@@ -872,6 +876,60 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova, + #include "qemu/bitops.h" + #include "hw/irq.h" +@@ -928,6 +932,61 @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd) } } @@ -39,7 +52,8 @@ index c1caa6bc3a..3d2151857d 100644 +{ +#ifdef __linux__ + IOMMUMemoryRegion *mr = smmu_iommu_mr(bs, sid); -+ SMMUEventInfo event = {.type = SMMU_EVT_NONE, .sid = sid}; ++ SMMUEventInfo event = {.type = SMMU_EVT_NONE, .sid = sid, ++ .inval_ste_allowed = true}; + IOMMUConfig iommu_config = {}; + SMMUTransCfg *cfg; + SMMUDevice *sdev; @@ -89,10 +103,18 @@ index c1caa6bc3a..3d2151857d 100644 +#endif +} + - static void smmuv3_s1_asid_inval(SMMUState *s, uint16_t asid) + static gboolean + smmuv3_invalidate_ste(gpointer key, gpointer value, gpointer user_data) { - SMMUDevice *sdev; -@@ -938,22 +996,14 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) +@@ -938,6 +997,7 @@ smmuv3_invalidate_ste(gpointer key, gpointer value, gpointer user_data) + if (sid < sid_range->start || sid > sid_range->end) { + return false; + } ++ smmuv3_notify_config_change(sid_range->state, sid); + trace_smmuv3_config_cache_inv(sid); + return true; + } +@@ -1008,22 +1068,14 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) case SMMU_CMD_CFGI_STE: { uint32_t sid = CMD_SID(&cmd); @@ -116,32 +138,24 @@ index c1caa6bc3a..3d2151857d 100644 break; } case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */ -@@ -970,14 +1020,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) - trace_smmuv3_cmdq_cfgi_ste_range(start, end); - - for (i = start; i <= end; i++) { -- IOMMUMemoryRegion *mr = smmu_iommu_mr(bs, i); -- SMMUDevice *sdev; -- -- if (!mr) { -- continue; -- } -- sdev = container_of(mr, SMMUDevice, iommu); -- smmuv3_flush_config(sdev); -+ smmuv3_notify_config_change(bs, i); +@@ -1038,6 +1090,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) } - break; - } + + mask = (1ULL << (range + 1)) - 1; ++ sid_range.state = bs; + sid_range.start = sid & ~mask; + sid_range.end = sid_range.start + mask; + diff --git a/hw/arm/trace-events b/hw/arm/trace-events -index 4512d20115..cbbe2ccafd 100644 +index 1447ad5a90..d9851d663e 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events -@@ -53,4 +53,4 @@ smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid %d" +@@ -53,4 +53,5 @@ smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x" smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s" smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s" - smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova) "iommu mr=%s asid=%d iova=0x%"PRIx64 -- + smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova, uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64 +smmuv3_notify_config_change(const char *name, uint8_t config, uint64_t s1ctxptr) "iommu mr=%s config=%d s1ctxptr=0x%"PRIx64 + -- 2.27.0 diff --git a/hw-arm-smmuv3-Post-load-stage-1-configurations-to-th.patch b/hw-arm-smmuv3-Post-load-stage-1-configurations-to-th.patch index c363acb60c0fce72a986b6056aa74bb578b7a992..0fc5f84460a60655713b48766bed2b7599042431 100644 --- a/hw-arm-smmuv3-Post-load-stage-1-configurations-to-th.patch +++ b/hw-arm-smmuv3-Post-load-stage-1-configurations-to-th.patch @@ -1,4 +1,4 @@ -From 06e43bc658aa80bb5f4da3e43c1c13d4cab6ebdd Mon Sep 17 00:00:00 2001 +From 1b95c995f032c21bf6607dda8ede0f5856bb190a Mon Sep 17 00:00:00 2001 From: Kunkun Jiang Date: Tue, 11 May 2021 10:08:16 +0800 Subject: [PATCH] hw/arm/smmuv3: Post-load stage 1 configurations to the host @@ -17,10 +17,10 @@ Signed-off-by: Kunkun Jiang 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c -index c26fba118c..f383143db1 100644 +index 45f21c53fe..291e3a12e8 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c -@@ -876,7 +876,7 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova, +@@ -932,7 +932,7 @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd) } } @@ -29,7 +29,7 @@ index c26fba118c..f383143db1 100644 { #ifdef __linux__ IOMMUMemoryRegion *mr = smmu_iommu_mr(bs, sid); -@@ -884,9 +884,10 @@ static void smmuv3_notify_config_change(SMMUState *bs, uint32_t sid) +@@ -941,9 +941,10 @@ static void smmuv3_notify_config_change(SMMUState *bs, uint32_t sid) IOMMUConfig iommu_config = {}; SMMUTransCfg *cfg; SMMUDevice *sdev; @@ -41,7 +41,7 @@ index c26fba118c..f383143db1 100644 } sdev = container_of(mr, SMMUDevice, iommu); -@@ -895,13 +896,13 @@ static void smmuv3_notify_config_change(SMMUState *bs, uint32_t sid) +@@ -952,13 +953,13 @@ static void smmuv3_notify_config_change(SMMUState *bs, uint32_t sid) smmuv3_flush_config(sdev); if (!pci_device_is_pasid_ops_set(sdev->bus, sdev->devfn)) { @@ -57,7 +57,7 @@ index c26fba118c..f383143db1 100644 } iommu_config.pasid_cfg.argsz = sizeof(struct iommu_pasid_table_config); -@@ -923,10 +924,13 @@ static void smmuv3_notify_config_change(SMMUState *bs, uint32_t sid) +@@ -980,10 +981,13 @@ static void smmuv3_notify_config_change(SMMUState *bs, uint32_t sid) iommu_config.pasid_cfg.config, iommu_config.pasid_cfg.base_ptr); @@ -72,7 +72,7 @@ index c26fba118c..f383143db1 100644 #endif } -@@ -1494,6 +1498,24 @@ static void smmu_realize(DeviceState *d, Error **errp) +@@ -1553,6 +1557,24 @@ static void smmu_realize(DeviceState *d, Error **errp) smmu_init_irq(s, dev); } @@ -97,7 +97,7 @@ index c26fba118c..f383143db1 100644 static const VMStateDescription vmstate_smmuv3_queue = { .name = "smmuv3_queue", .version_id = 1, -@@ -1512,6 +1534,7 @@ static const VMStateDescription vmstate_smmuv3 = { +@@ -1571,6 +1593,7 @@ static const VMStateDescription vmstate_smmuv3 = { .version_id = 1, .minimum_version_id = 1, .priority = MIG_PRI_IOMMU, diff --git a/hw-arm-smmuv3-Set-the-restoration-priority-of-the-vS.patch b/hw-arm-smmuv3-Set-the-restoration-priority-of-the-vS.patch deleted file mode 100644 index 1139feaed62705a6baebbecba25ad0355b761daf..0000000000000000000000000000000000000000 --- a/hw-arm-smmuv3-Set-the-restoration-priority-of-the-vS.patch +++ /dev/null @@ -1,33 +0,0 @@ -From eceb9213e23d15d5b4342b6a6a8368f4fec60c2f Mon Sep 17 00:00:00 2001 -From: Zenghui Yu -Date: Mon, 19 Oct 2020 17:15:08 +0800 -Subject: [PATCH] hw/arm/smmuv3: Set the restoration priority of the vSMMUv3 - explicitly - -Ensure the vSMMUv3 will be restored before all PCIe devices so that DMA -translation can work properly during migration. - -Signed-off-by: Zenghui Yu -Message-id: 20201019091508.197-1-yuzenghui@huawei.com -Acked-by: Eric Auger -Signed-off-by: Peter Maydell -Signed-off-by: Kunkun Jiang ---- - hw/arm/smmuv3.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c -index 7911944c59..3b5723e1e1 100644 ---- a/hw/arm/smmuv3.c -+++ b/hw/arm/smmuv3.c -@@ -1424,6 +1424,7 @@ static const VMStateDescription vmstate_smmuv3 = { - .name = "smmuv3", - .version_id = 1, - .minimum_version_id = 1, -+ .priority = MIG_PRI_IOMMU, - .fields = (VMStateField[]) { - VMSTATE_UINT32(features, SMMUv3State), - VMSTATE_UINT8(sid_size, SMMUv3State), --- -2.27.0 - diff --git a/hw-arm-smmuv3-Store-the-PASID-table-GPA-in-the-trans.patch b/hw-arm-smmuv3-Store-the-PASID-table-GPA-in-the-trans.patch index 8ed3590b6e3c3863486db0082be983a7b7d4968c..3bbf1dadc18e41dbfe5859f337c79d42ef557c0b 100644 --- a/hw-arm-smmuv3-Store-the-PASID-table-GPA-in-the-trans.patch +++ b/hw-arm-smmuv3-Store-the-PASID-table-GPA-in-the-trans.patch @@ -1,4 +1,4 @@ -From 6fc85d8a6022d94ffec4cc118472cde583706bfb Mon Sep 17 00:00:00 2001 +From f937ce4124d57eea27d516957a2efa0e7fbdf198 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 9 Aug 2018 20:56:44 +0200 Subject: [PATCH] hw/arm/smmuv3: Store the PASID table GPA in the translation @@ -17,10 +17,10 @@ Signed-off-by: Kunkun Jiang 2 files changed, 2 insertions(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c -index 83d59b6d28..f8e721f949 100644 +index 12f354a0d5..3416f6a639 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c -@@ -352,6 +352,7 @@ static int decode_ste(SMMUv3State *s, SMMUTransCfg *cfg, +@@ -358,6 +358,7 @@ static int decode_ste(SMMUv3State *s, SMMUTransCfg *cfg, "SMMUv3 S1 stalling fault model not allowed yet\n"); goto bad_ste; } @@ -29,10 +29,10 @@ index 83d59b6d28..f8e721f949 100644 bad_ste: diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h -index 1f37844e5c..353668f4ea 100644 +index 706be3c6d0..d578339935 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h -@@ -68,6 +68,7 @@ typedef struct SMMUTransCfg { +@@ -76,6 +76,7 @@ typedef struct SMMUTransCfg { uint8_t tbi; /* Top Byte Ignore */ uint16_t asid; SMMUTransTableInfo tt[2]; diff --git a/hw-arm-smmuv3-Support-16K-translation-granule.patch b/hw-arm-smmuv3-Support-16K-translation-granule.patch deleted file mode 100644 index 08c4bc5603401f6e5735daa6767dfa2aa2785255..0000000000000000000000000000000000000000 --- a/hw-arm-smmuv3-Support-16K-translation-granule.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 008dec30dea19950ff48a34c54441d065c1f228b Mon Sep 17 00:00:00 2001 -From: Kunkun Jiang -Date: Wed, 31 Mar 2021 14:47:13 +0800 -Subject: [PATCH] hw/arm/smmuv3: Support 16K translation granule - -The driver can query some bits in SMMUv3 IDR5 to learn which -translation granules are supported. Arm recommends that SMMUv3 -implementations support at least 4K and 64K granules. But in -the vSMMUv3, there seems to be no reason not to support 16K -translation granule. In addition, if 16K is not supported, -vSVA will failed to be enabled in the future for 16K guest -kernel. So it'd better to support it. - -Signed-off-by: Kunkun Jiang -Reviewed-by: Eric Auger -Tested-by: Eric Auger -Signed-off-by: Peter Maydell ---- - hw/arm/smmuv3.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c -index e96d5beb9a..7911944c59 100644 ---- a/hw/arm/smmuv3.c -+++ b/hw/arm/smmuv3.c -@@ -254,8 +254,9 @@ static void smmuv3_init_regs(SMMUv3State *s) - s->idr[1] = FIELD_DP32(s->idr[1], IDR1, EVENTQS, SMMU_EVENTQS); - s->idr[1] = FIELD_DP32(s->idr[1], IDR1, CMDQS, SMMU_CMDQS); - -- /* 4K and 64K granule support */ -+ /* 4K, 16K and 64K granule support */ - s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN4K, 1); -+ s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN16K, 1); - s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN64K, 1); - s->idr[5] = FIELD_DP32(s->idr[5], IDR5, OAS, SMMU_IDR5_OAS); /* 44 bits */ - -@@ -480,7 +481,8 @@ static int decode_cd(SMMUTransCfg *cfg, CD *cd, SMMUEventInfo *event) - - tg = CD_TG(cd, i); - tt->granule_sz = tg2granule(tg, i); -- if ((tt->granule_sz != 12 && tt->granule_sz != 16) || CD_ENDI(cd)) { -+ if ((tt->granule_sz != 12 && tt->granule_sz != 14 && -+ tt->granule_sz != 16) || CD_ENDI(cd)) { - goto bad_cd; - } - --- -2.27.0 - diff --git a/hw-arm-virt-Add-memory-hotplug-framework.patch b/hw-arm-virt-Add-memory-hotplug-framework.patch deleted file mode 100644 index dcb0f21f5b63e10636d889f6cae99a4d738d1d0e..0000000000000000000000000000000000000000 --- a/hw-arm-virt-Add-memory-hotplug-framework.patch +++ /dev/null @@ -1,130 +0,0 @@ -From e14fadc66d488ad10a10a2076721b72cc239ded9 Mon Sep 17 00:00:00 2001 -From: Eric Auger -Date: Wed, 18 Sep 2019 14:06:26 +0100 -Subject: [PATCH] hw/arm/virt: Add memory hotplug framework - -This patch adds the memory hot-plug/hot-unplug infrastructure -in machvirt. The device memory is not yet exposed to the Guest -either through DT or ACPI and hence both cold/hot plug of memory -is explicitly disabled for now. - -Signed-off-by: Eric Auger -Signed-off-by: Kwangwoo Lee -Signed-off-by: Shameer Kolothum -Reviewed-by: Peter Maydell -Reviewed-by: Igor Mammedov -Message-Id: <20190918130633.4872-5-shameerali.kolothum.thodi@huawei.com> -Acked-by: Peter Maydell -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin ---- - hw/arm/Kconfig | 2 ++ - hw/arm/virt.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 54 insertions(+), 1 deletion(-) - -diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig -index ab65ecd216..84961c17ab 100644 ---- a/hw/arm/Kconfig -+++ b/hw/arm/Kconfig -@@ -20,6 +20,8 @@ config ARM_VIRT - select SMBIOS - select VIRTIO_MMIO - select ACPI_PCI -+ select MEM_DEVICE -+ select DIMM - - config CHEETAH - bool -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 23d72aed97..c7c07fe3ac 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -65,6 +65,8 @@ - #include "hw/arm/smmuv3.h" - #include "hw/acpi/acpi.h" - #include "target/arm/internals.h" -+#include "hw/mem/pc-dimm.h" -+#include "hw/mem/nvdimm.h" - - #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ - static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ -@@ -1998,6 +2000,42 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) - return ms->possible_cpus; - } - -+static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, -+ Error **errp) -+{ -+ -+ /* -+ * The device memory is not yet exposed to the Guest either through -+ * DT or ACPI and hence both cold/hot plug of memory is explicitly -+ * disabled for now. -+ */ -+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -+ error_setg(errp, "memory cold/hot plug is not yet supported"); -+ return; -+ } -+ -+ pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), NULL, errp); -+} -+ -+static void virt_memory_plug(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); -+ Error *local_err = NULL; -+ -+ pc_dimm_plug(PC_DIMM(dev), MACHINE(vms), &local_err); -+ -+ error_propagate(errp, local_err); -+} -+ -+static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -+ virt_memory_pre_plug(hotplug_dev, dev, errp); -+ } -+} -+ - static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) - { -@@ -2009,12 +2047,23 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, - SYS_BUS_DEVICE(dev)); - } - } -+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -+ virt_memory_plug(hotplug_dev, dev, errp); -+ } -+} -+ -+static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, -+ DeviceState *dev, Error **errp) -+{ -+ error_setg(errp, "device unplug request for unsupported device" -+ " type: %s", object_get_typename(OBJECT(dev))); - } - - static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, - DeviceState *dev) - { -- if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE)) { -+ if (object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE) || -+ (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM))) { - return HOTPLUG_HANDLER(machine); - } - -@@ -2078,7 +2127,9 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) - mc->kvm_type = virt_kvm_type; - assert(!mc->get_hotplug_handler); - mc->get_hotplug_handler = virt_machine_get_hotplug_handler; -+ hc->pre_plug = virt_machine_device_pre_plug_cb; - hc->plug = virt_machine_device_plug_cb; -+ hc->unplug_request = virt_machine_device_unplug_request_cb; - mc->numa_mem_supported = true; - } - --- -2.19.1 diff --git a/hw-arm-virt-Assign-virt_madt_cpu_entry-to-acpi_ged-m.patch b/hw-arm-virt-Assign-virt_madt_cpu_entry-to-acpi_ged-m.patch new file mode 100644 index 0000000000000000000000000000000000000000..71aea39369b48af8680a8071e2234860adfb77a1 --- /dev/null +++ b/hw-arm-virt-Assign-virt_madt_cpu_entry-to-acpi_ged-m.patch @@ -0,0 +1,40 @@ +From ae74dda87e172ce82a8180d1a2e9c62904390f91 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 10 Apr 2020 10:05:54 +0800 +Subject: [PATCH] hw/arm/virt: Assign virt_madt_cpu_entry to acpi_ged madt_cpu + hook + +In build_cpus_aml, we will invoke this hook to build _MAT +aml mehtod for cpus. + +Signed-off-by: Keqian Zhu +Signed-off-by: Salil Mehta +--- + hw/arm/virt.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 47e98f09e8..44c29070c4 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -684,6 +684,7 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms) + static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + { + DeviceState *dev; ++ AcpiDeviceIfClass *adevc; + MachineState *ms = MACHINE(vms); + int irq = vms->irqmap[VIRT_ACPI_GED]; + uint32_t event = ACPI_GED_PWR_DOWN_EVT; +@@ -699,6 +700,9 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms) + dev = qdev_new(TYPE_ACPI_GED); + qdev_prop_set_uint32(dev, "ged-event", event); + ++ adevc = ACPI_DEVICE_IF_GET_CLASS(dev); ++ adevc->madt_cpu = virt_madt_cpu_entry; ++ + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq)); +-- +2.27.0 + diff --git a/hw-arm-virt-Enable-device-memory-cold-hot-plug-with-.patch b/hw-arm-virt-Enable-device-memory-cold-hot-plug-with-.patch deleted file mode 100644 index b32b2a01929189ff6f89e94f011d4d9cc3811a3b..0000000000000000000000000000000000000000 --- a/hw-arm-virt-Enable-device-memory-cold-hot-plug-with-.patch +++ /dev/null @@ -1,252 +0,0 @@ -From ce813d8daa2e01df52509f4bb52b9ab774408706 Mon Sep 17 00:00:00 2001 -From: Shameer Kolothum -Date: Wed, 18 Sep 2019 14:06:27 +0100 -Subject: [PATCH] hw/arm/virt: Enable device memory cold/hot plug with ACPI - boot - -This initializes the GED device with base memory and irq, configures -ged memory hotplug event and builds the corresponding aml code. With -this, both hot and cold plug of device memory is enabled now for Guest -with ACPI boot. Memory cold plug support with Guest DT boot is not yet -supported. - -As DSDT table gets changed by this, update bios-tables-test-allowed-diff.h -to avoid "make check" failure. - -Signed-off-by: Shameer Kolothum -Message-Id: <20190918130633.4872-6-shameerali.kolothum.thodi@huawei.com> -Acked-by: Peter Maydell -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Reviewed-by: Igor Mammedov ---- - hw/arm/Kconfig | 2 ++ - hw/arm/virt-acpi-build.c | 21 ++++++++++++++ - hw/arm/virt.c | 59 +++++++++++++++++++++++++++++++++++----- - include/hw/arm/virt.h | 4 +++ - 4 files changed, 79 insertions(+), 7 deletions(-) - -diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig -index 84961c17ab..ad7f7c089b 100644 ---- a/hw/arm/Kconfig -+++ b/hw/arm/Kconfig -@@ -22,6 +22,8 @@ config ARM_VIRT - select ACPI_PCI - select MEM_DEVICE - select DIMM -+ select ACPI_MEMORY_HOTPLUG -+ select ACPI_HW_REDUCED - - config CHEETAH - bool -diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c -index fe54411f6a..fca53ae01f 100644 ---- a/hw/arm/virt-acpi-build.c -+++ b/hw/arm/virt-acpi-build.c -@@ -40,6 +40,8 @@ - #include "hw/acpi/aml-build.h" - #include "hw/acpi/utils.h" - #include "hw/acpi/pci.h" -+#include "hw/acpi/memory_hotplug.h" -+#include "hw/acpi/generic_event_device.h" - #include "hw/pci/pcie_host.h" - #include "hw/pci/pci.h" - #include "hw/arm/virt.h" -@@ -779,6 +781,7 @@ static void - build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) - { - Aml *scope, *dsdt; -+ MachineState *ms = MACHINE(vms); - const MemMapEntry *memmap = vms->memmap; - const int *irqmap = vms->irqmap; - -@@ -803,6 +806,24 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) - vms->highmem, vms->highmem_ecam); - acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], - (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); -+ if (vms->acpi_dev) { -+ build_ged_aml(scope, "\\_SB."GED_DEVICE, -+ HOTPLUG_HANDLER(vms->acpi_dev), -+ irqmap[VIRT_ACPI_GED] + ARM_SPI_BASE, AML_SYSTEM_MEMORY, -+ memmap[VIRT_ACPI_GED].base); -+ } -+ -+ if (vms->acpi_dev) { -+ uint32_t event = object_property_get_uint(OBJECT(vms->acpi_dev), -+ "ged-event", &error_abort); -+ -+ if (event & ACPI_GED_MEM_HOTPLUG_EVT) { -+ build_memory_hotplug_aml(scope, ms->ram_slots, "\\_SB", NULL, -+ AML_SYSTEM_MEMORY, -+ memmap[VIRT_PCDIMM_ACPI].base); -+ } -+ } -+ - acpi_dsdt_add_power_button(scope); - - aml_append(dsdt, scope); -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index c7c07fe3ac..8ccabd5159 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -67,6 +67,7 @@ - #include "target/arm/internals.h" - #include "hw/mem/pc-dimm.h" - #include "hw/mem/nvdimm.h" -+#include "hw/acpi/generic_event_device.h" - - #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ - static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ -@@ -137,6 +138,8 @@ static const MemMapEntry base_memmap[] = { - [VIRT_GPIO] = { 0x09030000, 0x00001000 }, - [VIRT_SECURE_UART] = { 0x09040000, 0x00001000 }, - [VIRT_SMMU] = { 0x09050000, 0x00020000 }, -+ [VIRT_PCDIMM_ACPI] = { 0x09070000, MEMORY_HOTPLUG_IO_LEN }, -+ [VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN }, - [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, - [VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 }, - /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ -@@ -173,6 +176,7 @@ static const int a15irqmap[] = { - [VIRT_PCIE] = 3, /* ... to 6 */ - [VIRT_GPIO] = 7, - [VIRT_SECURE_UART] = 8, -+ [VIRT_ACPI_GED] = 9, - [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */ - [VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */ - [VIRT_SMMU] = 74, /* ...to 74 + NUM_SMMU_IRQS - 1 */ -@@ -630,6 +634,29 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms) - } - } - -+static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic) -+{ -+ DeviceState *dev; -+ MachineState *ms = MACHINE(vms); -+ int irq = vms->irqmap[VIRT_ACPI_GED]; -+ uint32_t event = 0; -+ -+ if (ms->ram_slots) { -+ event = ACPI_GED_MEM_HOTPLUG_EVT; -+ } -+ -+ dev = qdev_create(NULL, TYPE_ACPI_GED); -+ qdev_prop_set_uint32(dev, "ged-event", event); -+ -+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); -+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); -+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irq]); -+ -+ qdev_init_nofail(dev); -+ -+ return dev; -+} -+ - static void create_its(VirtMachineState *vms, DeviceState *gicdev) - { - const char *itsclass = its_class_name(); -@@ -1603,6 +1630,7 @@ static void machvirt_init(MachineState *machine) - MemoryRegion *ram = g_new(MemoryRegion, 1); - bool firmware_loaded; - bool aarch64 = true; -+ bool has_ged = !vmc->no_ged; - unsigned int smp_cpus = machine->smp.cpus; - unsigned int max_cpus = machine->smp.max_cpus; - -@@ -1824,6 +1852,10 @@ static void machvirt_init(MachineState *machine) - - create_gpio(vms, pic); - -+ if (has_ged && aarch64 && firmware_loaded && acpi_enabled) { -+ vms->acpi_dev = create_acpi_ged(vms, pic); -+ } -+ - /* Create mmio transports, so the user can create virtio backends - * (which will be automatically plugged in to the transports). If - * no backend is created the transport will just sit harmlessly idle. -@@ -2003,14 +2035,17 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms) - static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp) - { -+ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); -+ const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); - -- /* -- * The device memory is not yet exposed to the Guest either through -- * DT or ACPI and hence both cold/hot plug of memory is explicitly -- * disabled for now. -- */ -- if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -- error_setg(errp, "memory cold/hot plug is not yet supported"); -+ if (is_nvdimm) { -+ error_setg(errp, "nvdimm is not yet supported"); -+ return; -+ } -+ -+ if (!vms->acpi_dev) { -+ error_setg(errp, -+ "memory hotplug is not enabled: missing acpi-ged device"); - return; - } - -@@ -2020,11 +2055,18 @@ static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, - static void virt_memory_plug(HotplugHandler *hotplug_dev, - DeviceState *dev, Error **errp) - { -+ HotplugHandlerClass *hhc; - VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); - Error *local_err = NULL; - - pc_dimm_plug(PC_DIMM(dev), MACHINE(vms), &local_err); -+ if (local_err) { -+ goto out; -+ } - -+ hhc = HOTPLUG_HANDLER_GET_CLASS(vms->acpi_dev); -+ hhc->plug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &error_abort); -+out: - error_propagate(errp, local_err); - } - -@@ -2231,8 +2273,11 @@ DEFINE_VIRT_MACHINE_AS_LATEST(4, 1) - - static void virt_machine_4_0_options(MachineClass *mc) - { -+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); -+ - virt_machine_4_1_options(mc); - compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); -+ vmc->no_ged = true; - } - DEFINE_VIRT_MACHINE(4, 0) - -diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h -index a9d6977afc..0350285136 100644 ---- a/include/hw/arm/virt.h -+++ b/include/hw/arm/virt.h -@@ -78,6 +78,8 @@ enum { - VIRT_GPIO, - VIRT_SECURE_UART, - VIRT_SECURE_MEM, -+ VIRT_PCDIMM_ACPI, -+ VIRT_ACPI_GED, - VIRT_LOWMEMMAP_LAST, - }; - -@@ -107,6 +109,7 @@ typedef struct { - bool claim_edge_triggered_timers; - bool smbios_old_sys_ver; - bool no_highmem_ecam; -+ bool no_ged; /* Machines < 4.1 has no support for ACPI GED device */ - bool kvm_no_adjvtime; - } VirtMachineClass; - -@@ -135,6 +138,7 @@ typedef struct { - uint32_t iommu_phandle; - int psci_conduit; - hwaddr highest_gpa; -+ DeviceState *acpi_dev; - } VirtMachineState; - - #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) --- -2.19.1 diff --git a/hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch b/hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch index 1e3befaf62920ca12cae4c8ead6d731800ef79a8..fe733c62e37890f92821268c623da3adf22b7499 100644 --- a/hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch +++ b/hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch @@ -1,4 +1,4 @@ -From 3a0af1446395e74476a763ca12713b28c099a144 Mon Sep 17 00:00:00 2001 +From 7838609e9a7743af03c58ae46afd26070b2feea6 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Mon, 6 Apr 2020 12:50:54 +0800 Subject: [PATCH] hw/arm/virt: Factor out some CPU init codes to pre_plug hook @@ -10,90 +10,137 @@ let them be shared by all CPUs. Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta --- - hw/arm/virt.c | 108 +++++++++++++++++++++++++++----------------------- - 1 file changed, 58 insertions(+), 50 deletions(-) + hw/arm/virt.c | 197 ++++++++++++++++++++++++++------------------------ + 1 file changed, 103 insertions(+), 94 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 64532b61b2..83f4887e57 100644 +index a12e718686..149e0245d7 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -196,6 +196,8 @@ static const char *valid_cpus[] = { +@@ -213,6 +213,10 @@ static const char *valid_cpus[] = { ARM_CPU_TYPE_NAME("max"), }; - + +static MemoryRegion *secure_sysmem; ++static MemoryRegion *tag_sysmem; ++static MemoryRegion *secure_tag_sysmem; + static bool cpu_type_valid(const char *cpu) { int i; -@@ -1629,7 +1631,6 @@ static void machvirt_init(MachineState *machine) +@@ -1990,9 +1994,6 @@ static void machvirt_init(MachineState *machine) MachineClass *mc = MACHINE_GET_CLASS(machine); const CPUArchIdList *possible_cpus; MemoryRegion *sysmem = get_system_memory(); - MemoryRegion *secure_sysmem = NULL; +- MemoryRegion *tag_sysmem = NULL; +- MemoryRegion *secure_tag_sysmem = NULL; int n, virt_max_cpus; - MemoryRegion *ram = g_new(MemoryRegion, 1); bool firmware_loaded; -@@ -1752,57 +1753,10 @@ static void machvirt_init(MachineState *machine) + bool aarch64 = true; +@@ -2099,100 +2100,11 @@ static void machvirt_init(MachineState *machine) } - + cpuobj = object_new(possible_cpus->cpus[n].type); -- object_property_set_int(cpuobj, possible_cpus->cpus[n].arch_id, -- "mp-affinity", NULL); +- object_property_set_int(cpuobj, "mp-affinity", +- possible_cpus->cpus[n].arch_id, NULL); + aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL); - + cs = CPU(cpuobj); cs->cpu_index = n; -- + - numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj), - &error_fatal); - - aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL); - - if (!vms->secure) { -- object_property_set_bool(cpuobj, false, "has_el3", NULL); +- object_property_set_bool(cpuobj, "has_el3", false, NULL); - } - -- if (!vms->virt && object_property_find(cpuobj, "has_el2", NULL)) { -- object_property_set_bool(cpuobj, false, "has_el2", NULL); +- if (!vms->virt && object_property_find(cpuobj, "has_el2")) { +- object_property_set_bool(cpuobj, "has_el2", false, NULL); - } - - if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) { -- object_property_set_int(cpuobj, vms->psci_conduit, -- "psci-conduit", NULL); +- object_property_set_int(cpuobj, "psci-conduit", vms->psci_conduit, +- NULL); - - /* Secondary CPUs start in PSCI powered-down state */ - if (n > 0) { -- object_property_set_bool(cpuobj, true, -- "start-powered-off", NULL); +- object_property_set_bool(cpuobj, "start-powered-off", true, +- NULL); - } - } - - if (vmc->kvm_no_adjvtime && -- object_property_find(cpuobj, "kvm-no-adjvtime", NULL)) { -- object_property_set_bool(cpuobj, true, "kvm-no-adjvtime", NULL); +- object_property_find(cpuobj, "kvm-no-adjvtime")) { +- object_property_set_bool(cpuobj, "kvm-no-adjvtime", true, NULL); - } - -- if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) { -- object_property_set_bool(cpuobj, false, "pmu", NULL); +- if (vmc->no_kvm_steal_time && +- object_property_find(cpuobj, "kvm-steal-time")) { +- object_property_set_bool(cpuobj, "kvm-steal-time", false, NULL); - } - -- if (object_property_find(cpuobj, "reset-cbar", NULL)) { -- object_property_set_int(cpuobj, vms->memmap[VIRT_CPUPERIPHS].base, -- "reset-cbar", &error_abort); +- if (vmc->no_pmu && object_property_find(cpuobj, "pmu")) { +- object_property_set_bool(cpuobj, "pmu", false, NULL); - } - -- object_property_set_link(cpuobj, OBJECT(sysmem), "memory", +- if (object_property_find(cpuobj, "reset-cbar")) { +- object_property_set_int(cpuobj, "reset-cbar", +- vms->memmap[VIRT_CPUPERIPHS].base, +- &error_abort); +- } +- +- object_property_set_link(cpuobj, "memory", OBJECT(sysmem), - &error_abort); - if (vms->secure) { -- object_property_set_link(cpuobj, OBJECT(secure_sysmem), -- "secure-memory", &error_abort); +- object_property_set_link(cpuobj, "secure-memory", +- OBJECT(secure_sysmem), &error_abort); +- } +- +- if (vms->mte) { +- /* Create the memory region only once, but link to all cpus. */ +- if (!tag_sysmem) { +- /* +- * The property exists only if MemTag is supported. +- * If it is, we must allocate the ram to back that up. +- */ +- if (!object_property_find(cpuobj, "tag-memory")) { +- error_report("MTE requested, but not supported " +- "by the guest CPU"); +- exit(1); +- } +- +- tag_sysmem = g_new(MemoryRegion, 1); +- memory_region_init(tag_sysmem, OBJECT(machine), +- "tag-memory", UINT64_MAX / 32); +- +- if (vms->secure) { +- secure_tag_sysmem = g_new(MemoryRegion, 1); +- memory_region_init(secure_tag_sysmem, OBJECT(machine), +- "secure-tag-memory", UINT64_MAX / 32); +- +- /* As with ram, secure-tag takes precedence over tag. */ +- memory_region_add_subregion_overlap(secure_tag_sysmem, 0, +- tag_sysmem, -1); +- } +- } +- +- object_property_set_link(cpuobj, "tag-memory", OBJECT(tag_sysmem), +- &error_abort); +- if (vms->secure) { +- object_property_set_link(cpuobj, "secure-tag-memory", +- OBJECT(secure_tag_sysmem), +- &error_abort); +- } - } - - object_property_set_bool(cpuobj, true, "realized", &error_fatal); + qdev_realize(DEVICE(cpuobj), NULL, &error_fatal); object_unref(cpuobj); } -@@ -2089,10 +2043,16 @@ out: +@@ -2600,10 +2512,16 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev, static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -108,63 +155,107 @@ index 64532b61b2..83f4887e57 100644 + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(hotplug_dev); + const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); + MemoryRegion *sysmem = get_system_memory(); + int smp_clusters = ms->smp.clusters; int smp_cores = ms->smp.cores; int smp_threads = ms->smp.threads; - -@@ -2145,6 +2105,54 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, +@@ -2673,6 +2591,97 @@ static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev, return; } cpu->thread_id = topo.smt_id; + + /* Init some properties */ + -+ object_property_set_int(cpuobj, possible_cpus->cpus[cs->cpu_index].arch_id, -+ "mp-affinity", NULL); ++ object_property_set_int(cpuobj, "mp-affinity", ++ possible_cpus->cpus[cs->cpu_index].arch_id, NULL); + + numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj), + &error_fatal); + + if (!vms->secure) { -+ object_property_set_bool(cpuobj, false, "has_el3", NULL); ++ object_property_set_bool(cpuobj, "has_el3", false, NULL); + } + -+ if (!vms->virt && object_property_find(cpuobj, "has_el2", NULL)) { -+ object_property_set_bool(cpuobj, false, "has_el2", NULL); ++ if (!vms->virt && object_property_find(cpuobj, "has_el2")) { ++ object_property_set_bool(cpuobj, "has_el2", false, NULL); + } + + if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) { -+ object_property_set_int(cpuobj, vms->psci_conduit, -+ "psci-conduit", NULL); ++ object_property_set_int(cpuobj, "psci-conduit", vms->psci_conduit, ++ NULL); + + /* Secondary CPUs start in PSCI powered-down state */ + if (cs->cpu_index > 0) { -+ object_property_set_bool(cpuobj, true, -+ "start-powered-off", NULL); ++ object_property_set_bool(cpuobj, "start-powered-off", true, ++ NULL); + } + } + + if (vmc->kvm_no_adjvtime && -+ object_property_find(cpuobj, "kvm-no-adjvtime", NULL)) { -+ object_property_set_bool(cpuobj, true, "kvm-no-adjvtime", NULL); ++ object_property_find(cpuobj, "kvm-no-adjvtime")) { ++ object_property_set_bool(cpuobj, "kvm-no-adjvtime", true, NULL); ++ } ++ ++ if (vmc->no_kvm_steal_time && ++ object_property_find(cpuobj, "kvm-steal-time")) { ++ object_property_set_bool(cpuobj, "kvm-steal-time", false, NULL); + } + -+ if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) { -+ object_property_set_bool(cpuobj, false, "pmu", NULL); ++ if (vmc->no_pmu && object_property_find(cpuobj, "pmu")) { ++ object_property_set_bool(cpuobj, "pmu", false, NULL); + } + -+ if (object_property_find(cpuobj, "reset-cbar", NULL)) { -+ object_property_set_int(cpuobj, vms->memmap[VIRT_CPUPERIPHS].base, -+ "reset-cbar", &error_abort); ++ if (object_property_find(cpuobj, "reset-cbar")) { ++ object_property_set_int(cpuobj, "reset-cbar", ++ vms->memmap[VIRT_CPUPERIPHS].base, ++ &error_abort); + } + -+ object_property_set_link(cpuobj, OBJECT(sysmem), "memory", ++ object_property_set_link(cpuobj, "memory", OBJECT(sysmem), + &error_abort); + if (vms->secure) { -+ object_property_set_link(cpuobj, OBJECT(secure_sysmem), -+ "secure-memory", &error_abort); ++ object_property_set_link(cpuobj, "secure-memory", ++ OBJECT(secure_sysmem), &error_abort); ++ } ++ ++ if (vms->mte) { ++ /* Create the memory region only once, but link to all cpus. */ ++ if (!tag_sysmem) { ++ /* ++ * The property exists only if MemTag is supported. ++ * If it is, we must allocate the ram to back that up. ++ */ ++ if (!object_property_find(cpuobj, "tag-memory")) { ++ error_report("MTE requested, but not supported " ++ "by the guest CPU"); ++ exit(1); ++ } ++ ++ tag_sysmem = g_new(MemoryRegion, 1); ++ memory_region_init(tag_sysmem, OBJECT(ms), ++ "tag-memory", UINT64_MAX / 32); ++ ++ if (vms->secure) { ++ secure_tag_sysmem = g_new(MemoryRegion, 1); ++ memory_region_init(secure_tag_sysmem, OBJECT(ms), ++ "secure-tag-memory", UINT64_MAX / 32); ++ ++ /* As with ram, secure-tag takes precedence over tag. */ ++ memory_region_add_subregion_overlap(secure_tag_sysmem, 0, ++ tag_sysmem, -1); ++ } ++ } ++ ++ object_property_set_link(cpuobj, "tag-memory", OBJECT(tag_sysmem), ++ &error_abort); ++ if (vms->secure) { ++ object_property_set_link(cpuobj, "secure-tag-memory", ++ OBJECT(secure_tag_sysmem), ++ &error_abort); ++ } + } } - + static void virt_cpu_plug(HotplugHandler *hotplug_dev, --- -2.19.1 +-- +2.27.0 + diff --git a/hw-arm-virt-Init-PMU-for-hotplugged-vCPU.patch b/hw-arm-virt-Init-PMU-for-hotplugged-vCPU.patch deleted file mode 100644 index c124df5394121fdb0415b3b85d04fc3417a747aa..0000000000000000000000000000000000000000 --- a/hw-arm-virt-Init-PMU-for-hotplugged-vCPU.patch +++ /dev/null @@ -1,73 +0,0 @@ -From acc5162f1d1591ee4830f9b67934fc6d8a9ebbc1 Mon Sep 17 00:00:00 2001 -From: Keqian Zhu -Date: Tue, 8 Sep 2020 22:09:44 +0800 -Subject: [PATCH] hw/arm/virt: Init PMU for hotplugged vCPU - -Factor out PMU init code from fdt_add_pmu_nodes and -do PMU init for hotplugged vCPU. - -Signed-off-by: Keqian Zhu ---- - hw/arm/virt.c | 29 +++++++++++++++++++++-------- - 1 file changed, 21 insertions(+), 8 deletions(-) - -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 7afc6c5e..7506d0ff 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -605,6 +605,23 @@ static void fdt_add_gic_node(VirtMachineState *vms) - g_free(nodename); - } - -+static bool virt_cpu_init_pmu(const VirtMachineState *vms, CPUState *cpu) -+{ -+ ARMCPU *armcpu = ARM_CPU(cpu); -+ -+ if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { -+ return false; -+ } -+ if (kvm_enabled()) { -+ if (kvm_irqchip_in_kernel()) { -+ kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ)); -+ } -+ kvm_arm_pmu_init(cpu); -+ } -+ -+ return true; -+} -+ - static void fdt_add_pmu_nodes(const VirtMachineState *vms) - { - CPUState *cpu; -@@ -612,16 +629,9 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms) - uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI; - - CPU_FOREACH(cpu) { -- armcpu = ARM_CPU(cpu); -- if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { -+ if (!virt_cpu_init_pmu(vms, cpu)) { - return; - } -- if (kvm_enabled()) { -- if (kvm_irqchip_in_kernel()) { -- kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ)); -- } -- kvm_arm_pmu_init(cpu); -- } - } - - if (vms->gic_version == 2) { -@@ -2248,6 +2258,9 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev, - agcc->cpu_hotplug_realize(gicv3, ncpu); - connect_gic_cpu_irqs(vms, ncpu); - -+ /* Init PMU part */ -+ virt_cpu_init_pmu(vms, cs); -+ - /* Register CPU reset and trigger it manually */ - cpu_synchronize_state(cs); - cpu_hotplug_register_reset(ncpu); --- -2.23.0 - - diff --git a/hw-arm-virt-Introduce-cpu-topology-support.patch b/hw-arm-virt-Introduce-cpu-topology-support.patch deleted file mode 100644 index 932f467fe274453668edf80bac5d023817d6f95b..0000000000000000000000000000000000000000 --- a/hw-arm-virt-Introduce-cpu-topology-support.patch +++ /dev/null @@ -1,236 +0,0 @@ -From 73fc4af05ebe12d77915e6b3c85c48f5e0c432f3 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 22 Apr 2020 19:23:27 +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 -Signed-off-by: zhanghailiang -(picked-from https://patchwork.ozlabs.org/cover/939301/ which is pushed by -Andrew Jones ) ---- - device_tree.c | 32 ++++++++++++++++++++++ - hw/acpi/aml-build.c | 53 ++++++++++++++++++++++++++++++++++++ - hw/arm/virt-acpi-build.c | 4 +++ - hw/arm/virt.c | 32 +++++++++++++++++++++- - include/hw/acpi/aml-build.h | 2 ++ - include/sysemu/device_tree.h | 1 + - 6 files changed, 123 insertions(+), 1 deletion(-) - -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..f2c8c28f 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,58 @@ 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; -+ MachineState *ms = MACHINE(qdev_get_machine()); -+ unsigned int smp_cores = ms->smp.cores; -+ unsigned int smp_threads = ms->smp.threads; -+ -+ 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 29494ebd..fe54411f 100644 ---- a/hw/arm/virt-acpi-build.c -+++ b/hw/arm/virt-acpi-build.c -@@ -848,6 +848,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 0fa355ba..272455bc 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -44,6 +44,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" -@@ -312,7 +313,8 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) - int cpu; - int addr_cells = 1; - const MachineState *ms = MACHINE(vms); -- -+ unsigned int smp_cores = ms->smp.cores; -+ unsigned int smp_threads = ms->smp.threads; - /* - * From Documentation/devicetree/bindings/arm/cpus.txt - * On ARM v8 64-bit systems value should be set to 2, -@@ -368,8 +370,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.23.0 diff --git a/hw-arm-virt-Simplify-by-moving-the-gic-in-the-machin.patch b/hw-arm-virt-Simplify-by-moving-the-gic-in-the-machin.patch deleted file mode 100644 index 262cb508bcb8ba48bf93a3875957f2c9ace7698d..0000000000000000000000000000000000000000 --- a/hw-arm-virt-Simplify-by-moving-the-gic-in-the-machin.patch +++ /dev/null @@ -1,402 +0,0 @@ -From 5d1be90750551f1debf5767d7a6e2b9c50054c05 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= -Date: Mon, 9 Dec 2019 10:03:06 +0100 -Subject: [PATCH] hw/arm/virt: Simplify by moving the gic in the machine state -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Make the gic a field in the machine state, and instead of filling -an array of qemu_irq and passing it around, directly call -qdev_get_gpio_in() on the gic field. - -Signed-off-by: Philippe Mathieu-Daudé -Reviewed-by: Luc Michel -Message-id: 20191209090306.20433-1-philmd@redhat.com -Reviewed-by: Peter Maydell -Signed-off-by: Peter Maydell ---- - hw/arm/virt.c | 109 +++++++++++++++++++++--------------------- - include/hw/arm/virt.h | 1 + - 2 files changed, 55 insertions(+), 55 deletions(-) - -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 18321e522b..8638aeedb7 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -634,7 +634,7 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms) - } - } - --static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic) -+static inline DeviceState *create_acpi_ged(VirtMachineState *vms) - { - DeviceState *dev; - MachineState *ms = MACHINE(vms); -@@ -650,14 +650,14 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms, qemu_irq *pic) - - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base); -- sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irq]); -+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq)); - - qdev_init_nofail(dev); - - return dev; - } - --static void create_its(VirtMachineState *vms, DeviceState *gicdev) -+static void create_its(VirtMachineState *vms) - { - const char *itsclass = its_class_name(); - DeviceState *dev; -@@ -669,7 +669,7 @@ static void create_its(VirtMachineState *vms, DeviceState *gicdev) - - dev = qdev_create(NULL, itsclass); - -- object_property_set_link(OBJECT(dev), OBJECT(gicdev), "parent-gicv3", -+ object_property_set_link(OBJECT(dev), OBJECT(vms->gic), "parent-gicv3", - &error_abort); - qdev_init_nofail(dev); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_GIC_ITS].base); -@@ -677,7 +677,7 @@ static void create_its(VirtMachineState *vms, DeviceState *gicdev) - fdt_add_its_gic_node(vms); - } - --static void create_v2m(VirtMachineState *vms, qemu_irq *pic) -+static void create_v2m(VirtMachineState *vms) - { - int i; - int irq = vms->irqmap[VIRT_GIC_V2M]; -@@ -690,17 +690,17 @@ static void create_v2m(VirtMachineState *vms, qemu_irq *pic) - qdev_init_nofail(dev); - - for (i = 0; i < NUM_GICV2M_SPIS; i++) { -- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); -+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, -+ qdev_get_gpio_in(vms->gic, irq + i)); - } - - fdt_add_v2m_gic_node(vms); - } - --static void create_gic(VirtMachineState *vms, qemu_irq *pic) -+static void create_gic(VirtMachineState *vms) - { - MachineState *ms = MACHINE(vms); - /* We create a standalone GIC */ -- DeviceState *gicdev; - SysBusDevice *gicbusdev; - const char *gictype; - int type = vms->gic_version, i; -@@ -709,15 +709,15 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) - - gictype = (type == 3) ? gicv3_class_name() : gic_class_name(); - -- gicdev = qdev_create(NULL, gictype); -- qdev_prop_set_uint32(gicdev, "revision", type); -- qdev_prop_set_uint32(gicdev, "num-cpu", smp_cpus); -+ vms->gic = qdev_create(NULL, gictype); -+ qdev_prop_set_uint32(vms->gic, "revision", type); -+ qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus); - /* Note that the num-irq property counts both internal and external - * interrupts; there are always 32 of the former (mandated by GIC spec). - */ -- qdev_prop_set_uint32(gicdev, "num-irq", NUM_IRQS + 32); -+ qdev_prop_set_uint32(vms->gic, "num-irq", NUM_IRQS + 32); - if (!kvm_irqchip_in_kernel()) { -- qdev_prop_set_bit(gicdev, "has-security-extensions", vms->secure); -+ qdev_prop_set_bit(vms->gic, "has-security-extensions", vms->secure); - } - - if (type == 3) { -@@ -727,25 +727,25 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) - - nb_redist_regions = virt_gicv3_redist_region_count(vms); - -- qdev_prop_set_uint32(gicdev, "len-redist-region-count", -+ qdev_prop_set_uint32(vms->gic, "len-redist-region-count", - nb_redist_regions); -- qdev_prop_set_uint32(gicdev, "redist-region-count[0]", redist0_count); -+ qdev_prop_set_uint32(vms->gic, "redist-region-count[0]", redist0_count); - - if (nb_redist_regions == 2) { - uint32_t redist1_capacity = - vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE; - -- qdev_prop_set_uint32(gicdev, "redist-region-count[1]", -+ qdev_prop_set_uint32(vms->gic, "redist-region-count[1]", - MIN(smp_cpus - redist0_count, redist1_capacity)); - } - } else { - if (!kvm_irqchip_in_kernel()) { -- qdev_prop_set_bit(gicdev, "has-virtualization-extensions", -+ qdev_prop_set_bit(vms->gic, "has-virtualization-extensions", - vms->virt); - } - } -- qdev_init_nofail(gicdev); -- gicbusdev = SYS_BUS_DEVICE(gicdev); -+ qdev_init_nofail(vms->gic); -+ gicbusdev = SYS_BUS_DEVICE(vms->gic); - sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base); - if (type == 3) { - sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base); -@@ -781,23 +781,23 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) - - for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) { - qdev_connect_gpio_out(cpudev, irq, -- qdev_get_gpio_in(gicdev, -+ qdev_get_gpio_in(vms->gic, - ppibase + timer_irq[irq])); - } - - if (type == 3) { -- qemu_irq irq = qdev_get_gpio_in(gicdev, -+ qemu_irq irq = qdev_get_gpio_in(vms->gic, - ppibase + ARCH_GIC_MAINT_IRQ); - qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", - 0, irq); - } else if (vms->virt) { -- qemu_irq irq = qdev_get_gpio_in(gicdev, -+ qemu_irq irq = qdev_get_gpio_in(vms->gic, - ppibase + ARCH_GIC_MAINT_IRQ); - sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq); - } - - qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, -- qdev_get_gpio_in(gicdev, ppibase -+ qdev_get_gpio_in(vms->gic, ppibase - + VIRTUAL_PMU_IRQ)); - - sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); -@@ -809,20 +809,16 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic) - qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); - } - -- for (i = 0; i < NUM_IRQS; i++) { -- pic[i] = qdev_get_gpio_in(gicdev, i); -- } -- - fdt_add_gic_node(vms); - - if (type == 3 && vms->its) { -- create_its(vms, gicdev); -+ create_its(vms); - } else if (type == 2) { -- create_v2m(vms, pic); -+ create_v2m(vms); - } - } - --static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, -+static void create_uart(const VirtMachineState *vms, int uart, - MemoryRegion *mem, Chardev *chr) - { - char *nodename; -@@ -838,7 +834,7 @@ static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, - qdev_init_nofail(dev); - memory_region_add_subregion(mem, base, - sysbus_mmio_get_region(s, 0)); -- sysbus_connect_irq(s, 0, pic[irq]); -+ sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->gic, irq)); - - nodename = g_strdup_printf("/pl011@%" PRIx64, base); - qemu_fdt_add_subnode(vms->fdt, nodename); -@@ -880,7 +876,7 @@ static void create_cpufreq(const VirtMachineState *vms, MemoryRegion *mem) - memory_region_add_subregion(mem, base, sysbus_mmio_get_region(s, 0)); - } - --static void create_rtc(const VirtMachineState *vms, qemu_irq *pic) -+static void create_rtc(const VirtMachineState *vms) - { - char *nodename; - hwaddr base = vms->memmap[VIRT_RTC].base; -@@ -888,7 +884,7 @@ static void create_rtc(const VirtMachineState *vms, qemu_irq *pic) - int irq = vms->irqmap[VIRT_RTC]; - const char compat[] = "arm,pl031\0arm,primecell"; - -- sysbus_create_simple("pl031", base, pic[irq]); -+ sysbus_create_simple("pl031", base, qdev_get_gpio_in(vms->gic, irq)); - - nodename = g_strdup_printf("/pl031@%" PRIx64, base); - qemu_fdt_add_subnode(vms->fdt, nodename); -@@ -916,7 +912,7 @@ static void virt_powerdown_req(Notifier *n, void *opaque) - } - } - --static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) -+static void create_gpio(const VirtMachineState *vms) - { - char *nodename; - DeviceState *pl061_dev; -@@ -925,7 +921,8 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) - int irq = vms->irqmap[VIRT_GPIO]; - const char compat[] = "arm,pl061\0arm,primecell"; - -- pl061_dev = sysbus_create_simple("pl061", base, pic[irq]); -+ pl061_dev = sysbus_create_simple("pl061", base, -+ qdev_get_gpio_in(vms->gic, irq)); - - uint32_t phandle = qemu_fdt_alloc_phandle(vms->fdt); - nodename = g_strdup_printf("/pl061@%" PRIx64, base); -@@ -959,7 +956,7 @@ static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) - g_free(nodename); - } - --static void create_virtio_devices(const VirtMachineState *vms, qemu_irq *pic) -+static void create_virtio_devices(const VirtMachineState *vms) - { - int i; - hwaddr size = vms->memmap[VIRT_MMIO].size; -@@ -995,7 +992,8 @@ static void create_virtio_devices(const VirtMachineState *vms, qemu_irq *pic) - int irq = vms->irqmap[VIRT_MMIO] + i; - hwaddr base = vms->memmap[VIRT_MMIO].base + i * size; - -- sysbus_create_simple("virtio-mmio", base, pic[irq]); -+ sysbus_create_simple("virtio-mmio", base, -+ qdev_get_gpio_in(vms->gic, irq)); - } - - /* We add dtb nodes in reverse order so that they appear in the finished -@@ -1244,7 +1242,7 @@ static void create_pcie_irq_map(const VirtMachineState *vms, - 0x7 /* PCI irq */); - } - --static void create_smmu(const VirtMachineState *vms, qemu_irq *pic, -+static void create_smmu(const VirtMachineState *vms, - PCIBus *bus) - { - char *node; -@@ -1267,7 +1265,8 @@ static void create_smmu(const VirtMachineState *vms, qemu_irq *pic, - qdev_init_nofail(dev); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); - for (i = 0; i < NUM_SMMU_IRQS; i++) { -- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); -+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, -+ qdev_get_gpio_in(vms->gic, irq + i)); - } - - node = g_strdup_printf("/smmuv3@%" PRIx64, base); -@@ -1294,7 +1293,7 @@ static void create_smmu(const VirtMachineState *vms, qemu_irq *pic, - g_free(node); - } - --static void create_pcie(VirtMachineState *vms, qemu_irq *pic) -+static void create_pcie(VirtMachineState *vms) - { - hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base; - hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size; -@@ -1354,7 +1353,8 @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic) - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio); - - for (i = 0; i < GPEX_NUM_IRQS; i++) { -- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); -+ sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, -+ qdev_get_gpio_in(vms->gic, irq + i)); - gpex_set_irq_num(GPEX_HOST(dev), i, irq + i); - } - -@@ -1414,7 +1414,7 @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic) - if (vms->iommu) { - vms->iommu_phandle = qemu_fdt_alloc_phandle(vms->fdt); - -- create_smmu(vms, pic, pci->bus); -+ create_smmu(vms, pci->bus); - - qemu_fdt_setprop_cells(vms->fdt, nodename, "iommu-map", - 0x0, vms->iommu_phandle, 0x0, 0x10000); -@@ -1423,7 +1423,7 @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic) - g_free(nodename); - } - --static void create_platform_bus(VirtMachineState *vms, qemu_irq *pic) -+static void create_platform_bus(VirtMachineState *vms) - { - DeviceState *dev; - SysBusDevice *s; -@@ -1439,8 +1439,8 @@ static void create_platform_bus(VirtMachineState *vms, qemu_irq *pic) - - s = SYS_BUS_DEVICE(dev); - for (i = 0; i < PLATFORM_BUS_NUM_IRQS; i++) { -- int irqn = vms->irqmap[VIRT_PLATFORM_BUS] + i; -- sysbus_connect_irq(s, i, pic[irqn]); -+ int irq = vms->irqmap[VIRT_PLATFORM_BUS] + i; -+ sysbus_connect_irq(s, i, qdev_get_gpio_in(vms->gic, irq)); - } - - memory_region_add_subregion(sysmem, -@@ -1621,7 +1621,6 @@ static void machvirt_init(MachineState *machine) - VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine); - MachineClass *mc = MACHINE_GET_CLASS(machine); - const CPUArchIdList *possible_cpus; -- qemu_irq pic[NUM_IRQS]; - MemoryRegion *sysmem = get_system_memory(); - MemoryRegion *secure_sysmem = NULL; - int n, virt_max_cpus; -@@ -1829,29 +1828,29 @@ static void machvirt_init(MachineState *machine) - - virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem); - -- create_gic(vms, pic); -+ create_gic(vms); - - fdt_add_pmu_nodes(vms); - -- create_uart(vms, pic, VIRT_UART, sysmem, serial_hd(0)); -+ create_uart(vms, 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)); -+ create_uart(vms, VIRT_SECURE_UART, secure_sysmem, serial_hd(1)); - } - - vms->highmem_ecam &= vms->highmem && (!firmware_loaded || aarch64); - -- create_rtc(vms, pic); -+ create_rtc(vms); - -- create_pcie(vms, pic); -+ create_pcie(vms); - - if (has_ged && aarch64 && firmware_loaded && acpi_enabled) { -- vms->acpi_dev = create_acpi_ged(vms, pic); -+ vms->acpi_dev = create_acpi_ged(vms); - } else { -- create_gpio(vms, pic); -+ create_gpio(vms); - } - - /* connect powerdown request */ -@@ -1862,12 +1861,12 @@ static void machvirt_init(MachineState *machine) - * (which will be automatically plugged in to the transports). If - * no backend is created the transport will just sit harmlessly idle. - */ -- create_virtio_devices(vms, pic); -+ create_virtio_devices(vms); - - vms->fw_cfg = create_fw_cfg(vms, &address_space_memory); - rom_set_fw(vms->fw_cfg); - -- create_platform_bus(vms, pic); -+ create_platform_bus(vms); - - vms->bootinfo.ram_size = machine->ram_size; - vms->bootinfo.kernel_filename = machine->kernel_filename; -diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h -index dcceb9c615..3dfefca93b 100644 ---- a/include/hw/arm/virt.h -+++ b/include/hw/arm/virt.h -@@ -138,6 +138,7 @@ typedef struct { - uint32_t iommu_phandle; - int psci_conduit; - hwaddr highest_gpa; -+ DeviceState *gic; - DeviceState *acpi_dev; - Notifier powerdown_notifier; - } VirtMachineState; --- -2.19.1 diff --git a/hw-arm-virt-Support-CPU-cluster-on-ARM-virt-machine.patch b/hw-arm-virt-Support-CPU-cluster-on-ARM-virt-machine.patch new file mode 100644 index 0000000000000000000000000000000000000000..cd3241f25dc6a437d65bfeb4a3017b189440dd9b --- /dev/null +++ b/hw-arm-virt-Support-CPU-cluster-on-ARM-virt-machine.patch @@ -0,0 +1,69 @@ +From 1fab7ee365c8daccedd19d3a1be56babe36afcc6 Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Fri, 7 Jan 2022 16:32:27 +0800 +Subject: [PATCH 15/24] hw/arm/virt: Support CPU cluster on ARM virt machine + +ARM64 machines like Kunpeng Family Server Chips have a level +of hardware topology in which a group of CPU cores share L3 +cache tag or L2 cache. For example, Kunpeng 920 typically +has 6 or 8 clusters in each NUMA node (also represent range +of CPU die), and each cluster has 4 CPU cores. All clusters +share L3 cache data, but CPU cores in each cluster share a +local L3 tag. + +Running a guest kernel with Cluster-Aware Scheduling on the +Hosts which have physical clusters, if we can design a vCPU +topology with cluster level for guest kernel and then have +a dedicated vCPU pinning, the guest will gain scheduling +performance improvement from cache affinity of CPU cluster. + +So let's enable the support for this new parameter on ARM +virt machines. After this patch, we can define a 4-level +CPU hierarchy like: cpus=*,maxcpus=*,sockets=*,clusters=*, +cores=*,threads=*. + +Signed-off-by: Yanan Wang +Reviewed-by: Andrew Jones +Message-id: 20220107083232.16256-2-wangyanan55@huawei.com +Signed-off-by: Peter Maydell +--- + hw/arm/virt.c | 1 + + qemu-options.hx | 10 ++++++++++ + 2 files changed, 11 insertions(+) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 3c972fdab0..6ca9cbe2cf 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -2704,6 +2704,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) + hc->unplug_request = virt_machine_device_unplug_request_cb; + hc->unplug = virt_machine_device_unplug_cb; + mc->nvdimm_supported = true; ++ mc->smp_props.clusters_supported = true; + mc->auto_enable_numa_with_memhp = true; + mc->auto_enable_numa_with_memdev = true; + mc->default_ram_id = "mach-virt.ram"; +diff --git a/qemu-options.hx b/qemu-options.hx +index 0f26f7dad7..74d335e4c3 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -277,6 +277,16 @@ SRST + + -smp 16,sockets=2,dies=2,cores=2,threads=2,maxcpus=16 + ++ The following sub-option defines a CPU topology hierarchy (2 sockets ++ totally on the machine, 2 clusters per socket, 2 cores per cluster, ++ 2 threads per core) for ARM virt machines which support sockets/clusters ++ /cores/threads. Some members of the option can be omitted but their values ++ will be automatically computed: ++ ++ :: ++ ++ -smp 16,sockets=2,clusters=2,cores=2,threads=2,maxcpus=16 ++ + Historically preference was given to the coarsest topology parameters + when computing missing values (ie sockets preferred over cores, which + were preferred over threads), however, this behaviour is considered +-- +2.27.0 + diff --git a/hw-arm-virt-Support-cluster-level-in-DT-cpu-map.patch b/hw-arm-virt-Support-cluster-level-in-DT-cpu-map.patch new file mode 100644 index 0000000000000000000000000000000000000000..2d43030f818bee075d09e0403e7e29410f406a92 --- /dev/null +++ b/hw-arm-virt-Support-cluster-level-in-DT-cpu-map.patch @@ -0,0 +1,57 @@ +From 38d9ae59b9344f13198e6b4de03b04787bd6b89d Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Fri, 7 Jan 2022 16:32:28 +0800 +Subject: [PATCH 16/24] hw/arm/virt: Support cluster level in DT cpu-map + +Support one cluster level between core and physical package in the +cpu-map of Arm/virt devicetree. This is also consistent with Linux +Doc "Documentation/devicetree/bindings/cpu/cpu-topology.txt". + +Signed-off-by: Yanan Wang +Reviewed-by: Andrew Jones +Message-id: 20220107083232.16256-3-wangyanan55@huawei.com +Signed-off-by: Peter Maydell +--- + hw/arm/virt.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 6ca9cbe2cf..ddcb73f714 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -434,9 +434,8 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) + * can contain several layers of clustering within a single physical + * package and cluster nodes can be contained in parent cluster nodes. + * +- * Given that cluster is not yet supported in the vCPU topology, +- * we currently generate one cluster node within each socket node +- * by default. ++ * Note: currently we only support one layer of clustering within ++ * each physical package. + */ + qemu_fdt_add_subnode(ms->fdt, "/cpus/cpu-map"); + +@@ -446,14 +445,16 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) + + if (ms->smp.threads > 1) { + map_path = g_strdup_printf( +- "/cpus/cpu-map/socket%d/cluster0/core%d/thread%d", +- cpu / (ms->smp.cores * ms->smp.threads), ++ "/cpus/cpu-map/socket%d/cluster%d/core%d/thread%d", ++ cpu / (ms->smp.clusters * ms->smp.cores * ms->smp.threads), ++ (cpu / (ms->smp.cores * ms->smp.threads)) % ms->smp.clusters, + (cpu / ms->smp.threads) % ms->smp.cores, + cpu % ms->smp.threads); + } else { + map_path = g_strdup_printf( +- "/cpus/cpu-map/socket%d/cluster0/core%d", +- cpu / ms->smp.cores, ++ "/cpus/cpu-map/socket%d/cluster%d/core%d", ++ cpu / (ms->smp.clusters * ms->smp.cores), ++ (cpu / ms->smp.cores) % ms->smp.clusters, + cpu % ms->smp.cores); + } + qemu_fdt_add_path(ms->fdt, map_path); +-- +2.27.0 + diff --git a/hw-arm-virt-acpi-build-Add-PC-DIMM-in-SRAT.patch b/hw-arm-virt-acpi-build-Add-PC-DIMM-in-SRAT.patch deleted file mode 100644 index 0602ab8d4d0d7af63f034c9b66c984e5aed627a7..0000000000000000000000000000000000000000 --- a/hw-arm-virt-acpi-build-Add-PC-DIMM-in-SRAT.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 8d287871fd4e1b4654fe9e5011b80614cb44f6d8 Mon Sep 17 00:00:00 2001 -From: Shameer Kolothum -Date: Wed, 18 Sep 2019 14:06:28 +0100 -Subject: [PATCH] hw/arm/virt-acpi-build: Add PC-DIMM in SRAT - -Generate Memory Affinity Structures for PC-DIMM ranges. - -Also, Linux and Windows need ACPI SRAT table to make memory hotplug -work properly, however currently QEMU doesn't create SRAT table if -numa options aren't present on CLI. Hence add support(>=4.2) to -create numa node automatically (auto_enable_numa_with_memhp) when -QEMU is started with memory hotplug enabled but without '-numa' -options on CLI. - -Signed-off-by: Shameer Kolothum -Signed-off-by: Eric Auger -Reviewed-by: Igor Mammedov -Message-Id: <20190918130633.4872-7-shameerali.kolothum.thodi@huawei.com> -Acked-by: Peter Maydell -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin ---- - hw/arm/virt-acpi-build.c | 9 +++++++++ - hw/arm/virt.c | 2 ++ - 2 files changed, 11 insertions(+) - -diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c -index fca53ae01f..9622994e50 100644 ---- a/hw/arm/virt-acpi-build.c -+++ b/hw/arm/virt-acpi-build.c -@@ -592,6 +592,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) - int i, srat_start; - uint64_t mem_base; - MachineClass *mc = MACHINE_GET_CLASS(vms); -+ MachineState *ms = MACHINE(vms); - const CPUArchIdList *cpu_list = mc->possible_cpu_arch_ids(MACHINE(vms)); - - srat_start = table_data->len; -@@ -617,6 +618,14 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) - } - } - -+ if (ms->device_memory) { -+ numamem = acpi_data_push(table_data, sizeof *numamem); -+ build_srat_memory(numamem, ms->device_memory->base, -+ memory_region_size(&ms->device_memory->mr), -+ nb_numa_nodes - 1, -+ MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); -+ } -+ - build_header(linker, table_data, (void *)(table_data->data + srat_start), - "SRAT", table_data->len - srat_start, 3, NULL, NULL); - } -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 8ccabd5159..ab33cce4b3 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -2173,6 +2173,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) - hc->plug = virt_machine_device_plug_cb; - hc->unplug_request = virt_machine_device_unplug_request_cb; - mc->numa_mem_supported = true; -+ mc->auto_enable_numa_with_memhp = true; - } - - static void virt_instance_init(Object *obj) -@@ -2278,6 +2279,7 @@ 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); - vmc->no_ged = true; -+ mc->auto_enable_numa_with_memhp = false; - } - DEFINE_VIRT_MACHINE(4, 0) - --- -2.19.1 diff --git a/hw-arm-virt-add-missing-compat-for-kvm-no-adjvtime.patch b/hw-arm-virt-add-missing-compat-for-kvm-no-adjvtime.patch deleted file mode 100644 index 3d711678a6bbd365da89b3039509259f9ffe3c2e..0000000000000000000000000000000000000000 --- a/hw-arm-virt-add-missing-compat-for-kvm-no-adjvtime.patch +++ /dev/null @@ -1,25 +0,0 @@ -From fbcb4ffa8648d0aa5be01c11816423a483f245ae Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Tue, 26 May 2020 22:39:23 +0800 -Subject: [PATCH] hw/arm/virt: add missing compat for kvm-no-adjvtime - -Machine compatibility for kvm-no-adjvtime is missed, -let's add it for virt machine 4.0 - -Signed-off-by: Ying Fang - -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 4c727939..133d36a4 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -2492,6 +2492,7 @@ static void virt_machine_4_0_options(MachineClass *mc) - compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len); - vmc->no_ged = true; - mc->auto_enable_numa_with_memhp = false; -+ vmc->kvm_no_adjvtime = true; - } - DEFINE_VIRT_MACHINE(4, 0) - --- -2.23.0 - diff --git a/hw-arm-virt-vTPM-support.patch b/hw-arm-virt-vTPM-support.patch deleted file mode 100644 index cbdc68e62f88981b10ebd459ce101caaf10dba6d..0000000000000000000000000000000000000000 --- a/hw-arm-virt-vTPM-support.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 443ebab9c299b04f020a6873454facb078723141 Mon Sep 17 00:00:00 2001 -From: jiangfangjie -Date: Thu, 13 Aug 2020 20:01:10 +0800 -Subject: [PATCH 15/19] hw/arm/virt: vTPM support - -Let the TPM TIS SYSBUS device be dynamically instantiable -in ARM virt. A device tree node is dynamically created -(TPM via MMIO). - -The TPM Physical Presence interface (PPI) is not supported. - -To run with the swtmp TPM emulator, the qemu command line must -be augmented with: - - -chardev socket,id=chrtpm,path=swtpm-sock - -tpmdev emulator,id=tpm0,chardev=chrtpm - -device tpm-tis-device,tpmdev=tpm0 - -swtpm/libtpms command line example: - -swtpm socket --tpm2 -t -d --tpmstate dir=/tmp/tpm ---ctrl type=unixio,path=swtpm-sock - -Signed-off-by: Eric Auger -Reviewed-by: Stefan Berger -Tested-by: Ard Biesheuvel -Acked-by: Ard Biesheuvel -Message-id: 20200305165149.618-7-eric.auger@redhat.com -Signed-off-by: Stefan Berger -Signed-off-by: jiangfangjie ---- - hw/arm/Kconfig | 1 + - hw/arm/sysbus-fdt.c | 33 +++++++++++++++++++++++++++++++++ - hw/arm/virt.c | 7 +++++++ - 3 files changed, 41 insertions(+) - -diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig -index 15e18b0a..06e49f26 100644 ---- a/hw/arm/Kconfig -+++ b/hw/arm/Kconfig -@@ -5,6 +5,7 @@ config ARM_VIRT - imply VFIO_AMD_XGBE - imply VFIO_PLATFORM - imply VFIO_XGMAC -+ imply TPM_TIS_SYSBUS - select A15MPCORE - select ACPI - select ARM_SMMUV3 -diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c -index 57f94e65..c725d325 100644 ---- a/hw/arm/sysbus-fdt.c -+++ b/hw/arm/sysbus-fdt.c -@@ -30,6 +30,7 @@ - #include "hw/arm/sysbus-fdt.h" - #include "qemu/error-report.h" - #include "sysemu/device_tree.h" -+#include "sysemu/tpm.h" - #include "hw/platform-bus.h" - #include "sysemu/sysemu.h" - #include "hw/vfio/vfio-platform.h" -@@ -437,6 +438,37 @@ static bool vfio_platform_match(SysBusDevice *sbdev, - - #endif /* CONFIG_LINUX */ - -+/* -+ * add_tpm_tis_fdt_node: Create a DT node for TPM TIS -+ * -+ * See kernel documentation: -+ * Documentation/devicetree/bindings/security/tpm/tpm_tis_mmio.txt -+ * Optional interrupt for command completion is not exposed -+ */ -+static int add_tpm_tis_fdt_node(SysBusDevice *sbdev, void *opaque) -+{ -+ PlatformBusFDTData *data = opaque; -+ PlatformBusDevice *pbus = data->pbus; -+ void *fdt = data->fdt; -+ const char *parent_node = data->pbus_node_name; -+ char *nodename; -+ uint32_t reg_attr[2]; -+ uint64_t mmio_base; -+ -+ mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0); -+ nodename = g_strdup_printf("%s/tpm_tis@%" PRIx64, parent_node, mmio_base); -+ qemu_fdt_add_subnode(fdt, nodename); -+ -+ qemu_fdt_setprop_string(fdt, nodename, "compatible", "tcg,tpm-tis-mmio"); -+ -+ reg_attr[0] = cpu_to_be32(mmio_base); -+ reg_attr[1] = cpu_to_be32(0x5000); -+ qemu_fdt_setprop(fdt, nodename, "reg", reg_attr, 2 * sizeof(uint32_t)); -+ -+ g_free(nodename); -+ return 0; -+} -+ - static int no_fdt_node(SysBusDevice *sbdev, void *opaque) - { - return 0; -@@ -457,6 +489,7 @@ static const BindingEntry bindings[] = { - TYPE_BINDING(TYPE_VFIO_AMD_XGBE, add_amd_xgbe_fdt_node), - VFIO_PLATFORM_BINDING("amd,xgbe-seattle-v1a", add_amd_xgbe_fdt_node), - #endif -+ TYPE_BINDING(TYPE_TPM_TIS_SYSBUS, add_tpm_tis_fdt_node), - TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node), - TYPE_BINDING("", NULL), /* last element */ - }; -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 133d36a4..7afc6c5e 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -47,6 +47,7 @@ - #include "sysemu/numa.h" - #include "sysemu/cpus.h" - #include "sysemu/sysemu.h" -+#include "sysemu/tpm.h" - #include "sysemu/kvm.h" - #include "sysemu/cpus.h" - #include "sysemu/hw_accel.h" -@@ -2368,6 +2369,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) - machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_AMD_XGBE); - machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); - machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM); -+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS); - mc->block_default_type = IF_VIRTIO; - mc->no_cdrom = 1; - mc->pci_allow_0_address = true; -@@ -2481,6 +2483,11 @@ type_init(machvirt_machine_init); - - static void virt_machine_4_1_options(MachineClass *mc) - { -+ static GlobalProperty compat[] = { -+ { TYPE_TPM_TIS_SYSBUS, "ppi", "false" }, -+ }; -+ -+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); - } - DEFINE_VIRT_MACHINE_AS_LATEST(4, 1) - --- -2.23.0 - diff --git a/hw-arm64-add-vcpu-cache-info-support.patch b/hw-arm64-add-vcpu-cache-info-support.patch index 79e1dede39def063dc9d8a4f4b87339bcd39c435..3e8c82e626cca3592709f99af77a7092eddc3207 100644 --- a/hw-arm64-add-vcpu-cache-info-support.patch +++ b/hw-arm64-add-vcpu-cache-info-support.patch @@ -1,63 +1,68 @@ -From 5a0ed254f99ca37498bd81994b906b6984b5ffa9 Mon Sep 17 00:00:00 2001 +From c5cd762bb7513b6df07e26f4eb619dccbd1918b7 Mon Sep 17 00:00:00 2001 From: Ying Fang -Date: Wed, 22 Apr 2020 19:25:00 +0800 -Subject: [PATCH] hw/arm64: add vcpu cache info support +Date: Tue, 8 Feb 2022 11:31:15 +0800 +Subject: [PATCH 23/24] 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 Signed-off-by: Honghao +Signed-off-by: Ying Fang +Signed-off-by: Yanan Wang --- - hw/acpi/aml-build.c | 126 ++++++++++++++++++++++++++++++++++++ - hw/arm/virt.c | 80 ++++++++++++++++++++++- - include/hw/acpi/aml-build.h | 46 +++++++++++++ - 3 files changed, 251 insertions(+), 1 deletion(-) + hw/acpi/aml-build.c | 158 ++++++++++++++++++++++++++++++++++++ + hw/arm/virt.c | 72 ++++++++++++++++ + include/hw/acpi/aml-build.h | 47 +++++++++++ + tests/data/acpi/virt/PPTT | Bin 96 -> 208 bytes + 4 files changed, 277 insertions(+) diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c -index f2c8c28f..74e95005 100644 +index bb2cad63b5..bebf49622b 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c -@@ -55,6 +55,131 @@ static void build_append_array(GArray *array, GArray *val) - /* - * ACPI 6.2 Processor Properties Topology Table (PPTT) - */ +@@ -1994,6 +1994,163 @@ static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags, + } + } + +#ifdef __aarch64__ -+static void build_cache_head(GArray *tbl, uint32_t next_level) ++/* ++ * ACPI spec, Revision 6.3 ++ * 5.2.29.2 Cache Type Structure (Type 1) ++ */ ++static void build_cache_hierarchy_node(GArray *tbl, uint32_t next_level, ++ uint32_t cache_type) +{ + 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*/ ++ 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_int_noprefix(tbl, ARM_L1DCACHE_SETS, 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*/ ++ 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_int_noprefix(tbl, ARM_L1ICACHE_SETS, 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*/ ++ 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_int_noprefix(tbl, ARM_L2CACHE_SETS, 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*/ ++ 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_int_noprefix(tbl, ARM_L3CACHE_SETS, 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); @@ -68,208 +73,230 @@ index f2c8c28f..74e95005 100644 + 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) ++/* ++ * ACPI spec, Revision 6.3 ++ * 5.2.29 Processor Properties Topology Table (PPTT) ++ */ ++void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, ++ const char *oem_id, const char *oem_table_id) +{ -+ build_cache_head(tbl, next_level); -+ build_cache_tail(tbl, cache_type); -+} ++ MachineClass *mc = MACHINE_GET_CLASS(ms); ++ GQueue *list = g_queue_new(); ++ guint pptt_start = table_data->len; ++ guint parent_offset; ++ guint length, i; ++ int uid = 0; ++ int socket; ++ AcpiTable table = { .sig = "PPTT", .rev = 2, ++ .oem_id = oem_id, .oem_table_id = oem_table_id }; + -+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); -+} ++ acpi_table_begin(&table, table_data); + -+static void build_arm_cpu_hierarchy(GArray *tbl, -+ struct offset_status *offset, uint32_t id) -+{ -+ if (!offset) { -+ return; ++ for (socket = 0; socket < ms->smp.sockets; socket++) { ++ uint32_t l3_cache_offset = table_data->len - pptt_start; ++ build_cache_hierarchy_node(table_data, 0, ARM_L3_CACHE); ++ ++ g_queue_push_tail(list, ++ GUINT_TO_POINTER(table_data->len - pptt_start)); ++ build_processor_hierarchy_node( ++ table_data, ++ /* ++ * Physical package - represents the boundary ++ * of a physical package ++ */ ++ (1 << 0), ++ 0, socket, &l3_cache_offset, 1); + } -+ 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; -+ const MachineState *ms = MACHINE(qdev_get_machine()); -+ unsigned int smp_cores = ms->smp.cores; ++ if (mc->smp_props.clusters_supported) { ++ length = g_queue_get_length(list); ++ for (i = 0; i < length; i++) { ++ int cluster; + -+ acpi_data_push(table_data, sizeof(AcpiTableHeader)); ++ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); ++ for (cluster = 0; cluster < ms->smp.clusters; cluster++) { ++ g_queue_push_tail(list, ++ GUINT_TO_POINTER(table_data->len - pptt_start)); ++ build_processor_hierarchy_node( ++ table_data, ++ (0 << 0), /* not a physical package */ ++ parent_offset, cluster, NULL, 0); ++ } ++ } ++ } + -+ for (socket = 0; cpus < possible_cpus; socket++) { ++ length = g_queue_get_length(list); ++ for (i = 0; i < length; i++) { + 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++; ++ ++ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); ++ for (core = 0; core < ms->smp.cores; core++) { ++ uint32_t priv_rsrc[3] = {}; ++ priv_rsrc[0] = table_data->len - pptt_start; /* L2 cache offset */ ++ build_cache_hierarchy_node(table_data, 0, ARM_L2_CACHE); ++ ++ priv_rsrc[1] = table_data->len - pptt_start; /* L1 dcache offset */ ++ build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1D_CACHE); ++ ++ priv_rsrc[2] = table_data->len - pptt_start; /* L1 icache offset */ ++ build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1I_CACHE); ++ ++ if (ms->smp.threads > 1) { ++ g_queue_push_tail(list, ++ GUINT_TO_POINTER(table_data->len - pptt_start)); ++ build_processor_hierarchy_node( ++ table_data, ++ (0 << 0), /* not a physical package */ ++ parent_offset, core, priv_rsrc, 3); ++ } else { ++ build_processor_hierarchy_node( ++ table_data, ++ (1 << 1) | /* ACPI Processor ID valid */ ++ (1 << 3), /* Node is a Leaf */ ++ parent_offset, uid++, priv_rsrc, 3); ++ } ++ } ++ } ++ ++ length = g_queue_get_length(list); ++ for (i = 0; i < length; i++) { ++ int thread; ++ ++ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); ++ for (thread = 0; thread < ms->smp.threads; thread++) { ++ build_processor_hierarchy_node( ++ table_data, ++ (1 << 1) | /* ACPI Processor ID valid */ ++ (1 << 2) | /* Processor is a Thread */ ++ (1 << 3), /* Node is a Leaf */ ++ parent_offset, uid++, NULL, 0); + } + } + -+ build_header(linker, table_data, -+ (void *)(table_data->data + pptt_start), "PPTT", -+ table_data->len - pptt_start, 1, NULL, NULL); ++ g_queue_free(list); ++ acpi_table_end(linker, &table); +} + +#else - static void build_cpu_hierarchy(GArray *tbl, uint32_t flags, - uint32_t parent, uint32_t id) - { -@@ -103,6 +228,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); + /* + * ACPI spec, Revision 6.3 + * 5.2.29 Processor Properties Topology Table (PPTT) +@@ -2084,6 +2241,7 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + g_queue_free(list); + acpi_table_end(linker, &table); } +#endif - - #define ACPI_NAMESEG_LEN 4 - + + /* build rev1/rev3/rev5.1 FADT */ + void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f, diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 272455bc..9669c70b 100644 +index ddcb73f714..529c0d38b6 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -308,6 +308,81 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms) +@@ -350,6 +350,72 @@ 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; -+ const MachineState *ms = MACHINE(qdev_get_machine()); -+ unsigned int smp_cores = ms->smp.cores; -+ unsigned int sockets = vms->smp_cpus / smp_cores; -+ -+ /* If current is not equal to max */ -+ if (vms->smp_cpus % smp_cores) -+ sockets++; ++ const MachineState *ms = MACHINE(vms); ++ int cpus_per_socket = ms->smp.clusters * ms->smp.cores * ms->smp.threads; ++ int sockets = (ms->smp.cpus + cpus_per_socket - 1) / cpus_per_socket; + + 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)); ++ ++ qemu_fdt_add_subnode(ms->fdt, nodename); ++ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cache"); ++ qemu_fdt_setprop_string(ms->fdt, nodename, "cache-unified", "true"); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-level", 3); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", 0x2000000); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size", 128); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", 2048); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", ++ qemu_fdt_alloc_phandle(ms->fdt)); + g_free(nodename); + } +} + -+ +static void fdt_add_l2cache_nodes(const VirtMachineState *vms) +{ -+ int i, j; -+ const MachineState *ms = MACHINE(qdev_get_machine()); -+ unsigned int smp_cores = ms->smp.cores; -+ signed int sockets = vms->smp_cpus / smp_cores; ++ const MachineState *ms = MACHINE(vms); ++ int cpus_per_socket = ms->smp.clusters * ms->smp.cores * ms->smp.threads; ++ int cpu; + -+ /* If current is not equal to max */ -+ if (vms->smp_cpus % smp_cores) -+ sockets++; ++ for (cpu = 0; cpu < ms->smp.cpus; cpu++) { ++ char *next_path = g_strdup_printf("/cpus/l3-cache%d", ++ cpu / cpus_per_socket); ++ char *nodename = g_strdup_printf("/cpus/l2-cache%d", cpu); ++ ++ qemu_fdt_add_subnode(ms->fdt, nodename); ++ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cache"); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", 0x80000); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size", 64); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", 1024); ++ qemu_fdt_setprop_phandle(ms->fdt, nodename, "next-level-cache", ++ next_path); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", ++ qemu_fdt_alloc_phandle(ms->fdt)); + -+ 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); ++ g_free(nodename); + } +} + +static void fdt_add_l1cache_prop(const VirtMachineState *vms, -+ char *nodename, int cpu) ++ char *nodename, int cpu) +{ ++ const MachineState *ms = MACHINE(vms); + 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); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-size", 0x10000); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-line-size", 64); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-sets", 256); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-size", 0x10000); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-line-size", 64); ++ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-sets", 256); ++ qemu_fdt_setprop_phandle(ms->fdt, nodename, "next-level-cache", ++ cachename); + g_free(cachename); +} -+ + static void fdt_add_cpu_nodes(const VirtMachineState *vms) { int cpu; -@@ -341,6 +416,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); +@@ -384,6 +450,11 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) + qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#address-cells", addr_cells); + qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#size-cells", 0x0); + ++ if (!vmc->no_cpu_topology) { ++ fdt_add_l3cache_nodes(vms); ++ fdt_add_l2cache_nodes(vms); ++ } + - for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) { + for (cpu = smp_cpus - 1; cpu >= 0; cpu--) { char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu); ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); -@@ -369,7 +447,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); +@@ -413,6 +484,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) + } + + if (!vmc->no_cpu_topology) { ++ fdt_add_l1cache_prop(vms, nodename, cpu); + qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", + qemu_fdt_alloc_phandle(ms->fdt)); } -- -+ 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 +index 8346003a22..8e8ad8029e 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h -@@ -223,6 +223,52 @@ struct AcpiBuildTables { +@@ -221,6 +221,53 @@ struct AcpiBuildTables { BIOSLinker *linker; } AcpiBuildTables; - + +#ifdef __aarch64__ +/* Definitions of the hardcoded cache info*/ + @@ -282,28 +309,28 @@ index bfb0b100..0be3453a 100644 + +/* L1 data cache: */ +#define ARM_L1DCACHE_SIZE 65536 -+#define ARM_L1DCACHE_SET 256 ++#define ARM_L1DCACHE_SETS 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_SETS 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_SETS 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_SETS 2048 +#define ARM_L3CACHE_ASSOCIATIVITY 15 +#define ARM_L3CACHE_ATTRIBUTES 10 +#define ARM_L3CACHE_LINE_SIZE 128 @@ -316,8 +343,11 @@ index bfb0b100..0be3453a 100644 +}; + +#endif - /** - * init_aml_allocator: - * --- -2.23.0 ++ + typedef + struct CrsRangeEntry { + uint64_t base; + +-- +2.27.0 + diff --git a/hw-block-nvme-fix-pci-doorbell-size-calculation.patch b/hw-block-nvme-fix-pci-doorbell-size-calculation.patch deleted file mode 100644 index f0aa09670e471a344c220ae38b8f5ba43b263eaf..0000000000000000000000000000000000000000 --- a/hw-block-nvme-fix-pci-doorbell-size-calculation.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 1aa42c9269c762ad1b7efa41e92f734b093dce1c Mon Sep 17 00:00:00 2001 -From: Klaus Jensen -Date: Tue, 9 Jun 2020 21:03:12 +0200 -Subject: [PATCH 10/11] hw/block/nvme: fix pci doorbell size calculation -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The size of the BAR is 0x1000 (main registers) + 8 bytes for each -queue. Currently, the size of the BAR is calculated like so: - - n->reg_size = pow2ceil(0x1004 + 2 * (n->num_queues + 1) * 4); - -Since the 'num_queues' parameter already accounts for the admin queue, -this should in any case not need to be incremented by one. Also, the -size should be initialized to (0x1000). - - n->reg_size = pow2ceil(0x1000 + 2 * n->num_queues * 4); - -This, with the default value of num_queues (64), we will set aside room -for 1 admin queue and 63 I/O queues (4 bytes per doorbell, 2 doorbells -per queue). - -Signed-off-by: Klaus Jensen -Reviewed-by: Philippe Mathieu-Daudé -Reviewed-by: Maxim Levitsky -Reviewed-by: Keith Busch -Message-Id: <20200609190333.59390-2-its@irrelevant.dk> -Signed-off-by: Kevin Wolf -Signed-off-by: BiaoXiang Ye ---- - hw/block/nvme.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/hw/block/nvme.c b/hw/block/nvme.c -index 417068d8..edac2f1d 100644 ---- a/hw/block/nvme.c -+++ b/hw/block/nvme.c -@@ -42,6 +42,9 @@ - #include "trace.h" - #include "nvme.h" - -+#define NVME_REG_SIZE 0x1000 -+#define NVME_DB_SIZE 4 -+ - #define NVME_GUEST_ERR(trace, fmt, ...) \ - do { \ - (trace_##trace)(__VA_ARGS__); \ -@@ -1348,7 +1351,9 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp) - pcie_endpoint_cap_init(pci_dev, 0x80); - - n->num_namespaces = 1; -- n->reg_size = pow2ceil(0x1004 + 2 * (n->num_queues + 1) * 4); -+ -+ /* num_queues is really number of pairs, so each has two doorbells */ -+ n->reg_size = pow2ceil(NVME_REG_SIZE + 2 * n->num_queues * NVME_DB_SIZE); - n->ns_size = bs_size / (uint64_t)n->num_namespaces; - - n->namespaces = g_new0(NvmeNamespace, n->num_namespaces); --- -2.27.0.dirty - diff --git a/hw-block-nvme-fix-pin-based-interrupt-behavior.patch b/hw-block-nvme-fix-pin-based-interrupt-behavior.patch deleted file mode 100644 index 1fe1213d998869c0f87eabd5d75fc62c3750f06b..0000000000000000000000000000000000000000 --- a/hw-block-nvme-fix-pin-based-interrupt-behavior.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 74ef18c90684f0ae18aef071b9e11a5e8796177b Mon Sep 17 00:00:00 2001 -From: alexchen -Date: Tue, 8 Sep 2020 11:17:20 +0000 -Subject: [PATCH] hw/block/nvme: fix pin-based interrupt behavior - -First, since the device only supports MSI-X or pin-based interrupt, if -MSI-X is not enabled, it should not accept interrupt vectors different -from 0 when creating completion queues. - -Secondly, the irq_status NvmeCtrl member is meant to be compared to the -INTMS register, so it should only be 32 bits wide. And it is really only -useful when used with multi-message MSI. - -Third, since we do not force a 1-to-1 correspondence between cqid and -interrupt vector, the irq_status register should not have bits set -according to cqid, but according to the associated interrupt vector. - -Fix these issues, but keep irq_status available so we can easily support -multi-message MSI down the line. - -Fixes: 5e9aa92eb1a5 ("hw/block: Fix pin-based interrupt behaviour of NVMe") -Cc: "Michael S. Tsirkin" -Cc: Marcel Apfelbaum -Signed-off-by: Klaus Jensen -Reviewed-by: Keith Busch -Message-Id: <20200609190333.59390-8-its@irrelevant.dk> -Signed-off-by: Kevin Wolf -Signed-off-by: BiaoXiang Ye -Signed-off-by: Zhenyu Ye ---- - hw/block/nvme.c | 12 ++++++++---- - hw/block/nvme.h | 2 +- - 2 files changed, 9 insertions(+), 5 deletions(-) - -diff --git a/hw/block/nvme.c b/hw/block/nvme.c -index 36d6a8bb..e35c2e10 100644 ---- a/hw/block/nvme.c -+++ b/hw/block/nvme.c -@@ -115,8 +115,8 @@ static void nvme_irq_assert(NvmeCtrl *n, NvmeCQueue *cq) - msix_notify(&(n->parent_obj), cq->vector); - } else { - trace_nvme_irq_pin(); -- assert(cq->cqid < 64); -- n->irq_status |= 1 << cq->cqid; -+ assert(cq->vector < 32); -+ n->irq_status |= 1 << cq->vector; - nvme_irq_check(n); - } - } else { -@@ -130,8 +130,8 @@ static void nvme_irq_deassert(NvmeCtrl *n, NvmeCQueue *cq) - if (msix_enabled(&(n->parent_obj))) { - return; - } else { -- assert(cq->cqid < 64); -- n->irq_status &= ~(1 << cq->cqid); -+ assert(cq->vector < 32); -+ n->irq_status &= ~(1 << cq->vector); - nvme_irq_check(n); - } - } -@@ -630,6 +630,10 @@ static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeCmd *cmd) - trace_nvme_err_invalid_create_cq_addr(prp1); - return NVME_INVALID_FIELD | NVME_DNR; - } -+ if (unlikely(!msix_enabled(&n->parent_obj) && vector)) { -+ trace_nvme_err_invalid_create_cq_vector(vector); -+ return NVME_INVALID_IRQ_VECTOR | NVME_DNR; -+ } - if (unlikely(vector > n->num_queues)) { - trace_nvme_err_invalid_create_cq_vector(vector); - return NVME_INVALID_IRQ_VECTOR | NVME_DNR; -diff --git a/hw/block/nvme.h b/hw/block/nvme.h -index 557194ee..f4c1ff91 100644 ---- a/hw/block/nvme.h -+++ b/hw/block/nvme.h -@@ -78,7 +78,7 @@ typedef struct NvmeCtrl { - uint32_t cmbsz; - uint32_t cmbloc; - uint8_t *cmbuf; -- uint64_t irq_status; -+ uint32_t irq_status; - uint64_t host_timestamp; /* Timestamp sent by the host */ - uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */ - --- -2.23.0 - diff --git a/hw-core-Rename-smp_parse-machine_parse_smp_config.patch b/hw-core-Rename-smp_parse-machine_parse_smp_config.patch new file mode 100644 index 0000000000000000000000000000000000000000..8537cc6adec12daacbd87f61ab6e36656117c8b0 --- /dev/null +++ b/hw-core-Rename-smp_parse-machine_parse_smp_config.patch @@ -0,0 +1,114 @@ +From 2ce1daae407033e689a559b7346523b18651ee0a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 11 Nov 2021 10:21:23 +0100 +Subject: [PATCH 09/24] hw/core: Rename smp_parse() -> + machine_parse_smp_config() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +All methods related to MachineState are prefixed with "machine_". +smp_parse() does not need to be an exception. Rename it and +const'ify the SMPConfiguration argument, since it doesn't need +to be modified. + +Reviewed-by: Andrew Jones +Reviewed-by: Richard Henderson +Reviewed-by: Yanan Wang +Tested-by: Yanan Wang +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211216132015.815493-9-philmd@redhat.com> +--- + hw/core/machine-smp.c | 6 ++++-- + hw/core/machine.c | 2 +- + include/hw/boards.h | 3 ++- + tests/unit/test-smp-parse.c | 8 ++++---- + 4 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c +index 116a0cbbfa..2cbfd57429 100644 +--- a/hw/core/machine-smp.c ++++ b/hw/core/machine-smp.c +@@ -44,7 +44,8 @@ static char *cpu_hierarchy_to_string(MachineState *ms) + } + + /* +- * smp_parse - Generic function used to parse the given SMP configuration ++ * machine_parse_smp_config: Generic function used to parse the given ++ * SMP configuration + * + * Any missing parameter in "cpus/maxcpus/sockets/cores/threads" will be + * automatically computed based on the provided ones. +@@ -63,7 +64,8 @@ static char *cpu_hierarchy_to_string(MachineState *ms) + * introduced topology members which are likely to be target specific should + * be directly set as 1 if they are omitted (e.g. dies for PC since 4.1). + */ +-void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp) ++void machine_parse_smp_config(MachineState *ms, ++ const SMPConfiguration *config, Error **errp) + { + MachineClass *mc = MACHINE_GET_CLASS(ms); + unsigned cpus = config->has_cpus ? config->cpus : 0; +diff --git a/hw/core/machine.c b/hw/core/machine.c +index 53a99abc56..3993c534b9 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -761,7 +761,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name, + return; + } + +- smp_parse(ms, config, errp); ++ machine_parse_smp_config(ms, config, errp); + } + + static void machine_class_init(ObjectClass *oc, void *data) +diff --git a/include/hw/boards.h b/include/hw/boards.h +index 9c1c190104..7597cec440 100644 +--- a/include/hw/boards.h ++++ b/include/hw/boards.h +@@ -34,7 +34,8 @@ HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine); + void machine_set_cpu_numa_node(MachineState *machine, + const CpuInstanceProperties *props, + Error **errp); +-void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp); ++void machine_parse_smp_config(MachineState *ms, ++ const SMPConfiguration *config, Error **errp); + + /** + * machine_class_allow_dynamic_sysbus_dev: Add type to list of valid devices +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index 0f98c9509e..b6df8137fc 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -337,7 +337,7 @@ static const struct SMPTestData data_with_dies_invalid[] = { + }, + }; + +-static char *smp_config_to_string(SMPConfiguration *config) ++static char *smp_config_to_string(const SMPConfiguration *config) + { + return g_strdup_printf( + "(SMPConfiguration) {\n" +@@ -371,7 +371,7 @@ static char *cpu_topology_to_string(const CpuTopology *topo) + topo->cores, topo->threads, topo->max_cpus); + } + +-static void check_parse(MachineState *ms, SMPConfiguration *config, ++static void check_parse(MachineState *ms, const SMPConfiguration *config, + const CpuTopology *expect_topo, const char *expect_err, + bool is_valid) + { +@@ -380,8 +380,8 @@ static void check_parse(MachineState *ms, SMPConfiguration *config, + g_autofree char *output_topo_str = NULL; + Error *err = NULL; + +- /* call the generic parser smp_parse() */ +- smp_parse(ms, config, &err); ++ /* call the generic parser */ ++ machine_parse_smp_config(ms, config, &err); + + output_topo_str = cpu_topology_to_string(&ms->smp); + +-- +2.27.0 + diff --git a/hw-core-loader-Fix-possible-crash-in-rom_copy.patch b/hw-core-loader-Fix-possible-crash-in-rom_copy.patch deleted file mode 100644 index 770f12b1acf9dfc3c4289e9a9bea7d5936df1968..0000000000000000000000000000000000000000 --- a/hw-core-loader-Fix-possible-crash-in-rom_copy.patch +++ /dev/null @@ -1,45 +0,0 @@ -From aae0faa5d3bee91c66dc4c1543190f55a242771e Mon Sep 17 00:00:00 2001 -From: Thomas Huth -Date: Wed, 25 Sep 2019 14:16:43 +0200 -Subject: [PATCH] hw/core/loader: Fix possible crash in rom_copy() - -Both, "rom->addr" and "addr" are derived from the binary image -that can be loaded with the "-kernel" paramer. The code in -rom_copy() then calculates: - - d = dest + (rom->addr - addr); - -and uses "d" as destination in a memcpy() some lines later. Now with -bad kernel images, it is possible that rom->addr is smaller than addr, -thus "rom->addr - addr" gets negative and the memcpy() then tries to -copy contents from the image to a bad memory location. This could -maybe be used to inject code from a kernel image into the QEMU binary, -so we better fix it with an additional sanity check here. - -Cc: qemu-stable@nongnu.org -Reported-by: Guangming Liu -Buglink: https://bugs.launchpad.net/qemu/+bug/1844635 -Message-Id: <20190925130331.27825-1-thuth@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Thomas Huth -(cherry picked from commit e423455c4f23a1a828901c78fe6d03b7dde79319) -Signed-off-by: Michael Roth ---- - hw/core/loader.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/core/loader.c b/hw/core/loader.c -index 425bf69a99..838a34174a 100644 ---- a/hw/core/loader.c -+++ b/hw/core/loader.c -@@ -1242,7 +1242,7 @@ int rom_copy(uint8_t *dest, hwaddr addr, size_t size) - if (rom->addr + rom->romsize < addr) { - continue; - } -- if (rom->addr > end) { -+ if (rom->addr > end || rom->addr < addr) { - break; - } - --- -2.23.0 diff --git a/hw-core-machine-Introduce-CPU-cluster-topology-suppo.patch b/hw-core-machine-Introduce-CPU-cluster-topology-suppo.patch new file mode 100644 index 0000000000000000000000000000000000000000..39956fbd8ae741e31fdf2c4a2eca362a6ec9f891 --- /dev/null +++ b/hw-core-machine-Introduce-CPU-cluster-topology-suppo.patch @@ -0,0 +1,283 @@ +From bf4a20a82bd4804842dd2960db30e0be7ecb2d32 Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Tue, 28 Dec 2021 17:22:09 +0800 +Subject: [PATCH 11/24] hw/core/machine: Introduce CPU cluster topology support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The new Cluster-Aware Scheduling support has landed in Linux 5.16, +which has been proved to benefit the scheduling performance (e.g. +load balance and wake_affine strategy) on both x86_64 and AArch64. + +So now in Linux 5.16 we have four-level arch-neutral CPU topology +definition like below and a new scheduler level for clusters. +struct cpu_topology { + int thread_id; + int core_id; + int cluster_id; + int package_id; + int llc_id; + cpumask_t thread_sibling; + cpumask_t core_sibling; + cpumask_t cluster_sibling; + cpumask_t llc_sibling; +} + +A cluster generally means a group of CPU cores which share L2 cache +or other mid-level resources, and it is the shared resources that +is used to improve scheduler's behavior. From the point of view of +the size range, it's between CPU die and CPU core. For example, on +some ARM64 Kunpeng servers, we have 6 clusters in each NUMA node, +and 4 CPU cores in each cluster. The 4 CPU cores share a separate +L2 cache and a L3 cache tag, which brings cache affinity advantage. + +In virtualization, on the Hosts which have pClusters (physical +clusters), if we can design a vCPU topology with cluster level for +guest kernel and have a dedicated vCPU pinning. A Cluster-Aware +Guest kernel can also make use of the cache affinity of CPU clusters +to gain similar scheduling performance. + +This patch adds infrastructure for CPU cluster level topology +configuration and parsing, so that the user can specify cluster +parameter if their machines support it. + +Signed-off-by: Yanan Wang +Message-Id: <20211228092221.21068-3-wangyanan55@huawei.com> +Reviewed-by: Philippe Mathieu-Daudé +[PMD: Added '(since 7.0)' to @clusters in qapi/machine.json] +Signed-off-by: Philippe Mathieu-Daudé +--- + hw/core/machine-smp.c | 26 +++++++++++++++++++------- + hw/core/machine.c | 3 +++ + include/hw/boards.h | 6 +++++- + qapi/machine.json | 5 ++++- + qemu-options.hx | 7 ++++--- + softmmu/vl.c | 3 +++ + 6 files changed, 38 insertions(+), 12 deletions(-) + +diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c +index 2cbfd57429..b39ed21e65 100644 +--- a/hw/core/machine-smp.c ++++ b/hw/core/machine-smp.c +@@ -37,6 +37,10 @@ static char *cpu_hierarchy_to_string(MachineState *ms) + g_string_append_printf(s, " * dies (%u)", ms->smp.dies); + } + ++ if (mc->smp_props.clusters_supported) { ++ g_string_append_printf(s, " * clusters (%u)", ms->smp.clusters); ++ } ++ + g_string_append_printf(s, " * cores (%u)", ms->smp.cores); + g_string_append_printf(s, " * threads (%u)", ms->smp.threads); + +@@ -71,6 +75,7 @@ void machine_parse_smp_config(MachineState *ms, + unsigned cpus = config->has_cpus ? config->cpus : 0; + unsigned sockets = config->has_sockets ? config->sockets : 0; + unsigned dies = config->has_dies ? config->dies : 0; ++ unsigned clusters = config->has_clusters ? config->clusters : 0; + unsigned cores = config->has_cores ? config->cores : 0; + unsigned threads = config->has_threads ? config->threads : 0; + unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0; +@@ -82,6 +87,7 @@ void machine_parse_smp_config(MachineState *ms, + if ((config->has_cpus && config->cpus == 0) || + (config->has_sockets && config->sockets == 0) || + (config->has_dies && config->dies == 0) || ++ (config->has_clusters && config->clusters == 0) || + (config->has_cores && config->cores == 0) || + (config->has_threads && config->threads == 0) || + (config->has_maxcpus && config->maxcpus == 0)) { +@@ -97,8 +103,13 @@ void machine_parse_smp_config(MachineState *ms, + error_setg(errp, "dies not supported by this machine's CPU topology"); + return; + } ++ if (!mc->smp_props.clusters_supported && clusters > 1) { ++ error_setg(errp, "clusters not supported by this machine's CPU topology"); ++ return; ++ } + + dies = dies > 0 ? dies : 1; ++ clusters = clusters > 0 ? clusters : 1; + + /* compute missing values based on the provided ones */ + if (cpus == 0 && maxcpus == 0) { +@@ -113,41 +124,42 @@ void machine_parse_smp_config(MachineState *ms, + if (sockets == 0) { + cores = cores > 0 ? cores : 1; + threads = threads > 0 ? threads : 1; +- sockets = maxcpus / (dies * cores * threads); ++ sockets = maxcpus / (dies * clusters * cores * threads); + } else if (cores == 0) { + threads = threads > 0 ? threads : 1; +- cores = maxcpus / (sockets * dies * threads); ++ cores = maxcpus / (sockets * dies * clusters * threads); + } + } else { + /* prefer cores over sockets since 6.2 */ + if (cores == 0) { + sockets = sockets > 0 ? sockets : 1; + threads = threads > 0 ? threads : 1; +- cores = maxcpus / (sockets * dies * threads); ++ cores = maxcpus / (sockets * dies * clusters * threads); + } else if (sockets == 0) { + threads = threads > 0 ? threads : 1; +- sockets = maxcpus / (dies * cores * threads); ++ sockets = maxcpus / (dies * clusters * cores * threads); + } + } + + /* try to calculate omitted threads at last */ + if (threads == 0) { +- threads = maxcpus / (sockets * dies * cores); ++ threads = maxcpus / (sockets * dies * clusters * cores); + } + } + +- maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads; ++ maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * clusters * cores * threads; + cpus = cpus > 0 ? cpus : maxcpus; + + ms->smp.cpus = cpus; + ms->smp.sockets = sockets; + ms->smp.dies = dies; ++ ms->smp.clusters = clusters; + ms->smp.cores = cores; + ms->smp.threads = threads; + ms->smp.max_cpus = maxcpus; + + /* sanity-check of the computed topology */ +- if (sockets * dies * cores * threads != maxcpus) { ++ if (sockets * dies * clusters * cores * threads != maxcpus) { + g_autofree char *topo_msg = cpu_hierarchy_to_string(ms); + error_setg(errp, "Invalid CPU topology: " + "product of the hierarchy must match maxcpus: " +diff --git a/hw/core/machine.c b/hw/core/machine.c +index 3993c534b9..a4a2df405f 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -742,10 +742,12 @@ static void machine_get_smp(Object *obj, Visitor *v, const char *name, + .has_cpus = true, .cpus = ms->smp.cpus, + .has_sockets = true, .sockets = ms->smp.sockets, + .has_dies = true, .dies = ms->smp.dies, ++ .has_clusters = true, .clusters = ms->smp.clusters, + .has_cores = true, .cores = ms->smp.cores, + .has_threads = true, .threads = ms->smp.threads, + .has_maxcpus = true, .maxcpus = ms->smp.max_cpus, + }; ++ + if (!visit_type_SMPConfiguration(v, name, &config, &error_abort)) { + return; + } +@@ -932,6 +934,7 @@ static void machine_initfn(Object *obj) + ms->smp.max_cpus = mc->default_cpus; + ms->smp.sockets = 1; + ms->smp.dies = 1; ++ ms->smp.clusters = 1; + ms->smp.cores = 1; + ms->smp.threads = 1; + } +diff --git a/include/hw/boards.h b/include/hw/boards.h +index 7597cec440..f49a2578ea 100644 +--- a/include/hw/boards.h ++++ b/include/hw/boards.h +@@ -129,10 +129,12 @@ typedef struct { + * SMPCompatProps: + * @prefer_sockets - whether sockets are preferred over cores in smp parsing + * @dies_supported - whether dies are supported by the machine ++ * @clusters_supported - whether clusters are supported by the machine + */ + typedef struct { + bool prefer_sockets; + bool dies_supported; ++ bool clusters_supported; + } SMPCompatProps; + + /** +@@ -299,7 +301,8 @@ typedef struct DeviceMemoryState { + * @cpus: the number of present logical processors on the machine + * @sockets: the number of sockets on the machine + * @dies: the number of dies in one socket +- * @cores: the number of cores in one die ++ * @clusters: the number of clusters in one die ++ * @cores: the number of cores in one cluster + * @threads: the number of threads in one core + * @max_cpus: the maximum number of logical processors on the machine + */ +@@ -307,6 +310,7 @@ typedef struct CpuTopology { + unsigned int cpus; + unsigned int sockets; + unsigned int dies; ++ unsigned int clusters; + unsigned int cores; + unsigned int threads; + unsigned int max_cpus; +diff --git a/qapi/machine.json b/qapi/machine.json +index f1839acf20..8faa51074e 100644 +--- a/qapi/machine.json ++++ b/qapi/machine.json +@@ -1396,7 +1396,9 @@ + # + # @dies: number of dies per socket in the CPU topology + # +-# @cores: number of cores per die in the CPU topology ++# @clusters: number of clusters per die in the CPU topology (since 7.0) ++# ++# @cores: number of cores per cluster in the CPU topology + # + # @threads: number of threads per core in the CPU topology + # +@@ -1408,6 +1410,7 @@ + '*cpus': 'int', + '*sockets': 'int', + '*dies': 'int', ++ '*clusters': 'int', + '*cores': 'int', + '*threads': 'int', + '*maxcpus': 'int' } } +diff --git a/qemu-options.hx b/qemu-options.hx +index 7a59db7764..0f26f7dad7 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -206,13 +206,14 @@ SRST + ERST + + DEF("smp", HAS_ARG, QEMU_OPTION_smp, +- "-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]\n" ++ "-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,clusters=clusters][,cores=cores][,threads=threads]\n" + " set the number of initial CPUs to 'n' [default=1]\n" + " maxcpus= maximum number of total CPUs, including\n" + " offline CPUs for hotplug, etc\n" + " sockets= number of sockets on the machine board\n" + " dies= number of dies in one socket\n" +- " cores= number of cores in one die\n" ++ " clusters= number of clusters in one die\n" ++ " cores= number of cores in one cluster\n" + " threads= number of threads in one core\n" + "Note: Different machines may have different subsets of the CPU topology\n" + " parameters supported, so the actual meaning of the supported parameters\n" +@@ -228,7 +229,7 @@ DEF("smp", HAS_ARG, QEMU_OPTION_smp, + " must be set as 1 in the purpose of correct parsing.\n", + QEMU_ARCH_ALL) + SRST +-``-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]`` ++``-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,clusters=clusters][,cores=cores][,threads=threads]`` + Simulate a SMP system with '\ ``n``\ ' CPUs initially present on + the machine type board. On boards supporting CPU hotplug, the optional + '\ ``maxcpus``\ ' parameter can be set to enable further CPUs to be +diff --git a/softmmu/vl.c b/softmmu/vl.c +index 620a1f1367..d9e4c619d3 100644 +--- a/softmmu/vl.c ++++ b/softmmu/vl.c +@@ -726,6 +726,9 @@ static QemuOptsList qemu_smp_opts = { + }, { + .name = "dies", + .type = QEMU_OPT_NUMBER, ++ }, { ++ .name = "clusters", ++ .type = QEMU_OPT_NUMBER, + }, { + .name = "cores", + .type = QEMU_OPT_NUMBER, +-- +2.27.0 + diff --git a/hw-display-exynos4210_fimd-Fix-potential-NULL-pointe.patch b/hw-display-exynos4210_fimd-Fix-potential-NULL-pointe.patch deleted file mode 100644 index 98e3c3bed9a221c978c8f733e5d587dc2803180b..0000000000000000000000000000000000000000 --- a/hw-display-exynos4210_fimd-Fix-potential-NULL-pointe.patch +++ /dev/null @@ -1,46 +0,0 @@ -From b47d7ad29bc7f30d4ea3fdb0ef86942468416b79 Mon Sep 17 00:00:00 2001 -From: AlexChen -Date: Mon, 2 Nov 2020 16:52:17 +0000 -Subject: [PATCH] hw/display/exynos4210_fimd: Fix potential NULL pointer - dereference -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -In exynos4210_fimd_update(), the pointer s is dereferinced before -being check if it is valid, which may lead to NULL pointer dereference. -So move the assignment to global_width after checking that the s is valid. - -Reported-by: Euler Robot -Signed-off-by: Alex Chen -Reviewed-by: Philippe Mathieu-Daudé -Message-id: 5F9F8D88.9030102@huawei.com -Signed-off-by: Peter Maydell -(cherry-picked from commit 18520fa465) ---- - hw/display/exynos4210_fimd.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c -index 61f7408b1c..85b0ebf23a 100644 ---- a/hw/display/exynos4210_fimd.c -+++ b/hw/display/exynos4210_fimd.c -@@ -1271,12 +1271,14 @@ static void exynos4210_fimd_update(void *opaque) - bool blend = false; - uint8_t *host_fb_addr; - bool is_dirty = false; -- const int global_width = (s->vidtcon[2] & FIMD_VIDTCON2_SIZE_MASK) + 1; -+ int global_width; - - if (!s || !s->console || !s->enabled || - surface_bits_per_pixel(qemu_console_surface(s->console)) == 0) { - return; - } -+ -+ global_width = (s->vidtcon[2] & FIMD_VIDTCON2_SIZE_MASK) + 1; - exynos4210_update_resolution(s); - surface = qemu_console_surface(s->console); - --- -2.27.0 - diff --git a/hw-display-omap_lcdc-Fix-potential-NULL-pointer-dere.patch b/hw-display-omap_lcdc-Fix-potential-NULL-pointer-dere.patch deleted file mode 100644 index 9f11b2d8bbc047a93dd11cf9c6a16eb757676f86..0000000000000000000000000000000000000000 --- a/hw-display-omap_lcdc-Fix-potential-NULL-pointer-dere.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 38697076a98034a078c2411234b8979cf3cec6da Mon Sep 17 00:00:00 2001 -From: AlexChen -Date: Mon, 2 Nov 2020 16:52:17 +0000 -Subject: [PATCH] hw/display/omap_lcdc: Fix potential NULL pointer dereference - -In omap_lcd_interrupts(), the pointer omap_lcd is dereferinced before -being check if it is valid, which may lead to NULL pointer dereference. -So move the assignment to surface after checking that the omap_lcd is valid -and move surface_bits_per_pixel(surface) to after the surface assignment. - -Reported-by: Euler Robot -Signed-off-by: AlexChen -Message-id: 5F9CDB8A.9000001@huawei.com -Reviewed-by: Peter Maydell -Signed-off-by: Peter Maydell -(cherry-picked from commit 0080edc45e) ---- - hw/display/omap_lcdc.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - -diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c -index 07a5effe04..13ab73ec61 100644 ---- a/hw/display/omap_lcdc.c -+++ b/hw/display/omap_lcdc.c -@@ -77,14 +77,18 @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s) - static void omap_update_display(void *opaque) - { - struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque; -- DisplaySurface *surface = qemu_console_surface(omap_lcd->con); -+ DisplaySurface *surface; - draw_line_func draw_line; - int size, height, first, last; - int width, linesize, step, bpp, frame_offset; - hwaddr frame_base; - -- if (!omap_lcd || omap_lcd->plm == 1 || !omap_lcd->enable || -- !surface_bits_per_pixel(surface)) { -+ if (!omap_lcd || omap_lcd->plm == 1 || !omap_lcd->enable) { -+ return; -+ } -+ -+ surface = qemu_console_surface(omap_lcd->con); -+ if (!surface_bits_per_pixel(surface)) { - return; - } - --- -2.27.0 - diff --git a/hw-ehci-check-return-value-of-usb_packet_map.patch b/hw-ehci-check-return-value-of-usb_packet_map.patch deleted file mode 100644 index 2c05a2e61f8deef9a36ca8500cfabcb9736d14bc..0000000000000000000000000000000000000000 --- a/hw-ehci-check-return-value-of-usb_packet_map.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 02d63f9fd9655f1899dabbccaf0568bfaa3e97df Mon Sep 17 00:00:00 2001 -From: Li Qiang -Date: Wed, 12 Aug 2020 09:17:27 -0700 -Subject: [PATCH] hw: ehci: check return value of 'usb_packet_map' - -If 'usb_packet_map' fails, we should stop to process the usb -request. - -Signed-off-by: Li Qiang -Message-Id: <20200812161727.29412-1-liq3ea@163.com> -Signed-off-by: Gerd Hoffmann -(cherry-picked from 2fdb42d8) -Fix CVE-2020-25723 -Signed-off-by: Alex Chen ---- - hw/usb/hcd-ehci.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c -index 5f089f3005..433e6a4fc0 100644 ---- a/hw/usb/hcd-ehci.c -+++ b/hw/usb/hcd-ehci.c -@@ -1370,7 +1370,10 @@ static int ehci_execute(EHCIPacket *p, const char *action) - spd = (p->pid == USB_TOKEN_IN && NLPTR_TBIT(p->qtd.altnext) == 0); - usb_packet_setup(&p->packet, p->pid, ep, 0, p->qtdaddr, spd, - (p->qtd.token & QTD_TOKEN_IOC) != 0); -- usb_packet_map(&p->packet, &p->sgl); -+ if (usb_packet_map(&p->packet, &p->sgl)) { -+ qemu_sglist_destroy(&p->sgl); -+ return -1; -+ } - p->async = EHCI_ASYNC_INITIALIZED; - } - -@@ -1449,7 +1452,10 @@ static int ehci_process_itd(EHCIState *ehci, - if (ep && ep->type == USB_ENDPOINT_XFER_ISOC) { - usb_packet_setup(&ehci->ipacket, pid, ep, 0, addr, false, - (itd->transact[i] & ITD_XACT_IOC) != 0); -- usb_packet_map(&ehci->ipacket, &ehci->isgl); -+ if (usb_packet_map(&ehci->ipacket, &ehci->isgl)) { -+ qemu_sglist_destroy(&ehci->isgl); -+ return -1; -+ } - usb_handle_packet(dev, &ehci->ipacket); - usb_packet_unmap(&ehci->ipacket, &ehci->isgl); - } else { --- -2.27.0 - diff --git a/hw-ide-check-null-block-before-_cancel_dma_sync.patch b/hw-ide-check-null-block-before-_cancel_dma_sync.patch deleted file mode 100644 index 1ff20a9683ec88de3d3a67086ffc82eedff9697e..0000000000000000000000000000000000000000 --- a/hw-ide-check-null-block-before-_cancel_dma_sync.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 3b23698e240bd0efe987cf113e3bc8d233991d21 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Wed, 14 Oct 2020 15:57:18 +0800 -Subject: [PATCH] hw/ide: check null block before _cancel_dma_sync - -fix CVE-2020-25743 - -patch link: https://lists.nongnu.org/archive/html/qemu-devel/2020-09/msg05967.html - -When canceling an i/o operation via ide_cancel_dam_sync(), -a block pointer may be null. Add check to avoid null pointer -dereference. - - -> https://ruhr-uni-bochum.sciebo.de/s/NNWP2GfwzYKeKwE?path=%2Fide_nullptr1 - ==1803100==Hint: address points to the zero page. - #0 blk_bs ../block/block-backend.c:714 - #1 blk_drain ../block/block-backend.c:1715 - #2 ide_cancel_dma_sync ../hw/ide/core.c:723 - #3 bmdma_cmd_writeb ../hw/ide/core.c:723 - #4 bmdma_write ../hw/ide/pci.c:298 - #5 memory_region_write_accessor ../softmmu/memory.c:483 - #6 access_with_adjusted_size ../softmmu/memory.c:544 - #7 memory_region_dispatch_write ../softmmu/memory.c:1465 - #8 flatview_write_continue ../exe.c:3176 - ... - -Reported-by: Ruhr-University -Signed-off-by: Prasad J Pandit ---- - hw/ide/core.c | 1 + - hw/ide/pci.c | 5 ++++- - 2 files changed, 5 insertions(+), 1 deletion(-) - -diff --git a/hw/ide/core.c b/hw/ide/core.c -index f76f7e5234..8105187f49 100644 ---- a/hw/ide/core.c -+++ b/hw/ide/core.c -@@ -718,6 +718,7 @@ void ide_cancel_dma_sync(IDEState *s) - * whole DMA operation will be submitted to disk with a single - * aio operation with preadv/pwritev. - */ -+ assert(s->blk); - if (s->bus->dma->aiocb) { - trace_ide_cancel_dma_sync_remaining(); - blk_drain(s->blk); -diff --git a/hw/ide/pci.c b/hw/ide/pci.c -index b50091b615..b47e675456 100644 ---- a/hw/ide/pci.c -+++ b/hw/ide/pci.c -@@ -295,7 +295,10 @@ void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val) - /* Ignore writes to SSBM if it keeps the old value */ - if ((val & BM_CMD_START) != (bm->cmd & BM_CMD_START)) { - if (!(val & BM_CMD_START)) { -- ide_cancel_dma_sync(idebus_active_if(bm->bus)); -+ IDEState *s = idebus_active_if(bm->bus); -+ if (s->blk) { -+ ide_cancel_dma_sync(s); -+ } - bm->status &= ~BM_STATUS_DMAING; - } else { - bm->cur_addr = bm->addr; --- -2.23.0 - diff --git a/hw-intc-arm_gic-Fix-interrupt-ID-in-GICD_SGIR-regist.patch b/hw-intc-arm_gic-Fix-interrupt-ID-in-GICD_SGIR-regist.patch deleted file mode 100644 index de999b8c89a41d54879d2fd22cc3b852e6c16138..0000000000000000000000000000000000000000 --- a/hw-intc-arm_gic-Fix-interrupt-ID-in-GICD_SGIR-regist.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 3e28567104500238b89ea6b4d684c5350194fea9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= -Date: Mon, 21 Jun 2021 10:12:41 +0800 -Subject: [PATCH] hw/intc/arm_gic: Fix interrupt ID in GICD_SGIR register -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fix CVE-2021-20221 - -Per the ARM Generic Interrupt Controller Architecture specification -(document "ARM IHI 0048B.b (ID072613)"), the SGIINTID field is 4 bit, -not 10: - - - 4.3 Distributor register descriptions - - 4.3.15 Software Generated Interrupt Register, GICD_SG - - - Table 4-21 GICD_SGIR bit assignments - - The Interrupt ID of the SGI to forward to the specified CPU - interfaces. The value of this field is the Interrupt ID, in - the range 0-15, for example a value of 0b0011 specifies - Interrupt ID 3. - -Correct the irq mask to fix an undefined behavior (which eventually -lead to a heap-buffer-overflow, see [Buglink]): - - $ echo 'writel 0x8000f00 0xff4affb0' | qemu-system-aarch64 -M virt,accel=qtest -qtest stdio - [I 1612088147.116987] OPENED - [R +0.278293] writel 0x8000f00 0xff4affb0 - ../hw/intc/arm_gic.c:1498:13: runtime error: index 944 out of bounds for type 'uint8_t [16][8]' - SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../hw/intc/arm_gic.c:1498:13 - -This fixes a security issue when running with KVM on Arm with -kernel-irqchip=off. (The default is kernel-irqchip=on, which is -unaffected, and which is also the correct choice for performance.) - -Cc: qemu-stable@nongnu.org -Fixes: CVE-2021-20221 -Fixes: 9ee6e8bb ("ARMv7 support.") -Buglink: https://bugs.launchpad.net/qemu/+bug/1913916 -Buglink: https://bugs.launchpad.net/qemu/+bug/1913917 - -Reported-by: Alexander Bulekov's avatarAlexander Bulekov -Signed-off-by: Philippe Mathieu-Daudé's avatarPhilippe Mathieu-Daudé -Message-id: 20210131103401.217160-1-f4bug@amsat.org -Reviewed-by: Peter Maydell's avatarPeter Maydell -Signed-off-by: Peter Maydell's avatarPeter Maydell - -Signed-off-by: Jiajie Li ---- - hw/intc/arm_gic.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c -index 77427a4188..492dabaa1c 100644 ---- a/hw/intc/arm_gic.c -+++ b/hw/intc/arm_gic.c -@@ -1454,7 +1454,7 @@ static void gic_dist_writel(void *opaque, hwaddr offset, - int target_cpu; - - cpu = gic_get_current_cpu(s); -- irq = value & 0x3ff; -+ irq = value & 0xf; - switch ((value >> 24) & 3) { - case 0: - mask = (value >> 16) & ALL_CPU_MASK; --- -2.27.0 - diff --git a/hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch b/hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch index 2b77e0b0ce8a678b0c13b7f9f852522617b90c71..926a619152e8af57e0c55b2664d4b2d0c4fc9445 100644 --- a/hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch +++ b/hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch @@ -1,4 +1,4 @@ -From 6bbfb186c8d66b745aeb08143d3198fcedc52d6c Mon Sep 17 00:00:00 2001 +From e94b8dc43d416b3ebf316faf14309fe4c4d0b4f0 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Mon, 6 Apr 2020 11:26:35 +0800 Subject: [PATCH] hw/intc/gicv3: Add CPU hotplug realize hook @@ -17,13 +17,13 @@ Signed-off-by: Salil Mehta 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c -index 2fe79f794d..cacef26546 100644 +index 40016cb84a..9591cfbcc0 100644 --- a/hw/intc/arm_gicv3.c +++ b/hw/intc/arm_gicv3.c -@@ -361,6 +361,19 @@ static const MemoryRegionOps gic_ops[] = { +@@ -376,6 +376,19 @@ static const MemoryRegionOps gic_ops[] = { } }; - + +static void gicv3_cpu_realize(GICv3State *s, int i) +{ + gicv3_init_one_cpuif(s, i); @@ -40,32 +40,32 @@ index 2fe79f794d..cacef26546 100644 static void arm_gic_realize(DeviceState *dev, Error **errp) { /* Device instance realize function for the GIC sysbus device */ -@@ -388,7 +401,7 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) - } - +@@ -393,7 +406,7 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) + gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops); + for (i = 0; i < s->num_cpu; i++) { - gicv3_init_one_cpuif(s, i); + gicv3_cpu_realize(s, i); } } - -@@ -398,6 +411,8 @@ static void arm_gicv3_class_init(ObjectClass *klass, void *data) + +@@ -403,6 +416,8 @@ static void arm_gicv3_class_init(ObjectClass *klass, void *data) ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass); ARMGICv3Class *agc = ARM_GICV3_CLASS(klass); - + + agc->parent_cpu_hotplug_realize = agcc->cpu_hotplug_realize; + agcc->cpu_hotplug_realize = arm_gicv3_cpu_hotplug_realize; agcc->post_load = arm_gicv3_post_load; device_class_set_parent_realize(dc, arm_gic_realize, &agc->parent_realize); } diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c -index 798f295d7c..8740a52c9f 100644 +index 1a11d1986d..f8ef6817a4 100644 --- a/hw/intc/arm_gicv3_common.c +++ b/hw/intc/arm_gicv3_common.c -@@ -313,6 +313,11 @@ static void arm_gicv3_common_cpu_realize(GICv3State *s, int ncpu) +@@ -311,6 +311,11 @@ static void arm_gicv3_common_cpu_realize(GICv3State *s, int ncpu) gicv3_set_gicv3state(cpu, &s->cpu[ncpu]); } - + +static void arm_gicv3_common_cpu_hotplug_realize(GICv3State *s, int ncpu) +{ + arm_gicv3_common_cpu_realize(s, ncpu); @@ -74,45 +74,45 @@ index 798f295d7c..8740a52c9f 100644 static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) { GICv3State *s = ARM_GICV3_COMMON(dev); -@@ -357,6 +362,7 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) - +@@ -371,6 +376,7 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + for (i = 0; i < s->num_cpu; i++) { CPUState *cpu = qemu_get_cpu(i); + uint64_t cpu_affid; - int last; - -@@ -508,12 +514,14 @@ static Property arm_gicv3_common_properties[] = { + + arm_gicv3_common_cpu_realize(s, i); +@@ -537,12 +543,14 @@ static Property arm_gicv3_common_properties[] = { static void arm_gicv3_common_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass); ARMLinuxBootIfClass *albifc = ARM_LINUX_BOOT_IF_CLASS(klass); - + dc->reset = arm_gicv3_common_reset; dc->realize = arm_gicv3_common_realize; - dc->props = arm_gicv3_common_properties; + device_class_set_props(dc, arm_gicv3_common_properties); dc->vmsd = &vmstate_gicv3; + agcc->cpu_hotplug_realize = arm_gicv3_common_cpu_hotplug_realize; albifc->arm_linux_init = arm_gic_common_linux_init; } - + diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c -index b2936938cb..f8d7be5479 100644 +index 596b31998b..95271e754b 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c -@@ -78,6 +78,7 @@ typedef struct KVMARMGICv3Class { +@@ -76,6 +76,7 @@ struct KVMARMGICv3Class { ARMGICv3CommonClass parent_class; DeviceRealize parent_realize; void (*parent_reset)(DeviceState *dev); + CPUHotplugRealize parent_cpu_hotplug_realize; - } KVMARMGICv3Class; - + }; + static void kvm_arm_gicv3_set_irq(void *opaque, int irq, int level) -@@ -768,6 +769,14 @@ static void kvm_arm_gicv3_cpu_realize(GICv3State *s, int ncpu) +@@ -771,6 +772,14 @@ static void kvm_arm_gicv3_cpu_realize(GICv3State *s, int ncpu) define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); } - + +static void kvm_arm_gicv3_cpu_hotplug_realize(GICv3State *s, int ncpu) +{ + KVMARMGICv3Class *kagcc = KVM_ARM_GICV3_GET_CLASS(s); @@ -124,47 +124,48 @@ index b2936938cb..f8d7be5479 100644 static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) { GICv3State *s = KVM_ARM_GICV3(dev); -@@ -884,6 +893,8 @@ static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data) +@@ -881,6 +890,8 @@ static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data) ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass); KVMARMGICv3Class *kgc = KVM_ARM_GICV3_CLASS(klass); - + + kgc->parent_cpu_hotplug_realize = agcc->cpu_hotplug_realize; + agcc->cpu_hotplug_realize = kvm_arm_gicv3_cpu_hotplug_realize; agcc->pre_save = kvm_arm_gicv3_get; agcc->post_load = kvm_arm_gicv3_put; device_class_set_parent_realize(dc, kvm_arm_gicv3_realize, diff --git a/include/hw/intc/arm_gicv3.h b/include/hw/intc/arm_gicv3.h -index 4a6fd85e22..98f2bdb7e9 100644 +index a81a6ae7ec..e360556bd5 100644 --- a/include/hw/intc/arm_gicv3.h +++ b/include/hw/intc/arm_gicv3.h -@@ -26,6 +26,8 @@ typedef struct ARMGICv3Class { +@@ -26,6 +26,8 @@ struct ARMGICv3Class { ARMGICv3CommonClass parent_class; /*< public >*/ - + + CPUHotplugRealize parent_cpu_hotplug_realize; + DeviceRealize parent_realize; - } ARMGICv3Class; - + }; + diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h -index 31ec9a1ae4..45cc50ed3b 100644 +index fc38e4b7dc..c208a191ff 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h -@@ -286,11 +286,15 @@ GICV3_BITMAP_ACCESSORS(edge_trigger) - #define ARM_GICV3_COMMON_GET_CLASS(obj) \ - OBJECT_GET_CLASS(ARMGICv3CommonClass, (obj), TYPE_ARM_GICV3_COMMON) - +@@ -306,11 +306,15 @@ typedef struct ARMGICv3CommonClass ARMGICv3CommonClass; + DECLARE_OBJ_CHECKERS(GICv3State, ARMGICv3CommonClass, + ARM_GICV3_COMMON, TYPE_ARM_GICV3_COMMON) + +typedef void (*CPUHotplugRealize)(GICv3State *s, int ncpu); + - typedef struct ARMGICv3CommonClass { + struct ARMGICv3CommonClass { /*< private >*/ SysBusDeviceClass parent_class; /*< public >*/ - + + CPUHotplugRealize cpu_hotplug_realize; + void (*pre_save)(GICv3State *s); void (*post_load)(GICv3State *s); - } ARMGICv3CommonClass; --- -2.19.1 + }; +-- +2.27.0 + diff --git a/hw-net-e1000e-advance-desc_offset-in-case-of-null-de.patch b/hw-net-e1000e-advance-desc_offset-in-case-of-null-de.patch deleted file mode 100644 index 3bffc1cf188e0ca6167e1ffb3cd138f14073dc8b..0000000000000000000000000000000000000000 --- a/hw-net-e1000e-advance-desc_offset-in-case-of-null-de.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 2b157688d19da5ce4fca6b5f3c78d2e309ecec9a Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Wed, 11 Nov 2020 18:36:36 +0530 -Subject: [PATCH] hw/net/e1000e: advance desc_offset in case of null descriptor - -While receiving packets via e1000e_write_packet_to_guest() routine, -'desc_offset' is advanced only when RX descriptor is processed. And -RX descriptor is not processed if it has NULL buffer address. -This may lead to an infinite loop condition. Increament 'desc_offset' -to process next descriptor in the ring to avoid infinite loop. - -Reported-by: Cheol-woo Myung <330cjfdn@gmail.com> -Signed-off-by: Prasad J Pandit -Signed-off-by: Jason Wang -(cherry-picked from c2cb5116) -Fix CVE-2020-28916 -Signed-off-by: Alex Chen ---- - hw/net/e1000e_core.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c -index 2a221c2ef9..e45d47f584 100644 ---- a/hw/net/e1000e_core.c -+++ b/hw/net/e1000e_core.c -@@ -1595,13 +1595,13 @@ e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt, - (const char *) &fcs_pad, e1000x_fcs_len(core->mac)); - } - } -- desc_offset += desc_size; -- if (desc_offset >= total_size) { -- is_last = true; -- } - } else { /* as per intel docs; skip descriptors with null buf addr */ - trace_e1000e_rx_null_descriptor(); - } -+ desc_offset += desc_size; -+ if (desc_offset >= total_size) { -+ is_last = true; -+ } - - e1000e_write_rx_descr(core, desc, is_last ? core->rx_pkt : NULL, - rss_info, do_ps ? ps_hdr_len : 0, &bastate.written); --- -2.27.0 - diff --git a/hw-net-fix-vmxnet3-live-migration.patch b/hw-net-fix-vmxnet3-live-migration.patch deleted file mode 100644 index be97b3ac0dc76d839f646078151cddc0861ab094..0000000000000000000000000000000000000000 --- a/hw-net-fix-vmxnet3-live-migration.patch +++ /dev/null @@ -1,136 +0,0 @@ -From b8b9f58ee5d3cff0a1e7cca770fe632043efb728 Mon Sep 17 00:00:00 2001 -From: Marcel Apfelbaum -Date: Fri, 5 Jul 2019 04:07:11 +0300 -Subject: [PATCH] hw/net: fix vmxnet3 live migration - -At some point vmxnet3 live migration stopped working and git-bisect -didn't help finding a working version. -The issue is the PCI configuration space is not being migrated -successfully and MSIX remains masked at destination. - -Remove the migration differentiation between PCI and PCIe since -the logic resides now inside VMSTATE_PCI_DEVICE. -Remove also the VMXNET3_COMPAT_FLAG_DISABLE_PCIE based differentiation -since at 'realize' time is decided if the device is PCI or PCIe, -then the above macro is enough. - -Use the opportunity to move to the standard VMSTATE_MSIX -instead of the deprecated SaveVMHandlers. - -Signed-off-by: Marcel Apfelbaum -Message-Id: <20190705010711.23277-1-marcel.apfelbaum@gmail.com> -Tested-by: Sukrit Bhatnagar -Reviewed-by: Dmitry Fleytman -Signed-off-by: Dr. David Alan Gilbert ---- - hw/net/vmxnet3.c | 52 ++---------------------------------------------- - 1 file changed, 2 insertions(+), 50 deletions(-) - -diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c -index ecc4f5bcf0..bf8e6ca4c9 100644 ---- a/hw/net/vmxnet3.c -+++ b/hw/net/vmxnet3.c -@@ -2153,21 +2153,6 @@ vmxnet3_cleanup_msi(VMXNET3State *s) - msi_uninit(d); - } - --static void --vmxnet3_msix_save(QEMUFile *f, void *opaque) --{ -- PCIDevice *d = PCI_DEVICE(opaque); -- msix_save(d, f); --} -- --static int --vmxnet3_msix_load(QEMUFile *f, void *opaque, int version_id) --{ -- PCIDevice *d = PCI_DEVICE(opaque); -- msix_load(d, f); -- return 0; --} -- - static const MemoryRegionOps b0_ops = { - .read = vmxnet3_io_bar0_read, - .write = vmxnet3_io_bar0_write, -@@ -2188,11 +2173,6 @@ static const MemoryRegionOps b1_ops = { - }, - }; - --static SaveVMHandlers savevm_vmxnet3_msix = { -- .save_state = vmxnet3_msix_save, -- .load_state = vmxnet3_msix_load, --}; -- - static uint64_t vmxnet3_device_serial_num(VMXNET3State *s) - { - uint64_t dsn_payload; -@@ -2215,7 +2195,6 @@ static uint64_t vmxnet3_device_serial_num(VMXNET3State *s) - - static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp) - { -- DeviceState *dev = DEVICE(pci_dev); - VMXNET3State *s = VMXNET3(pci_dev); - int ret; - -@@ -2261,8 +2240,6 @@ static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp) - pcie_dev_ser_num_init(pci_dev, VMXNET3_DSN_OFFSET, - vmxnet3_device_serial_num(s)); - } -- -- register_savevm_live(dev, "vmxnet3-msix", -1, 1, &savevm_vmxnet3_msix, s); - } - - static void vmxnet3_instance_init(Object *obj) -@@ -2452,29 +2429,6 @@ static const VMStateDescription vmstate_vmxnet3_int_state = { - } - }; - --static bool vmxnet3_vmstate_need_pcie_device(void *opaque) --{ -- VMXNET3State *s = VMXNET3(opaque); -- -- return !(s->compat_flags & VMXNET3_COMPAT_FLAG_DISABLE_PCIE); --} -- --static bool vmxnet3_vmstate_test_pci_device(void *opaque, int version_id) --{ -- return !vmxnet3_vmstate_need_pcie_device(opaque); --} -- --static const VMStateDescription vmstate_vmxnet3_pcie_device = { -- .name = "vmxnet3/pcie", -- .version_id = 1, -- .minimum_version_id = 1, -- .needed = vmxnet3_vmstate_need_pcie_device, -- .fields = (VMStateField[]) { -- VMSTATE_PCI_DEVICE(parent_obj, VMXNET3State), -- VMSTATE_END_OF_LIST() -- } --}; -- - static const VMStateDescription vmstate_vmxnet3 = { - .name = "vmxnet3", - .version_id = 1, -@@ -2482,9 +2436,8 @@ static const VMStateDescription vmstate_vmxnet3 = { - .pre_save = vmxnet3_pre_save, - .post_load = vmxnet3_post_load, - .fields = (VMStateField[]) { -- VMSTATE_STRUCT_TEST(parent_obj, VMXNET3State, -- vmxnet3_vmstate_test_pci_device, 0, -- vmstate_pci_device, PCIDevice), -+ VMSTATE_PCI_DEVICE(parent_obj, VMXNET3State), -+ VMSTATE_MSIX(parent_obj, VMXNET3State), - VMSTATE_BOOL(rx_packets_compound, VMXNET3State), - VMSTATE_BOOL(rx_vlan_stripping, VMXNET3State), - VMSTATE_BOOL(lro_supported, VMXNET3State), -@@ -2520,7 +2473,6 @@ static const VMStateDescription vmstate_vmxnet3 = { - }, - .subsections = (const VMStateDescription*[]) { - &vmxstate_vmxnet3_mcast_list, -- &vmstate_vmxnet3_pcie_device, - NULL - } - }; --- -2.27.0 - diff --git a/hw-net-net_tx_pkt-fix-assertion-failure-in-net_tx_pk.patch b/hw-net-net_tx_pkt-fix-assertion-failure-in-net_tx_pk.patch deleted file mode 100644 index a763f93bc4859f6f38fa8f6d83da6d84f1ab01f2..0000000000000000000000000000000000000000 --- a/hw-net-net_tx_pkt-fix-assertion-failure-in-net_tx_pk.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 596e7e8908b742f727d02ec9ab747116573f67e0 Mon Sep 17 00:00:00 2001 -From: Mauro Matteo Cascella -Date: Sat, 1 Aug 2020 18:42:38 +0200 -Subject: [PATCH] hw/net/net_tx_pkt: fix assertion failure in - net_tx_pkt_add_raw_fragment() - -An assertion failure issue was found in the code that processes network packets -while adding data fragments into the packet context. It could be abused by a -malicious guest to abort the QEMU process on the host. This patch replaces the -affected assert() with a conditional statement, returning false if the current -data fragment exceeds max_raw_frags. - -Reported-by: Alexander Bulekov -Reported-by: Ziming Zhang -Reviewed-by: Dmitry Fleytman -Signed-off-by: Mauro Matteo Cascella -Signed-off-by: Jason Wang ---- - hw/net/net_tx_pkt.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c -index 162f802dd7..54d4c3bbd0 100644 ---- a/hw/net/net_tx_pkt.c -+++ b/hw/net/net_tx_pkt.c -@@ -379,7 +379,10 @@ bool net_tx_pkt_add_raw_fragment(struct NetTxPkt *pkt, hwaddr pa, - hwaddr mapped_len = 0; - struct iovec *ventry; - assert(pkt); -- assert(pkt->max_raw_frags > pkt->raw_frags); -+ -+ if (pkt->raw_frags >= pkt->max_raw_frags) { -+ return false; -+ } - - if (!len) { - return true; --- -2.23.0 - diff --git a/hw-net-rocker_of_dpa-fix-double-free-bug-of-rocker-d.patch b/hw-net-rocker-fix-security-vulnerability.patch similarity index 33% rename from hw-net-rocker_of_dpa-fix-double-free-bug-of-rocker-d.patch rename to hw-net-rocker-fix-security-vulnerability.patch index dd3a972936049057760b5819669beec96cbeb48c..c841e9709c0b60127be40a7f163f3f9fcd0124bc 100644 --- a/hw-net-rocker_of_dpa-fix-double-free-bug-of-rocker-d.patch +++ b/hw-net-rocker-fix-security-vulnerability.patch @@ -1,29 +1,18 @@ -From e921d308845a0249126c59655d985007acf58ed7 Mon Sep 17 00:00:00 2001 -From: Qiang Ning -Date: Mon, 12 Jul 2021 17:30:45 +0800 -Subject: [PATCH] hw/net/rocker_of_dpa: fix double free bug of rocker device +From 9a8de722b047ba66f70e87fb29b877935c187457 Mon Sep 17 00:00:00 2001 +From: Lichang Zhao +Date: Thu, 10 Feb 2022 16:54:06 +0800 +Subject: [PATCH] hw/net/rocker: fix security vulnerability -The of_dpa_cmd_add_l2_flood function of the rocker device -releases the memory of group->l2_flood.group_ids before -applying for new memory. If the l2_group configured by -the guest does not match the input group->l2_flood.group_ids, -the err_out branch is redirected to release the memory of the -group->l2_flood.group_ids branch. The pointer is not set to -NULL after the memory is freed. When the guest accesses the -of_dpa_cmd_add_l2_flood function again, the memory of -group->l2_flood.group_ids is released again. As a result, -the memory is double free. +fix security vulnerability -Fix that by setting group->l2_flood.group_ids to NULL after free. - -Signed-off-by: Jiajie Li -Signed-off-by: Qiang Ning +Signed-off-by: Lichang zhao +Signed-off-by: Jinhao Gao --- hw/net/rocker/rocker_of_dpa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c -index 8e347d1ee4..0c9de5f014 100644 +index b3b8c5bb6d..8ac26e6beb 100644 --- a/hw/net/rocker/rocker_of_dpa.c +++ b/hw/net/rocker/rocker_of_dpa.c @@ -2070,6 +2070,7 @@ static int of_dpa_cmd_add_l2_flood(OfDpa *of_dpa, OfDpaGroup *group, diff --git a/hw-net-xgmac-Fix-buffer-overflow-in-xgmac_enet_send.patch b/hw-net-xgmac-Fix-buffer-overflow-in-xgmac_enet_send.patch deleted file mode 100644 index 62be98b6f147c098f57efbad27cbc6a5831d5ea2..0000000000000000000000000000000000000000 --- a/hw-net-xgmac-Fix-buffer-overflow-in-xgmac_enet_send.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 2d18434c1ca66d68f80954be6828a3770176dab4 Mon Sep 17 00:00:00 2001 -From: Mauro Matteo Cascella -Date: Fri, 10 Jul 2020 11:19:41 +0200 -Subject: [PATCH] hw/net/xgmac: Fix buffer overflow in xgmac_enet_send() - -A buffer overflow issue was reported by Mr. Ziming Zhang, CC'd here. It -occurs while sending an Ethernet frame due to missing break statements -and improper checking of the buffer size. - -Reported-by: Ziming Zhang -Signed-off-by: Mauro Matteo Cascella -Reviewed-by: Peter Maydell -Signed-off-by: Jason Wang ---- - hw/net/xgmac.c | 14 ++++++++++++-- - 1 file changed, 12 insertions(+), 2 deletions(-) - -diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c -index f49df95b07..f496f7ed4c 100644 ---- a/hw/net/xgmac.c -+++ b/hw/net/xgmac.c -@@ -217,21 +217,31 @@ static void xgmac_enet_send(XgmacState *s) - } - len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff); - -+ /* -+ * FIXME: these cases of malformed tx descriptors (bad sizes) -+ * should probably be reported back to the guest somehow -+ * rather than simply silently stopping processing, but we -+ * don't know what the hardware does in this situation. -+ * This will only happen for buggy guests anyway. -+ */ - if ((bd.buffer1_size & 0xfff) > 2048) { - DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- " - "xgmac buffer 1 len on send > 2048 (0x%x)\n", - __func__, bd.buffer1_size & 0xfff); -+ break; - } - if ((bd.buffer2_size & 0xfff) != 0) { - DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- " - "xgmac buffer 2 len on send != 0 (0x%x)\n", - __func__, bd.buffer2_size & 0xfff); -+ break; - } -- if (len >= sizeof(frame)) { -+ if (frame_size + len >= sizeof(frame)) { - DEBUGF_BRK("qemu:%s: buffer overflow %d read into %zu " -- "buffer\n" , __func__, len, sizeof(frame)); -+ "buffer\n" , __func__, frame_size + len, sizeof(frame)); - DEBUGF_BRK("qemu:%s: buffer1.size=%d; buffer2.size=%d\n", - __func__, bd.buffer1_size, bd.buffer2_size); -+ break; - } - - cpu_physical_memory_read(bd.buffer1_addr, ptr, len); --- -2.23.0 - diff --git a/hw-pci-host-add-pci-intack-write-method.patch b/hw-pci-host-add-pci-intack-write-method.patch deleted file mode 100644 index bb09d022bb7b23fae8cc34e7c7feae65c6e5bc3e..0000000000000000000000000000000000000000 --- a/hw-pci-host-add-pci-intack-write-method.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 80214941ed6ce24983d8f161a7c9532678acc6f1 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Thu, 25 Mar 2021 17:03:57 +0800 -Subject: [PATCH] hw/pci-host: add pci-intack write method - -fix CVE-2020-15469 - -Add pci-intack mmio write method to avoid NULL pointer dereference -issue. - -Reported-by: Lei Sun -Reviewed-by: Li Qiang -Signed-off-by: Prasad J Pandit - -Signed-off-by: Jiajie Li ---- - hw/pci-host/prep.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c -index c564f234af..f03c81f651 100644 ---- a/hw/pci-host/prep.c -+++ b/hw/pci-host/prep.c -@@ -26,6 +26,7 @@ - #include "qemu/osdep.h" - #include "qemu-common.h" - #include "qemu/units.h" -+#include "qemu/log.h" - #include "qapi/error.h" - #include "hw/hw.h" - #include "hw/pci/pci.h" -@@ -117,8 +118,15 @@ static uint64_t raven_intack_read(void *opaque, hwaddr addr, - return pic_read_irq(isa_pic); - } - -+static void raven_intack_write(void *opaque, hwaddr addr, -+ uint64_t data, unsigned size) -+{ -+ qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__); -+} -+ - static const MemoryRegionOps raven_intack_ops = { - .read = raven_intack_read, -+ .write = raven_intack_write, - .valid = { - .max_access_size = 1, - }, --- -2.27.0 - diff --git a/hw-pci-pci_bridge-Correct-pci_bridge_io-memory-regio.patch b/hw-pci-pci_bridge-Correct-pci_bridge_io-memory-regio.patch deleted file mode 100644 index 76497d9ef4f4e111baba53cdd84ac7b7dbecb112..0000000000000000000000000000000000000000 --- a/hw-pci-pci_bridge-Correct-pci_bridge_io-memory-regio.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 595a0d0a0f21cd73863ea3b78ecccb6e0ea8b7a8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= -Date: Mon, 1 Jun 2020 16:29:25 +0200 -Subject: [PATCH 2/5] hw/pci/pci_bridge: Correct pci_bridge_io memory region - size -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -memory_region_set_size() handle the 16 Exabytes limit by -special-casing the UINT64_MAX value. This is not a problem -for the 32-bit maximum, 4 GiB. -By using the UINT32_MAX value, the pci_bridge_io MemoryRegion -ends up missing 1 byte: - - (qemu) info mtree - memory-region: pci_bridge_io - 0000000000000000-00000000fffffffe (prio 0, i/o): pci_bridge_io - 0000000000000060-0000000000000060 (prio 0, i/o): i8042-data - 0000000000000064-0000000000000064 (prio 0, i/o): i8042-cmd - 00000000000001ce-00000000000001d1 (prio 0, i/o): vbe - 0000000000000378-000000000000037f (prio 0, i/o): parallel - 00000000000003b4-00000000000003b5 (prio 0, i/o): vga - ... - -Fix by using the correct value. We now have: - - memory-region: pci_bridge_io - 0000000000000000-00000000ffffffff (prio 0, i/o): pci_bridge_io - 0000000000000060-0000000000000060 (prio 0, i/o): i8042-data - 0000000000000064-0000000000000064 (prio 0, i/o): i8042-cmd - ... - -Reviewed-by: Peter Maydell -Signed-off-by: Philippe Mathieu-Daudé -Message-Id: <20200601142930.29408-4-f4bug@amsat.org> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Reviewed-by: Richard Henderson ---- - hw/pci/pci_bridge.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c -index 715b9a4f..d67c691d 100644 ---- a/hw/pci/pci_bridge.c -+++ b/hw/pci/pci_bridge.c -@@ -30,6 +30,7 @@ - */ - - #include "qemu/osdep.h" -+#include "qemu/units.h" - #include "hw/pci/pci_bridge.h" - #include "hw/pci/pci_bus.h" - #include "qemu/module.h" -@@ -381,7 +382,7 @@ void pci_bridge_initfn(PCIDevice *dev, const char *typename) - memory_region_init(&br->address_space_mem, OBJECT(br), "pci_bridge_pci", UINT64_MAX); - sec_bus->address_space_io = &br->address_space_io; - memory_region_init(&br->address_space_io, OBJECT(br), "pci_bridge_io", -- UINT32_MAX); -+ 4 * GiB); - br->windows = pci_bridge_region_init(br); - QLIST_INIT(&sec_bus->child); - QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling); --- -2.23.0 - diff --git a/hw-pci-pcie-Move-hot-plug-capability-check-to-pre_pl.patch b/hw-pci-pcie-Move-hot-plug-capability-check-to-pre_pl.patch deleted file mode 100644 index e2f772c6ac1ac3c7b5cdcbf5e2ac033903a723e3..0000000000000000000000000000000000000000 --- a/hw-pci-pcie-Move-hot-plug-capability-check-to-pre_pl.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 86f70ed090478cc3b569b3606eb2723a0baadb52 Mon Sep 17 00:00:00 2001 -From: Julia Suvorova -Date: Tue, 16 Jun 2020 12:25:36 -0400 -Subject: [PATCH] hw/pci/pcie: Move hot plug capability check to pre_plug - callback - -RH-Author: Julia Suvorova -Message-id: <20200616122536.1027685-1-jusual@redhat.com> -Patchwork-id: 97548 -O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/1] hw/pci/pcie: Move hot plug capability check to pre_plug callback -Bugzilla: 1820531 -RH-Acked-by: Danilo de Paula -RH-Acked-by: Auger Eric -RH-Acked-by: Sergio Lopez Pascual - -BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1820531 -BRANCH: rhel-av-8.2.1 -UPSTREAM: merged -BREW: 29422092 - -Check for hot plug capability earlier to avoid removing devices attached -during the initialization process. - -Run qemu with an unattached drive: - -drive file=$FILE,if=none,id=drive0 \ - -device pcie-root-port,id=rp0,slot=3,bus=pcie.0,hotplug=off -Hotplug a block device: - device_add virtio-blk-pci,id=blk0,drive=drive0,bus=rp0 -If hotplug fails on plug_cb, drive0 will be deleted. - -Fixes: 0501e1aa1d32a6 ("hw/pci/pcie: Forbid hot-plug if it's disabled on the slot") - -Acked-by: Igor Mammedov -Signed-off-by: Julia Suvorova -Message-Id: <20200604125947.881210-1-jusual@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry picked from commit 0dabc0f6544f2c0310546f6d6cf3b68979580a9c) -Signed-off-by: Eduardo Lima (Etrunko) ---- - hw/pci/pcie.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c -index 2b4eedd2bb..b5190a3a55 100644 ---- a/hw/pci/pcie.c -+++ b/hw/pci/pcie.c -@@ -419,6 +419,17 @@ static void pcie_cap_slot_plug_common(PCIDevice *hotplug_dev, DeviceState *dev, - void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp) - { -+ PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev); -+ uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap; -+ uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP); -+ -+ /* Check if hot-plug is disabled on the slot */ -+ if (dev->hotplugged && (sltcap & PCI_EXP_SLTCAP_HPC) == 0) { -+ error_setg(errp, "Hot-plug failed: unsupported by the port device '%s'", -+ DEVICE(hotplug_pdev)->id); -+ return; -+ } -+ - pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, errp); - } - --- -2.27.0 - diff --git a/hw-ppc-Kconfig-Enable-TPM_SPAPR-as-part-of-PSERIES-c.patch b/hw-ppc-Kconfig-Enable-TPM_SPAPR-as-part-of-PSERIES-c.patch deleted file mode 100644 index ad3fc3a8356d20d28805db548c12b2b3745e8054..0000000000000000000000000000000000000000 --- a/hw-ppc-Kconfig-Enable-TPM_SPAPR-as-part-of-PSERIES-c.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 95cbe18c649a20f98562a993537a67e0ad78bf36 Mon Sep 17 00:00:00 2001 -From: Stefan Berger -Date: Tue, 21 Jan 2020 10:29:34 -0500 -Subject: [PATCH 08/19] hw/ppc/Kconfig: Enable TPM_SPAPR as part of PSERIES - config -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Stefan Berger -Reviewed-by: Marc-André Lureau -Reviewed-by: David Gibson -Message-Id: <20200121152935.649898-6-stefanb@linux.ibm.com> -[dwg: Use default in Kconfig rather than select to avoid breaking - Windows host build] -Signed-off-by: David Gibson -Signed-off-by: jiangfangjie ---- - hw/tpm/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig -index 4d4ab085..9e67d990 100644 ---- a/hw/tpm/Kconfig -+++ b/hw/tpm/Kconfig -@@ -25,6 +25,6 @@ config TPM_EMULATOR - - config TPM_SPAPR - bool -- default n -+ default y - depends on TPM && PSERIES - select TPMDEV --- -2.23.0 - diff --git a/hw-scsi-megasas-Fix-possible-out-of-bounds-array-acc.patch b/hw-scsi-megasas-Fix-possible-out-of-bounds-array-acc.patch deleted file mode 100644 index 12c907453efdaa1141217b3adccf27d4099ee924..0000000000000000000000000000000000000000 --- a/hw-scsi-megasas-Fix-possible-out-of-bounds-array-acc.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 5ec15fabe78e385a81e44c7944cd05309de7f36e Mon Sep 17 00:00:00 2001 -From: Thomas Huth -Date: Mon, 15 Jun 2020 09:26:29 +0200 -Subject: [PATCH 7/9] hw/scsi/megasas: Fix possible out-of-bounds array access - in tracepoints -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some tracepoints in megasas.c use a guest-controlled value as an index -into the mfi_frame_desc[] array. Thus a malicious guest could cause an -out-of-bounds error here. Fortunately, the impact is very low since this -can only happen when the corresponding tracepoints have been enabled -before, but the problem should be fixed anyway with a proper check. - -Buglink: https://bugs.launchpad.net/qemu/+bug/1882065 -Signed-off-by: Thomas Huth -Message-Id: <20200615072629.32321-1-thuth@redhat.com> -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Paolo Bonzini ---- - hw/scsi/megasas.c | 36 +++++++++++++++++++++++------------- - 1 file changed, 23 insertions(+), 13 deletions(-) - -diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c -index 94469e8169..9421f4d14e 100644 ---- a/hw/scsi/megasas.c -+++ b/hw/scsi/megasas.c -@@ -53,10 +53,6 @@ - #define MEGASAS_FLAG_USE_QUEUE64 1 - #define MEGASAS_MASK_USE_QUEUE64 (1 << MEGASAS_FLAG_USE_QUEUE64) - --static const char *mfi_frame_desc[] = { -- "MFI init", "LD Read", "LD Write", "LD SCSI", "PD SCSI", -- "MFI Doorbell", "MFI Abort", "MFI SMP", "MFI Stop"}; -- - typedef struct MegasasCmd { - uint32_t index; - uint16_t flags; -@@ -182,6 +178,20 @@ static void megasas_frame_set_scsi_status(MegasasState *s, - stb_pci_dma(pci, frame + offsetof(struct mfi_frame_header, scsi_status), v); - } - -+static inline const char *mfi_frame_desc(unsigned int cmd) -+{ -+ static const char *mfi_frame_descs[] = { -+ "MFI init", "LD Read", "LD Write", "LD SCSI", "PD SCSI", -+ "MFI Doorbell", "MFI Abort", "MFI SMP", "MFI Stop" -+ }; -+ -+ if (cmd < ARRAY_SIZE(mfi_frame_descs)) { -+ return mfi_frame_descs[cmd]; -+ } -+ -+ return "Unknown"; -+} -+ - /* - * Context is considered opaque, but the HBA firmware is running - * in little endian mode. So convert it to little endian, too. -@@ -1669,25 +1679,25 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd, - if (is_logical) { - if (target_id >= MFI_MAX_LD || lun_id != 0) { - trace_megasas_scsi_target_not_present( -- mfi_frame_desc[frame_cmd], is_logical, target_id, lun_id); -+ mfi_frame_desc(frame_cmd), is_logical, target_id, lun_id); - return MFI_STAT_DEVICE_NOT_FOUND; - } - } - sdev = scsi_device_find(&s->bus, 0, target_id, lun_id); - - cmd->iov_size = le32_to_cpu(cmd->frame->header.data_len); -- trace_megasas_handle_scsi(mfi_frame_desc[frame_cmd], is_logical, -+ trace_megasas_handle_scsi(mfi_frame_desc(frame_cmd), is_logical, - target_id, lun_id, sdev, cmd->iov_size); - - if (!sdev || (megasas_is_jbod(s) && is_logical)) { - trace_megasas_scsi_target_not_present( -- mfi_frame_desc[frame_cmd], is_logical, target_id, lun_id); -+ mfi_frame_desc(frame_cmd), is_logical, target_id, lun_id); - return MFI_STAT_DEVICE_NOT_FOUND; - } - - if (cdb_len > 16) { - trace_megasas_scsi_invalid_cdb_len( -- mfi_frame_desc[frame_cmd], is_logical, -+ mfi_frame_desc(frame_cmd), is_logical, - target_id, lun_id, cdb_len); - megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE)); - cmd->frame->header.scsi_status = CHECK_CONDITION; -@@ -1705,7 +1715,7 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd, - cmd->req = scsi_req_new(sdev, cmd->index, lun_id, cdb, cmd); - if (!cmd->req) { - trace_megasas_scsi_req_alloc_failed( -- mfi_frame_desc[frame_cmd], target_id, lun_id); -+ mfi_frame_desc(frame_cmd), target_id, lun_id); - megasas_write_sense(cmd, SENSE_CODE(NO_SENSE)); - cmd->frame->header.scsi_status = BUSY; - s->event_count++; -@@ -1750,17 +1760,17 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd) - } - - trace_megasas_handle_io(cmd->index, -- mfi_frame_desc[frame_cmd], target_id, lun_id, -+ mfi_frame_desc(frame_cmd), target_id, lun_id, - (unsigned long)lba_start, (unsigned long)lba_count); - if (!sdev) { - trace_megasas_io_target_not_present(cmd->index, -- mfi_frame_desc[frame_cmd], target_id, lun_id); -+ mfi_frame_desc(frame_cmd), target_id, lun_id); - return MFI_STAT_DEVICE_NOT_FOUND; - } - - if (cdb_len > 16) { - trace_megasas_scsi_invalid_cdb_len( -- mfi_frame_desc[frame_cmd], 1, target_id, lun_id, cdb_len); -+ mfi_frame_desc(frame_cmd), 1, target_id, lun_id, cdb_len); - megasas_write_sense(cmd, SENSE_CODE(INVALID_OPCODE)); - cmd->frame->header.scsi_status = CHECK_CONDITION; - s->event_count++; -@@ -1780,7 +1790,7 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd) - lun_id, cdb, cmd); - if (!cmd->req) { - trace_megasas_scsi_req_alloc_failed( -- mfi_frame_desc[frame_cmd], target_id, lun_id); -+ mfi_frame_desc(frame_cmd), target_id, lun_id); - megasas_write_sense(cmd, SENSE_CODE(NO_SENSE)); - cmd->frame->header.scsi_status = BUSY; - s->event_count++; --- -2.25.1 - diff --git a/hw-sd-sdhci-Fix-DMA-Transfer-Block-Size-field.patch b/hw-sd-sdhci-Fix-DMA-Transfer-Block-Size-field.patch deleted file mode 100644 index 42df9650a9e378fbb0d96afbd5b8a844c8ed64c7..0000000000000000000000000000000000000000 --- a/hw-sd-sdhci-Fix-DMA-Transfer-Block-Size-field.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 8b8d3992db22a583b69b6e2ae1d9cd87e2179e21 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Fri, 18 Sep 2020 10:55:22 +0800 -Subject: [PATCH] hw/sd/sdhci: Fix DMA Transfer Block Size field The 'Transfer - Block Size' field is 12-bit wide. See section '2.2.2 Block Size Register - (Offset 004h)' in datasheet. - -Buglink: https://bugs.launchpad.net/qemu/+bug/1892960 - -diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c -index 7b80b1d9..acf482b8 100644 ---- a/hw/sd/sdhci.c -+++ b/hw/sd/sdhci.c -@@ -1127,7 +1127,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) - break; - case SDHC_BLKSIZE: - if (!TRANSFERRING_DATA(s->prnsts)) { -- MASKED_WRITE(s->blksize, mask, value); -+ MASKED_WRITE(s->blksize, mask, extract32(value, 0, 12)); - MASKED_WRITE(s->blkcnt, mask >> 16, value >> 16); - } - --- -2.23.0 - diff --git a/hw-tpm-rename-Error-parameter-to-more-common-errp.patch b/hw-tpm-rename-Error-parameter-to-more-common-errp.patch deleted file mode 100644 index a47a1ae68da792d7811b9d85cb5cbd5f5d5ac0cd..0000000000000000000000000000000000000000 --- a/hw-tpm-rename-Error-parameter-to-more-common-errp.patch +++ /dev/null @@ -1,58 +0,0 @@ -From f2dceb3cde537210896a2cadb8958cfd310113a3 Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Thu, 5 Dec 2019 20:46:30 +0300 -Subject: [PATCH 01/19] hw/tpm: rename Error ** parameter to more common errp -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Vladimir Sementsov-Ogievskiy -Reviewed-by: Stefan Berger -Message-Id: <20191205174635.18758-17-vsementsov@virtuozzo.com> -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Markus Armbruster -Signed-off-by: jiangfangjie ---- - hw/tpm/tpm_emulator.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c -index fc0b512f..38bf5fd6 100644 ---- a/hw/tpm/tpm_emulator.c -+++ b/hw/tpm/tpm_emulator.c -@@ -155,7 +155,7 @@ static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_emu, - const uint8_t *in, uint32_t in_len, - uint8_t *out, uint32_t out_len, - bool *selftest_done, -- Error **err) -+ Error **errp) - { - ssize_t ret; - bool is_selftest = false; -@@ -165,20 +165,20 @@ static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_emu, - is_selftest = tpm_util_is_selftest(in, in_len); - } - -- ret = qio_channel_write_all(tpm_emu->data_ioc, (char *)in, in_len, err); -+ ret = qio_channel_write_all(tpm_emu->data_ioc, (char *)in, in_len, errp); - if (ret != 0) { - return -1; - } - - ret = qio_channel_read_all(tpm_emu->data_ioc, (char *)out, -- sizeof(struct tpm_resp_hdr), err); -+ sizeof(struct tpm_resp_hdr), errp); - if (ret != 0) { - return -1; - } - - ret = qio_channel_read_all(tpm_emu->data_ioc, - (char *)out + sizeof(struct tpm_resp_hdr), -- tpm_cmd_get_size(out) - sizeof(struct tpm_resp_hdr), err); -+ tpm_cmd_get_size(out) - sizeof(struct tpm_resp_hdr), errp); - if (ret != 0) { - return -1; - } --- -2.23.0 - diff --git a/hw-usb-core-fix-buffer-overflow.patch b/hw-usb-core-fix-buffer-overflow.patch deleted file mode 100644 index 494955788a2506fd2d28521ff234118025fbe674..0000000000000000000000000000000000000000 --- a/hw-usb-core-fix-buffer-overflow.patch +++ /dev/null @@ -1,46 +0,0 @@ -hw-usb-core-fix-buffer-overflow - -From 18ad0451f113ffc3a2ff59c059d189cca1e42842 Mon Sep 17 00:00:00 2001 -From: root -Date: Wed, 19 Aug 2020 17:04:04 +0800 -Subject: [PATCH] hw/usb/core.c fix buffer overflow - -Store calculated setup_len in a local variable, verify it, - and only write it to the struct (USBDevice->setup_len) in case it passed the - sanity checks. - -This prevents other code (do_token_{in,out} function specifically) -from working with invalid USBDevice->setup_len values and overruning -the USBDevice->setup_buf[] buffer. -Store -Fixes: CVE-2020-14364 -Signed-off-by: Gred Hoffman ---- - hw/usb/core.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/hw/usb/core.c b/hw/usb/core.c -index 5abd128b..12342f13 100644 ---- a/hw/usb/core.c -+++ b/hw/usb/core.c -@@ -144,6 +144,8 @@ static void do_token_setup(USBDevice *s, USBPacket *p) - "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n", - s->setup_len, sizeof(s->data_buf)); - p->status = USB_RET_STALL; -+ s->setup_len = 0; -+ s->setup_state = SETUP_STATE_ACK; - return; - } - -@@ -277,6 +279,8 @@ static void do_parameter(USBDevice *s, USBPacket *p) - "usb_generic_handle_packet: ctrl buffer too small (%d > %zu)\n", - s->setup_len, sizeof(s->data_buf)); - p->status = USB_RET_STALL; -+ s->setup_len = 0; -+ s->setup_state = SETUP_STATE_ACK; - return; - } - --- -2.23.0 - diff --git a/hw-usb-hcd-ohci-check-for-processed-TD-before-retire.patch b/hw-usb-hcd-ohci-check-for-processed-TD-before-retire.patch deleted file mode 100644 index 96a45b8100318237976abc51ac2b584b569e018a..0000000000000000000000000000000000000000 --- a/hw-usb-hcd-ohci-check-for-processed-TD-before-retire.patch +++ /dev/null @@ -1,40 +0,0 @@ -From b1398dc6f3eb16e006167bdd8666fb7c52918e13 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Tue, 15 Sep 2020 23:52:59 +0530 -Subject: [PATCH] hw: usb: hcd-ohci: check for processed TD before retire - -While servicing OHCI transfer descriptors(TD), ohci_service_iso_td -retires a TD if it has passed its time frame. It does not check if -the TD was already processed once and holds an error code in TD_CC. -It may happen if the TD list has a loop. Add check to avoid an -infinite loop condition. - -Signed-off-by: Prasad J Pandit -Reviewed-by: Li Qiang -Message-id: 20200915182259.68522-3-ppandit@redhat.com -Signed-off-by: Gerd Hoffmann -(cherry-picked from 1be90ebe) -Fix CVE-2020-25625 -Signed-off-by: Alex Chen ---- - hw/usb/hcd-ohci.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c -index 4f6fdbc0a7..ffe52a09d7 100644 ---- a/hw/usb/hcd-ohci.c -+++ b/hw/usb/hcd-ohci.c -@@ -689,6 +689,10 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, - the next ISO TD of the same ED */ - trace_usb_ohci_iso_td_relative_frame_number_big(relative_frame_number, - frame_count); -+ if (OHCI_CC_DATAOVERRUN == OHCI_BM(iso_td.flags, TD_CC)) { -+ /* avoid infinite loop */ -+ return 1; -+ } - OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN); - ed->head &= ~OHCI_DPTR_MASK; - ed->head |= (iso_td.next & OHCI_DPTR_MASK); --- -2.27.0 - diff --git a/hw-usb-hcd-ohci-check-len-and-frame_number-variables.patch b/hw-usb-hcd-ohci-check-len-and-frame_number-variables.patch deleted file mode 100644 index 0133d70db8abfb7338a57f5cf305c68ac8811e56..0000000000000000000000000000000000000000 --- a/hw-usb-hcd-ohci-check-len-and-frame_number-variables.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 789723b95045b6e44d1d1aef56a8bcb255a10476 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Tue, 15 Sep 2020 23:52:58 +0530 -Subject: [PATCH] hw: usb: hcd-ohci: check len and frame_number variables - -While servicing the OHCI transfer descriptors(TD), OHCI host -controller derives variables 'start_addr', 'end_addr', 'len' -etc. from values supplied by the host controller driver. -Host controller driver may supply values such that using -above variables leads to out-of-bounds access issues. -Add checks to avoid them. - -AddressSanitizer: stack-buffer-overflow on address 0x7ffd53af76a0 - READ of size 2 at 0x7ffd53af76a0 thread T0 - #0 ohci_service_iso_td ../hw/usb/hcd-ohci.c:734 - #1 ohci_service_ed_list ../hw/usb/hcd-ohci.c:1180 - #2 ohci_process_lists ../hw/usb/hcd-ohci.c:1214 - #3 ohci_frame_boundary ../hw/usb/hcd-ohci.c:1257 - #4 timerlist_run_timers ../util/qemu-timer.c:572 - #5 qemu_clock_run_timers ../util/qemu-timer.c:586 - #6 qemu_clock_run_all_timers ../util/qemu-timer.c:672 - #7 main_loop_wait ../util/main-loop.c:527 - #8 qemu_main_loop ../softmmu/vl.c:1676 - #9 main ../softmmu/main.c:50 - -Reported-by: Gaoning Pan -Reported-by: Yongkang Jia -Reported-by: Yi Ren -Signed-off-by: Prasad J Pandit -Message-id: 20200915182259.68522-2-ppandit@redhat.com -Signed-off-by: Gerd Hoffmann -(cherry-picked from 1328fe0c) -Fix CVE-2020-25624 -Signed-off-by: Alex Chen ---- - hw/usb/hcd-ohci.c | 24 ++++++++++++++++++++++-- - 1 file changed, 22 insertions(+), 2 deletions(-) - -diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c -index ffe52a09d7..d2dd8efd58 100644 ---- a/hw/usb/hcd-ohci.c -+++ b/hw/usb/hcd-ohci.c -@@ -733,7 +733,11 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, - } - - start_offset = iso_td.offset[relative_frame_number]; -- next_offset = iso_td.offset[relative_frame_number + 1]; -+ if (relative_frame_number < frame_count) { -+ next_offset = iso_td.offset[relative_frame_number + 1]; -+ } else { -+ next_offset = iso_td.be; -+ } - - if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) || - ((relative_frame_number < frame_count) && -@@ -766,7 +770,12 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, - } - } else { - /* Last packet in the ISO TD */ -- end_addr = iso_td.be; -+ end_addr = next_offset; -+ } -+ -+ if (start_addr > end_addr) { -+ trace_usb_ohci_iso_td_bad_cc_overrun(start_addr, end_addr); -+ return 1; - } - - if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) { -@@ -775,6 +784,9 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, - } else { - len = end_addr - start_addr + 1; - } -+ if (len > sizeof(ohci->usb_buf)) { -+ len = sizeof(ohci->usb_buf); -+ } - - if (len && dir != OHCI_TD_DIR_IN) { - if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len, -@@ -977,8 +989,16 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) - if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) { - len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff); - } else { -+ if (td.cbp > td.be) { -+ trace_usb_ohci_iso_td_bad_cc_overrun(td.cbp, td.be); -+ ohci_die(ohci); -+ return 1; -+ } - len = (td.be - td.cbp) + 1; - } -+ if (len > sizeof(ohci->usb_buf)) { -+ len = sizeof(ohci->usb_buf); -+ } - - pktlen = len; - if (len && dir != OHCI_TD_DIR_IN) { --- -2.27.0 - diff --git a/hw-usb-reduce-the-vpcu-cost-of-UHCI-when-VNC-disconn.patch b/hw-usb-reduce-the-vpcu-cost-of-UHCI-when-VNC-disconn.patch new file mode 100644 index 0000000000000000000000000000000000000000..ef734a61a77554550863159a804acf5019f40328 --- /dev/null +++ b/hw-usb-reduce-the-vpcu-cost-of-UHCI-when-VNC-disconn.patch @@ -0,0 +1,459 @@ +From 93f01916f0c1e11f38edb8ccc4118c940d9c089f Mon Sep 17 00:00:00 2001 +From: eillon +Date: Tue, 8 Feb 2022 22:43:59 -0500 +Subject: [PATCH] hw/usb: reduce the vpcu cost of UHCI when VNC disconnect + +Reduce the vpcu cost by set a lower FRAME_TIMER_FREQ of the UHCI +when VNC client disconnected. This can reduce about 3% cost of +vcpu thread. + +Signed-off-by: eillon +--- + hw/usb/core.c | 5 ++-- + hw/usb/desc.c | 7 +++-- + hw/usb/dev-hid.c | 2 +- + hw/usb/hcd-uhci.c | 63 ++++++++++++++++++++++++++++++++++------ + hw/usb/hcd-uhci.h | 1 + + hw/usb/host-libusb.c | 32 ++++++++++++++++++++ + include/hw/usb.h | 1 + + include/qemu/timer.h | 28 ++++++++++++++++++ + ui/vnc.c | 4 +++ + util/qemu-timer.c | 69 ++++++++++++++++++++++++++++++++++++++++++++ + 10 files changed, 197 insertions(+), 15 deletions(-) + +diff --git a/hw/usb/core.c b/hw/usb/core.c +index 975f76250a..51b36126ca 100644 +--- a/hw/usb/core.c ++++ b/hw/usb/core.c +@@ -87,7 +87,7 @@ void usb_device_reset(USBDevice *dev) + return; + } + usb_device_handle_reset(dev); +- dev->remote_wakeup = 0; ++ dev->remote_wakeup &= ~USB_DEVICE_REMOTE_WAKEUP; + dev->addr = 0; + dev->state = USB_STATE_DEFAULT; + } +@@ -105,7 +105,8 @@ void usb_wakeup(USBEndpoint *ep, unsigned int stream) + */ + return; + } +- if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) { ++ if ((dev->remote_wakeup & USB_DEVICE_REMOTE_WAKEUP) ++ && dev->port && dev->port->ops->wakeup) { + dev->port->ops->wakeup(dev->port); + } + if (bus->ops->wakeup_endpoint) { +diff --git a/hw/usb/desc.c b/hw/usb/desc.c +index 8b6eaea407..78bbe74c71 100644 +--- a/hw/usb/desc.c ++++ b/hw/usb/desc.c +@@ -751,7 +751,7 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, + if (config->bmAttributes & USB_CFG_ATT_SELFPOWER) { + data[0] |= 1 << USB_DEVICE_SELF_POWERED; + } +- if (dev->remote_wakeup) { ++ if (dev->remote_wakeup & USB_DEVICE_REMOTE_WAKEUP) { + data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP; + } + data[1] = 0x00; +@@ -761,14 +761,15 @@ int usb_desc_handle_control(USBDevice *dev, USBPacket *p, + } + case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: + if (value == USB_DEVICE_REMOTE_WAKEUP) { +- dev->remote_wakeup = 0; ++ dev->remote_wakeup &= ~USB_DEVICE_REMOTE_WAKEUP; + ret = 0; + } + trace_usb_clear_device_feature(dev->addr, value, ret); + break; + case DeviceOutRequest | USB_REQ_SET_FEATURE: ++ dev->remote_wakeup |= USB_DEVICE_REMOTE_WAKEUP_IS_SUPPORTED; + if (value == USB_DEVICE_REMOTE_WAKEUP) { +- dev->remote_wakeup = 1; ++ dev->remote_wakeup |= USB_DEVICE_REMOTE_WAKEUP; + ret = 0; + } + trace_usb_set_device_feature(dev->addr, value, ret); +diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c +index 1c7ae97c30..9fb89f6955 100644 +--- a/hw/usb/dev-hid.c ++++ b/hw/usb/dev-hid.c +@@ -745,7 +745,7 @@ static int usb_ptr_post_load(void *opaque, int version_id) + { + USBHIDState *s = opaque; + +- if (s->dev.remote_wakeup) { ++ if (s->dev.remote_wakeup & USB_DEVICE_REMOTE_WAKEUP) { + hid_pointer_activate(&s->hid); + } + return 0; +diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c +index d1b5657d72..693c68f445 100644 +--- a/hw/usb/hcd-uhci.c ++++ b/hw/usb/hcd-uhci.c +@@ -44,6 +44,8 @@ + #include "hcd-uhci.h" + + #define FRAME_TIMER_FREQ 1000 ++#define FRAME_TIMER_FREQ_LAZY 10 ++#define USB_DEVICE_NEED_NORMAL_FREQ "QEMU USB Tablet" + + #define FRAME_MAX_LOOPS 256 + +@@ -111,6 +113,22 @@ static void uhci_async_cancel(UHCIAsync *async); + static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td); + static void uhci_resume(void *opaque); + ++static int64_t uhci_frame_timer_freq = FRAME_TIMER_FREQ_LAZY; ++ ++static void uhci_set_frame_freq(int freq) ++{ ++ if (freq <= 0) { ++ return; ++ } ++ ++ uhci_frame_timer_freq = freq; ++} ++ ++static qemu_usb_controller qemu_uhci = { ++ .name = "uhci", ++ .qemu_set_freq = uhci_set_frame_freq, ++}; ++ + static inline int32_t uhci_queue_token(UHCI_TD *td) + { + if ((td->token & (0xf << 15)) == 0) { +@@ -353,7 +371,7 @@ static int uhci_post_load(void *opaque, int version_id) + + if (version_id < 2) { + s->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + +- (NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ); ++ (NANOSECONDS_PER_SECOND / uhci_frame_timer_freq); + } + return 0; + } +@@ -394,8 +412,29 @@ static void uhci_port_write(void *opaque, hwaddr addr, + if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) { + /* start frame processing */ + trace_usb_uhci_schedule_start(); +- s->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + +- (NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ); ++ ++ /* ++ * If the frequency of frame_timer is too slow, Guest OS (Win2012) would become ++ * blue-screen after hotplugging some vcpus. ++ * If this USB device support the remote-wakeup, the UHCI controller ++ * will enter global suspend mode when there is no input for several seconds. ++ * In this case, Qemu will delete the frame_timer. Since the frame_timer has been deleted, ++ * there is no influence to the performance of Vms. So, we can change the frequency to 1000. ++ * After that the frequency will be safe when we trigger the frame_timer again. ++ * Excepting this, there are two ways to change the frequency: ++ * 1)VNC connect/disconnect;2)attach/detach USB device. ++ */ ++ if ((uhci_frame_timer_freq != FRAME_TIMER_FREQ) ++ && (s->ports[0].port.dev) ++ && (!memcmp(s->ports[0].port.dev->product_desc, ++ USB_DEVICE_NEED_NORMAL_FREQ, strlen(USB_DEVICE_NEED_NORMAL_FREQ))) ++ && (s->ports[0].port.dev->remote_wakeup & USB_DEVICE_REMOTE_WAKEUP_IS_SUPPORTED)) { ++ qemu_log("turn up the frequency of UHCI controller to %d\n", FRAME_TIMER_FREQ); ++ uhci_frame_timer_freq = FRAME_TIMER_FREQ; ++ } ++ ++ s->frame_time = NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ; ++ s->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->frame_time; + timer_mod(s->frame_timer, s->expire_time); + s->status &= ~UHCI_STS_HCHALTED; + } else if (!(val & UHCI_CMD_RS)) { +@@ -1083,7 +1122,6 @@ static void uhci_frame_timer(void *opaque) + UHCIState *s = opaque; + uint64_t t_now, t_last_run; + int i, frames; +- const uint64_t frame_t = NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ; + + s->completions_only = false; + qemu_bh_cancel(s->bh); +@@ -1099,14 +1137,14 @@ static void uhci_frame_timer(void *opaque) + } + + /* We still store expire_time in our state, for migration */ +- t_last_run = s->expire_time - frame_t; ++ t_last_run = s->expire_time - s->frame_time; + t_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + + /* Process up to MAX_FRAMES_PER_TICK frames */ +- frames = (t_now - t_last_run) / frame_t; ++ frames = (t_now - t_last_run) / s->frame_time; + if (frames > s->maxframes) { + int skipped = frames - s->maxframes; +- s->expire_time += skipped * frame_t; ++ s->expire_time += skipped * s->frame_time; + s->frnum = (s->frnum + skipped) & 0x7ff; + frames -= skipped; + } +@@ -1123,7 +1161,7 @@ static void uhci_frame_timer(void *opaque) + /* The spec says frnum is the frame currently being processed, and + * the guest must look at frnum - 1 on interrupt, so inc frnum now */ + s->frnum = (s->frnum + 1) & 0x7ff; +- s->expire_time += frame_t; ++ s->expire_time += s->frame_time; + } + + /* Complete the previous frame(s) */ +@@ -1134,7 +1172,12 @@ static void uhci_frame_timer(void *opaque) + } + s->pending_int_mask = 0; + +- timer_mod(s->frame_timer, t_now + frame_t); ++ /* expire_time is calculated from last frame_time, we should calculate it ++ * according to new frame_time which equals to ++ * NANOSECONDS_PER_SECOND / uhci_frame_timer_freq */ ++ s->expire_time -= s->frame_time - NANOSECONDS_PER_SECOND / uhci_frame_timer_freq; ++ s->frame_time = NANOSECONDS_PER_SECOND / uhci_frame_timer_freq; ++ timer_mod(s->frame_timer, t_now + s->frame_time); + } + + static const MemoryRegionOps uhci_ioport_ops = { +@@ -1196,8 +1239,10 @@ void usb_uhci_common_realize(PCIDevice *dev, Error **errp) + s->bh = qemu_bh_new(uhci_bh, s); + s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, uhci_frame_timer, s); + s->num_ports_vmstate = NB_PORTS; ++ s->frame_time = NANOSECONDS_PER_SECOND / uhci_frame_timer_freq; + QTAILQ_INIT(&s->queues); + ++ qemu_register_usb_controller(&qemu_uhci, QEMU_USB_CONTROLLER_UHCI); + memory_region_init_io(&s->io_bar, OBJECT(s), &uhci_ioport_ops, s, + "uhci", 0x20); + +diff --git a/hw/usb/hcd-uhci.h b/hw/usb/hcd-uhci.h +index c85ab7868e..5194d22ab4 100644 +--- a/hw/usb/hcd-uhci.h ++++ b/hw/usb/hcd-uhci.h +@@ -50,6 +50,7 @@ typedef struct UHCIState { + uint16_t status; + uint16_t intr; /* interrupt enable register */ + uint16_t frnum; /* frame number */ ++ uint64_t frame_time; /* frame time in ns */ + uint32_t fl_base_addr; /* frame list base address */ + uint8_t sof_timing; + uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */ +diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c +index d0d46dd0a4..8f521ad586 100644 +--- a/hw/usb/host-libusb.c ++++ b/hw/usb/host-libusb.c +@@ -945,6 +945,30 @@ static void usb_host_ep_update(USBHostDevice *s) + libusb_free_config_descriptor(conf); + } + ++static unsigned int usb_get_controller_type(int speed) ++{ ++ unsigned int type = MAX_USB_CONTROLLER_TYPES; ++ ++ switch (speed) { ++ case USB_SPEED_SUPER: ++ type = QEMU_USB_CONTROLLER_XHCI; ++ break; ++ case USB_SPEED_HIGH: ++ type = QEMU_USB_CONTROLLER_EHCI; ++ break; ++ case USB_SPEED_FULL: ++ type = QEMU_USB_CONTROLLER_UHCI; ++ break; ++ case USB_SPEED_LOW: ++ type = QEMU_USB_CONTROLLER_OHCI; ++ break; ++ default: ++ break; ++ } ++ ++ return type; ++} ++ + static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd) + { + USBDevice *udev = USB_DEVICE(s); +@@ -1054,6 +1078,12 @@ static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd) + } + + trace_usb_host_open_success(bus_num, addr); ++ ++ /* change ehci frame time freq when USB passthrough */ ++ qemu_log("usb host speed is %d\n", udev->speed); ++ qemu_timer_set_mode(QEMU_TIMER_USB_NORMAL_MODE, ++ usb_get_controller_type(udev->speed)); ++ + return 0; + + fail: +@@ -1129,6 +1159,8 @@ static int usb_host_close(USBHostDevice *s) + } + + usb_host_auto_check(NULL); ++ qemu_timer_set_mode(QEMU_TIMER_USB_LAZY_MODE, ++ usb_get_controller_type(udev->speed)); + return 0; + } + +diff --git a/include/hw/usb.h b/include/hw/usb.h +index 33668dd0a9..fa3a176159 100644 +--- a/include/hw/usb.h ++++ b/include/hw/usb.h +@@ -142,6 +142,7 @@ + + #define USB_DEVICE_SELF_POWERED 0 + #define USB_DEVICE_REMOTE_WAKEUP 1 ++#define USB_DEVICE_REMOTE_WAKEUP_IS_SUPPORTED 2 + + #define USB_DT_DEVICE 0x01 + #define USB_DT_CONFIG 0x02 +diff --git a/include/qemu/timer.h b/include/qemu/timer.h +index 88ef114689..d263fad9a4 100644 +--- a/include/qemu/timer.h ++++ b/include/qemu/timer.h +@@ -91,6 +91,34 @@ struct QEMUTimer { + int scale; + }; + ++#define QEMU_USB_NORMAL_FREQ 1000 ++#define QEMU_USB_LAZY_FREQ 10 ++#define MAX_USB_CONTROLLER_TYPES 4 ++#define QEMU_USB_CONTROLLER_OHCI 0 ++#define QEMU_USB_CONTROLLER_UHCI 1 ++#define QEMU_USB_CONTROLLER_EHCI 2 ++#define QEMU_USB_CONTROLLER_XHCI 3 ++ ++typedef void (*QEMUSetFreqHandler) (int freq); ++ ++typedef struct qemu_usb_controller { ++ const char *name; ++ QEMUSetFreqHandler qemu_set_freq; ++} qemu_usb_controller; ++ ++typedef qemu_usb_controller* qemu_usb_controller_ptr; ++ ++enum qemu_timer_mode { ++ QEMU_TIMER_USB_NORMAL_MODE = 1 << 0, /* Set when VNC connect or ++ * with usb dev passthrough ++ */ ++ QEMU_TIMER_USB_LAZY_MODE = 1 << 1, /* Set when VNC disconnect */ ++}; ++ ++int qemu_register_usb_controller(qemu_usb_controller_ptr controller, ++ unsigned int type); ++int qemu_timer_set_mode(enum qemu_timer_mode mode, unsigned int type); ++ + extern QEMUTimerListGroup main_loop_tlg; + + /* +diff --git a/ui/vnc.c b/ui/vnc.c +index af02522e84..bc86c20370 100644 +--- a/ui/vnc.c ++++ b/ui/vnc.c +@@ -1379,6 +1379,8 @@ void vnc_disconnect_finish(VncState *vs) + g_free(vs->zrle); + g_free(vs->tight); + g_free(vs); ++ ++ qemu_timer_set_mode(QEMU_TIMER_USB_LAZY_MODE, QEMU_USB_CONTROLLER_UHCI); + } + + size_t vnc_client_io_error(VncState *vs, ssize_t ret, Error *err) +@@ -3333,6 +3335,8 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc, + } + } + } ++ ++ qemu_timer_set_mode(QEMU_TIMER_USB_NORMAL_MODE, QEMU_USB_CONTROLLER_UHCI); + } + + void vnc_start_protocol(VncState *vs) +diff --git a/util/qemu-timer.c b/util/qemu-timer.c +index f36c75e594..40e8c83722 100644 +--- a/util/qemu-timer.c ++++ b/util/qemu-timer.c +@@ -23,6 +23,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/log.h" + #include "qemu/main-loop.h" + #include "qemu/timer.h" + #include "qemu/lockable.h" +@@ -75,6 +76,74 @@ struct QEMUTimerList { + QemuEvent timers_done_ev; + }; + ++typedef struct qemu_controller_timer_state { ++ qemu_usb_controller_ptr controller; ++ int refs; ++} controller_timer_state; ++ ++typedef controller_timer_state* controller_timer_state_ptr; ++ ++static controller_timer_state uhci_timer_state = { ++ .controller = NULL, ++ .refs = 0, ++}; ++ ++static controller_timer_state_ptr \ ++ qemu_usb_controller_tab[MAX_USB_CONTROLLER_TYPES] = {NULL, ++ &uhci_timer_state, ++ NULL, NULL}; ++ ++int qemu_register_usb_controller(qemu_usb_controller_ptr controller, ++ unsigned int type) ++{ ++ if (type != QEMU_USB_CONTROLLER_UHCI) { ++ return 0; ++ } ++ ++ /* for companion EHCI controller will create three UHCI controllers, ++ * we init it only once. ++ */ ++ if (!qemu_usb_controller_tab[type]->controller) { ++ qemu_log("the usb controller (%d) registed frame handler\n", type); ++ qemu_usb_controller_tab[type]->controller = controller; ++ } ++ ++ return 0; ++} ++ ++int qemu_timer_set_mode(enum qemu_timer_mode mode, unsigned int type) ++{ ++ if (type != QEMU_USB_CONTROLLER_UHCI) { ++ qemu_log("the usb controller (%d) no need change frame frep\n", type); ++ return 0; ++ } ++ ++ if (!qemu_usb_controller_tab[type]->controller) { ++ qemu_log("the usb controller (%d) not registed yet\n", type); ++ return 0; ++ } ++ ++ if (mode == QEMU_TIMER_USB_NORMAL_MODE) { ++ if (qemu_usb_controller_tab[type]->refs++ > 0) { ++ return 0; ++ } ++ qemu_usb_controller_tab[type]->controller-> ++ qemu_set_freq(QEMU_USB_NORMAL_FREQ); ++ qemu_log("Set the controller (%d) of freq %d HZ,\n", ++ type, QEMU_USB_NORMAL_FREQ); ++ } else { ++ if (--qemu_usb_controller_tab[type]->refs > 0) { ++ return 0; ++ } ++ qemu_usb_controller_tab[type]->controller-> ++ qemu_set_freq(QEMU_USB_LAZY_FREQ); ++ qemu_log("Set the controller(type:%d) of freq %d HZ,\n", ++ type, QEMU_USB_LAZY_FREQ); ++ } ++ ++ return 0; ++} ++ + /** + * qemu_clock_ptr: + * @type: type of clock +-- +2.27.0 + diff --git a/hw-vfio-common-trace-vfio_connect_container-operatio.patch b/hw-vfio-common-trace-vfio_connect_container-operatio.patch deleted file mode 100644 index bd952359250359770ea8d51711e88be943ee2c72..0000000000000000000000000000000000000000 --- a/hw-vfio-common-trace-vfio_connect_container-operatio.patch +++ /dev/null @@ -1,53 +0,0 @@ -From b107e6ec2a5a34e0ba95345a89dcf5f505ad9da4 Mon Sep 17 00:00:00 2001 -From: Eric Auger -Date: Mon, 22 Feb 2021 10:13:55 -0500 -Subject: [PATCH] hw/vfio/common: trace vfio_connect_container operations - -We currently trace vfio_disconnect_container() but we do not trace -the container <-> group creation, which can be useful to understand -the VFIO topology. - -Signed-off-by: Eric Auger -Signed-off-by: Kunkun Jiang ---- - hw/vfio/common.c | 3 +++ - hw/vfio/trace-events | 2 ++ - 2 files changed, 5 insertions(+) - -diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index 206fb83e28..fefa2ccfdf 100644 ---- a/hw/vfio/common.c -+++ b/hw/vfio/common.c -@@ -1848,6 +1848,8 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, - QLIST_FOREACH(container, &space->containers, next) { - if (!ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &container->fd)) { - group->container = container; -+ trace_vfio_connect_existing_container(group->groupid, -+ container->fd); - QLIST_INSERT_HEAD(&container->group_list, group, container_next); - vfio_kvm_device_add_group(group); - return 0; -@@ -1881,6 +1883,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, - if (ret) { - goto free_container_exit; - } -+ trace_vfio_connect_new_container(group->groupid, container->fd); - - switch (container->iommu_type) { - case VFIO_TYPE1v2_IOMMU: -diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events -index 575ebde6e0..561dc6e758 100644 ---- a/hw/vfio/trace-events -+++ b/hw/vfio/trace-events -@@ -102,6 +102,8 @@ vfio_listener_region_add_no_dma_map(const char *name, uint64_t iova, uint64_t si - vfio_listener_region_del_skip(uint64_t start, uint64_t end) "SKIPPING region_del 0x%"PRIx64" - 0x%"PRIx64 - vfio_listener_region_del(uint64_t start, uint64_t end) "region_del 0x%"PRIx64" - 0x%"PRIx64 - vfio_disconnect_container(int fd) "close container->fd=%d" -+vfio_connect_existing_container(int groupid, int container_fd) "group=%d existing container fd=%d" -+vfio_connect_new_container(int groupid, int container_fd) "group=%d new container fd=%d" - vfio_put_group(int fd) "close group->fd=%d" - vfio_get_device(const char * name, unsigned int flags, unsigned int num_regions, unsigned int num_irqs) "Device %s flags: %u, regions: %u, irqs: %u" - vfio_put_base_device(int fd) "close vdev->fd=%d" --- -2.27.0 - diff --git a/hw-xhci-check-return-value-of-usb_packet_map.patch b/hw-xhci-check-return-value-of-usb_packet_map.patch deleted file mode 100644 index fd81478de3a588852232349f483bbf16dd403034..0000000000000000000000000000000000000000 --- a/hw-xhci-check-return-value-of-usb_packet_map.patch +++ /dev/null @@ -1,31 +0,0 @@ -From e43f0019b0aff881c562c8d2428bce6b3d55845c Mon Sep 17 00:00:00 2001 -From: Li Qiang -Date: Fri, 18 Sep 2020 11:08:28 +0800 -Subject: [PATCH] hw: xhci: check return value of 'usb_packet_map' - -Currently we don't check the return value of 'usb_packet_map', -this will cause an NAF issue. This is LP#1891341. -Following is the reproducer provided in: --->https://bugs.launchpad.net/qemu/+bug/1891341 - -This patch fixes this. - -diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c -index a21485fe..3b25abca 100644 ---- a/hw/usb/hcd-xhci.c -+++ b/hw/usb/hcd-xhci.c -@@ -1614,7 +1614,10 @@ static int xhci_setup_packet(XHCITransfer *xfer) - xhci_xfer_create_sgl(xfer, dir == USB_TOKEN_IN); /* Also sets int_req */ - usb_packet_setup(&xfer->packet, dir, ep, xfer->streamid, - xfer->trbs[0].addr, false, xfer->int_req); -- usb_packet_map(&xfer->packet, &xfer->sgl); -+ if (usb_packet_map(&xfer->packet, &xfer->sgl)) { -+ qemu_sglist_destroy(&xfer->sgl); -+ return -1; -+ } - DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n", - xfer->packet.pid, ep->dev->addr, ep->nr); - return 0; --- -2.23.0 - diff --git a/i386-Add-CPUID-bit-for-CLZERO-and-XSAVEERPTR.patch b/i386-Add-CPUID-bit-for-CLZERO-and-XSAVEERPTR.patch deleted file mode 100644 index dfa4a7064590348b9353dee3515e9682d926cd3d..0000000000000000000000000000000000000000 --- a/i386-Add-CPUID-bit-for-CLZERO-and-XSAVEERPTR.patch +++ /dev/null @@ -1,44 +0,0 @@ -From a6206163d42156cb9de290f914c6883c77b012b9 Mon Sep 17 00:00:00 2001 -From: Sebastian Andrzej Siewior -Date: Wed, 25 Sep 2019 23:49:48 +0200 -Subject: [PATCH] i386: Add CPUID bit for CLZERO and XSAVEERPTR - -The CPUID bits CLZERO and XSAVEERPTR are availble on AMD's ZEN platform -and could be passed to the guest. - -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Paolo Bonzini ---- - target/i386/cpu.c | 2 +- - target/i386/cpu.h | 2 ++ - 2 files changed, 3 insertions(+), 1 deletion(-) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index f09612f9da..e65f372f25 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -1134,7 +1134,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { - [FEAT_8000_0008_EBX] = { - .type = CPUID_FEATURE_WORD, - .feat_names = { -- NULL, NULL, NULL, NULL, -+ "clzero", NULL, "xsaveerptr", NULL, - NULL, NULL, NULL, NULL, - NULL, "wbnoinvd", NULL, NULL, - "ibpb", NULL, NULL, NULL, -diff --git a/target/i386/cpu.h b/target/i386/cpu.h -index 7ff8ddd464..24d489db0f 100644 ---- a/target/i386/cpu.h -+++ b/target/i386/cpu.h -@@ -696,6 +696,8 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; - - #define CPUID_7_1_EAX_AVX512_BF16 (1U << 5) /* AVX512 BFloat16 Instruction */ - -+#define CPUID_8000_0008_EBX_CLZERO (1U << 0) /* CLZERO instruction */ -+#define CPUID_8000_0008_EBX_XSAVEERPTR (1U << 2) /* Always save/restore FP error pointers */ - #define CPUID_8000_0008_EBX_WBNOINVD (1U << 9) /* Write back and - do not invalidate cache */ - #define CPUID_8000_0008_EBX_IBPB (1U << 12) /* Indirect Branch Prediction Barrier */ --- -2.27.0 - diff --git a/i386-Add-MSR-feature-bit-for-MDS-NO.patch b/i386-Add-MSR-feature-bit-for-MDS-NO.patch deleted file mode 100644 index 9a24836e3bf8e9084dea784deec9f75b50f96633..0000000000000000000000000000000000000000 --- a/i386-Add-MSR-feature-bit-for-MDS-NO.patch +++ /dev/null @@ -1,34 +0,0 @@ -From aaa6c86f46232c68f6846b2da859e4e0b8198664 Mon Sep 17 00:00:00 2001 -From: Cathy Zhang -Date: Tue, 22 Oct 2019 15:35:26 +0800 -Subject: [PATCH] i386: Add MSR feature bit for MDS-NO - -Define MSR_ARCH_CAP_MDS_NO in the IA32_ARCH_CAPABILITIES MSR to allow -CPU models to report the feature when host supports it. - -Signed-off-by: Cathy Zhang -Reviewed-by: Xiaoyao Li -Reviewed-by: Tao Xu -Message-Id: <1571729728-23284-2-git-send-email-cathy.zhang@intel.com> -Signed-off-by: Eduardo Habkost - -Signed-off-by: Jingyi Wang ---- - target/i386/cpu.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/target/i386/cpu.h b/target/i386/cpu.h -index 488b4dc778..9ef868eb71 100644 ---- a/target/i386/cpu.h -+++ b/target/i386/cpu.h -@@ -747,6 +747,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; - #define MSR_ARCH_CAP_RSBA (1U << 2) - #define MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY (1U << 3) - #define MSR_ARCH_CAP_SSB_NO (1U << 4) -+#define MSR_ARCH_CAP_MDS_NO (1U << 5) - - #define MSR_CORE_CAP_SPLIT_LOCK_DETECT (1U << 5) - --- -2.27.0 - diff --git a/i386-Add-macro-for-stibp.patch b/i386-Add-macro-for-stibp.patch deleted file mode 100644 index bf53f56757197ffdc94f388b01800a82d32aed4a..0000000000000000000000000000000000000000 --- a/i386-Add-macro-for-stibp.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 67f68f735af6b1ba829689af2e021bba97e7132a Mon Sep 17 00:00:00 2001 -From: Cathy Zhang -Date: Tue, 22 Oct 2019 15:35:27 +0800 -Subject: [PATCH] i386: Add macro for stibp - -stibp feature is already added through the following commit. -https://github.com/qemu/qemu/commit/0e8916582991b9fd0b94850a8444b8b80d0a0955 - -Add a macro for it to allow CPU models to report it when host supports. - -Signed-off-by: Cathy Zhang -Reviewed-by: Xiaoyao Li -Reviewed-by: Tao Xu -Message-Id: <1571729728-23284-3-git-send-email-cathy.zhang@intel.com> -Signed-off-by: Eduardo Habkost - -Signed-off-by: Jingyi Wang ---- - target/i386/cpu.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/target/i386/cpu.h b/target/i386/cpu.h -index 9ef868eb71..58d8c48964 100644 ---- a/target/i386/cpu.h -+++ b/target/i386/cpu.h -@@ -689,6 +689,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; - #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network Instructions */ - #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */ - #define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Speculation Control */ -+#define CPUID_7_0_EDX_STIBP (1U << 27) /* Single Thread Indirect Branch Predictors */ - #define CPUID_7_0_EDX_ARCH_CAPABILITIES (1U << 29) /*Arch Capabilities*/ - #define CPUID_7_0_EDX_CORE_CAPABILITY (1U << 30) /*Core Capability*/ - #define CPUID_7_0_EDX_SPEC_CTRL_SSBD (1U << 31) /* Speculative Store Bypass Disable */ --- -2.27.0 - diff --git a/i386-Add-new-CPU-model-Cooperlake.patch b/i386-Add-new-CPU-model-Cooperlake.patch deleted file mode 100644 index 60d249fdcd743a6c57c3d1c7051de82c0e1fefe4..0000000000000000000000000000000000000000 --- a/i386-Add-new-CPU-model-Cooperlake.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 8e9eb2f71396e3293d9ba9b1cfaf5f1487f1d475 Mon Sep 17 00:00:00 2001 -From: Cathy Zhang -Date: Tue, 22 Oct 2019 15:35:28 +0800 -Subject: [PATCH] i386: Add new CPU model Cooperlake - -Cooper Lake is intel's successor to Cascade Lake, the new -CPU model inherits features from Cascadelake-Server, while -add one platform associated new feature: AVX512_BF16. Meanwhile, -add STIBP for speculative execution. - -Signed-off-by: Cathy Zhang -Reviewed-by: Xiaoyao Li -Reviewed-by: Tao Xu -Message-Id: <1571729728-23284-4-git-send-email-cathy.zhang@intel.com> -Reviewed-by: Bruce Rogers -Signed-off-by: Eduardo Habkost - -Signed-off-by: Jingyi Wang ---- - target/i386/cpu.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 60 insertions(+) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index 1ade90c28b..5329d73316 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -2378,6 +2378,66 @@ static X86CPUDefinition builtin_x86_defs[] = { - { /* end of list */ } - } - }, -+ { -+ .name = "Cooperlake", -+ .level = 0xd, -+ .vendor = CPUID_VENDOR_INTEL, -+ .family = 6, -+ .model = 85, -+ .stepping = 10, -+ .features[FEAT_1_EDX] = -+ CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | -+ CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | -+ CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | -+ CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | -+ CPUID_DE | CPUID_FP87, -+ .features[FEAT_1_ECX] = -+ CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | -+ CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | -+ CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | -+ CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | -+ CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | -+ CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, -+ .features[FEAT_8000_0001_EDX] = -+ CPUID_EXT2_LM | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP | -+ CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, -+ .features[FEAT_8000_0001_ECX] = -+ CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, -+ .features[FEAT_7_0_EBX] = -+ CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | -+ CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | -+ CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | -+ CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | -+ CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLWB | -+ CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | -+ CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | -+ CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT, -+ .features[FEAT_7_0_ECX] = -+ CPUID_7_0_ECX_PKU | -+ CPUID_7_0_ECX_AVX512VNNI, -+ .features[FEAT_7_0_EDX] = -+ CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_STIBP | -+ CPUID_7_0_EDX_SPEC_CTRL_SSBD | CPUID_7_0_EDX_ARCH_CAPABILITIES, -+ .features[FEAT_ARCH_CAPABILITIES] = -+ MSR_ARCH_CAP_RDCL_NO | MSR_ARCH_CAP_IBRS_ALL | -+ MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY | MSR_ARCH_CAP_MDS_NO, -+ .features[FEAT_7_1_EAX] = -+ CPUID_7_1_EAX_AVX512_BF16, -+ /* -+ * Missing: XSAVES (not supported by some Linux versions, -+ * including v4.1 to v4.12). -+ * KVM doesn't yet expose any XSAVES state save component, -+ * and the only one defined in Skylake (processor tracing) -+ * probably will block migration anyway. -+ */ -+ .features[FEAT_XSAVE] = -+ CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | -+ CPUID_XSAVE_XGETBV1, -+ .features[FEAT_6_EAX] = -+ CPUID_6_EAX_ARAT, -+ .xlevel = 0x80000008, -+ .model_id = "Intel Xeon Processor (Cooperlake)", -+ }, - { - .name = "Icelake-Client", - .level = 0xd, --- -2.27.0 - diff --git a/i386-Resolve-CPU-models-to-v1-by-default.patch b/i386-Resolve-CPU-models-to-v1-by-default.patch deleted file mode 100644 index f8c6315866df7028a1135869a7aa44234eb07b44..0000000000000000000000000000000000000000 --- a/i386-Resolve-CPU-models-to-v1-by-default.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 6a5e994c1dec959143f6d3f83169a7adcb173fc4 Mon Sep 17 00:00:00 2001 -From: Eduardo Habkost -Date: Thu, 5 Dec 2019 19:33:39 -0300 -Subject: [PATCH] i386: Resolve CPU models to v1 by default - -When using `query-cpu-definitions` using `-machine none`, -QEMU is resolving all CPU models to their latest versions. The -actual CPU model version being used by another machine type (e.g. -`pc-q35-4.0`) might be different. - -In theory, this was OK because the correct CPU model -version is returned when using the correct `-machine` argument. - -Except that in practice, this breaks libvirt expectations: -libvirt always use `-machine none` when checking if a CPU model -is runnable, because runnability is not expected to be affected -when the machine type is changed. - -For example, when running on a Haswell host without TSX, -Haswell-v4 is runnable, but Haswell-v1 is not. On those hosts, -`query-cpu-definitions` says Haswell is runnable if using -`-machine none`, but Haswell is actually not runnable using any -of the `pc-*` machine types (because they resolve Haswell to -Haswell-v1). In other words, we're breaking the "runnability -guarantee" we promised to not break for a few releases (see -qemu-deprecated.texi). - -To address this issue, change the default CPU model version to v1 -on all machine types, so we make `query-cpu-definitions` output -when using `-machine none` match the results when using `pc-*`. -This will change in the future (the plan is to always return the -latest CPU model version if using `-machine none`), but only -after giving libvirt the opportunity to adapt. - -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1779078 -Signed-off-by: Eduardo Habkost -Message-Id: <20191205223339.764534-1-ehabkost@redhat.com> -Signed-off-by: Eduardo Habkost ---- - qemu-deprecated.texi | 8 ++++++++ - target/i386/cpu.c | 8 +++++++- - 2 files changed, 15 insertions(+), 1 deletion(-) - -diff --git a/qemu-deprecated.texi b/qemu-deprecated.texi -index fff07bb2a3..719ac23d72 100644 ---- a/qemu-deprecated.texi -+++ b/qemu-deprecated.texi -@@ -331,3 +331,11 @@ existing CPU models. Management software that needs runnability - guarantees must resolve the CPU model aliases using te - ``alias-of'' field returned by the ``query-cpu-definitions'' QMP - command. -+ -+While those guarantees are kept, the return value of -+``query-cpu-definitions'' will have existing CPU model aliases -+point to a version that doesn't break runnability guarantees -+(specifically, version 1 of those CPU models). In future QEMU -+versions, aliases will point to newer CPU model versions -+depending on the machine type, so management software must -+resolve CPU model aliases before starting a virtual machine. -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index e0f3a2dd99..22e0e89718 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -3933,7 +3933,13 @@ static PropValue tcg_default_props[] = { - }; - - --X86CPUVersion default_cpu_version = CPU_VERSION_LATEST; -+/* -+ * We resolve CPU model aliases using -v1 when using "-machine -+ * none", but this is just for compatibility while libvirt isn't -+ * adapted to resolve CPU model versions before creating VMs. -+ * See "Runnability guarantee of CPU models" at * qemu-deprecated.texi. -+ */ -+X86CPUVersion default_cpu_version = 1; - - void x86_cpu_set_default_version(X86CPUVersion version) - { --- -2.27.0 - diff --git a/i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch b/i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch new file mode 100644 index 0000000000000000000000000000000000000000..7ffe327361a0156af4134d1fa57e987b5ada1b1a --- /dev/null +++ b/i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch @@ -0,0 +1,64 @@ +From 475988057789a1f4dcd7354c8a07fd37dcbac79f Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Thu, 10 Feb 2022 20:06:01 +0800 +Subject: [PATCH] i386: cache passthrough: Update AMD 8000_001D.EAX[25:14] + based on vCPU topo + +On AMD target, when host cache passthrough is disabled we will +emulate the guest caches with default values and initialize the +shared cpu list of the caches based on vCPU topology. However +when host cache passthrough is enabled, the shared cpu list is +consistent with host regardless what the vCPU topology is. + +For example, when cache passthrough is enabled, running a guest +with vThreads=1 on a host with pThreads=2, we will get that there +are every *two* logical vCPUs sharing a L1/L2 cache, which is not +consistent with the vCPU topology (vThreads=1). + +So let's reinitialize BITs[25:14] of AMD CPUID 8000_001D.EAX +based on the actual vCPU topology instead of host pCPU topology. + +Signed-off-by: Yanan Wang +--- + target/i386/cpu.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index c1fe2895fd..002e32650d 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5724,9 +5724,31 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + } + break; + case 0x8000001D: ++ /* Populate AMD Processor Cache Information */ + *eax = 0; + if (cpu->cache_info_passthrough) { + host_cpuid(index, count, eax, ebx, ecx, edx); ++ ++ /* ++ * Clear BITs[25:14] and then update them based on the guest ++ * vCPU topology, like what we do in encode_cache_cpuid8000001d ++ * when cache_info_passthrough is not enabled. ++ */ ++ *eax &= ~0x03FFC000; ++ switch (count) { ++ case 0: /* L1 dcache info */ ++ case 1: /* L1 icache info */ ++ case 2: /* L2 cache info */ ++ *eax |= ((topo_info.threads_per_core - 1) << 14); ++ break; ++ case 3: /* L3 cache info */ ++ *eax |= ((topo_info.cores_per_die * ++ topo_info.threads_per_core - 1) << 14); ++ break; ++ default: /* end of info */ ++ *eax = *ebx = *ecx = *edx = 0; ++ break; ++ } + break; + } + switch (count) { +-- +2.27.0 + diff --git a/i386-cache-passthrough-Update-Intel-CPUID4.EAX-25-14.patch b/i386-cache-passthrough-Update-Intel-CPUID4.EAX-25-14.patch new file mode 100644 index 0000000000000000000000000000000000000000..a0fc157bf3e84734665871a86ca53bb25e5bbec5 --- /dev/null +++ b/i386-cache-passthrough-Update-Intel-CPUID4.EAX-25-14.patch @@ -0,0 +1,88 @@ +From 3eaa433ca1cbee753698893b7732819ba2e31302 Mon Sep 17 00:00:00 2001 +From: Jian Wang +Date: Thu, 10 Feb 2022 19:43:55 +0800 +Subject: [PATCH] i386: cache passthrough: Update Intel CPUID4.EAX[25:14] based + on vCPU topo + +On Intel target, when host cache passthrough is disabled we will +emulate the guest caches with default values and initialize the +shared cpu list of the caches based on vCPU topology. However when +host cache passthrough is enabled, the shared cpu list is consistent +with host regardless what the vCPU topology is. + +For example, when cache passthrough is enabled, running a guest +with vThreads=1 on a host with pThreads=2, we will get that there +are every *two* logical vCPUs sharing a L1/L2 cache, which is not +consistent with the vCPU topology (vThreads=1). + +So let's reinitialize BITs[25:14] of Intel CPUID 4 based on the +actual vCPU topology instead of host pCPU topology. + +Signed-off-by: Jian Wang +Signed-off-by: Yanan Wang +--- + target/i386/cpu.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 868cf3e7e8..c1fe2895fd 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5196,7 +5196,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + { + X86CPU *cpu = env_archcpu(env); + CPUState *cs = env_cpu(env); +- uint32_t die_offset; ++ uint32_t die_offset, smt_width; + uint32_t limit; + uint32_t signature[3]; + X86CPUTopoInfo topo_info; +@@ -5205,6 +5205,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + topo_info.cores_per_die = cs->nr_cores; + topo_info.threads_per_core = cs->nr_threads; + ++ die_offset = apicid_die_offset(&topo_info); ++ smt_width = apicid_smt_width(&topo_info); ++ + /* Calculate & apply limits for different index ranges */ + if (index >= 0xC0000000) { + limit = env->cpuid_xlevel2; +@@ -5272,8 +5275,25 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + /* cache info: needed for Core compatibility */ + if (cpu->cache_info_passthrough) { + host_cpuid(index, count, eax, ebx, ecx, edx); +- /* QEMU gives out its own APIC IDs, never pass down bits 31..26. */ +- *eax &= ~0xFC000000; ++ /* ++ * QEMU gives out its own APIC IDs, never pass down bits 31..26. ++ * Update the cache topo bits 25..14, according to the guest ++ * vCPU topology instead of the host pCPU topology. ++ */ ++ *eax &= ~0xFFFFC000; ++ switch (count) { ++ case 0: /* L1 dcache info */ ++ case 1: /* L1 icache info */ ++ case 2: /* L2 cache info */ ++ *eax |= ((1 << smt_width) - 1) << 14; ++ break; ++ case 3: /* L3 cache info */ ++ *eax |= ((1 << die_offset) - 1) << 14; ++ break; ++ default: /* end of info */ ++ *eax = *ebx = *ecx = *edx = 0; ++ break; ++ } + if ((*eax & 31) && cs->nr_cores > 1) { + *eax |= (cs->nr_cores - 1) << 26; + } +@@ -5298,7 +5318,6 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + eax, ebx, ecx, edx); + break; + case 3: /* L3 cache info */ +- die_offset = apicid_die_offset(&topo_info); + if (cpu->enable_l3_cache) { + encode_cache_cpuid4(env->cache_info_cpuid4.l3_cache, + (1 << die_offset), cs->nr_cores, +-- +2.27.0 + diff --git a/i386-cpu-Don-t-add-unavailable_features-to-env-user_.patch b/i386-cpu-Don-t-add-unavailable_features-to-env-user_.patch deleted file mode 100644 index 3e42e71e5d9e2d038d4540fa0b57b87adcbf92d7..0000000000000000000000000000000000000000 --- a/i386-cpu-Don-t-add-unavailable_features-to-env-user_.patch +++ /dev/null @@ -1,33 +0,0 @@ -From e6f3e08acd55d13cbb154ff8abb1b3c2ed658285 Mon Sep 17 00:00:00 2001 -From: Xiaoyao Li -Date: Tue, 14 Jul 2020 01:44:36 +0800 -Subject: [PATCH] i386/cpu: Don't add unavailable_features to - env->user_features - -Features unavailable due to absent of their dependent features should -not be added to env->user_features. env->user_features only contains the -feature explicity specified with -feature/+feature by user. - -Fixes: 99e24dbdaa68 ("target/i386: introduce generic feature dependency mechanism") -Signed-off-by: Xiaoyao Li -Message-Id: <20200713174436.41070-3-xiaoyao.li@intel.com> -Signed-off-by: Eduardo Habkost ---- - target/i386/cpu.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index 6f27a5170a..e0f3a2dd99 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -6173,7 +6173,6 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) - unavailable_features & env->user_features[d->to.index], - "This feature depends on other features that were not requested"); - -- env->user_features[d->to.index] |= unavailable_features; - env->features[d->to.index] &= ~unavailable_features; - } - } --- -2.27.0 - diff --git a/i386-cpu-fix-compile-error-in-all-target-configure.patch b/i386-cpu-fix-compile-error-in-all-target-configure.patch new file mode 100644 index 0000000000000000000000000000000000000000..0cadfa1a02feaf82b60c2582d8de35c8d040dafd --- /dev/null +++ b/i386-cpu-fix-compile-error-in-all-target-configure.patch @@ -0,0 +1,69 @@ +From 11498c2d92e703923d373b64ad3f33aec5f383f2 Mon Sep 17 00:00:00 2001 +From: Jiajie Li +Date: Thu, 17 Feb 2022 09:51:13 +0800 +Subject: [PATCH] i386/cpu: fix compile error in all target configure + +When compile with `./configure && make -j`, there will be +error: "unknown type name `ram_addr_t`", fix the error by +adding compilation macro to control it. + +Signed-off-by: Jiajie Li +--- + target/i386/cpu.c | 16 ++++++++-------- + target/i386/cpu.h | 2 ++ + 2 files changed, 10 insertions(+), 8 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index a4732a7372..d9dca1dafb 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -6711,14 +6711,6 @@ static bool x86_cpu_get_paging_enabled(const CPUState *cs) + + return cpu->env.cr[0] & CR0_PG_MASK; + } +-#endif /* !CONFIG_USER_ONLY */ +- +-static void x86_cpu_set_pc(CPUState *cs, vaddr value) +-{ +- X86CPU *cpu = X86_CPU(cs); +- +- cpu->env.eip = value; +-} + + /* At present, we check the vm is *LARGE* or not, i.e. whether + * the memory size is more than 4T or not. +@@ -6736,6 +6728,14 @@ void x86_cpu_adjuest_by_ram_size(ram_addr_t ram_size, X86CPU *cpu) + cpu->fill_mtrr_mask = true; + } + } ++#endif /* !CONFIG_USER_ONLY */ ++ ++static void x86_cpu_set_pc(CPUState *cs, vaddr value) ++{ ++ X86CPU *cpu = X86_CPU(cs); ++ ++ cpu->env.eip = value; ++} + + int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request) + { +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 6f777fd6ca..d9296a9abc 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1842,10 +1842,12 @@ struct X86CPU { + extern const VMStateDescription vmstate_x86_cpu; + #endif + ++#ifndef CONFIG_USER_ONLY + #define DEFAULT_VM_CPU_PHYS_BITS 42 + #define LARGE_VM_CPU_PHYS_BITS 46 + + void x86_cpu_adjuest_by_ram_size(ram_addr_t ram_size, X86CPU *cpu); ++#endif + + int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request); + +-- +2.27.0 + diff --git a/i6300esb-watchdog-bugfix-Add-a-runstate-transition.patch b/i6300esb-watchdog-bugfix-Add-a-runstate-transition.patch new file mode 100644 index 0000000000000000000000000000000000000000..f207f407048f49c972b8bf75548b081b567395a2 --- /dev/null +++ b/i6300esb-watchdog-bugfix-Add-a-runstate-transition.patch @@ -0,0 +1,42 @@ +From 3c283ea7ca1902b9d221897fd65c5edb1d16e004 Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Fri, 11 Feb 2022 20:33:47 +0800 +Subject: [PATCH] i6300esb watchdog: bugfix: Add a runstate transition + +QEMU will abort() for the reasons now: + + invalid runstate transition: 'prelaunch' -> 'postmigrate' + Aborted + +This happens when: + |<- watchdog timeout happened, then sets reset_requested to + | SHUTDOWN_CAUSE_GUEST_RESET; + |<- hot-migration thread sets vm state to RUN_STATE_FINISH_MIGRATE + | before the last time of migration; + |<- main thread gets the change of reset_requested and triggers + | reset, then sets vm state to RUN_STATE_PRELAUNCH; + |<- hot-migration thread sets vm state to RUN_STATE_POSTMIGRATE. + +Then 'prelaunch' -> 'postmigrate' runstate transition will happen. +It is legal so add this transition to runstate_transitions_def. + +Signed-off-by: Jinhua Cao +--- + softmmu/runstate.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/softmmu/runstate.c b/softmmu/runstate.c +index 5736d908db..680994cdf8 100644 +--- a/softmmu/runstate.c ++++ b/softmmu/runstate.c +@@ -115,6 +115,7 @@ static const RunStateTransition runstate_transitions_def[] = { + { RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING }, + { RUN_STATE_PRELAUNCH, RUN_STATE_FINISH_MIGRATE }, + { RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE }, ++ { RUN_STATE_PRELAUNCH, RUN_STATE_POSTMIGRATE }, + + { RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING }, + { RUN_STATE_FINISH_MIGRATE, RUN_STATE_PAUSED }, +-- +2.27.0 + diff --git a/ide-Fix-incorrect-handling-of-some-PRDTs-in-ide_dma_.patch b/ide-Fix-incorrect-handling-of-some-PRDTs-in-ide_dma_.patch deleted file mode 100644 index 9570b46b755e06705212253195a6605d738db350..0000000000000000000000000000000000000000 --- a/ide-Fix-incorrect-handling-of-some-PRDTs-in-ide_dma_.patch +++ /dev/null @@ -1,89 +0,0 @@ -From ed78352a59ea7acf7520d4d47a96b9911bae7fc3 Mon Sep 17 00:00:00 2001 -From: Alexander Popov -Date: Mon, 23 Dec 2019 20:51:16 +0300 -Subject: [PATCH] ide: Fix incorrect handling of some PRDTs in ide_dma_cb() - -The commit a718978ed58a from July 2015 introduced the assertion which -implies that the size of successful DMA transfers handled in ide_dma_cb() -should be multiple of 512 (the size of a sector). But guest systems can -initiate DMA transfers that don't fit this requirement. - -For fixing that let's check the number of bytes prepared for the transfer -by the prepare_buf() handler. The code in ide_dma_cb() must behave -according to the Programming Interface for Bus Master IDE Controller -(Revision 1.0 5/16/94): -1. If PRDs specified a smaller size than the IDE transfer - size, then the Interrupt and Active bits in the Controller - status register are not set (Error Condition). -2. If the size of the physical memory regions was equal to - the IDE device transfer size, the Interrupt bit in the - Controller status register is set to 1, Active bit is set to 0. -3. If PRDs specified a larger size than the IDE transfer size, - the Interrupt and Active bits in the Controller status register - are both set to 1. - -Signed-off-by: Alexander Popov -Reviewed-by: Kevin Wolf -Message-id: 20191223175117.508990-2-alex.popov@linux.com -Signed-off-by: John Snow - -diff --git a/hw/ide/core.c b/hw/ide/core.c -index 754ff4dc34..80000eb766 100644 ---- a/hw/ide/core.c -+++ b/hw/ide/core.c -@@ -849,6 +849,7 @@ static void ide_dma_cb(void *opaque, int ret) - int64_t sector_num; - uint64_t offset; - bool stay_active = false; -+ int32_t prep_size = 0; - - if (ret == -EINVAL) { - ide_dma_error(s); -@@ -863,13 +864,15 @@ static void ide_dma_cb(void *opaque, int ret) - } - } - -- n = s->io_buffer_size >> 9; -- if (n > s->nsector) { -- /* The PRDs were longer than needed for this request. Shorten them so -- * we don't get a negative remainder. The Active bit must remain set -- * after the request completes. */ -+ if (s->io_buffer_size > s->nsector * 512) { -+ /* -+ * The PRDs were longer than needed for this request. -+ * The Active bit must remain set after the request completes. -+ */ - n = s->nsector; - stay_active = true; -+ } else { -+ n = s->io_buffer_size >> 9; - } - - sector_num = ide_get_sector(s); -@@ -892,9 +895,20 @@ static void ide_dma_cb(void *opaque, int ret) - n = s->nsector; - s->io_buffer_index = 0; - s->io_buffer_size = n * 512; -- if (s->bus->dma->ops->prepare_buf(s->bus->dma, s->io_buffer_size) < 512) { -- /* The PRDs were too short. Reset the Active bit, but don't raise an -- * interrupt. */ -+ prep_size = s->bus->dma->ops->prepare_buf(s->bus->dma, s->io_buffer_size); -+ /* prepare_buf() must succeed and respect the limit */ -+ assert(prep_size >= 0 && prep_size <= n * 512); -+ -+ /* -+ * Now prep_size stores the number of bytes in the sglist, and -+ * s->io_buffer_size stores the number of bytes described by the PRDs. -+ */ -+ -+ if (prep_size < n * 512) { -+ /* -+ * The PRDs are too short for this request. Error condition! -+ * Reset the Active bit and don't raise the interrupt. -+ */ - s->status = READY_STAT | SEEK_STAT; - dma_buf_commit(s, 0); - goto eot; --- -2.23.0 - diff --git a/ide-ahci-add-check-to-avoid-null-dereference-CVE-201.patch b/ide-ahci-add-check-to-avoid-null-dereference-CVE-201.patch index 97824d4d27236961e5a9c3e3f4242e73d1334d44..7cd2ccff36dc717b01363728e5d48f6be9661e0e 100644 --- a/ide-ahci-add-check-to-avoid-null-dereference-CVE-201.patch +++ b/ide-ahci-add-check-to-avoid-null-dereference-CVE-201.patch @@ -1,4 +1,4 @@ -From c7fd5f3841f14c24e442fb6968c9f2d9e016f28a Mon Sep 17 00:00:00 2001 +From 9169beed83ea77059a7240aae5621dcfb3178cba Mon Sep 17 00:00:00 2001 From: Prasad J Pandit Date: Mon, 21 Jun 2021 09:22:35 +0800 Subject: [PATCH] ide: ahci: add check to avoid null dereference @@ -14,15 +14,16 @@ Reported-by: Bugs SysSec Signed-off-by: Prasad J Pandit Signed-off-by: Jiajie Li +Signed-off-by: Yan Wang --- hw/ide/ahci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c -index 6aaf66534a..a7be0ae4fe 100644 +index a94c6e26fb..256b58026a 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c -@@ -1455,8 +1455,10 @@ static void ahci_commit_buf(IDEDMA *dma, uint32_t tx_bytes) +@@ -1459,8 +1459,10 @@ static void ahci_commit_buf(const IDEDMA *dma, uint32_t tx_bytes) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); @@ -34,7 +35,7 @@ index 6aaf66534a..a7be0ae4fe 100644 + } } - static int ahci_dma_rw_buf(IDEDMA *dma, int is_write) + static int ahci_dma_rw_buf(const IDEDMA *dma, bool is_write) -- 2.27.0 diff --git a/ide-atapi-check-io_buffer_index-in-ide_atapi_cmd_rep.patch b/ide-atapi-check-io_buffer_index-in-ide_atapi_cmd_rep.patch deleted file mode 100644 index da58bb9cc28d6e193d7b55ba530768d69a04324a..0000000000000000000000000000000000000000 --- a/ide-atapi-check-io_buffer_index-in-ide_atapi_cmd_rep.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 5209fbd340efe3fa7f8ea82f671db2fa04dda19b Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Tue, 23 Feb 2021 15:20:03 +0800 -Subject: [PATCH] ide:atapi: check io_buffer_index in ide_atapi_cmd_reply_end - -Fix CVE-2020-29443 - -During data transfer via packet command in 'ide_atapi_cmd_reply_end' -'s->io_buffer_index' could exceed the 's->io_buffer' length, leading -to OOB access issue. Add check to avoid it. - ... - #9 ahci_pio_transfer ../hw/ide/ahci.c:1383 - #10 ide_transfer_start_norecurse ../hw/ide/core.c:553 - #11 ide_atapi_cmd_reply_end ../hw/ide/atapi.c:284 - #12 ide_atapi_cmd_read_pio ../hw/ide/atapi.c:329 - #13 ide_atapi_cmd_read ../hw/ide/atapi.c:442 - #14 cmd_read ../hw/ide/atapi.c:988 - #15 ide_atapi_cmd ../hw/ide/atapi.c:1352 - #16 ide_transfer_start ../hw/ide/core.c:561 - #17 cmd_packet ../hw/ide/core.c:1729 - #18 ide_exec_cmd ../hw/ide/core.c:2107 - #19 handle_reg_h2d_fis ../hw/ide/ahci.c:1267 - #20 handle_cmd ../hw/ide/ahci.c:1318 - #21 check_cmd ../hw/ide/ahci.c:592 - #22 ahci_port_write ../hw/ide/ahci.c:373 - #23 ahci_mem_write ../hw/ide/ahci.c:513 - -Reported-by: Wenxiang Qian -Signed-off-by: Prasad J Pandit - -Signed-off-by: Jiajie Li ---- - hw/ide/atapi.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c -index 1b0f66cc08..fc9dc87f03 100644 ---- a/hw/ide/atapi.c -+++ b/hw/ide/atapi.c -@@ -300,6 +300,9 @@ void ide_atapi_cmd_reply_end(IDEState *s) - s->packet_transfer_size -= size; - s->elementary_transfer_size -= size; - s->io_buffer_index += size; -+ if (s->io_buffer_index > s->io_buffer_total_len) { -+ return; -+ } - - /* Some adapters process PIO data right away. In that case, we need - * to avoid mutual recursion between ide_transfer_start --- -2.27.0 - diff --git a/ide-fix-leak-from-qemu_allocate_irqs.patch b/ide-fix-leak-from-qemu_allocate_irqs.patch deleted file mode 100644 index dce6e906ce92e7e303d2198d7a612905ca0632c1..0000000000000000000000000000000000000000 --- a/ide-fix-leak-from-qemu_allocate_irqs.patch +++ /dev/null @@ -1,28 +0,0 @@ -From df35f8fe2687df32cb65f6a03b8dd80314cc4c53 Mon Sep 17 00:00:00 2001 -From: lizhengui -Date: Wed, 9 Sep 2020 15:00:08 +0800 -Subject: [PATCH] ide: fix leak from qemu_allocate_irqs - -The array returned by qemu_allocate_irqs is malloced, free it. - -Signed-off-by: Paolo Bonzini -Reviewed-by: Thomas Huth ---- - hw/ide/cmd646.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c -index ed23aabf..a149cd6c 100644 ---- a/hw/ide/cmd646.c -+++ b/hw/ide/cmd646.c -@@ -299,6 +299,7 @@ static void pci_cmd646_ide_realize(PCIDevice *dev, Error **errp) - d->bmdma[i].bus = &d->bus[i]; - ide_register_restart_cb(&d->bus[i]); - } -+ g_free(irq); - - vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d); - qemu_register_reset(cmd646_reset, d); --- -2.19.1 - diff --git a/imx7-ccm-add-digprog-mmio-write-method.patch b/imx7-ccm-add-digprog-mmio-write-method.patch deleted file mode 100644 index b68bf028b9b3e9bc2fe2d1838f6d3cf64dce7866..0000000000000000000000000000000000000000 --- a/imx7-ccm-add-digprog-mmio-write-method.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 5979338f8fb4562f7af32c58b7e7542d7396954e Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Thu, 25 Mar 2021 17:29:28 +0800 -Subject: [PATCH] imx7-ccm: add digprog mmio write method - -fix CVE-2020-15469 - -Add digprog mmio write method to avoid assert failure during -initialisation. - -Reviewed-by: Li Qiang -Signed-off-by: Prasad J Pandit - -Signed-off-by: Jiajie Li ---- - hw/misc/imx7_ccm.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/hw/misc/imx7_ccm.c b/hw/misc/imx7_ccm.c -index d9bdcf1027..831311a7c8 100644 ---- a/hw/misc/imx7_ccm.c -+++ b/hw/misc/imx7_ccm.c -@@ -130,8 +130,15 @@ static const struct MemoryRegionOps imx7_set_clr_tog_ops = { - }, - }; - -+static void imx7_digprog_write(void *opaque, hwaddr addr, -+ uint64_t data, unsigned size) -+{ -+ qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__); -+} -+ - static const struct MemoryRegionOps imx7_digprog_ops = { - .read = imx7_set_clr_tog_read, -+ .write = imx7_digprog_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .impl = { - .min_access_size = 4, --- -2.27.0 - diff --git a/include-Make-headers-more-self-contained.patch b/include-Make-headers-more-self-contained.patch deleted file mode 100644 index 565471c8ce67ec70b0bb5691f66cba384b8a1202..0000000000000000000000000000000000000000 --- a/include-Make-headers-more-self-contained.patch +++ /dev/null @@ -1,1551 +0,0 @@ -From 1b6a1ef572411efee7cbf1b65aeb15c704b997cc Mon Sep 17 00:00:00 2001 -From: Markus Armbruster -Date: Mon, 12 Aug 2019 07:23:31 +0200 -Subject: [PATCH] include: Make headers more self-contained -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Back in 2016, we discussed[1] rules for headers, and these were -generally liked: - -1. Have a carefully curated header that's included everywhere first. We - got that already thanks to Peter: osdep.h. - -2. Headers should normally include everything they need beyond osdep.h. - If exceptions are needed for some reason, they must be documented in - the header. If all that's needed from a header is typedefs, put - those into qemu/typedefs.h instead of including the header. - -3. Cyclic inclusion is forbidden. - -This patch gets include/ closer to obeying 2. - -It's actually extracted from my "[RFC] Baby steps towards saner -headers" series[2], which demonstrates a possible path towards -checking 2 automatically. It passes the RFC test there. - -[1] Message-ID: <87h9g8j57d.fsf@blackfin.pond.sub.org> - https://lists.nongnu.org/archive/html/qemu-devel/2016-03/msg03345.html -[2] Message-Id: <20190711122827.18970-1-armbru@redhat.com> - https://lists.nongnu.org/archive/html/qemu-devel/2019-07/msg02715.html - -Signed-off-by: Markus Armbruster -Reviewed-by: Alistair Francis -Message-Id: <20190812052359.30071-2-armbru@redhat.com> -Tested-by: Philippe Mathieu-Daudé ---- - include/block/raw-aio.h | 2 ++ - include/block/write-threshold.h | 2 ++ - include/disas/disas.h | 1 + - include/exec/cputlb.h | 3 +++ - include/exec/exec-all.h | 1 + - include/exec/ioport.h | 2 ++ - include/exec/memory-internal.h | 2 ++ - include/exec/ram_addr.h | 1 + - include/exec/softmmu-semi.h | 2 ++ - include/exec/tb-hash.h | 2 ++ - include/exec/user/thunk.h | 2 ++ - include/fpu/softfloat-macros.h | 2 ++ - include/hw/acpi/pci.h | 3 +++ - include/hw/acpi/tco.h | 3 +++ - include/hw/adc/stm32f2xx_adc.h | 2 ++ - include/hw/arm/allwinner-a10.h | 1 + - include/hw/arm/aspeed_soc.h | 1 + - include/hw/arm/bcm2836.h | 1 + - include/hw/arm/exynos4210.h | 3 +-- - include/hw/arm/fsl-imx25.h | 1 + - include/hw/arm/fsl-imx31.h | 1 + - include/hw/arm/sharpsl.h | 3 +++ - include/hw/arm/xlnx-zynqmp.h | 1 + - include/hw/block/fdc.h | 2 ++ - include/hw/block/flash.h | 1 + - include/hw/char/escc.h | 1 + - include/hw/char/xilinx_uartlite.h | 2 ++ - include/hw/core/generic-loader.h | 1 + - include/hw/cris/etraxfs.h | 1 + - include/hw/cris/etraxfs_dma.h | 3 +++ - include/hw/display/i2c-ddc.h | 1 + - include/hw/empty_slot.h | 2 ++ - include/hw/gpio/bcm2835_gpio.h | 1 + - include/hw/i2c/aspeed_i2c.h | 2 ++ - include/hw/i386/apic_internal.h | 1 + - include/hw/i386/ioapic_internal.h | 1 + - include/hw/intc/allwinner-a10-pic.h | 2 ++ - include/hw/intc/heathrow_pic.h | 2 ++ - include/hw/intc/mips_gic.h | 1 + - include/hw/isa/vt82c686.h | 2 ++ - include/hw/mips/cps.h | 1 + - include/hw/misc/macio/cuda.h | 2 ++ - include/hw/misc/macio/gpio.h | 3 +++ - include/hw/misc/macio/macio.h | 2 ++ - include/hw/misc/macio/pmu.h | 3 +++ - include/hw/misc/mips_cmgcr.h | 2 ++ - include/hw/misc/mips_cpc.h | 2 ++ - include/hw/misc/pvpanic.h | 3 +++ - include/hw/net/allwinner_emac.h | 1 + - include/hw/net/lance.h | 1 + - include/hw/nvram/chrp_nvram.h | 2 ++ - include/hw/pci-host/sabre.h | 2 ++ - include/hw/pci-host/uninorth.h | 2 +- - include/hw/pci/pcie_aer.h | 1 + - include/hw/ppc/pnv_core.h | 1 + - include/hw/ppc/ppc4xx.h | 4 ++++ - include/hw/ppc/spapr_irq.h | 3 +++ - include/hw/ppc/spapr_vio.h | 1 + - include/hw/ppc/spapr_xive.h | 2 ++ - include/hw/ppc/xive_regs.h | 3 +++ - include/hw/riscv/boot.h | 2 ++ - include/hw/riscv/riscv_hart.h | 3 +++ - include/hw/riscv/sifive_clint.h | 2 ++ - include/hw/riscv/sifive_e.h | 1 + - include/hw/riscv/sifive_plic.h | 2 +- - include/hw/riscv/sifive_prci.h | 2 ++ - include/hw/riscv/sifive_test.h | 2 ++ - include/hw/riscv/sifive_u.h | 1 + - include/hw/riscv/sifive_uart.h | 3 +++ - include/hw/riscv/spike.h | 3 +++ - include/hw/riscv/virt.h | 3 +++ - include/hw/s390x/ap-device.h | 3 +++ - include/hw/s390x/css-bridge.h | 3 ++- - include/hw/s390x/css.h | 1 + - include/hw/s390x/tod.h | 2 +- - include/hw/semihosting/console.h | 2 ++ - include/hw/sh4/sh_intc.h | 1 + - include/hw/sparc/sparc64.h | 2 ++ - include/hw/ssi/aspeed_smc.h | 1 + - include/hw/ssi/xilinx_spips.h | 1 + - include/hw/timer/allwinner-a10-pit.h | 1 + - include/hw/timer/i8254_internal.h | 1 + - include/hw/timer/m48t59.h | 2 ++ - include/hw/timer/mc146818rtc_regs.h | 2 ++ - include/hw/timer/xlnx-zynqmp-rtc.h | 1 + - include/hw/virtio/virtio-access.h | 1 + - include/hw/virtio/virtio-gpu-bswap.h | 1 + - include/hw/virtio/virtio-rng.h | 1 + - include/hw/watchdog/wdt_aspeed.h | 1 + - include/libdecnumber/decNumberLocal.h | 1 + - include/migration/cpu.h | 3 +++ - include/monitor/hmp-target.h | 2 ++ - include/qemu/atomic128.h | 2 ++ - include/qemu/ratelimit.h | 2 ++ - include/qemu/thread-win32.h | 2 +- - include/sysemu/balloon.h | 1 + - include/sysemu/cryptodev-vhost-user.h | 3 +++ - include/sysemu/hvf.h | 1 + - include/sysemu/iothread.h | 1 + - include/sysemu/kvm_int.h | 2 ++ - include/sysemu/memory_mapping.h | 2 ++ - include/sysemu/xen-mapcache.h | 2 ++ - include/ui/egl-helpers.h | 3 +++ - include/ui/input.h | 1 + - include/ui/spice-display.h | 1 + - target/hppa/cpu.h | 2 +- - 106 files changed, 183 insertions(+), 8 deletions(-) - -diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h -index 0cb7cc74a2..4629f24d08 100644 ---- a/include/block/raw-aio.h -+++ b/include/block/raw-aio.h -@@ -12,9 +12,11 @@ - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ -+ - #ifndef QEMU_RAW_AIO_H - #define QEMU_RAW_AIO_H - -+#include "block/aio.h" - #include "qemu/coroutine.h" - #include "qemu/iov.h" - -diff --git a/include/block/write-threshold.h b/include/block/write-threshold.h -index 80d8aab5d0..c646f267a4 100644 ---- a/include/block/write-threshold.h -+++ b/include/block/write-threshold.h -@@ -9,9 +9,11 @@ - * This work is licensed under the terms of the GNU LGPL, version 2 or later. - * See the COPYING.LIB file in the top-level directory. - */ -+ - #ifndef BLOCK_WRITE_THRESHOLD_H - #define BLOCK_WRITE_THRESHOLD_H - -+#include "block/block_int.h" - - /* - * bdrv_write_threshold_set: -diff --git a/include/disas/disas.h b/include/disas/disas.h -index 15da511f49..ba47e9197c 100644 ---- a/include/disas/disas.h -+++ b/include/disas/disas.h -@@ -1,6 +1,7 @@ - #ifndef QEMU_DISAS_H - #define QEMU_DISAS_H - -+#include "exec/hwaddr.h" - - #ifdef NEED_CPU_H - #include "cpu.h" -diff --git a/include/exec/cputlb.h b/include/exec/cputlb.h -index 5373188be3..a62cfb28d5 100644 ---- a/include/exec/cputlb.h -+++ b/include/exec/cputlb.h -@@ -16,9 +16,12 @@ - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -+ - #ifndef CPUTLB_H - #define CPUTLB_H - -+#include "exec/cpu-common.h" -+ - #if !defined(CONFIG_USER_ONLY) - /* cputlb.c */ - void tlb_protect_code(ram_addr_t ram_addr); -diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h -index 16034ee651..135aeaab0d 100644 ---- a/include/exec/exec-all.h -+++ b/include/exec/exec-all.h -@@ -20,6 +20,7 @@ - #ifndef EXEC_ALL_H - #define EXEC_ALL_H - -+#include "cpu.h" - #include "exec/tb-context.h" - #include "sysemu/cpus.h" - -diff --git a/include/exec/ioport.h b/include/exec/ioport.h -index a298b89ce1..97feb296d2 100644 ---- a/include/exec/ioport.h -+++ b/include/exec/ioport.h -@@ -24,6 +24,8 @@ - #ifndef IOPORT_H - #define IOPORT_H - -+#include "exec/memory.h" -+ - #define MAX_IOPORTS (64 * 1024) - #define IOPORTS_MASK (MAX_IOPORTS - 1) - -diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h -index d1a9dd1ec8..ef4fb92371 100644 ---- a/include/exec/memory-internal.h -+++ b/include/exec/memory-internal.h -@@ -20,6 +20,8 @@ - #ifndef MEMORY_INTERNAL_H - #define MEMORY_INTERNAL_H - -+#include "cpu.h" -+ - #ifndef CONFIG_USER_ONLY - static inline AddressSpaceDispatch *flatview_to_dispatch(FlatView *fv) - { -diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h -index 523440662b..27a164b669 100644 ---- a/include/exec/ram_addr.h -+++ b/include/exec/ram_addr.h -@@ -20,6 +20,7 @@ - #define RAM_ADDR_H - - #ifndef CONFIG_USER_ONLY -+#include "cpu.h" - #include "hw/xen/xen.h" - #include "sysemu/tcg.h" - #include "exec/ramlist.h" -diff --git a/include/exec/softmmu-semi.h b/include/exec/softmmu-semi.h -index 970837992e..fbcae88f4b 100644 ---- a/include/exec/softmmu-semi.h -+++ b/include/exec/softmmu-semi.h -@@ -10,6 +10,8 @@ - #ifndef SOFTMMU_SEMI_H - #define SOFTMMU_SEMI_H - -+#include "cpu.h" -+ - static inline uint64_t softmmu_tget64(CPUArchState *env, target_ulong addr) - { - uint64_t val; -diff --git a/include/exec/tb-hash.h b/include/exec/tb-hash.h -index 4f3a37d927..805235d321 100644 ---- a/include/exec/tb-hash.h -+++ b/include/exec/tb-hash.h -@@ -20,6 +20,8 @@ - #ifndef EXEC_TB_HASH_H - #define EXEC_TB_HASH_H - -+#include "exec/cpu-defs.h" -+#include "exec/exec-all.h" - #include "qemu/xxhash.h" - - #ifdef CONFIG_SOFTMMU -diff --git a/include/exec/user/thunk.h b/include/exec/user/thunk.h -index 8d3af5a3be..eae2c27f99 100644 ---- a/include/exec/user/thunk.h -+++ b/include/exec/user/thunk.h -@@ -16,10 +16,12 @@ - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -+ - #ifndef THUNK_H - #define THUNK_H - - #include "cpu.h" -+#include "exec/user/abitypes.h" - - /* types enums definitions */ - -diff --git a/include/fpu/softfloat-macros.h b/include/fpu/softfloat-macros.h -index c55aa6d174..be83a833ec 100644 ---- a/include/fpu/softfloat-macros.h -+++ b/include/fpu/softfloat-macros.h -@@ -82,6 +82,8 @@ this code that are retained. - #ifndef FPU_SOFTFLOAT_MACROS_H - #define FPU_SOFTFLOAT_MACROS_H - -+#include "fpu/softfloat.h" -+ - /*---------------------------------------------------------------------------- - | Shifts `a' right by the number of bits given in `count'. If any nonzero - | bits are shifted off, they are ``jammed'' into the least significant bit of -diff --git a/include/hw/acpi/pci.h b/include/hw/acpi/pci.h -index 8bbd32cf45..bf2a3ed0ba 100644 ---- a/include/hw/acpi/pci.h -+++ b/include/hw/acpi/pci.h -@@ -22,9 +22,12 @@ - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - */ -+ - #ifndef HW_ACPI_PCI_H - #define HW_ACPI_PCI_H - -+#include "hw/acpi/bios-linker-loader.h" -+ - typedef struct AcpiMcfgInfo { - uint64_t base; - uint32_t size; -diff --git a/include/hw/acpi/tco.h b/include/hw/acpi/tco.h -index d19dd59353..726f840cce 100644 ---- a/include/hw/acpi/tco.h -+++ b/include/hw/acpi/tco.h -@@ -6,9 +6,12 @@ - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ -+ - #ifndef HW_ACPI_TCO_H - #define HW_ACPI_TCO_H - -+#include "exec/memory.h" -+#include "migration/vmstate.h" - - /* As per ICH9 spec, the internal timer has an error of ~0.6s on every tick */ - #define TCO_TICK_NSEC 600000000LL -diff --git a/include/hw/adc/stm32f2xx_adc.h b/include/hw/adc/stm32f2xx_adc.h -index a72f734eb1..663b79f4f3 100644 ---- a/include/hw/adc/stm32f2xx_adc.h -+++ b/include/hw/adc/stm32f2xx_adc.h -@@ -25,6 +25,8 @@ - #ifndef HW_STM32F2XX_ADC_H - #define HW_STM32F2XX_ADC_H - -+#include "hw/sysbus.h" -+ - #define ADC_SR 0x00 - #define ADC_CR1 0x04 - #define ADC_CR2 0x08 -diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h -index e99fe2ea2e..7182ce5c4b 100644 ---- a/include/hw/arm/allwinner-a10.h -+++ b/include/hw/arm/allwinner-a10.h -@@ -11,6 +11,7 @@ - #include "hw/ide/ahci.h" - - #include "sysemu/sysemu.h" -+#include "target/arm/cpu.h" - - - #define AW_A10_PIC_REG_BASE 0x01c20400 -diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h -index cef605ad6b..976fd6be93 100644 ---- a/include/hw/arm/aspeed_soc.h -+++ b/include/hw/arm/aspeed_soc.h -@@ -22,6 +22,7 @@ - #include "hw/ssi/aspeed_smc.h" - #include "hw/watchdog/wdt_aspeed.h" - #include "hw/net/ftgmac100.h" -+#include "target/arm/cpu.h" - - #define ASPEED_SPIS_NUM 2 - #define ASPEED_WDTS_NUM 3 -diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h -index a2cb8454de..97187f72be 100644 ---- a/include/hw/arm/bcm2836.h -+++ b/include/hw/arm/bcm2836.h -@@ -13,6 +13,7 @@ - - #include "hw/arm/bcm2835_peripherals.h" - #include "hw/intc/bcm2836_control.h" -+#include "target/arm/cpu.h" - - #define TYPE_BCM283X "bcm283x" - #define BCM283X(obj) OBJECT_CHECK(BCM283XState, (obj), TYPE_BCM283X) -diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h -index aa137271c0..f0f23b0e9b 100644 ---- a/include/hw/arm/exynos4210.h -+++ b/include/hw/arm/exynos4210.h -@@ -19,13 +19,12 @@ - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . -- * - */ - - #ifndef EXYNOS4210_H - #define EXYNOS4210_H - --#include "exec/memory.h" -+#include "hw/sysbus.h" - #include "target/arm/cpu-qom.h" - - #define EXYNOS4210_NCPUS 2 -diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h -index 3280ab1fb0..241efb52ae 100644 ---- a/include/hw/arm/fsl-imx25.h -+++ b/include/hw/arm/fsl-imx25.h -@@ -27,6 +27,7 @@ - #include "hw/i2c/imx_i2c.h" - #include "hw/gpio/imx_gpio.h" - #include "exec/memory.h" -+#include "target/arm/cpu.h" - - #define TYPE_FSL_IMX25 "fsl,imx25" - #define FSL_IMX25(obj) OBJECT_CHECK(FslIMX25State, (obj), TYPE_FSL_IMX25) -diff --git a/include/hw/arm/fsl-imx31.h b/include/hw/arm/fsl-imx31.h -index e68a81efd7..ac5ca9826a 100644 ---- a/include/hw/arm/fsl-imx31.h -+++ b/include/hw/arm/fsl-imx31.h -@@ -26,6 +26,7 @@ - #include "hw/i2c/imx_i2c.h" - #include "hw/gpio/imx_gpio.h" - #include "exec/memory.h" -+#include "target/arm/cpu.h" - - #define TYPE_FSL_IMX31 "fsl,imx31" - #define FSL_IMX31(obj) OBJECT_CHECK(FslIMX31State, (obj), TYPE_FSL_IMX31) -diff --git a/include/hw/arm/sharpsl.h b/include/hw/arm/sharpsl.h -index 5bf6db1fa2..89e168fbff 100644 ---- a/include/hw/arm/sharpsl.h -+++ b/include/hw/arm/sharpsl.h -@@ -3,9 +3,12 @@ - * - * This file is licensed under the GNU GPL. - */ -+ - #ifndef QEMU_SHARPSL_H - #define QEMU_SHARPSL_H - -+#include "exec/hwaddr.h" -+ - #define zaurus_printf(format, ...) \ - fprintf(stderr, "%s: " format, __func__, ##__VA_ARGS__) - -diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h -index 35804ea80a..6cb65e7537 100644 ---- a/include/hw/arm/xlnx-zynqmp.h -+++ b/include/hw/arm/xlnx-zynqmp.h -@@ -32,6 +32,7 @@ - #include "hw/intc/xlnx-zynqmp-ipi.h" - #include "hw/timer/xlnx-zynqmp-rtc.h" - #include "hw/cpu/cluster.h" -+#include "target/arm/cpu.h" - - #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp" - #define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \ -diff --git a/include/hw/block/fdc.h b/include/hw/block/fdc.h -index 8cece84326..f4fe2f471b 100644 ---- a/include/hw/block/fdc.h -+++ b/include/hw/block/fdc.h -@@ -1,6 +1,8 @@ - #ifndef HW_FDC_H - #define HW_FDC_H - -+#include "exec/hwaddr.h" -+#include "hw/irq.h" - #include "qapi/qapi-types-block.h" - - /* fdc.c */ -diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h -index 1acaf7de80..83a75f3170 100644 ---- a/include/hw/block/flash.h -+++ b/include/hw/block/flash.h -@@ -4,6 +4,7 @@ - /* NOR flash devices */ - - #include "exec/memory.h" -+#include "migration/vmstate.h" - - /* pflash_cfi01.c */ - -diff --git a/include/hw/char/escc.h b/include/hw/char/escc.h -index 42aca83611..d5196c53e6 100644 ---- a/include/hw/char/escc.h -+++ b/include/hw/char/escc.h -@@ -3,6 +3,7 @@ - - #include "chardev/char-fe.h" - #include "chardev/char-serial.h" -+#include "hw/sysbus.h" - #include "ui/input.h" - - /* escc.c */ -diff --git a/include/hw/char/xilinx_uartlite.h b/include/hw/char/xilinx_uartlite.h -index 634086b657..99d8bbf405 100644 ---- a/include/hw/char/xilinx_uartlite.h -+++ b/include/hw/char/xilinx_uartlite.h -@@ -15,6 +15,8 @@ - #ifndef XILINX_UARTLITE_H - #define XILINX_UARTLITE_H - -+#include "hw/sysbus.h" -+ - static inline DeviceState *xilinx_uartlite_create(hwaddr addr, - qemu_irq irq, - Chardev *chr) -diff --git a/include/hw/core/generic-loader.h b/include/hw/core/generic-loader.h -index dd27c42ab0..9ffce1c5a3 100644 ---- a/include/hw/core/generic-loader.h -+++ b/include/hw/core/generic-loader.h -@@ -19,6 +19,7 @@ - #define GENERIC_LOADER_H - - #include "elf.h" -+#include "hw/qdev-core.h" - - typedef struct GenericLoaderState { - /* */ -diff --git a/include/hw/cris/etraxfs.h b/include/hw/cris/etraxfs.h -index 8da965addb..494222d315 100644 ---- a/include/hw/cris/etraxfs.h -+++ b/include/hw/cris/etraxfs.h -@@ -27,6 +27,7 @@ - - #include "net/net.h" - #include "hw/cris/etraxfs_dma.h" -+#include "hw/sysbus.h" - - /* Instantiate an ETRAXFS Ethernet MAC. */ - static inline DeviceState * -diff --git a/include/hw/cris/etraxfs_dma.h b/include/hw/cris/etraxfs_dma.h -index f6f33e0980..31ae360611 100644 ---- a/include/hw/cris/etraxfs_dma.h -+++ b/include/hw/cris/etraxfs_dma.h -@@ -1,6 +1,9 @@ - #ifndef HW_ETRAXFS_DMA_H - #define HW_ETRAXFS_DMA_H - -+#include "exec/hwaddr.h" -+#include "hw/irq.h" -+ - struct dma_context_metadata { - /* data descriptor md */ - uint16_t metadata; -diff --git a/include/hw/display/i2c-ddc.h b/include/hw/display/i2c-ddc.h -index c29443c5af..1cf53a0c8d 100644 ---- a/include/hw/display/i2c-ddc.h -+++ b/include/hw/display/i2c-ddc.h -@@ -20,6 +20,7 @@ - #define I2C_DDC_H - - #include "hw/display/edid.h" -+#include "hw/i2c/i2c.h" - - /* A simple I2C slave which just returns the contents of its EDID blob. */ - struct I2CDDCState { -diff --git a/include/hw/empty_slot.h b/include/hw/empty_slot.h -index 123a9f8989..cb9a221aa6 100644 ---- a/include/hw/empty_slot.h -+++ b/include/hw/empty_slot.h -@@ -1,6 +1,8 @@ - #ifndef HW_EMPTY_SLOT_H - #define HW_EMPTY_SLOT_H - -+#include "exec/hwaddr.h" -+ - /* empty_slot.c */ - void empty_slot_init(hwaddr addr, uint64_t slot_size); - -diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h -index 9f8e0c720c..b0de0a3c74 100644 ---- a/include/hw/gpio/bcm2835_gpio.h -+++ b/include/hw/gpio/bcm2835_gpio.h -@@ -15,6 +15,7 @@ - #define BCM2835_GPIO_H - - #include "hw/sd/sd.h" -+#include "hw/sysbus.h" - - typedef struct BCM2835GpioState { - SysBusDevice parent_obj; -diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h -index f9020acdef..a2753f0bbb 100644 ---- a/include/hw/i2c/aspeed_i2c.h -+++ b/include/hw/i2c/aspeed_i2c.h -@@ -17,10 +17,12 @@ - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -+ - #ifndef ASPEED_I2C_H - #define ASPEED_I2C_H - - #include "hw/i2c/i2c.h" -+#include "hw/sysbus.h" - - #define TYPE_ASPEED_I2C "aspeed.i2c" - #define ASPEED_I2C(obj) \ -diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h -index 1209eb483a..b04bdd947f 100644 ---- a/include/hw/i386/apic_internal.h -+++ b/include/hw/i386/apic_internal.h -@@ -24,6 +24,7 @@ - #include "cpu.h" - #include "exec/memory.h" - #include "qemu/timer.h" -+#include "target/i386/cpu-qom.h" - - /* APIC Local Vector Table */ - #define APIC_LVT_TIMER 0 -diff --git a/include/hw/i386/ioapic_internal.h b/include/hw/i386/ioapic_internal.h -index 07002f9662..3d2eec2aa7 100644 ---- a/include/hw/i386/ioapic_internal.h -+++ b/include/hw/i386/ioapic_internal.h -@@ -24,6 +24,7 @@ - - #include "hw/hw.h" - #include "exec/memory.h" -+#include "hw/i386/ioapic.h" - #include "hw/sysbus.h" - #include "qemu/notify.h" - -diff --git a/include/hw/intc/allwinner-a10-pic.h b/include/hw/intc/allwinner-a10-pic.h -index 1d314a70d9..a5895401d1 100644 ---- a/include/hw/intc/allwinner-a10-pic.h -+++ b/include/hw/intc/allwinner-a10-pic.h -@@ -1,6 +1,8 @@ - #ifndef ALLWINNER_A10_PIC_H - #define ALLWINNER_A10_PIC_H - -+#include "hw/sysbus.h" -+ - #define TYPE_AW_A10_PIC "allwinner-a10-pic" - #define AW_A10_PIC(obj) OBJECT_CHECK(AwA10PICState, (obj), TYPE_AW_A10_PIC) - -diff --git a/include/hw/intc/heathrow_pic.h b/include/hw/intc/heathrow_pic.h -index 6c91ec91bb..b163e27ab9 100644 ---- a/include/hw/intc/heathrow_pic.h -+++ b/include/hw/intc/heathrow_pic.h -@@ -26,6 +26,8 @@ - #ifndef HW_INTC_HEATHROW_PIC_H - #define HW_INTC_HEATHROW_PIC_H - -+#include "hw/sysbus.h" -+ - #define TYPE_HEATHROW "heathrow" - #define HEATHROW(obj) OBJECT_CHECK(HeathrowState, (obj), TYPE_HEATHROW) - -diff --git a/include/hw/intc/mips_gic.h b/include/hw/intc/mips_gic.h -index 902a12b178..8428287bf9 100644 ---- a/include/hw/intc/mips_gic.h -+++ b/include/hw/intc/mips_gic.h -@@ -13,6 +13,7 @@ - - #include "qemu/units.h" - #include "hw/timer/mips_gictimer.h" -+#include "hw/sysbus.h" - #include "cpu.h" - /* - * GIC Specific definitions -diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h -index c3c2b6e786..a54c3fe60a 100644 ---- a/include/hw/isa/vt82c686.h -+++ b/include/hw/isa/vt82c686.h -@@ -1,6 +1,8 @@ - #ifndef HW_VT82C686_H - #define HW_VT82C686_H - -+#include "hw/irq.h" -+ - #define TYPE_VT82C686B_SUPERIO "vt82c686b-superio" - - /* vt82c686.c */ -diff --git a/include/hw/mips/cps.h b/include/hw/mips/cps.h -index aab1af926d..a941c55f27 100644 ---- a/include/hw/mips/cps.h -+++ b/include/hw/mips/cps.h -@@ -25,6 +25,7 @@ - #include "hw/intc/mips_gic.h" - #include "hw/misc/mips_cpc.h" - #include "hw/misc/mips_itu.h" -+#include "target/mips/cpu.h" - - #define TYPE_MIPS_CPS "mips-cps" - #define MIPS_CPS(obj) OBJECT_CHECK(MIPSCPSState, (obj), TYPE_MIPS_CPS) -diff --git a/include/hw/misc/macio/cuda.h b/include/hw/misc/macio/cuda.h -index 7dad469142..5768075ac5 100644 ---- a/include/hw/misc/macio/cuda.h -+++ b/include/hw/misc/macio/cuda.h -@@ -26,6 +26,8 @@ - #ifndef CUDA_H - #define CUDA_H - -+#include "hw/misc/mos6522.h" -+ - /* CUDA commands (2nd byte) */ - #define CUDA_WARM_START 0x0 - #define CUDA_AUTOPOLL 0x1 -diff --git a/include/hw/misc/macio/gpio.h b/include/hw/misc/macio/gpio.h -index 2838ae5fde..24a4364b39 100644 ---- a/include/hw/misc/macio/gpio.h -+++ b/include/hw/misc/macio/gpio.h -@@ -26,6 +26,9 @@ - #ifndef MACIO_GPIO_H - #define MACIO_GPIO_H - -+#include "hw/ppc/openpic.h" -+#include "hw/sysbus.h" -+ - #define TYPE_MACIO_GPIO "macio-gpio" - #define MACIO_GPIO(obj) OBJECT_CHECK(MacIOGPIOState, (obj), TYPE_MACIO_GPIO) - -diff --git a/include/hw/misc/macio/macio.h b/include/hw/misc/macio/macio.h -index 970058b6ed..070a694eb5 100644 ---- a/include/hw/misc/macio/macio.h -+++ b/include/hw/misc/macio/macio.h -@@ -27,10 +27,12 @@ - #define MACIO_H - - #include "hw/char/escc.h" -+#include "hw/ide/internal.h" - #include "hw/intc/heathrow_pic.h" - #include "hw/misc/macio/cuda.h" - #include "hw/misc/macio/gpio.h" - #include "hw/misc/macio/pmu.h" -+#include "hw/ppc/mac.h" - #include "hw/ppc/mac_dbdma.h" - #include "hw/ppc/openpic.h" - -diff --git a/include/hw/misc/macio/pmu.h b/include/hw/misc/macio/pmu.h -index d10895ba5f..7ef83dee4c 100644 ---- a/include/hw/misc/macio/pmu.h -+++ b/include/hw/misc/macio/pmu.h -@@ -10,6 +10,9 @@ - #ifndef PMU_H - #define PMU_H - -+#include "hw/misc/mos6522.h" -+#include "hw/misc/macio/gpio.h" -+ - /* - * PMU commands - */ -diff --git a/include/hw/misc/mips_cmgcr.h b/include/hw/misc/mips_cmgcr.h -index c9dfcb4b84..3e6e223273 100644 ---- a/include/hw/misc/mips_cmgcr.h -+++ b/include/hw/misc/mips_cmgcr.h -@@ -10,6 +10,8 @@ - #ifndef MIPS_CMGCR_H - #define MIPS_CMGCR_H - -+#include "hw/sysbus.h" -+ - #define TYPE_MIPS_GCR "mips-gcr" - #define MIPS_GCR(obj) OBJECT_CHECK(MIPSGCRState, (obj), TYPE_MIPS_GCR) - -diff --git a/include/hw/misc/mips_cpc.h b/include/hw/misc/mips_cpc.h -index 72c834e039..3f670578b0 100644 ---- a/include/hw/misc/mips_cpc.h -+++ b/include/hw/misc/mips_cpc.h -@@ -20,6 +20,8 @@ - #ifndef MIPS_CPC_H - #define MIPS_CPC_H - -+#include "hw/sysbus.h" -+ - #define CPC_ADDRSPACE_SZ 0x6000 - - /* CPC blocks offsets relative to base address */ -diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h -index 1ee071a703..ae0c8188ce 100644 ---- a/include/hw/misc/pvpanic.h -+++ b/include/hw/misc/pvpanic.h -@@ -11,9 +11,12 @@ - * See the COPYING file in the top-level directory. - * - */ -+ - #ifndef HW_MISC_PVPANIC_H - #define HW_MISC_PVPANIC_H - -+#include "qom/object.h" -+ - #define TYPE_PVPANIC "pvpanic" - - #define PVPANIC_IOPORT_PROP "ioport" -diff --git a/include/hw/net/allwinner_emac.h b/include/hw/net/allwinner_emac.h -index 905a43deb4..5013207d15 100644 ---- a/include/hw/net/allwinner_emac.h -+++ b/include/hw/net/allwinner_emac.h -@@ -27,6 +27,7 @@ - #include "net/net.h" - #include "qemu/fifo8.h" - #include "hw/net/mii.h" -+#include "hw/sysbus.h" - - #define TYPE_AW_EMAC "allwinner-emac" - #define AW_EMAC(obj) OBJECT_CHECK(AwEmacState, (obj), TYPE_AW_EMAC) -diff --git a/include/hw/net/lance.h b/include/hw/net/lance.h -index ffdd35c4d7..0357f5f65c 100644 ---- a/include/hw/net/lance.h -+++ b/include/hw/net/lance.h -@@ -31,6 +31,7 @@ - - #include "net/net.h" - #include "hw/net/pcnet.h" -+#include "hw/sysbus.h" - - #define TYPE_LANCE "lance" - #define SYSBUS_PCNET(obj) \ -diff --git a/include/hw/nvram/chrp_nvram.h b/include/hw/nvram/chrp_nvram.h -index b4f5b2b104..09941a9be4 100644 ---- a/include/hw/nvram/chrp_nvram.h -+++ b/include/hw/nvram/chrp_nvram.h -@@ -18,6 +18,8 @@ - #ifndef CHRP_NVRAM_H - #define CHRP_NVRAM_H - -+#include "qemu/bswap.h" -+ - /* OpenBIOS NVRAM partition */ - typedef struct { - uint8_t signature; -diff --git a/include/hw/pci-host/sabre.h b/include/hw/pci-host/sabre.h -index 9afa4938fd..99b5aefbec 100644 ---- a/include/hw/pci-host/sabre.h -+++ b/include/hw/pci-host/sabre.h -@@ -1,6 +1,8 @@ - #ifndef HW_PCI_HOST_SABRE_H - #define HW_PCI_HOST_SABRE_H - -+#include "hw/pci/pci.h" -+#include "hw/pci/pci_host.h" - #include "hw/sparc/sun4u_iommu.h" - - #define MAX_IVEC 0x40 -diff --git a/include/hw/pci-host/uninorth.h b/include/hw/pci-host/uninorth.h -index 060324536a..9a5cabd4c5 100644 ---- a/include/hw/pci-host/uninorth.h -+++ b/include/hw/pci-host/uninorth.h -@@ -26,7 +26,7 @@ - #define UNINORTH_H - - #include "hw/hw.h" -- -+#include "hw/pci/pci_host.h" - #include "hw/ppc/openpic.h" - - /* UniNorth version */ -diff --git a/include/hw/pci/pcie_aer.h b/include/hw/pci/pcie_aer.h -index 729a9439c8..502dcd7eba 100644 ---- a/include/hw/pci/pcie_aer.h -+++ b/include/hw/pci/pcie_aer.h -@@ -22,6 +22,7 @@ - #define QEMU_PCIE_AER_H - - #include "hw/hw.h" -+#include "hw/pci/pci_regs.h" - - /* definitions which PCIExpressDevice uses */ - -diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h -index d0926454a9..bfbd2ec42a 100644 ---- a/include/hw/ppc/pnv_core.h -+++ b/include/hw/ppc/pnv_core.h -@@ -21,6 +21,7 @@ - #define PPC_PNV_CORE_H - - #include "hw/cpu/core.h" -+#include "target/ppc/cpu.h" - - #define TYPE_PNV_CORE "powernv-cpu-core" - #define PNV_CORE(obj) \ -diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h -index 39a7ba1ce6..90f8866138 100644 ---- a/include/hw/ppc/ppc4xx.h -+++ b/include/hw/ppc/ppc4xx.h -@@ -25,6 +25,10 @@ - #ifndef PPC4XX_H - #define PPC4XX_H - -+#include "hw/ppc/ppc.h" -+#include "exec/cpu-common.h" -+#include "exec/memory.h" -+ - /* PowerPC 4xx core initialization */ - PowerPCCPU *ppc4xx_init(const char *cpu_model, - clk_setup_t *cpu_clk, clk_setup_t *tb_clk, -diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h -index f965a58f89..cd6e18b05e 100644 ---- a/include/hw/ppc/spapr_irq.h -+++ b/include/hw/ppc/spapr_irq.h -@@ -10,6 +10,9 @@ - #ifndef HW_SPAPR_IRQ_H - #define HW_SPAPR_IRQ_H - -+#include "hw/irq.h" -+#include "target/ppc/cpu-qom.h" -+ - /* - * IRQ range offsets per device type - */ -diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h -index 97951fc6b4..92bfa72caf 100644 ---- a/include/hw/ppc/spapr_vio.h -+++ b/include/hw/ppc/spapr_vio.h -@@ -22,6 +22,7 @@ - * License along with this library; if not, see . - */ - -+#include "hw/ppc/spapr.h" - #include "sysemu/dma.h" - - #define TYPE_VIO_SPAPR_DEVICE "vio-spapr-device" -diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h -index 7197144265..a39e672f27 100644 ---- a/include/hw/ppc/spapr_xive.h -+++ b/include/hw/ppc/spapr_xive.h -@@ -10,7 +10,9 @@ - #ifndef PPC_SPAPR_XIVE_H - #define PPC_SPAPR_XIVE_H - -+#include "hw/ppc/spapr_irq.h" - #include "hw/ppc/xive.h" -+#include "sysemu/sysemu.h" - - #define TYPE_SPAPR_XIVE "spapr-xive" - #define SPAPR_XIVE(obj) OBJECT_CHECK(SpaprXive, (obj), TYPE_SPAPR_XIVE) -diff --git a/include/hw/ppc/xive_regs.h b/include/hw/ppc/xive_regs.h -index 1a8c5b5e64..b0c68ab5f7 100644 ---- a/include/hw/ppc/xive_regs.h -+++ b/include/hw/ppc/xive_regs.h -@@ -16,6 +16,9 @@ - #ifndef PPC_XIVE_REGS_H - #define PPC_XIVE_REGS_H - -+#include "qemu/bswap.h" -+#include "qemu/host-utils.h" -+ - /* - * Interrupt source number encoding on PowerBUS - */ -diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h -index d56f2ae3eb..1f21c2bef1 100644 ---- a/include/hw/riscv/boot.h -+++ b/include/hw/riscv/boot.h -@@ -20,6 +20,8 @@ - #ifndef RISCV_BOOT_H - #define RISCV_BOOT_H - -+#include "exec/cpu-defs.h" -+ - void riscv_find_and_load_firmware(MachineState *machine, - const char *default_machine_firmware, - hwaddr firmware_load_addr); -diff --git a/include/hw/riscv/riscv_hart.h b/include/hw/riscv/riscv_hart.h -index 0671d88a44..3b52b50571 100644 ---- a/include/hw/riscv/riscv_hart.h -+++ b/include/hw/riscv/riscv_hart.h -@@ -21,6 +21,9 @@ - #ifndef HW_RISCV_HART_H - #define HW_RISCV_HART_H - -+#include "hw/sysbus.h" -+#include "target/riscv/cpu.h" -+ - #define TYPE_RISCV_HART_ARRAY "riscv.hart_array" - - #define RISCV_HART_ARRAY(obj) \ -diff --git a/include/hw/riscv/sifive_clint.h b/include/hw/riscv/sifive_clint.h -index e2865be1d1..ae8286c884 100644 ---- a/include/hw/riscv/sifive_clint.h -+++ b/include/hw/riscv/sifive_clint.h -@@ -20,6 +20,8 @@ - #ifndef HW_SIFIVE_CLINT_H - #define HW_SIFIVE_CLINT_H - -+#include "hw/sysbus.h" -+ - #define TYPE_SIFIVE_CLINT "riscv.sifive.clint" - - #define SIFIVE_CLINT(obj) \ -diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h -index d175b24cb2..9c868dd7f9 100644 ---- a/include/hw/riscv/sifive_e.h -+++ b/include/hw/riscv/sifive_e.h -@@ -19,6 +19,7 @@ - #ifndef HW_SIFIVE_E_H - #define HW_SIFIVE_E_H - -+#include "hw/riscv/riscv_hart.h" - #include "hw/riscv/sifive_gpio.h" - - #define TYPE_RISCV_E_SOC "riscv.sifive.e.soc" -diff --git a/include/hw/riscv/sifive_plic.h b/include/hw/riscv/sifive_plic.h -index ce8907f6aa..b0edba2884 100644 ---- a/include/hw/riscv/sifive_plic.h -+++ b/include/hw/riscv/sifive_plic.h -@@ -21,7 +21,7 @@ - #ifndef HW_SIFIVE_PLIC_H - #define HW_SIFIVE_PLIC_H - --#include "hw/irq.h" -+#include "hw/sysbus.h" - - #define TYPE_SIFIVE_PLIC "riscv.sifive.plic" - -diff --git a/include/hw/riscv/sifive_prci.h b/include/hw/riscv/sifive_prci.h -index bd51c4af3c..8b7de134f8 100644 ---- a/include/hw/riscv/sifive_prci.h -+++ b/include/hw/riscv/sifive_prci.h -@@ -19,6 +19,8 @@ - #ifndef HW_SIFIVE_PRCI_H - #define HW_SIFIVE_PRCI_H - -+#include "hw/sysbus.h" -+ - enum { - SIFIVE_PRCI_HFROSCCFG = 0x0, - SIFIVE_PRCI_HFXOSCCFG = 0x4, -diff --git a/include/hw/riscv/sifive_test.h b/include/hw/riscv/sifive_test.h -index 71d4c9fad7..3a603a6ead 100644 ---- a/include/hw/riscv/sifive_test.h -+++ b/include/hw/riscv/sifive_test.h -@@ -19,6 +19,8 @@ - #ifndef HW_SIFIVE_TEST_H - #define HW_SIFIVE_TEST_H - -+#include "hw/sysbus.h" -+ - #define TYPE_SIFIVE_TEST "riscv.sifive.test" - - #define SIFIVE_TEST(obj) \ -diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h -index 892f0eee21..be021ce256 100644 ---- a/include/hw/riscv/sifive_u.h -+++ b/include/hw/riscv/sifive_u.h -@@ -20,6 +20,7 @@ - #define HW_SIFIVE_U_H - - #include "hw/net/cadence_gem.h" -+#include "hw/riscv/riscv_hart.h" - - #define TYPE_RISCV_U_SOC "riscv.sifive.u.soc" - #define RISCV_U_SOC(obj) \ -diff --git a/include/hw/riscv/sifive_uart.h b/include/hw/riscv/sifive_uart.h -index c8dc1c57fd..65668825a3 100644 ---- a/include/hw/riscv/sifive_uart.h -+++ b/include/hw/riscv/sifive_uart.h -@@ -20,6 +20,9 @@ - #ifndef HW_SIFIVE_UART_H - #define HW_SIFIVE_UART_H - -+#include "chardev/char-fe.h" -+#include "hw/sysbus.h" -+ - enum { - SIFIVE_UART_TXFIFO = 0, - SIFIVE_UART_RXFIFO = 4, -diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h -index 641b70da67..03d870363c 100644 ---- a/include/hw/riscv/spike.h -+++ b/include/hw/riscv/spike.h -@@ -19,6 +19,9 @@ - #ifndef HW_RISCV_SPIKE_H - #define HW_RISCV_SPIKE_H - -+#include "hw/riscv/riscv_hart.h" -+#include "hw/sysbus.h" -+ - typedef struct { - /*< private >*/ - SysBusDevice parent_obj; -diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h -index d01a1a85c4..6e5fbe5d3b 100644 ---- a/include/hw/riscv/virt.h -+++ b/include/hw/riscv/virt.h -@@ -19,6 +19,9 @@ - #ifndef HW_RISCV_VIRT_H - #define HW_RISCV_VIRT_H - -+#include "hw/riscv/riscv_hart.h" -+#include "hw/sysbus.h" -+ - typedef struct { - /*< private >*/ - SysBusDevice parent_obj; -diff --git a/include/hw/s390x/ap-device.h b/include/hw/s390x/ap-device.h -index 765e9082a3..8df9cd2954 100644 ---- a/include/hw/s390x/ap-device.h -+++ b/include/hw/s390x/ap-device.h -@@ -7,9 +7,12 @@ - * your option) any later version. See the COPYING file in the top-level - * directory. - */ -+ - #ifndef HW_S390X_AP_DEVICE_H - #define HW_S390X_AP_DEVICE_H - -+#include "hw/qdev-core.h" -+ - #define AP_DEVICE_TYPE "ap-device" - - typedef struct APDevice { -diff --git a/include/hw/s390x/css-bridge.h b/include/hw/s390x/css-bridge.h -index 5a0203be5f..f7ed2d9a03 100644 ---- a/include/hw/s390x/css-bridge.h -+++ b/include/hw/s390x/css-bridge.h -@@ -12,8 +12,9 @@ - - #ifndef HW_S390X_CSS_BRIDGE_H - #define HW_S390X_CSS_BRIDGE_H -+ - #include "qom/object.h" --#include "hw/qdev-core.h" -+#include "hw/sysbus.h" - - /* virtual css bridge */ - typedef struct VirtualCssBridge { -diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h -index d033387fba..f46bcafb16 100644 ---- a/include/hw/s390x/css.h -+++ b/include/hw/s390x/css.h -@@ -17,6 +17,7 @@ - #include "hw/s390x/s390_flic.h" - #include "hw/s390x/ioinst.h" - #include "sysemu/kvm.h" -+#include "target/s390x/cpu-qom.h" - - /* Channel subsystem constants. */ - #define MAX_DEVNO 65535 -diff --git a/include/hw/s390x/tod.h b/include/hw/s390x/tod.h -index 9c4a6000c3..d71f4ea8a7 100644 ---- a/include/hw/s390x/tod.h -+++ b/include/hw/s390x/tod.h -@@ -12,7 +12,7 @@ - #define HW_S390_TOD_H - - #include "hw/qdev.h" --#include "s390-tod.h" -+#include "target/s390x/s390-tod.h" - - typedef struct S390TOD { - uint8_t high; -diff --git a/include/hw/semihosting/console.h b/include/hw/semihosting/console.h -index cfab572c0c..9be9754bcd 100644 ---- a/include/hw/semihosting/console.h -+++ b/include/hw/semihosting/console.h -@@ -9,6 +9,8 @@ - #ifndef SEMIHOST_CONSOLE_H - #define SEMIHOST_CONSOLE_H - -+#include "cpu.h" -+ - /** - * qemu_semihosting_console_outs: - * @env: CPUArchState -diff --git a/include/hw/sh4/sh_intc.h b/include/hw/sh4/sh_intc.h -index b7c2404334..3d3efde059 100644 ---- a/include/hw/sh4/sh_intc.h -+++ b/include/hw/sh4/sh_intc.h -@@ -1,6 +1,7 @@ - #ifndef SH_INTC_H - #define SH_INTC_H - -+#include "exec/memory.h" - #include "hw/irq.h" - - typedef unsigned char intc_enum; -diff --git a/include/hw/sparc/sparc64.h b/include/hw/sparc/sparc64.h -index 21ab79e343..4ced36fb5a 100644 ---- a/include/hw/sparc/sparc64.h -+++ b/include/hw/sparc/sparc64.h -@@ -1,6 +1,8 @@ - #ifndef HW_SPARC_SPARC64_H - #define HW_SPARC_SPARC64_H - -+#include "target/sparc/cpu-qom.h" -+ - #define IVEC_MAX 0x40 - - SPARCCPU *sparc64_cpu_devinit(const char *cpu_type, uint64_t prom_addr); -diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h -index 591279ba1f..aa07dac4fe 100644 ---- a/include/hw/ssi/aspeed_smc.h -+++ b/include/hw/ssi/aspeed_smc.h -@@ -26,6 +26,7 @@ - #define ASPEED_SMC_H - - #include "hw/ssi/ssi.h" -+#include "hw/sysbus.h" - - typedef struct AspeedSegments { - hwaddr addr; -diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h -index a0a0ae7584..6a39b55a7b 100644 ---- a/include/hw/ssi/xilinx_spips.h -+++ b/include/hw/ssi/xilinx_spips.h -@@ -28,6 +28,7 @@ - #include "hw/ssi/ssi.h" - #include "qemu/fifo32.h" - #include "hw/stream.h" -+#include "hw/sysbus.h" - - typedef struct XilinxSPIPS XilinxSPIPS; - -diff --git a/include/hw/timer/allwinner-a10-pit.h b/include/hw/timer/allwinner-a10-pit.h -index c0cc3e2169..871c95b512 100644 ---- a/include/hw/timer/allwinner-a10-pit.h -+++ b/include/hw/timer/allwinner-a10-pit.h -@@ -2,6 +2,7 @@ - #define ALLWINNER_A10_PIT_H - - #include "hw/ptimer.h" -+#include "hw/sysbus.h" - - #define TYPE_AW_A10_PIT "allwinner-A10-timer" - #define AW_A10_PIT(obj) OBJECT_CHECK(AwA10PITState, (obj), TYPE_AW_A10_PIT) -diff --git a/include/hw/timer/i8254_internal.h b/include/hw/timer/i8254_internal.h -index c37a438f82..e611c6f227 100644 ---- a/include/hw/timer/i8254_internal.h -+++ b/include/hw/timer/i8254_internal.h -@@ -27,6 +27,7 @@ - - #include "hw/hw.h" - #include "hw/isa/isa.h" -+#include "hw/timer/i8254.h" - #include "qemu/timer.h" - - typedef struct PITChannelState { -diff --git a/include/hw/timer/m48t59.h b/include/hw/timer/m48t59.h -index 43efc91f56..d3fb50e08c 100644 ---- a/include/hw/timer/m48t59.h -+++ b/include/hw/timer/m48t59.h -@@ -1,6 +1,8 @@ - #ifndef HW_M48T59_H - #define HW_M48T59_H - -+#include "exec/hwaddr.h" -+#include "hw/irq.h" - #include "qom/object.h" - - #define TYPE_NVRAM "nvram" -diff --git a/include/hw/timer/mc146818rtc_regs.h b/include/hw/timer/mc146818rtc_regs.h -index c62f17bf2d..bfbb57e570 100644 ---- a/include/hw/timer/mc146818rtc_regs.h -+++ b/include/hw/timer/mc146818rtc_regs.h -@@ -25,6 +25,8 @@ - #ifndef MC146818RTC_REGS_H - #define MC146818RTC_REGS_H - -+#include "qemu/timer.h" -+ - #define RTC_ISA_IRQ 8 - - #define RTC_SECONDS 0 -diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h b/include/hw/timer/xlnx-zynqmp-rtc.h -index 6e9134edf6..97e32322ed 100644 ---- a/include/hw/timer/xlnx-zynqmp-rtc.h -+++ b/include/hw/timer/xlnx-zynqmp-rtc.h -@@ -28,6 +28,7 @@ - #define HW_TIMER_XLNX_ZYNQMP_RTC_H - - #include "hw/register.h" -+#include "hw/sysbus.h" - - #define TYPE_XLNX_ZYNQMP_RTC "xlnx-zynmp.rtc" - -diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h -index bdf58f3119..6818a23a2d 100644 ---- a/include/hw/virtio/virtio-access.h -+++ b/include/hw/virtio/virtio-access.h -@@ -16,6 +16,7 @@ - #ifndef QEMU_VIRTIO_ACCESS_H - #define QEMU_VIRTIO_ACCESS_H - -+#include "exec/hwaddr.h" - #include "hw/virtio/virtio.h" - #include "hw/virtio/virtio-bus.h" - -diff --git a/include/hw/virtio/virtio-gpu-bswap.h b/include/hw/virtio/virtio-gpu-bswap.h -index 38d12160f6..203f9e1718 100644 ---- a/include/hw/virtio/virtio-gpu-bswap.h -+++ b/include/hw/virtio/virtio-gpu-bswap.h -@@ -15,6 +15,7 @@ - #define HW_VIRTIO_GPU_BSWAP_H - - #include "qemu/bswap.h" -+#include "standard-headers/linux/virtio_gpu.h" - - static inline void - virtio_gpu_ctrl_hdr_bswap(struct virtio_gpu_ctrl_hdr *hdr) -diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h -index 922dce7cac..ff699335e3 100644 ---- a/include/hw/virtio/virtio-rng.h -+++ b/include/hw/virtio/virtio-rng.h -@@ -12,6 +12,7 @@ - #ifndef QEMU_VIRTIO_RNG_H - #define QEMU_VIRTIO_RNG_H - -+#include "hw/virtio/virtio.h" - #include "sysemu/rng.h" - #include "sysemu/rng-random.h" - #include "standard-headers/linux/virtio_rng.h" -diff --git a/include/hw/watchdog/wdt_aspeed.h b/include/hw/watchdog/wdt_aspeed.h -index daef0c0e23..8c5691ce20 100644 ---- a/include/hw/watchdog/wdt_aspeed.h -+++ b/include/hw/watchdog/wdt_aspeed.h -@@ -10,6 +10,7 @@ - #ifndef WDT_ASPEED_H - #define WDT_ASPEED_H - -+#include "hw/misc/aspeed_scu.h" - #include "hw/sysbus.h" - - #define TYPE_ASPEED_WDT "aspeed.wdt" -diff --git a/include/libdecnumber/decNumberLocal.h b/include/libdecnumber/decNumberLocal.h -index 12cf1d8b6f..4d53c077f2 100644 ---- a/include/libdecnumber/decNumberLocal.h -+++ b/include/libdecnumber/decNumberLocal.h -@@ -44,6 +44,7 @@ - #define DECNLAUTHOR "Mike Cowlishaw" /* Who to blame */ - - #include "libdecnumber/dconfig.h" -+ #include "libdecnumber/decContext.h" - - /* Conditional code flag -- set this to match hardware platform */ - /* 1=little-endian, 0=big-endian */ -diff --git a/include/migration/cpu.h b/include/migration/cpu.h -index a40bd3549f..da1618d620 100644 ---- a/include/migration/cpu.h -+++ b/include/migration/cpu.h -@@ -1,7 +1,10 @@ - /* Declarations for use for CPU state serialization. */ -+ - #ifndef MIGRATION_CPU_H - #define MIGRATION_CPU_H - -+#include "exec/cpu-defs.h" -+ - #if TARGET_LONG_BITS == 64 - #define qemu_put_betl qemu_put_be64 - #define qemu_get_betl qemu_get_be64 -diff --git a/include/monitor/hmp-target.h b/include/monitor/hmp-target.h -index 454e8ed155..8b7820a3ad 100644 ---- a/include/monitor/hmp-target.h -+++ b/include/monitor/hmp-target.h -@@ -25,6 +25,8 @@ - #ifndef MONITOR_HMP_TARGET_H - #define MONITOR_HMP_TARGET_H - -+#include "cpu.h" -+ - #define MD_TLONG 0 - #define MD_I32 1 - -diff --git a/include/qemu/atomic128.h b/include/qemu/atomic128.h -index ddd0d55d31..6b34484e15 100644 ---- a/include/qemu/atomic128.h -+++ b/include/qemu/atomic128.h -@@ -13,6 +13,8 @@ - #ifndef QEMU_ATOMIC128_H - #define QEMU_ATOMIC128_H - -+#include "qemu/int128.h" -+ - /* - * GCC is a house divided about supporting large atomic operations. - * -diff --git a/include/qemu/ratelimit.h b/include/qemu/ratelimit.h -index 1b38291823..01da8d63f1 100644 ---- a/include/qemu/ratelimit.h -+++ b/include/qemu/ratelimit.h -@@ -14,6 +14,8 @@ - #ifndef QEMU_RATELIMIT_H - #define QEMU_RATELIMIT_H - -+#include "qemu/timer.h" -+ - typedef struct { - int64_t slice_start_time; - int64_t slice_end_time; -diff --git a/include/qemu/thread-win32.h b/include/qemu/thread-win32.h -index 50af5dd7ab..d0a1a9597e 100644 ---- a/include/qemu/thread-win32.h -+++ b/include/qemu/thread-win32.h -@@ -47,6 +47,6 @@ struct QemuThread { - }; - - /* Only valid for joinable threads. */ --HANDLE qemu_thread_get_handle(QemuThread *thread); -+HANDLE qemu_thread_get_handle(struct QemuThread *thread); - - #endif -diff --git a/include/sysemu/balloon.h b/include/sysemu/balloon.h -index c8f6145257..aea0c44985 100644 ---- a/include/sysemu/balloon.h -+++ b/include/sysemu/balloon.h -@@ -14,6 +14,7 @@ - #ifndef QEMU_BALLOON_H - #define QEMU_BALLOON_H - -+#include "exec/cpu-common.h" - #include "qapi/qapi-types-misc.h" - - typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target); -diff --git a/include/sysemu/cryptodev-vhost-user.h b/include/sysemu/cryptodev-vhost-user.h -index 6debf53fc5..0d3421e7e8 100644 ---- a/include/sysemu/cryptodev-vhost-user.h -+++ b/include/sysemu/cryptodev-vhost-user.h -@@ -20,9 +20,12 @@ - * License along with this library; if not, see . - * - */ -+ - #ifndef CRYPTODEV_VHOST_USER_H - #define CRYPTODEV_VHOST_USER_H - -+#include "sysemu/cryptodev-vhost.h" -+ - #define VHOST_USER_MAX_AUTH_KEY_LEN 512 - #define VHOST_USER_MAX_CIPHER_KEY_LEN 64 - -diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h -index d275b5a843..dd1722f2df 100644 ---- a/include/sysemu/hvf.h -+++ b/include/sysemu/hvf.h -@@ -13,6 +13,7 @@ - #ifndef HVF_H - #define HVF_H - -+#include "cpu.h" - #include "qemu/bitops.h" - #include "exec/memory.h" - #include "sysemu/accel.h" -diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h -index 5f6240d5cb..6181486401 100644 ---- a/include/sysemu/iothread.h -+++ b/include/sysemu/iothread.h -@@ -16,6 +16,7 @@ - - #include "block/aio.h" - #include "qemu/thread.h" -+#include "qom/object.h" - - #define TYPE_IOTHREAD "iothread" - -diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h -index 31df465fdc..787dbc7770 100644 ---- a/include/sysemu/kvm_int.h -+++ b/include/sysemu/kvm_int.h -@@ -9,6 +9,8 @@ - #ifndef QEMU_KVM_INT_H - #define QEMU_KVM_INT_H - -+#include "exec/cpu-common.h" -+#include "exec/memory.h" - #include "sysemu/sysemu.h" - #include "sysemu/accel.h" - #include "sysemu/kvm.h" -diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h -index 58452457ce..1b440df486 100644 ---- a/include/sysemu/memory_mapping.h -+++ b/include/sysemu/memory_mapping.h -@@ -15,6 +15,8 @@ - #define MEMORY_MAPPING_H - - #include "qemu/queue.h" -+#include "exec/cpu-common.h" -+#include "exec/cpu-defs.h" - #include "exec/memory.h" - - typedef struct GuestPhysBlock { -diff --git a/include/sysemu/xen-mapcache.h b/include/sysemu/xen-mapcache.h -index a03e2f1878..c8e7c2f6cf 100644 ---- a/include/sysemu/xen-mapcache.h -+++ b/include/sysemu/xen-mapcache.h -@@ -9,6 +9,8 @@ - #ifndef XEN_MAPCACHE_H - #define XEN_MAPCACHE_H - -+#include "exec/cpu-common.h" -+ - typedef hwaddr (*phys_offset_to_gaddr_t)(hwaddr phys_offset, - ram_addr_t size); - #ifdef CONFIG_XEN -diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h -index d714127799..58bd3a1ec4 100644 ---- a/include/ui/egl-helpers.h -+++ b/include/ui/egl-helpers.h -@@ -4,6 +4,9 @@ - #include - #include - #include -+#include "qapi/qapi-types-ui.h" -+#include "ui/console.h" -+#include "ui/shader.h" - - extern EGLDisplay *qemu_egl_display; - extern EGLConfig qemu_egl_config; -diff --git a/include/ui/input.h b/include/ui/input.h -index 8c8ccb999f..c86219a1c1 100644 ---- a/include/ui/input.h -+++ b/include/ui/input.h -@@ -2,6 +2,7 @@ - #define INPUT_H - - #include "qapi/qapi-types-ui.h" -+#include "qemu/notify.h" - - #define INPUT_EVENT_MASK_KEY (1< - #include - #include - #include -diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h -index aab251bc4b..e9fba96be9 100644 ---- a/target/hppa/cpu.h -+++ b/target/hppa/cpu.h -@@ -22,7 +22,7 @@ - - #include "cpu-qom.h" - #include "exec/cpu-defs.h" -- -+#include "exec/memory.h" - - /* PA-RISC 1.x processors have a strong memory model. */ - /* ??? While we do not yet implement PA-RISC 2.0, those processors have --- -2.27.0 - diff --git a/intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch b/intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch deleted file mode 100644 index d69dcc71825a8ed70e133ffb7d28af03a08485a1..0000000000000000000000000000000000000000 --- a/intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 15849387df5c25e8ebaef19e2a16e8d428675f5d Mon Sep 17 00:00:00 2001 -From: Eric Auger -Date: Thu, 3 Oct 2019 17:46:39 +0200 -Subject: [PATCH 2/3] intc/arm_gic: Support IRQ injection for more than 256 - vpus - -Host kernels that expose the KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 capability -allow injection of interrupts along with vcpu ids larger than 255. -Let's encode the vpcu id on 12 bits according to the upgraded KVM_IRQ_LINE -ABI when needed. - -Given that we have two callsites that need to assemble -the value for kvm_set_irq(), a new helper routine, kvm_arm_set_irq -is introduced. - -Without that patch qemu exits with "kvm_set_irq: Invalid argument" -message. - -Signed-off-by: Eric Auger -Reported-by: Zenghui Yu -Reviewed-by: Richard Henderson -Reviewed-by: Andrew Jones -Acked-by: Marc Zyngier -Message-id: 20191003154640.22451-3-eric.auger@redhat.com -Signed-off-by: Peter Maydell -(cherry-picked from commit f6530926e2310147a7844a3e663230d47b3d7333) -Signed-off-by: Zenghui Yu ---- - hw/intc/arm_gic_kvm.c | 7 ++----- - target/arm/cpu.c | 10 ++++------ - target/arm/kvm.c | 12 ++++++++++++ - target/arm/kvm_arm.h | 1 + - 4 files changed, 19 insertions(+), 11 deletions(-) - -diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c -index a611e8ee..7d600a61 100644 ---- a/hw/intc/arm_gic_kvm.c -+++ b/hw/intc/arm_gic_kvm.c -@@ -55,7 +55,7 @@ void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level) - * has separate fields in the irq number for type, - * CPU number and interrupt number. - */ -- int kvm_irq, irqtype, cpu; -+ int irqtype, cpu; - - if (irq < (num_irq - GIC_INTERNAL)) { - /* External interrupt. The kernel numbers these like the GIC -@@ -72,10 +72,7 @@ void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level) - cpu = irq / GIC_INTERNAL; - irq %= GIC_INTERNAL; - } -- kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT) -- | (cpu << KVM_ARM_IRQ_VCPU_SHIFT) | irq; -- -- kvm_set_irq(kvm_state, kvm_irq, !!level); -+ kvm_arm_set_irq(cpu, irqtype, irq, !!level); - } - - static void kvm_arm_gicv2_set_irq(void *opaque, int irq, int level) -diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index 41557821..0b4c8e27 100644 ---- a/target/arm/cpu.c -+++ b/target/arm/cpu.c -@@ -561,16 +561,16 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level) - ARMCPU *cpu = opaque; - CPUARMState *env = &cpu->env; - CPUState *cs = CPU(cpu); -- int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT; - uint32_t linestate_bit; -+ int irq_id; - - switch (irq) { - case ARM_CPU_IRQ: -- kvm_irq |= KVM_ARM_IRQ_CPU_IRQ; -+ irq_id = KVM_ARM_IRQ_CPU_IRQ; - linestate_bit = CPU_INTERRUPT_HARD; - break; - case ARM_CPU_FIQ: -- kvm_irq |= KVM_ARM_IRQ_CPU_FIQ; -+ irq_id = KVM_ARM_IRQ_CPU_FIQ; - linestate_bit = CPU_INTERRUPT_FIQ; - break; - default: -@@ -582,9 +582,7 @@ static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level) - } else { - env->irq_line_state &= ~linestate_bit; - } -- -- kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT; -- kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0); -+ kvm_arm_set_irq(cs->cpu_index, KVM_ARM_IRQ_TYPE_CPU, irq_id, !!level); - #endif - } - -diff --git a/target/arm/kvm.c b/target/arm/kvm.c -index 79a79f01..f60185ad 100644 ---- a/target/arm/kvm.c -+++ b/target/arm/kvm.c -@@ -728,6 +728,18 @@ int kvm_arm_vgic_probe(void) - } - } - -+int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level) -+{ -+ int kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT) | irq; -+ int cpu_idx1 = cpu % 256; -+ int cpu_idx2 = cpu / 256; -+ -+ kvm_irq |= (cpu_idx1 << KVM_ARM_IRQ_VCPU_SHIFT) | -+ (cpu_idx2 << KVM_ARM_IRQ_VCPU2_SHIFT); -+ -+ return kvm_set_irq(kvm_state, kvm_irq, !!level); -+} -+ - int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, - uint64_t address, uint32_t data, PCIDevice *dev) - { -diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h -index 2a07333c..a9f3ccab 100644 ---- a/target/arm/kvm_arm.h -+++ b/target/arm/kvm_arm.h -@@ -235,6 +235,7 @@ int kvm_arm_vgic_probe(void); - - void kvm_arm_pmu_set_irq(CPUState *cs, int irq); - void kvm_arm_pmu_init(CPUState *cs); -+int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level); - - #else - --- -2.19.1 - diff --git a/intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch b/intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch index 30175fb5126a8a9b7138c206365b61c96bcddaf0..a68cdcbeecbc625c0313bc0bcf2b206eea5c8c17 100644 --- a/intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch +++ b/intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch @@ -1,4 +1,4 @@ -From 0a75312c069d89be94bcaa688429d8f60a0c528b Mon Sep 17 00:00:00 2001 +From 3ed7dcc4a8ccf443d125e7908d8293b562c68d4b Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Fri, 10 Apr 2020 13:15:35 +0800 Subject: [PATCH] intc/gicv3: Add pre-sizing capability to GICv3 @@ -20,17 +20,17 @@ Signed-off-by: Salil Mehta --- hw/arm/virt.c | 17 +++++++++++---- hw/intc/arm_gicv3.c | 43 +++++++++++++++++++++++++------------- - hw/intc/arm_gicv3_common.c | 23 ++++++++++++++++++-- + hw/intc/arm_gicv3_common.c | 22 +++++++++++++++++-- hw/intc/arm_gicv3_cpuif.c | 4 ++++ hw/intc/arm_gicv3_kvm.c | 28 ++++++++++++++++++++++++- include/hw/arm/virt.h | 3 ++- - 6 files changed, 96 insertions(+), 22 deletions(-) + 6 files changed, 95 insertions(+), 22 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index 55d403bad6..dda22194b5 100644 +index 0af0a996a1..b1224fb1e4 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c -@@ -761,14 +761,19 @@ static void create_gic(VirtMachineState *vms) +@@ -827,14 +827,19 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem) SysBusDevice *gicbusdev; const char *gictype; int type = vms->gic_version, i; @@ -39,38 +39,38 @@ index 55d403bad6..dda22194b5 100644 + /* The number of CPUs present before boot */ unsigned int smp_cpus = ms->smp.cpus; uint32_t nb_redist_regions = 0; - + + assert(num_cpus >= smp_cpus); + gictype = (type == 3) ? gicv3_class_name() : gic_class_name(); - - vms->gic = qdev_create(NULL, gictype); + + vms->gic = qdev_new(gictype); qdev_prop_set_uint32(vms->gic, "revision", type); - qdev_prop_set_uint32(vms->gic, "num-cpu", smp_cpus); + qdev_prop_set_uint32(vms->gic, "num-cpu", num_cpus); /* Note that the num-irq property counts both internal and external * interrupts; there are always 32 of the former (mandated by GIC spec). */ -@@ -780,7 +785,7 @@ static void create_gic(VirtMachineState *vms) +@@ -846,7 +851,7 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem) if (type == 3) { uint32_t redist0_capacity = vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE; - uint32_t redist0_count = MIN(smp_cpus, redist0_capacity); + uint32_t redist0_count = MIN(num_cpus, redist0_capacity); - + nb_redist_regions = virt_gicv3_redist_region_count(vms); - -@@ -793,7 +798,7 @@ static void create_gic(VirtMachineState *vms) + +@@ -867,7 +872,7 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem) vms->memmap[VIRT_HIGH_GIC_REDIST2].size / GICV3_REDIST_SIZE; - + qdev_prop_set_uint32(vms->gic, "redist-region-count[1]", - MIN(smp_cpus - redist0_count, redist1_capacity)); + MIN(num_cpus - redist0_count, redist1_capacity)); } } else { if (!kvm_irqchip_in_kernel()) { -@@ -820,7 +825,11 @@ static void create_gic(VirtMachineState *vms) - +@@ -894,7 +899,11 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem) + /* Wire the outputs from each CPU's generic timer and the GICv3 * maintenance interrupt signal to the appropriate GIC PPI inputs, - * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs. @@ -83,43 +83,43 @@ index 55d403bad6..dda22194b5 100644 for (i = 0; i < smp_cpus; i++) { connect_gic_cpu_irqs(vms, i); diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c -index cacef26546..a60185113f 100644 +index 9591cfbcc0..864d4e4034 100644 --- a/hw/intc/arm_gicv3.c +++ b/hw/intc/arm_gicv3.c -@@ -20,6 +20,7 @@ +@@ -19,6 +19,7 @@ + #include "qapi/error.h" #include "qemu/module.h" - #include "hw/sysbus.h" #include "hw/intc/arm_gicv3.h" -+#include "qom/cpu.h" ++#include "hw/core/cpu.h" #include "gicv3_internal.h" - + static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t prio) -@@ -206,7 +207,9 @@ static void gicv3_update_noirqset(GICv3State *s, int start, int len) +@@ -217,7 +218,9 @@ static void gicv3_update_noirqset(GICv3State *s, int start, int len) assert(len > 0); - + for (i = 0; i < s->num_cpu; i++) { - s->cpu[i].seenbetter = false; + if (qemu_get_cpu(i)) { + s->cpu[i].seenbetter = false; + } } - + /* Find the highest priority pending interrupt in this range. */ -@@ -248,16 +251,18 @@ static void gicv3_update_noirqset(GICv3State *s, int start, int len) +@@ -259,16 +262,18 @@ static void gicv3_update_noirqset(GICv3State *s, int start, int len) * now be the new best one). */ for (i = 0; i < s->num_cpu; i++) { - GICv3CPUState *cs = &s->cpu[i]; + if (qemu_get_cpu(i)) { + GICv3CPUState *cs = &s->cpu[i]; - + - if (cs->seenbetter) { - cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq); - } + if (cs->seenbetter) { + cs->hppi.grp = gicv3_irq_group(cs->gic, cs, cs->hppi.irq); + } - + - if (!cs->seenbetter && cs->hppi.prio != 0xff && - cs->hppi.irq >= start && cs->hppi.irq < start + len) { - gicv3_full_update_noirqset(s); @@ -132,8 +132,8 @@ index cacef26546..a60185113f 100644 } } } -@@ -268,7 +273,9 @@ void gicv3_update(GICv3State *s, int start, int len) - +@@ -279,7 +284,9 @@ void gicv3_update(GICv3State *s, int start, int len) + gicv3_update_noirqset(s, start, len); for (i = 0; i < s->num_cpu; i++) { - gicv3_cpuif_update(&s->cpu[i]); @@ -142,21 +142,21 @@ index cacef26546..a60185113f 100644 + } } } - -@@ -280,7 +287,9 @@ void gicv3_full_update_noirqset(GICv3State *s) + +@@ -291,7 +298,9 @@ void gicv3_full_update_noirqset(GICv3State *s) int i; - + for (i = 0; i < s->num_cpu; i++) { - s->cpu[i].hppi.prio = 0xff; + if (qemu_get_cpu(i)) { + s->cpu[i].hppi.prio = 0xff; + } } - + /* Note that we can guarantee that these functions will not -@@ -291,7 +300,9 @@ void gicv3_full_update_noirqset(GICv3State *s) +@@ -302,7 +311,9 @@ void gicv3_full_update_noirqset(GICv3State *s) gicv3_update_noirqset(s, GIC_INTERNAL, s->num_irq - GIC_INTERNAL); - + for (i = 0; i < s->num_cpu; i++) { - gicv3_redist_update_noirqset(&s->cpu[i]); + if (qemu_get_cpu(i)) { @@ -164,9 +164,9 @@ index cacef26546..a60185113f 100644 + } } } - -@@ -304,7 +315,9 @@ void gicv3_full_update(GICv3State *s) - + +@@ -315,7 +326,9 @@ void gicv3_full_update(GICv3State *s) + gicv3_full_update_noirqset(s); for (i = 0; i < s->num_cpu; i++) { - gicv3_cpuif_update(&s->cpu[i]); @@ -175,10 +175,10 @@ index cacef26546..a60185113f 100644 + } } } - -@@ -401,7 +414,9 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) - } - + +@@ -406,7 +419,9 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) + gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops); + for (i = 0; i < s->num_cpu; i++) { - gicv3_cpu_realize(s, i); + if (qemu_get_cpu(i)) { @@ -186,42 +186,43 @@ index cacef26546..a60185113f 100644 + } } } - + diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c -index 8740a52c9f..913bf068be 100644 +index f8ef6817a4..a4976b2ba0 100644 --- a/hw/intc/arm_gicv3_common.c +++ b/hw/intc/arm_gicv3_common.c -@@ -24,10 +24,12 @@ +@@ -24,12 +24,14 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/module.h" +#include "qemu/error-report.h" - #include "qom/cpu.h" + #include "hw/core/cpu.h" #include "hw/intc/arm_gicv3_common.h" + #include "hw/qdev-properties.h" + #include "migration/vmstate.h" #include "gicv3_internal.h" #include "hw/arm/linux-boot-if.h" +#include "hw/boards.h" #include "sysemu/kvm.h" - - -@@ -363,10 +365,15 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + + +@@ -377,9 +379,14 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) for (i = 0; i < s->num_cpu; i++) { CPUState *cpu = qemu_get_cpu(i); - + + MachineState *ms = MACHINE(qdev_get_machine()); + MachineClass *mc = MACHINE_GET_CLASS(ms); + const CPUArchIdList *possible_cpus = NULL; uint64_t cpu_affid; - int last; - + - arm_gicv3_common_cpu_realize(s, i); + if (cpu) { + arm_gicv3_common_cpu_realize(s, i); + } - + /* Pre-construct the GICR_TYPER: * For our implementation: -@@ -380,7 +387,19 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) +@@ -393,7 +400,18 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) * VLPIS == 0 (virtual LPIs not supported) * PLPIS == 0 (physical LPIs not supported) */ @@ -238,33 +239,32 @@ index 8740a52c9f..913bf068be 100644 + possible_cpus = mc->possible_cpu_arch_ids(ms); + cpu_affid = possible_cpus->cpus[i].arch_id; + } -+ - last = (i == s->num_cpu - 1); - + /* The CPU mp-affinity property is in MPIDR register format; squash + * the affinity bytes into 32 bits as the GICR_TYPER has them. diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c -index 56aa5efede..a20aa693ea 100644 +index 70809bcddd..274a40a40c 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c -@@ -1648,6 +1648,10 @@ static void icc_generate_sgi(CPUARMState *env, GICv3CPUState *cs, +@@ -1676,6 +1676,10 @@ static void icc_generate_sgi(CPUARMState *env, GICv3CPUState *cs, aff, targetlist); - + for (i = 0; i < s->num_cpu; i++) { + if (!qemu_get_cpu(i)) { + continue; + } + GICv3CPUState *ocs = &s->cpu[i]; - + if (irm) { diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c -index f8d7be5479..8eea7c9dd9 100644 +index 95271e754b..2e2b08e31f 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c -@@ -341,6 +341,10 @@ static void kvm_arm_gicv3_put(GICv3State *s) +@@ -342,6 +342,10 @@ static void kvm_arm_gicv3_put(GICv3State *s) for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { GICv3CPUState *c = &s->cpu[ncpu]; - + + if (!qemu_get_cpu(ncpu)) { + continue; + } @@ -272,21 +272,21 @@ index f8d7be5479..8eea7c9dd9 100644 reg64 = c->gicr_propbaser; regl = (uint32_t)reg64; kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, true); -@@ -366,6 +370,10 @@ static void kvm_arm_gicv3_put(GICv3State *s) +@@ -361,6 +365,10 @@ static void kvm_arm_gicv3_put(GICv3State *s) for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { GICv3CPUState *c = &s->cpu[ncpu]; - + + if (!qemu_get_cpu(ncpu)) { + continue; + } + reg = c->gicr_ctlr; kvm_gicr_access(s, GICR_CTLR, ncpu, ®, true); - -@@ -462,6 +470,10 @@ static void kvm_arm_gicv3_put(GICv3State *s) + +@@ -457,6 +465,10 @@ static void kvm_arm_gicv3_put(GICv3State *s) GICv3CPUState *c = &s->cpu[ncpu]; int num_pri_bits; - + + if (!qemu_get_cpu(ncpu)) { + continue; + } @@ -294,19 +294,19 @@ index f8d7be5479..8eea7c9dd9 100644 kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, true); kvm_gicc_access(s, ICC_CTLR_EL1, ncpu, &c->icc_ctlr_el1[GICV3_NS], true); -@@ -525,6 +537,10 @@ static void kvm_arm_gicv3_get(GICv3State *s) +@@ -524,6 +536,10 @@ static void kvm_arm_gicv3_get(GICv3State *s) /* Redistributor state (one per CPU) */ - + for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { + if (!qemu_get_cpu(ncpu)) { + continue; + } + GICv3CPUState *c = &s->cpu[ncpu]; - + kvm_gicr_access(s, GICR_CTLR, ncpu, ®, false); -@@ -560,6 +576,10 @@ static void kvm_arm_gicv3_get(GICv3State *s) - +@@ -559,6 +575,10 @@ static void kvm_arm_gicv3_get(GICv3State *s) + if (redist_typer & GICR_TYPER_PLPIS) { for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { + if (!qemu_get_cpu(ncpu)) { @@ -314,11 +314,11 @@ index f8d7be5479..8eea7c9dd9 100644 + } + GICv3CPUState *c = &s->cpu[ncpu]; - + kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, false); -@@ -613,6 +633,10 @@ static void kvm_arm_gicv3_get(GICv3State *s) +@@ -612,6 +632,10 @@ static void kvm_arm_gicv3_get(GICv3State *s) */ - + for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { + if (!qemu_get_cpu(ncpu)) { + continue; @@ -326,32 +326,33 @@ index f8d7be5479..8eea7c9dd9 100644 + GICv3CPUState *c = &s->cpu[ncpu]; int num_pri_bits; - -@@ -806,7 +830,9 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) - } - + +@@ -805,7 +829,9 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) + gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL); + for (i = 0; i < s->num_cpu; i++) { - kvm_arm_gicv3_cpu_realize(s, i); + if (qemu_get_cpu(i)) { + kvm_arm_gicv3_cpu_realize(s, i); + } } - + /* Try to create the device via the device control API */ diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h -index 6880ebe07c..beef4c8002 100644 +index 2a838620d8..947d41f767 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h -@@ -168,8 +168,9 @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms) +@@ -196,8 +196,9 @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms) vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE; - - assert(vms->gic_version == 3); + + assert(vms->gic_version == VIRT_GIC_VERSION_3); + GICv3State *s = ARM_GICV3_COMMON(vms->gic); - -- return vms->smp_cpus > redist0_capacity ? 2 : 1; + +- return MACHINE(vms)->smp.cpus > redist0_capacity ? 2 : 1; + return s->num_cpu > redist0_capacity ? 2 : 1; } - + #endif /* QEMU_ARM_VIRT_H */ --- -2.19.1 +-- +2.27.0 + diff --git a/intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch b/intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch index 5232d3f2aeda4d3a8a83a725173eaff72d2af8d5..043573e8e69b51928402404d6bbc5fd8dd577e7d 100644 --- a/intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch +++ b/intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch @@ -1,4 +1,4 @@ -From a7391f391336024986a5997e3beae8882c983ed0 Mon Sep 17 00:00:00 2001 +From 06cb0756a01796352861b4d47d59db1bde84ec6f Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Fri, 10 Apr 2020 12:55:17 +0800 Subject: [PATCH] intc/gicv3_common: Factor out arm_gicv3_common_cpu_realize @@ -14,13 +14,13 @@ Signed-off-by: Salil Mehta 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c -index 5edabb928f..798f295d7c 100644 +index 9884d2e39b..1a11d1986d 100644 --- a/hw/intc/arm_gicv3_common.c +++ b/hw/intc/arm_gicv3_common.c -@@ -303,6 +303,16 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler, +@@ -301,6 +301,16 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler, } } - + +static void arm_gicv3_common_cpu_realize(GICv3State *s, int ncpu) +{ + CPUState *cpu = qemu_get_cpu(ncpu); @@ -34,17 +34,18 @@ index 5edabb928f..798f295d7c 100644 static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) { GICv3State *s = ARM_GICV3_COMMON(dev); -@@ -350,10 +360,7 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) +@@ -363,10 +373,7 @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp) + CPUState *cpu = qemu_get_cpu(i); uint64_t cpu_affid; - int last; - + - s->cpu[i].cpu = cpu; - s->cpu[i].gic = s; - /* Store GICv3CPUState in CPUARMState gicv3state pointer */ - gicv3_set_gicv3state(cpu, &s->cpu[i]); + arm_gicv3_common_cpu_realize(s, i); - + /* Pre-construct the GICR_TYPER: * For our implementation: --- -2.19.1 +-- +2.27.0 + diff --git a/intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch b/intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch index 95c60b02c66e48b2fbe6d64c5e139aa3ecdcfae9..87c93443458f9c763eae9dfc0b0406f27a9b205e 100644 --- a/intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch +++ b/intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch @@ -1,4 +1,4 @@ -From de97ff4a01008ad98f7d69adc4b84843fff3ce19 Mon Sep 17 00:00:00 2001 +From 62b5c897e367c3db477a680b7557662347677433 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Fri, 10 Apr 2020 10:59:55 +0800 Subject: [PATCH] intc/gicv3_cpuif: Factor out gicv3_init_one_cpuif @@ -16,36 +16,36 @@ Signed-off-by: Salil Mehta 3 files changed, 64 insertions(+), 65 deletions(-) diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c -index 66eaa97198..2fe79f794d 100644 +index 9f5f815db9..40016cb84a 100644 --- a/hw/intc/arm_gicv3.c +++ b/hw/intc/arm_gicv3.c -@@ -367,6 +367,7 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) +@@ -382,6 +382,7 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) GICv3State *s = ARM_GICV3(dev); ARMGICv3Class *agc = ARM_GICV3_GET_CLASS(s); Error *local_err = NULL; + int i; - + agc->parent_realize(dev, &local_err); if (local_err) { -@@ -386,7 +387,9 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) - return; - } - +@@ -391,7 +392,9 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) + + gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops); + - gicv3_init_cpuif(s); + for (i = 0; i < s->num_cpu; i++) { + gicv3_init_one_cpuif(s, i); + } } - + static void arm_gicv3_class_init(ObjectClass *klass, void *data) diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c -index 3b212d91c8..56aa5efede 100644 +index 85fc369e55..70809bcddd 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c -@@ -2597,78 +2597,74 @@ static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque) +@@ -2625,76 +2625,72 @@ static void gicv3_cpuif_el_change_hook(ARMCPU *cpu, void *opaque) gicv3_cpuif_update(cs); } - + -void gicv3_init_cpuif(GICv3State *s) +void gicv3_init_one_cpuif(GICv3State *s, int ncpu) { @@ -64,11 +64,6 @@ index 3b212d91c8..56aa5efede 100644 - * which case we'd get the wrong value. - * So instead we define the regs with no ri->opaque info, and - * get back to the GICv3CPUState from the CPUARMState. -- */ -- define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); -- if (arm_feature(&cpu->env, ARM_FEATURE_EL2) -- && cpu->gic_num_lrs) { -- int j; + ARMCPU *cpu = ARM_CPU(qemu_get_cpu(ncpu)); + GICv3CPUState *cs = &s->cpu[ncpu]; + @@ -83,17 +78,24 @@ index 3b212d91c8..56aa5efede 100644 + if (arm_feature(&cpu->env, ARM_FEATURE_EL2) + && cpu->gic_num_lrs) { + int j; - -- cs->maintenance_irq = cpu->gicv3_maintenance_interrupt; -+ cs->maintenance_irq = cpu->gicv3_maintenance_interrupt; - -- cs->num_list_regs = cpu->gic_num_lrs; -- cs->vpribits = cpu->gic_vpribits; -- cs->vprebits = cpu->gic_vprebits; ++ + cs->num_list_regs = cpu->gic_num_lrs; + cs->vpribits = cpu->gic_vpribits; + cs->vprebits = cpu->gic_vprebits; - ++ ++ /* Check against architectural constraints: getting these ++ * wrong would be a bug in the CPU code defining these, ++ * and the implementation relies on them holding. + */ +- define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); +- if (arm_feature(&cpu->env, ARM_FEATURE_EL2) +- && cpu->gic_num_lrs) { +- int j; +- +- cs->num_list_regs = cpu->gic_num_lrs; +- cs->vpribits = cpu->gic_vpribits; +- cs->vprebits = cpu->gic_vprebits; +- - /* Check against architectural constraints: getting these - * wrong would be a bug in the CPU code defining these, - * and the implementation relies on them holding. @@ -101,17 +103,13 @@ index 3b212d91c8..56aa5efede 100644 - g_assert(cs->vprebits <= cs->vpribits); - g_assert(cs->vprebits >= 5 && cs->vprebits <= 7); - g_assert(cs->vpribits >= 5 && cs->vpribits <= 8); -+ /* Check against architectural constraints: getting these -+ * wrong would be a bug in the CPU code defining these, -+ * and the implementation relies on them holding. -+ */ + g_assert(cs->vprebits <= cs->vpribits); + g_assert(cs->vprebits >= 5 && cs->vprebits <= 7); + g_assert(cs->vpribits >= 5 && cs->vpribits <= 8); - + - define_arm_cp_regs(cpu, gicv3_cpuif_hcr_reginfo); + define_arm_cp_regs(cpu, gicv3_cpuif_hcr_reginfo); - + - for (j = 0; j < cs->num_list_regs; j++) { - /* Note that the AArch64 LRs are 64-bit; the AArch32 LRs - * are split into two cp15 regs, LR (the low part, with the @@ -181,17 +179,18 @@ index 3b212d91c8..56aa5efede 100644 + arm_register_el_change_hook(cpu, gicv3_cpuif_el_change_hook, cs); } diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h -index 05303a55c8..cfbfe8a549 100644 +index b9c37453b0..65db012600 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h -@@ -297,7 +297,7 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data, - void gicv3_dist_set_irq(GICv3State *s, int irq, int level); - void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level); +@@ -495,7 +495,7 @@ void gicv3_redist_update_lpi(GICv3CPUState *cs); + */ + void gicv3_redist_update_lpi_only(GICv3CPUState *cs); void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns); -void gicv3_init_cpuif(GICv3State *s); +void gicv3_init_one_cpuif(GICv3State *s, int ncpu); - + /** * gicv3_cpuif_update: --- -2.19.1 +-- +2.27.0 + diff --git a/intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch b/intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch index 6af9a8f4f55fa4ce936c9d5898cd5c232abcaa9a..f9f4b940cc5efc5bb52f9be0f4b4e72c57e31769 100644 --- a/intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch +++ b/intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch @@ -1,4 +1,4 @@ -From f45964c7e0df4ef17457a9ea92bfd255064139e1 Mon Sep 17 00:00:00 2001 +From dd03bc60712bd41a9606742ea4b769aa8e360655 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Fri, 10 Apr 2020 12:49:12 +0800 Subject: [PATCH] intc/kvm_gicv3: Factor out kvm_arm_gicv3_cpu_realize @@ -14,32 +14,33 @@ Signed-off-by: Salil Mehta 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c -index b1e74147ba..b2936938cb 100644 +index 5ec5ff9ef6..596b31998b 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c -@@ -761,6 +761,12 @@ static void vm_change_state_handler(void *opaque, int running, +@@ -764,6 +764,12 @@ static void vm_change_state_handler(void *opaque, bool running, } } - + +static void kvm_arm_gicv3_cpu_realize(GICv3State *s, int ncpu) +{ + ARMCPU *cpu = ARM_CPU(qemu_get_cpu(ncpu)); + + define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); +} - + static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) { -@@ -791,9 +797,7 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) - } - +@@ -790,9 +796,7 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) + gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL); + for (i = 0; i < s->num_cpu; i++) { - ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i)); - - define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); + kvm_arm_gicv3_cpu_realize(s, i); } - + /* Try to create the device via the device control API */ --- -2.19.1 +-- +2.27.0 + diff --git a/io-Don-t-use-flag-of-printf-format.patch b/io-Don-t-use-flag-of-printf-format.patch deleted file mode 100644 index 61f3b71dda336dbc2c833b323880f7dd3be09dec..0000000000000000000000000000000000000000 --- a/io-Don-t-use-flag-of-printf-format.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0aa003cd0e117cb160da7d4b6e50630bf2fedfd6 Mon Sep 17 00:00:00 2001 -From: AlexChen -Date: Mon, 19 Oct 2020 20:12:02 +0800 -Subject: [PATCH] io: Don't use '#' flag of printf format -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: AlexChen -Signed-off-by: Daniel P. Berrangé -(cherry-picked from commit 77b7829e75) ---- - io/channel-websock.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/io/channel-websock.c b/io/channel-websock.c -index fc36d44eba..d48a929e49 100644 ---- a/io/channel-websock.c -+++ b/io/channel-websock.c -@@ -734,7 +734,7 @@ static int qio_channel_websock_decode_header(QIOChannelWebsock *ioc, - opcode != QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE && - opcode != QIO_CHANNEL_WEBSOCK_OPCODE_PING && - opcode != QIO_CHANNEL_WEBSOCK_OPCODE_PONG) { -- error_setg(errp, "unsupported opcode: %#04x; only binary, close, " -+ error_setg(errp, "unsupported opcode: 0x%04x; only binary, close, " - "ping, and pong websocket frames are supported", opcode); - qio_channel_websock_write_close( - ioc, QIO_CHANNEL_WEBSOCK_STATUS_INVALID_DATA , --- -2.27.0 - diff --git a/iommu-Introduce-generic-header.patch b/iommu-Introduce-generic-header.patch index 76e0c0c80ff83bfd8a5f0130ca73c0623e0efc35..84f3d77c057bee4e80d68e8dbf92c473089109f0 100644 --- a/iommu-Introduce-generic-header.patch +++ b/iommu-Introduce-generic-header.patch @@ -1,4 +1,4 @@ -From e8055075dbbc932afccc1f18f4acc093fe9e4dc3 Mon Sep 17 00:00:00 2001 +From 5e312f7b41ec48dc7dc9805af9f52aa8ed393bf9 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 9 Jul 2019 12:20:12 +0200 Subject: [PATCH] iommu: Introduce generic header diff --git a/iotests-143-Create-socket-in-SOCK_DIR.patch b/iotests-143-Create-socket-in-SOCK_DIR.patch deleted file mode 100644 index 31d6a8421e46d181deb1e7c6792f78546a3d873e..0000000000000000000000000000000000000000 --- a/iotests-143-Create-socket-in-SOCK_DIR.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 2e8fecd9e963c740cfe73d0de4491541423e185f Mon Sep 17 00:00:00 2001 -From: Max Reitz -Date: Thu, 17 Oct 2019 15:31:40 +0200 -Subject: [PATCH] iotests/143: Create socket in $SOCK_DIR - -Signed-off-by: Max Reitz -Reviewed-by: Eric Blake -Reviewed-by: Thomas Huth -Message-id: 20191017133155.5327-9-mreitz@redhat.com -Signed-off-by: Max Reitz ---- - tests/qemu-iotests/143 | 6 +++--- - tests/qemu-iotests/143.out | 2 +- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/tests/qemu-iotests/143 b/tests/qemu-iotests/143 -index 92249ac8da..f649b36195 100755 ---- a/tests/qemu-iotests/143 -+++ b/tests/qemu-iotests/143 -@@ -29,7 +29,7 @@ status=1 # failure is the default! - _cleanup() - { - _cleanup_qemu -- rm -f "$TEST_DIR/nbd" -+ rm -f "$SOCK_DIR/nbd" - } - trap "_cleanup; exit \$status" 0 1 2 3 15 - -@@ -51,12 +51,12 @@ _send_qemu_cmd $QEMU_HANDLE \ - _send_qemu_cmd $QEMU_HANDLE \ - "{ 'execute': 'nbd-server-start', - 'arguments': { 'addr': { 'type': 'unix', -- 'data': { 'path': '$TEST_DIR/nbd' }}}}" \ -+ 'data': { 'path': '$SOCK_DIR/nbd' }}}}" \ - 'return' - - # This should just result in a client error, not in the server crashing - $QEMU_IO_PROG -f raw -c quit \ -- "nbd+unix:///no_such_export?socket=$TEST_DIR/nbd" 2>&1 \ -+ "nbd+unix:///no_such_export?socket=$SOCK_DIR/nbd" 2>&1 \ - | _filter_qemu_io | _filter_nbd - - _send_qemu_cmd $QEMU_HANDLE \ -diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out -index ee71b5aa42..037d34a409 100644 ---- a/tests/qemu-iotests/143.out -+++ b/tests/qemu-iotests/143.out -@@ -1,7 +1,7 @@ - QA output created by 143 - {"return": {}} - {"return": {}} --qemu-io: can't open device nbd+unix:///no_such_export?socket=TEST_DIR/nbd: Requested export not available -+qemu-io: can't open device nbd+unix:///no_such_export?socket=SOCK_DIR/nbd: Requested export not available - server reported: export 'no_such_export' not present - {"return": {}} - {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} --- -2.27.0 - diff --git a/ip_reass-Fix-use-after-free.patch b/ip_reass-Fix-use-after-free.patch deleted file mode 100644 index b26e8afb629d7d768608fdc471a9cf754be36f7e..0000000000000000000000000000000000000000 --- a/ip_reass-Fix-use-after-free.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 63b07dfe20a0d4971b0929d27359f478ba2d816b Mon Sep 17 00:00:00 2001 -From: Samuel Thibault -Date: Fri, 22 May 2020 10:52:55 +0800 -Subject: [PATCH] ip_reass: Fix use after free - -Using ip_deq after m_free might read pointers from an allocation reuse. - -This would be difficult to exploit, but that is still related with -CVE-2019-14378 which generates fragmented IP packets that would trigger this -issue and at least produce a DoS. -Signed-off-by: Samuel Thibault's avatarSamuel Thibault - -diff --git a/slirp/src/ip_input.c b/slirp/src/ip_input.c -index 8c75d91..c07d7d4 100644 ---- a/slirp/src/ip_input.c -+++ b/slirp/src/ip_input.c -@@ -292,6 +292,7 @@ static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp) - */ - while (q != (struct ipasfrag *)&fp->frag_link && - ip->ip_off + ip->ip_len > q->ipf_off) { -+ struct ipasfrag *prev; - i = (ip->ip_off + ip->ip_len) - q->ipf_off; - if (i < q->ipf_len) { - q->ipf_len -= i; -@@ -299,9 +300,10 @@ static struct ip *ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp) - m_adj(dtom(slirp, q), i); - break; - } -+ prev = q; - q = q->ipf_next; -- m_free(dtom(slirp, q->ipf_prev)); -- ip_deq(q->ipf_prev); -+ ip_deq(prev); -+ m_free(dtom(slirp, prev)); - } - - insert: --- -1.8.3.1 - diff --git a/iscsi-Cap-block-count-from-GET-LBA-STATUS-CVE-2020-1.patch b/iscsi-Cap-block-count-from-GET-LBA-STATUS-CVE-2020-1.patch deleted file mode 100644 index e6abdf7a51d13c4a94ee722164df1fbc54ed48bb..0000000000000000000000000000000000000000 --- a/iscsi-Cap-block-count-from-GET-LBA-STATUS-CVE-2020-1.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 693fd2acdf14dd86c0bf852610f1c2cca80a74dc Mon Sep 17 00:00:00 2001 -From: Felipe Franciosi -Date: Thu, 23 Jan 2020 12:44:59 +0000 -Subject: [PATCH] iscsi: Cap block count from GET LBA STATUS (CVE-2020-1711) - -When querying an iSCSI server for the provisioning status of blocks (via -GET LBA STATUS), Qemu only validates that the response descriptor zero's -LBA matches the one requested. Given the SCSI spec allows servers to -respond with the status of blocks beyond the end of the LUN, Qemu may -have its heap corrupted by clearing/setting too many bits at the end of -its allocmap for the LUN. - -A malicious guest in control of the iSCSI server could carefully program -Qemu's heap (by selectively setting the bitmap) and then smash it. - -This limits the number of bits that iscsi_co_block_status() will try to -update in the allocmap so it can't overflow the bitmap. - -Fixes: CVE-2020-1711 -Cc: qemu-stable@nongnu.org -Signed-off-by: Felipe Franciosi -Signed-off-by: Peter Turschmid -Signed-off-by: Raphael Norwitz -Signed-off-by: Kevin Wolf - -diff --git a/block/iscsi.c b/block/iscsi.c -index 2aea7e3f13..cbd57294ab 100644 ---- a/block/iscsi.c -+++ b/block/iscsi.c -@@ -701,7 +701,7 @@ static int coroutine_fn iscsi_co_block_status(BlockDriverState *bs, - struct scsi_get_lba_status *lbas = NULL; - struct scsi_lba_status_descriptor *lbasd = NULL; - struct IscsiTask iTask; -- uint64_t lba; -+ uint64_t lba, max_bytes; - int ret; - - iscsi_co_init_iscsitask(iscsilun, &iTask); -@@ -721,6 +721,7 @@ static int coroutine_fn iscsi_co_block_status(BlockDriverState *bs, - } - - lba = offset / iscsilun->block_size; -+ max_bytes = (iscsilun->num_blocks - lba) * iscsilun->block_size; - - qemu_mutex_lock(&iscsilun->mutex); - retry: -@@ -764,7 +765,7 @@ retry: - goto out_unlock; - } - -- *pnum = (int64_t) lbasd->num_blocks * iscsilun->block_size; -+ *pnum = MIN((int64_t) lbasd->num_blocks * iscsilun->block_size, max_bytes); - - if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED || - lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) { --- -2.21.1 (Apple Git-122.3) - diff --git a/json-Fix-a-memleak-in-parse_pair.patch b/json-Fix-a-memleak-in-parse_pair.patch deleted file mode 100644 index c39776e6160b48f0f5bd1834899a0d186b03eeb7..0000000000000000000000000000000000000000 --- a/json-Fix-a-memleak-in-parse_pair.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 503d231e06c159c1530a76b1740b3ec7e47619e5 Mon Sep 17 00:00:00 2001 -From: Alex Chen -Date: Fri, 13 Nov 2020 14:55:25 +0000 -Subject: [PATCH] json: Fix a memleak in parse_pair() - -In qobject_type(), NULL is returned when the 'QObject' returned from parse_value() is not of QString type, -and this 'QObject' memory will leaked. -So we need to first cache the 'QObject' returned from parse_value(), and finally -free 'QObject' memory at the end of the function. -Also, we add a testcast about invalid dict key. - -The memleak stack is as follows: -Direct leak of 32 byte(s) in 1 object(s) allocated from: - #0 0xfffe4b3c34fb in __interceptor_malloc (/lib64/libasan.so.4+0xd34fb) - #1 0xfffe4ae48aa3 in g_malloc (/lib64/libglib-2.0.so.0+0x58aa3) - #2 0xaaab3557d9f7 in qnum_from_int qemu/qobject/qnum.c:25 - #3 0xaaab35584d23 in parse_literal qemu/qobject/json-parser.c:511 - #4 0xaaab35584d23 in parse_value qemu/qobject/json-parser.c:554 - #5 0xaaab35583d77 in parse_pair qemu/qobject/json-parser.c:270 - #6 0xaaab355845db in parse_object qemu/qobject/json-parser.c:327 - #7 0xaaab355845db in parse_value qemu/qobject/json-parser.c:546 - #8 0xaaab35585b1b in json_parser_parse qemu/qobject/json-parser.c:580 - #9 0xaaab35583703 in json_message_process_token qemu/qobject/json-streamer.c:92 - #10 0xaaab355ddccf in json_lexer_feed_char qemu/qobject/json-lexer.c:313 - #11 0xaaab355de0eb in json_lexer_feed qemu/qobject/json-lexer.c:350 - #12 0xaaab354aff67 in tcp_chr_read qemu/chardev/char-socket.c:525 - #13 0xfffe4ae429db in g_main_context_dispatch (/lib64/libglib-2.0.so.0+0x529db) - #14 0xfffe4ae42d8f (/lib64/libglib-2.0.so.0+0x52d8f) - #15 0xfffe4ae430df in g_main_loop_run (/lib64/libglib-2.0.so.0+0x530df) - #16 0xaaab34d70bff in iothread_run qemu/iothread.c:82 - #17 0xaaab3559d71b in qemu_thread_start qemu/util/qemu-thread-posix.c:519 - -Fixes: 532fb5328473 ("qapi: Make more of qobject_to()") -Reported-by: Euler Robot -Signed-off-by: Alex Chen -Signed-off-by: Chen Qun -Signed-off-by: Markus Armbruster -Message-Id: <20201113145525.85151-1-alex.chen@huawei.com> -[Commit message tweaked] -(cherry-picked form commit 922d42bb) ---- - qobject/json-parser.c | 12 ++++++------ - tests/check-qjson.c | 9 +++++++++ - 2 files changed, 15 insertions(+), 6 deletions(-) - -diff --git a/qobject/json-parser.c b/qobject/json-parser.c -index 7d23e12e33..840909ea6a 100644 ---- a/qobject/json-parser.c -+++ b/qobject/json-parser.c -@@ -257,8 +257,9 @@ static JSONToken *parser_context_peek_token(JSONParserContext *ctxt) - */ - static int parse_pair(JSONParserContext *ctxt, QDict *dict) - { -+ QObject *key_obj = NULL; -+ QString *key; - QObject *value; -- QString *key = NULL; - JSONToken *peek, *token; - - peek = parser_context_peek_token(ctxt); -@@ -267,7 +268,8 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict) - goto out; - } - -- key = qobject_to(QString, parse_value(ctxt)); -+ key_obj = parse_value(ctxt); -+ key = qobject_to(QString, key_obj); - if (!key) { - parse_error(ctxt, peek, "key is not a string in object"); - goto out; -@@ -297,13 +299,11 @@ static int parse_pair(JSONParserContext *ctxt, QDict *dict) - - qdict_put_obj(dict, qstring_get_str(key), value); - -- qobject_unref(key); -- -+ qobject_unref(key_obj); - return 0; - - out: -- qobject_unref(key); -- -+ qobject_unref(key_obj); - return -1; - } - -diff --git a/tests/check-qjson.c b/tests/check-qjson.c -index fa2afccb0a..5e3e08fe79 100644 ---- a/tests/check-qjson.c -+++ b/tests/check-qjson.c -@@ -1415,6 +1415,14 @@ static void invalid_dict_comma(void) - g_assert(obj == NULL); - } - -+static void invalid_dict_key(void) -+{ -+ Error *err = NULL; -+ QObject *obj = qobject_from_json("{32:'abc'}", &err); -+ error_free_or_abort(&err); -+ g_assert(obj == NULL); -+} -+ - static void unterminated_literal(void) - { - Error *err = NULL; -@@ -1500,6 +1508,7 @@ int main(int argc, char **argv) - g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma); - g_test_add_func("/errors/invalid_array_comma", invalid_array_comma); - g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma); -+ g_test_add_func("/errors/invalid_dict_key", invalid_dict_key); - g_test_add_func("/errors/unterminated/literal", unterminated_literal); - g_test_add_func("/errors/limits/nesting", limits_nesting); - g_test_add_func("/errors/multiple_values", multiple_values); --- -2.27.0 - diff --git a/kvm-Reallocate-dirty_bmap-when-we-change-a-slot.patch b/kvm-Reallocate-dirty_bmap-when-we-change-a-slot.patch deleted file mode 100644 index dfa8bf6a01201096881ec49e34ddf0ed18eec84f..0000000000000000000000000000000000000000 --- a/kvm-Reallocate-dirty_bmap-when-we-change-a-slot.patch +++ /dev/null @@ -1,99 +0,0 @@ -From ccfc5c99103e2f633084c906197075392f625a80 Mon Sep 17 00:00:00 2001 -From: "Dr. David Alan Gilbert" -Date: Thu, 21 Nov 2019 16:56:45 +0000 -Subject: [PATCH] kvm: Reallocate dirty_bmap when we change a slot - -kvm_set_phys_mem can be called to reallocate a slot by something the -guest does (e.g. writing to PAM and other chipset registers). -This can happen in the middle of a migration, and if we're unlucky -it can now happen between the split 'sync' and 'clear'; the clear -asserts if there's no bmap to clear. Recreate the bmap whenever -we change the slot, keeping the clear path happy. - -Typically this is triggered by the guest rebooting during a migrate. - -Corresponds to: -https://bugzilla.redhat.com/show_bug.cgi?id=1772774 -https://bugzilla.redhat.com/show_bug.cgi?id=1771032 - -Signed-off-by: Dr. David Alan Gilbert -Reviewed-by: Peter Xu -Signed-off-by: Kunkun Jiang ---- - accel/kvm/kvm-all.c | 44 +++++++++++++++++++++++++++++--------------- - 1 file changed, 29 insertions(+), 15 deletions(-) - -diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c -index 6828f6a1f9..5a6b89cc2a 100644 ---- a/accel/kvm/kvm-all.c -+++ b/accel/kvm/kvm-all.c -@@ -536,6 +536,27 @@ static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section, - - #define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1)) - -+/* Allocate the dirty bitmap for a slot */ -+static void kvm_memslot_init_dirty_bitmap(KVMSlot *mem) -+{ -+ /* -+ * XXX bad kernel interface alert -+ * For dirty bitmap, kernel allocates array of size aligned to -+ * bits-per-long. But for case when the kernel is 64bits and -+ * the userspace is 32bits, userspace can't align to the same -+ * bits-per-long, since sizeof(long) is different between kernel -+ * and user space. This way, userspace will provide buffer which -+ * may be 4 bytes less than the kernel will use, resulting in -+ * userspace memory corruption (which is not detectable by valgrind -+ * too, in most cases). -+ * So for now, let's align to 64 instead of HOST_LONG_BITS here, in -+ * a hope that sizeof(long) won't become >8 any time soon. -+ */ -+ hwaddr bitmap_size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS), -+ /*HOST_LONG_BITS*/ 64) / 8; -+ mem->dirty_bmap = g_malloc0(bitmap_size); -+} -+ - /** - * kvm_physical_sync_dirty_bitmap - Sync dirty bitmap from kernel space - * -@@ -568,23 +589,9 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml, - goto out; - } - -- /* XXX bad kernel interface alert -- * For dirty bitmap, kernel allocates array of size aligned to -- * bits-per-long. But for case when the kernel is 64bits and -- * the userspace is 32bits, userspace can't align to the same -- * bits-per-long, since sizeof(long) is different between kernel -- * and user space. This way, userspace will provide buffer which -- * may be 4 bytes less than the kernel will use, resulting in -- * userspace memory corruption (which is not detectable by valgrind -- * too, in most cases). -- * So for now, let's align to 64 instead of HOST_LONG_BITS here, in -- * a hope that sizeof(long) won't become >8 any time soon. -- */ - if (!mem->dirty_bmap) { -- hwaddr bitmap_size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS), -- /*HOST_LONG_BITS*/ 64) / 8; - /* Allocate on the first log_sync, once and for all */ -- mem->dirty_bmap = g_malloc0(bitmap_size); -+ kvm_memslot_init_dirty_bitmap(mem); - } - - d.dirty_bitmap = mem->dirty_bmap; -@@ -1066,6 +1073,13 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml, - mem->ram = ram; - mem->flags = kvm_mem_flags(mr); - -+ if (mem->flags & KVM_MEM_LOG_DIRTY_PAGES) { -+ /* -+ * Reallocate the bmap; it means it doesn't disappear in -+ * middle of a migrate. -+ */ -+ kvm_memslot_init_dirty_bitmap(mem); -+ } - err = kvm_set_user_memory_region(kml, mem, true); - if (err) { - fprintf(stderr, "%s: error registering slot: %s\n", __func__, --- -2.27.0 - diff --git a/kvm-split-too-big-memory-section-on-several-memslots.patch b/kvm-split-too-big-memory-section-on-several-memslots.patch deleted file mode 100644 index 9a94e21a773498e07764996501664313b9c98522..0000000000000000000000000000000000000000 --- a/kvm-split-too-big-memory-section-on-several-memslots.patch +++ /dev/null @@ -1,246 +0,0 @@ -From 33f5a810b0edc1ac67163f396bd345e04b5c11e8 Mon Sep 17 00:00:00 2001 -From: Igor Mammedov -Date: Tue, 24 Sep 2019 10:47:50 -0400 -Subject: [PATCH] kvm: split too big memory section on several memslots - -Max memslot size supported by kvm on s390 is 8Tb, -move logic of splitting RAM in chunks upto 8T to KVM code. - -This way it will hide KVM specific restrictions in KVM code -and won't affect board level design decisions. Which would allow -us to avoid misusing memory_region_allocate_system_memory() API -and eventually use a single hostmem backend for guest RAM. - -Signed-off-by: Igor Mammedov -Message-Id: <20190924144751.24149-4-imammedo@redhat.com> -Reviewed-by: Peter Xu -Acked-by: Paolo Bonzini -Signed-off-by: Christian Borntraeger -Signed-off-by: Kunkun Jiang ---- - accel/kvm/kvm-all.c | 124 +++++++++++++++++++++++++-------------- - include/sysemu/kvm_int.h | 1 + - 2 files changed, 81 insertions(+), 44 deletions(-) - -diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c -index 84edbe8bb1..6828f6a1f9 100644 ---- a/accel/kvm/kvm-all.c -+++ b/accel/kvm/kvm-all.c -@@ -138,6 +138,7 @@ bool kvm_direct_msi_allowed; - bool kvm_ioeventfd_any_length_allowed; - bool kvm_msi_use_devid; - static bool kvm_immediate_exit; -+static hwaddr kvm_max_slot_size = ~0; - - static const KVMCapabilityInfo kvm_required_capabilites[] = { - KVM_CAP_INFO(USER_MEMORY), -@@ -458,7 +459,7 @@ static int kvm_slot_update_flags(KVMMemoryListener *kml, KVMSlot *mem, - static int kvm_section_update_flags(KVMMemoryListener *kml, - MemoryRegionSection *section) - { -- hwaddr start_addr, size; -+ hwaddr start_addr, size, slot_size; - KVMSlot *mem; - int ret = 0; - -@@ -469,13 +470,18 @@ static int kvm_section_update_flags(KVMMemoryListener *kml, - - kvm_slots_lock(kml); - -- mem = kvm_lookup_matching_slot(kml, start_addr, size); -- if (!mem) { -- /* We don't have a slot if we want to trap every access. */ -- goto out; -- } -+ while (size && !ret) { -+ slot_size = MIN(kvm_max_slot_size, size); -+ mem = kvm_lookup_matching_slot(kml, start_addr, slot_size); -+ if (!mem) { -+ /* We don't have a slot if we want to trap every access. */ -+ goto out; -+ } - -- ret = kvm_slot_update_flags(kml, mem, section->mr); -+ ret = kvm_slot_update_flags(kml, mem, section->mr); -+ start_addr += slot_size; -+ size -= slot_size; -+ } - - out: - kvm_slots_unlock(kml); -@@ -548,11 +554,15 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml, - struct kvm_dirty_log d = {}; - KVMSlot *mem; - hwaddr start_addr, size; -+ hwaddr slot_size, slot_offset = 0; - int ret = 0; - - size = kvm_align_section(section, &start_addr); -- if (size) { -- mem = kvm_lookup_matching_slot(kml, start_addr, size); -+ while (size) { -+ MemoryRegionSection subsection = *section; -+ -+ slot_size = MIN(kvm_max_slot_size, size); -+ mem = kvm_lookup_matching_slot(kml, start_addr, slot_size); - if (!mem) { - /* We don't have a slot if we want to trap every access. */ - goto out; -@@ -570,11 +580,11 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml, - * So for now, let's align to 64 instead of HOST_LONG_BITS here, in - * a hope that sizeof(long) won't become >8 any time soon. - */ -- size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS), -- /*HOST_LONG_BITS*/ 64) / 8; - if (!mem->dirty_bmap) { -+ hwaddr bitmap_size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS), -+ /*HOST_LONG_BITS*/ 64) / 8; - /* Allocate on the first log_sync, once and for all */ -- mem->dirty_bmap = g_malloc0(size); -+ mem->dirty_bmap = g_malloc0(bitmap_size); - } - - d.dirty_bitmap = mem->dirty_bmap; -@@ -585,7 +595,13 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml, - goto out; - } - -- kvm_get_dirty_pages_log_range(section, d.dirty_bitmap); -+ subsection.offset_within_region += slot_offset; -+ subsection.size = int128_make64(slot_size); -+ kvm_get_dirty_pages_log_range(&subsection, d.dirty_bitmap); -+ -+ slot_offset += slot_size; -+ start_addr += slot_size; -+ size -= slot_size; - } - out: - return ret; -@@ -974,6 +990,14 @@ kvm_check_extension_list(KVMState *s, const KVMCapabilityInfo *list) - return NULL; - } - -+void kvm_set_max_memslot_size(hwaddr max_slot_size) -+{ -+ g_assert( -+ ROUND_UP(max_slot_size, qemu_real_host_page_size) == max_slot_size -+ ); -+ kvm_max_slot_size = max_slot_size; -+} -+ - static void kvm_set_phys_mem(KVMMemoryListener *kml, - MemoryRegionSection *section, bool add) - { -@@ -981,7 +1005,7 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml, - int err; - MemoryRegion *mr = section->mr; - bool writeable = !mr->readonly && !mr->rom_device; -- hwaddr start_addr, size; -+ hwaddr start_addr, size, slot_size; - void *ram; - - if (!memory_region_is_ram(mr)) { -@@ -1006,41 +1030,52 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml, - kvm_slots_lock(kml); - - if (!add) { -- mem = kvm_lookup_matching_slot(kml, start_addr, size); -- if (!mem) { -- goto out; -- } -- if (mem->flags & KVM_MEM_LOG_DIRTY_PAGES) { -- kvm_physical_sync_dirty_bitmap(kml, section); -- } -+ do { -+ slot_size = MIN(kvm_max_slot_size, size); -+ mem = kvm_lookup_matching_slot(kml, start_addr, slot_size); -+ if (!mem) { -+ goto out; -+ } -+ if (mem->flags & KVM_MEM_LOG_DIRTY_PAGES) { -+ kvm_physical_sync_dirty_bitmap(kml, section); -+ } - -- /* unregister the slot */ -- g_free(mem->dirty_bmap); -- mem->dirty_bmap = NULL; -- mem->memory_size = 0; -- mem->flags = 0; -- err = kvm_set_user_memory_region(kml, mem, false); -- if (err) { -- fprintf(stderr, "%s: error unregistering slot: %s\n", -- __func__, strerror(-err)); -- abort(); -- } -+ /* unregister the slot */ -+ g_free(mem->dirty_bmap); -+ mem->dirty_bmap = NULL; -+ mem->memory_size = 0; -+ mem->flags = 0; -+ err = kvm_set_user_memory_region(kml, mem, false); -+ if (err) { -+ fprintf(stderr, "%s: error unregistering slot: %s\n", -+ __func__, strerror(-err)); -+ abort(); -+ } -+ start_addr += slot_size; -+ size -= slot_size; -+ } while (size); - goto out; - } - - /* register the new slot */ -- mem = kvm_alloc_slot(kml); -- mem->memory_size = size; -- mem->start_addr = start_addr; -- mem->ram = ram; -- mem->flags = kvm_mem_flags(mr); -- -- err = kvm_set_user_memory_region(kml, mem, true); -- if (err) { -- fprintf(stderr, "%s: error registering slot: %s\n", __func__, -- strerror(-err)); -- abort(); -- } -+ do { -+ slot_size = MIN(kvm_max_slot_size, size); -+ mem = kvm_alloc_slot(kml); -+ mem->memory_size = slot_size; -+ mem->start_addr = start_addr; -+ mem->ram = ram; -+ mem->flags = kvm_mem_flags(mr); -+ -+ err = kvm_set_user_memory_region(kml, mem, true); -+ if (err) { -+ fprintf(stderr, "%s: error registering slot: %s\n", __func__, -+ strerror(-err)); -+ abort(); -+ } -+ start_addr += slot_size; -+ ram += slot_size; -+ size -= slot_size; -+ } while (size); - - out: - kvm_slots_unlock(kml); -@@ -2880,6 +2915,7 @@ static bool kvm_accel_has_memory(MachineState *ms, AddressSpace *as, - - for (i = 0; i < kvm->nr_as; ++i) { - if (kvm->as[i].as == as && kvm->as[i].ml) { -+ size = MIN(kvm_max_slot_size, size); - return NULL != kvm_lookup_matching_slot(kvm->as[i].ml, - start_addr, size); - } -diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h -index 787dbc7770..f8e884f146 100644 ---- a/include/sysemu/kvm_int.h -+++ b/include/sysemu/kvm_int.h -@@ -43,4 +43,5 @@ typedef struct KVMMemoryListener { - void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml, - AddressSpace *as, int as_id); - -+void kvm_set_max_memslot_size(hwaddr max_slot_size); - #endif --- -2.27.0 - diff --git a/libvhost-user-Fix-some-memtable-remap-cases.patch b/libvhost-user-Fix-some-memtable-remap-cases.patch deleted file mode 100644 index 4f4d0c9f7d4d55064785426f3014ee6efbac1d63..0000000000000000000000000000000000000000 --- a/libvhost-user-Fix-some-memtable-remap-cases.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 8fa62daca5978e77ed690797a882c3d0aad8d0d4 Mon Sep 17 00:00:00 2001 -From: "Dr. David Alan Gilbert" -Date: Mon, 12 Aug 2019 17:35:19 +0100 -Subject: [PATCH] libvhost-user: Fix some memtable remap cases - -If a new setmemtable command comes in once the vhost threads are -running, it will remap the guests address space and the threads -will now be looking in the wrong place. - -Fortunately we're running this command under lock, so we can -update the queue mappings so that threads will look in the new-right -place. - -Note: This doesn't fix things that the threads might be doing -without a lock (e.g. a readv/writev!) That's for another time. - -Signed-off-by: Dr. David Alan Gilbert ---- - contrib/libvhost-user/libvhost-user.c | 33 ++++++++++++++++++++------- - contrib/libvhost-user/libvhost-user.h | 3 +++ - 2 files changed, 28 insertions(+), 8 deletions(-) - -diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c -index fb75837032..164e6d1df8 100644 ---- a/contrib/libvhost-user/libvhost-user.c -+++ b/contrib/libvhost-user/libvhost-user.c -@@ -559,6 +559,21 @@ vu_reset_device_exec(VuDev *dev, VhostUserMsg *vmsg) - return false; - } - -+static bool -+map_ring(VuDev *dev, VuVirtq *vq) -+{ -+ vq->vring.desc = qva_to_va(dev, vq->vra.desc_user_addr); -+ vq->vring.used = qva_to_va(dev, vq->vra.used_user_addr); -+ vq->vring.avail = qva_to_va(dev, vq->vra.avail_user_addr); -+ -+ DPRINT("Setting virtq addresses:\n"); -+ DPRINT(" vring_desc at %p\n", vq->vring.desc); -+ DPRINT(" vring_used at %p\n", vq->vring.used); -+ DPRINT(" vring_avail at %p\n", vq->vring.avail); -+ -+ return !(vq->vring.desc && vq->vring.used && vq->vring.avail); -+} -+ - static bool - vu_set_mem_table_exec_postcopy(VuDev *dev, VhostUserMsg *vmsg) - { -@@ -762,6 +777,14 @@ vu_set_mem_table_exec(VuDev *dev, VhostUserMsg *vmsg) - close(vmsg->fds[i]); - } - -+ for (i = 0; i < dev->max_queues; i++) { -+ if (dev->vq[i].vring.desc) { -+ if (map_ring(dev, &dev->vq[i])) { -+ vu_panic(dev, "remaping queue %d during setmemtable", i); -+ } -+ } -+ } -+ - return false; - } - -@@ -848,18 +871,12 @@ vu_set_vring_addr_exec(VuDev *dev, VhostUserMsg *vmsg) - DPRINT(" avail_user_addr: 0x%016" PRIx64 "\n", vra->avail_user_addr); - DPRINT(" log_guest_addr: 0x%016" PRIx64 "\n", vra->log_guest_addr); - -+ vq->vra = *vra; - vq->vring.flags = vra->flags; -- vq->vring.desc = qva_to_va(dev, vra->desc_user_addr); -- vq->vring.used = qva_to_va(dev, vra->used_user_addr); -- vq->vring.avail = qva_to_va(dev, vra->avail_user_addr); - vq->vring.log_guest_addr = vra->log_guest_addr; - -- DPRINT("Setting virtq addresses:\n"); -- DPRINT(" vring_desc at %p\n", vq->vring.desc); -- DPRINT(" vring_used at %p\n", vq->vring.used); -- DPRINT(" vring_avail at %p\n", vq->vring.avail); - -- if (!(vq->vring.desc && vq->vring.used && vq->vring.avail)) { -+ if (map_ring(dev, vq)) { - vu_panic(dev, "Invalid vring_addr message"); - return false; - } -diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h -index 1844b6f8d4..5cb7708559 100644 ---- a/contrib/libvhost-user/libvhost-user.h -+++ b/contrib/libvhost-user/libvhost-user.h -@@ -327,6 +327,9 @@ typedef struct VuVirtq { - int err_fd; - unsigned int enable; - bool started; -+ -+ /* Guest addresses of our ring */ -+ struct vhost_vring_addr vra; - } VuVirtq; - - enum VuWatchCondtion { --- -2.27.0 - diff --git a/libvhost-user-fix-SLAVE_SEND_FD-handling.patch b/libvhost-user-fix-SLAVE_SEND_FD-handling.patch deleted file mode 100644 index 71cbf7baa7b59006c74a8eadb9b74b10079a9a9d..0000000000000000000000000000000000000000 --- a/libvhost-user-fix-SLAVE_SEND_FD-handling.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 28a9a3558a427493049723fff390add7026653eb Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Tue, 3 Sep 2019 23:04:22 +0300 -Subject: [PATCH] libvhost-user: fix SLAVE_SEND_FD handling - -It doesn't look like this could possibly work properly since -VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD is defined to 10, but the -dev->protocol_features has a bitmap. I suppose the peer this -was tested with also supported VHOST_USER_PROTOCOL_F_LOG_SHMFD, -in which case the test would always be false, but nevertheless -the code seems wrong. - -Use has_feature() to fix this. - -Fixes: d84599f56c82 ("libvhost-user: support host notifier") -Signed-off-by: Johannes Berg -Message-Id: <20190903200422.11693-1-johannes@sipsolutions.net> -Reviewed-by: Tiwei Bie -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry picked from commit 8726b70b449896f1211f869ec4f608904f027207) -Signed-off-by: Michael Roth ---- - contrib/libvhost-user/libvhost-user.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c -index 4b36e35a82..cb5f5770e4 100644 ---- a/contrib/libvhost-user/libvhost-user.c -+++ b/contrib/libvhost-user/libvhost-user.c -@@ -1097,7 +1097,8 @@ bool vu_set_queue_host_notifier(VuDev *dev, VuVirtq *vq, int fd, - - vmsg.fd_num = fd_num; - -- if ((dev->protocol_features & VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD) == 0) { -+ if (!has_feature(dev->protocol_features, -+ VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD)) { - return false; - } - --- -2.23.0 diff --git a/linux-headers-Update-against-Add-migration-support-f.patch b/linux-headers-Update-against-Add-migration-support-f.patch deleted file mode 100644 index 1bfef98c0c9b6771ccbe2fbd700a233e09cd9baf..0000000000000000000000000000000000000000 --- a/linux-headers-Update-against-Add-migration-support-f.patch +++ /dev/null @@ -1,517 +0,0 @@ -From 7ab9ce4016ec48e0af8010f742ee39fc84342d00 Mon Sep 17 00:00:00 2001 -From: Jinhao Gao -Date: Fri, 23 Jul 2021 14:55:12 +0800 -Subject: [PATCH] linux headers: Update against "Add migration support for VFIO - devices" - -Update linux-headers/linux/vfio.h against Linux 5.9-rc7 for the -VFIO migration support series. - -Signed-off-by: Jinhao Gao -Signed-off-by: Shenming Lu ---- - linux-headers/linux/vfio.h | 420 +++++++++++++++++++++++++++++++++++-- - 1 file changed, 405 insertions(+), 15 deletions(-) - -diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h -index 24f505199f..a90672494d 100644 ---- a/linux-headers/linux/vfio.h -+++ b/linux-headers/linux/vfio.h -@@ -295,15 +295,39 @@ struct vfio_region_info_cap_type { - __u32 subtype; /* type specific */ - }; - -+/* -+ * List of region types, global per bus driver. -+ * If you introduce a new type, please add it here. -+ */ -+ -+/* PCI region type containing a PCI vendor part */ - #define VFIO_REGION_TYPE_PCI_VENDOR_TYPE (1 << 31) - #define VFIO_REGION_TYPE_PCI_VENDOR_MASK (0xffff) -+#define VFIO_REGION_TYPE_GFX (1) -+#define VFIO_REGION_TYPE_CCW (2) -+#define VFIO_REGION_TYPE_MIGRATION (3) -+ -+/* sub-types for VFIO_REGION_TYPE_PCI_* */ - --/* 8086 Vendor sub-types */ -+/* 8086 vendor PCI sub-types */ - #define VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION (1) - #define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2) - #define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG (3) - --#define VFIO_REGION_TYPE_GFX (1) -+/* 10de vendor PCI sub-types */ -+/* -+ * NVIDIA GPU NVlink2 RAM is coherent RAM mapped onto the host address space. -+ */ -+#define VFIO_REGION_SUBTYPE_NVIDIA_NVLINK2_RAM (1) -+ -+/* 1014 vendor PCI sub-types */ -+/* -+ * IBM NPU NVlink2 ATSD (Address Translation Shootdown) register of NPU -+ * to do TLB invalidation on a GPU. -+ */ -+#define VFIO_REGION_SUBTYPE_IBM_NVLINK2_ATSD (1) -+ -+/* sub-types for VFIO_REGION_TYPE_GFX */ - #define VFIO_REGION_SUBTYPE_GFX_EDID (1) - - /** -@@ -353,24 +377,237 @@ struct vfio_region_gfx_edid { - #define VFIO_DEVICE_GFX_LINK_STATE_DOWN 2 - }; - --#define VFIO_REGION_TYPE_CCW (2) --/* ccw sub-types */ -+/* sub-types for VFIO_REGION_TYPE_CCW */ - #define VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD (1) -+#define VFIO_REGION_SUBTYPE_CCW_SCHIB (2) -+#define VFIO_REGION_SUBTYPE_CCW_CRW (3) - --/* -- * 10de vendor sub-type -- * -- * NVIDIA GPU NVlink2 RAM is coherent RAM mapped onto the host address space. -- */ --#define VFIO_REGION_SUBTYPE_NVIDIA_NVLINK2_RAM (1) -+/* sub-types for VFIO_REGION_TYPE_MIGRATION */ -+#define VFIO_REGION_SUBTYPE_MIGRATION (1) - - /* -- * 1014 vendor sub-type -+ * The structure vfio_device_migration_info is placed at the 0th offset of -+ * the VFIO_REGION_SUBTYPE_MIGRATION region to get and set VFIO device related -+ * migration information. Field accesses from this structure are only supported -+ * at their native width and alignment. Otherwise, the result is undefined and -+ * vendor drivers should return an error. - * -- * IBM NPU NVlink2 ATSD (Address Translation Shootdown) register of NPU -- * to do TLB invalidation on a GPU. -+ * device_state: (read/write) -+ * - The user application writes to this field to inform the vendor driver -+ * about the device state to be transitioned to. -+ * - The vendor driver should take the necessary actions to change the -+ * device state. After successful transition to a given state, the -+ * vendor driver should return success on write(device_state, state) -+ * system call. If the device state transition fails, the vendor driver -+ * should return an appropriate -errno for the fault condition. -+ * - On the user application side, if the device state transition fails, -+ * that is, if write(device_state, state) returns an error, read -+ * device_state again to determine the current state of the device from -+ * the vendor driver. -+ * - The vendor driver should return previous state of the device unless -+ * the vendor driver has encountered an internal error, in which case -+ * the vendor driver may report the device_state VFIO_DEVICE_STATE_ERROR. -+ * - The user application must use the device reset ioctl to recover the -+ * device from VFIO_DEVICE_STATE_ERROR state. If the device is -+ * indicated to be in a valid device state by reading device_state, the -+ * user application may attempt to transition the device to any valid -+ * state reachable from the current state or terminate itself. -+ * -+ * device_state consists of 3 bits: -+ * - If bit 0 is set, it indicates the _RUNNING state. If bit 0 is clear, -+ * it indicates the _STOP state. When the device state is changed to -+ * _STOP, driver should stop the device before write() returns. -+ * - If bit 1 is set, it indicates the _SAVING state, which means that the -+ * driver should start gathering device state information that will be -+ * provided to the VFIO user application to save the device's state. -+ * - If bit 2 is set, it indicates the _RESUMING state, which means that -+ * the driver should prepare to resume the device. Data provided through -+ * the migration region should be used to resume the device. -+ * Bits 3 - 31 are reserved for future use. To preserve them, the user -+ * application should perform a read-modify-write operation on this -+ * field when modifying the specified bits. -+ * -+ * +------- _RESUMING -+ * |+------ _SAVING -+ * ||+----- _RUNNING -+ * ||| -+ * 000b => Device Stopped, not saving or resuming -+ * 001b => Device running, which is the default state -+ * 010b => Stop the device & save the device state, stop-and-copy state -+ * 011b => Device running and save the device state, pre-copy state -+ * 100b => Device stopped and the device state is resuming -+ * 101b => Invalid state -+ * 110b => Error state -+ * 111b => Invalid state -+ * -+ * State transitions: -+ * -+ * _RESUMING _RUNNING Pre-copy Stop-and-copy _STOP -+ * (100b) (001b) (011b) (010b) (000b) -+ * 0. Running or default state -+ * | -+ * -+ * 1. Normal Shutdown (optional) -+ * |------------------------------------->| -+ * -+ * 2. Save the state or suspend -+ * |------------------------->|---------->| -+ * -+ * 3. Save the state during live migration -+ * |----------->|------------>|---------->| -+ * -+ * 4. Resuming -+ * |<---------| -+ * -+ * 5. Resumed -+ * |--------->| -+ * -+ * 0. Default state of VFIO device is _RUNNNG when the user application starts. -+ * 1. During normal shutdown of the user application, the user application may -+ * optionally change the VFIO device state from _RUNNING to _STOP. This -+ * transition is optional. The vendor driver must support this transition but -+ * must not require it. -+ * 2. When the user application saves state or suspends the application, the -+ * device state transitions from _RUNNING to stop-and-copy and then to _STOP. -+ * On state transition from _RUNNING to stop-and-copy, driver must stop the -+ * device, save the device state and send it to the application through the -+ * migration region. The sequence to be followed for such transition is given -+ * below. -+ * 3. In live migration of user application, the state transitions from _RUNNING -+ * to pre-copy, to stop-and-copy, and to _STOP. -+ * On state transition from _RUNNING to pre-copy, the driver should start -+ * gathering the device state while the application is still running and send -+ * the device state data to application through the migration region. -+ * On state transition from pre-copy to stop-and-copy, the driver must stop -+ * the device, save the device state and send it to the user application -+ * through the migration region. -+ * Vendor drivers must support the pre-copy state even for implementations -+ * where no data is provided to the user before the stop-and-copy state. The -+ * user must not be required to consume all migration data before the device -+ * transitions to a new state, including the stop-and-copy state. -+ * The sequence to be followed for above two transitions is given below. -+ * 4. To start the resuming phase, the device state should be transitioned from -+ * the _RUNNING to the _RESUMING state. -+ * In the _RESUMING state, the driver should use the device state data -+ * received through the migration region to resume the device. -+ * 5. After providing saved device data to the driver, the application should -+ * change the state from _RESUMING to _RUNNING. -+ * -+ * reserved: -+ * Reads on this field return zero and writes are ignored. -+ * -+ * pending_bytes: (read only) -+ * The number of pending bytes still to be migrated from the vendor driver. -+ * -+ * data_offset: (read only) -+ * The user application should read data_offset field from the migration -+ * region. The user application should read the device data from this -+ * offset within the migration region during the _SAVING state or write -+ * the device data during the _RESUMING state. See below for details of -+ * sequence to be followed. -+ * -+ * data_size: (read/write) -+ * The user application should read data_size to get the size in bytes of -+ * the data copied in the migration region during the _SAVING state and -+ * write the size in bytes of the data copied in the migration region -+ * during the _RESUMING state. -+ * -+ * The format of the migration region is as follows: -+ * ------------------------------------------------------------------ -+ * |vfio_device_migration_info| data section | -+ * | | /////////////////////////////// | -+ * ------------------------------------------------------------------ -+ * ^ ^ -+ * offset 0-trapped part data_offset -+ * -+ * The structure vfio_device_migration_info is always followed by the data -+ * section in the region, so data_offset will always be nonzero. The offset -+ * from where the data is copied is decided by the kernel driver. The data -+ * section can be trapped, mmapped, or partitioned, depending on how the kernel -+ * driver defines the data section. The data section partition can be defined -+ * as mapped by the sparse mmap capability. If mmapped, data_offset must be -+ * page aligned, whereas initial section which contains the -+ * vfio_device_migration_info structure, might not end at the offset, which is -+ * page aligned. The user is not required to access through mmap regardless -+ * of the capabilities of the region mmap. -+ * The vendor driver should determine whether and how to partition the data -+ * section. The vendor driver should return data_offset accordingly. -+ * -+ * The sequence to be followed while in pre-copy state and stop-and-copy state -+ * is as follows: -+ * a. Read pending_bytes, indicating the start of a new iteration to get device -+ * data. Repeated read on pending_bytes at this stage should have no side -+ * effects. -+ * If pending_bytes == 0, the user application should not iterate to get data -+ * for that device. -+ * If pending_bytes > 0, perform the following steps. -+ * b. Read data_offset, indicating that the vendor driver should make data -+ * available through the data section. The vendor driver should return this -+ * read operation only after data is available from (region + data_offset) -+ * to (region + data_offset + data_size). -+ * c. Read data_size, which is the amount of data in bytes available through -+ * the migration region. -+ * Read on data_offset and data_size should return the offset and size of -+ * the current buffer if the user application reads data_offset and -+ * data_size more than once here. -+ * d. Read data_size bytes of data from (region + data_offset) from the -+ * migration region. -+ * e. Process the data. -+ * f. Read pending_bytes, which indicates that the data from the previous -+ * iteration has been read. If pending_bytes > 0, go to step b. -+ * -+ * The user application can transition from the _SAVING|_RUNNING -+ * (pre-copy state) to the _SAVING (stop-and-copy) state regardless of the -+ * number of pending bytes. The user application should iterate in _SAVING -+ * (stop-and-copy) until pending_bytes is 0. -+ * -+ * The sequence to be followed while _RESUMING device state is as follows: -+ * While data for this device is available, repeat the following steps: -+ * a. Read data_offset from where the user application should write data. -+ * b. Write migration data starting at the migration region + data_offset for -+ * the length determined by data_size from the migration source. -+ * c. Write data_size, which indicates to the vendor driver that data is -+ * written in the migration region. Vendor driver must return this write -+ * operations on consuming data. Vendor driver should apply the -+ * user-provided migration region data to the device resume state. -+ * -+ * If an error occurs during the above sequences, the vendor driver can return -+ * an error code for next read() or write() operation, which will terminate the -+ * loop. The user application should then take the next necessary action, for -+ * example, failing migration or terminating the user application. -+ * -+ * For the user application, data is opaque. The user application should write -+ * data in the same order as the data is received and the data should be of -+ * same transaction size at the source. - */ --#define VFIO_REGION_SUBTYPE_IBM_NVLINK2_ATSD (1) -+ -+struct vfio_device_migration_info { -+ __u32 device_state; /* VFIO device state */ -+#define VFIO_DEVICE_STATE_STOP (0) -+#define VFIO_DEVICE_STATE_RUNNING (1 << 0) -+#define VFIO_DEVICE_STATE_SAVING (1 << 1) -+#define VFIO_DEVICE_STATE_RESUMING (1 << 2) -+#define VFIO_DEVICE_STATE_MASK (VFIO_DEVICE_STATE_RUNNING | \ -+ VFIO_DEVICE_STATE_SAVING | \ -+ VFIO_DEVICE_STATE_RESUMING) -+ -+#define VFIO_DEVICE_STATE_VALID(state) \ -+ (state & VFIO_DEVICE_STATE_RESUMING ? \ -+ (state & VFIO_DEVICE_STATE_MASK) == VFIO_DEVICE_STATE_RESUMING : 1) -+ -+#define VFIO_DEVICE_STATE_IS_ERROR(state) \ -+ ((state & VFIO_DEVICE_STATE_MASK) == (VFIO_DEVICE_STATE_SAVING | \ -+ VFIO_DEVICE_STATE_RESUMING)) -+ -+#define VFIO_DEVICE_STATE_SET_ERROR(state) \ -+ ((state & ~VFIO_DEVICE_STATE_MASK) | VFIO_DEVICE_SATE_SAVING | \ -+ VFIO_DEVICE_STATE_RESUMING) -+ -+ __u32 reserved; -+ __u64 pending_bytes; -+ __u64 data_offset; -+ __u64 data_size; -+}; - - /* - * The MSIX mappable capability informs that MSIX data of a BAR can be mmapped -@@ -570,6 +807,7 @@ enum { - - enum { - VFIO_CCW_IO_IRQ_INDEX, -+ VFIO_CCW_CRW_IRQ_INDEX, - VFIO_CCW_NUM_IRQS - }; - -@@ -700,6 +938,43 @@ struct vfio_device_ioeventfd { - - #define VFIO_DEVICE_IOEVENTFD _IO(VFIO_TYPE, VFIO_BASE + 16) - -+/** -+ * VFIO_DEVICE_FEATURE - _IORW(VFIO_TYPE, VFIO_BASE + 17, -+ * struct vfio_device_feature) -+ * -+ * Get, set, or probe feature data of the device. The feature is selected -+ * using the FEATURE_MASK portion of the flags field. Support for a feature -+ * can be probed by setting both the FEATURE_MASK and PROBE bits. A probe -+ * may optionally include the GET and/or SET bits to determine read vs write -+ * access of the feature respectively. Probing a feature will return success -+ * if the feature is supported and all of the optionally indicated GET/SET -+ * methods are supported. The format of the data portion of the structure is -+ * specific to the given feature. The data portion is not required for -+ * probing. GET and SET are mutually exclusive, except for use with PROBE. -+ * -+ * Return 0 on success, -errno on failure. -+ */ -+struct vfio_device_feature { -+ __u32 argsz; -+ __u32 flags; -+#define VFIO_DEVICE_FEATURE_MASK (0xffff) /* 16-bit feature index */ -+#define VFIO_DEVICE_FEATURE_GET (1 << 16) /* Get feature into data[] */ -+#define VFIO_DEVICE_FEATURE_SET (1 << 17) /* Set feature from data[] */ -+#define VFIO_DEVICE_FEATURE_PROBE (1 << 18) /* Probe feature support */ -+ __u8 data[]; -+}; -+ -+#define VFIO_DEVICE_FEATURE _IO(VFIO_TYPE, VFIO_BASE + 17) -+ -+/* -+ * Provide support for setting a PCI VF Token, which is used as a shared -+ * secret between PF and VF drivers. This feature may only be set on a -+ * PCI SR-IOV PF when SR-IOV is enabled on the PF and there are no existing -+ * open VFs. Data provided when setting this feature is a 16-byte array -+ * (__u8 b[16]), representing a UUID. -+ */ -+#define VFIO_DEVICE_FEATURE_PCI_VF_TOKEN (0) -+ - /* -------- API for Type1 VFIO IOMMU -------- */ - - /** -@@ -714,7 +989,54 @@ struct vfio_iommu_type1_info { - __u32 argsz; - __u32 flags; - #define VFIO_IOMMU_INFO_PGSIZES (1 << 0) /* supported page sizes info */ -- __u64 iova_pgsizes; /* Bitmap of supported page sizes */ -+#define VFIO_IOMMU_INFO_CAPS (1 << 1) /* Info supports caps */ -+ __u64 iova_pgsizes; /* Bitmap of supported page sizes */ -+ __u32 cap_offset; /* Offset within info struct of first cap */ -+}; -+ -+/* -+ * The IOVA capability allows to report the valid IOVA range(s) -+ * excluding any non-relaxable reserved regions exposed by -+ * devices attached to the container. Any DMA map attempt -+ * outside the valid iova range will return error. -+ * -+ * The structures below define version 1 of this capability. -+ */ -+#define VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE 1 -+ -+struct vfio_iova_range { -+ __u64 start; -+ __u64 end; -+}; -+ -+struct vfio_iommu_type1_info_cap_iova_range { -+ struct vfio_info_cap_header header; -+ __u32 nr_iovas; -+ __u32 reserved; -+ struct vfio_iova_range iova_ranges[]; -+}; -+ -+/* -+ * The migration capability allows to report supported features for migration. -+ * -+ * The structures below define version 1 of this capability. -+ * -+ * The existence of this capability indicates that IOMMU kernel driver supports -+ * dirty page logging. -+ * -+ * pgsize_bitmap: Kernel driver returns bitmap of supported page sizes for dirty -+ * page logging. -+ * max_dirty_bitmap_size: Kernel driver returns maximum supported dirty bitmap -+ * size in bytes that can be used by user applications when getting the dirty -+ * bitmap. -+ */ -+#define VFIO_IOMMU_TYPE1_INFO_CAP_MIGRATION 2 -+ -+struct vfio_iommu_type1_info_cap_migration { -+ struct vfio_info_cap_header header; -+ __u32 flags; -+ __u64 pgsize_bitmap; -+ __u64 max_dirty_bitmap_size; /* in bytes */ - }; - - #define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12) -@@ -737,6 +1059,12 @@ struct vfio_iommu_type1_dma_map { - - #define VFIO_IOMMU_MAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 13) - -+struct vfio_bitmap { -+ __u64 pgsize; /* page size for bitmap in bytes */ -+ __u64 size; /* in bytes */ -+ __u64 *data; /* one bit per page */ -+}; -+ - /** - * VFIO_IOMMU_UNMAP_DMA - _IOWR(VFIO_TYPE, VFIO_BASE + 14, - * struct vfio_dma_unmap) -@@ -746,12 +1074,23 @@ struct vfio_iommu_type1_dma_map { - * field. No guarantee is made to the user that arbitrary unmaps of iova - * or size different from those used in the original mapping call will - * succeed. -+ * VFIO_DMA_UNMAP_FLAG_GET_DIRTY_BITMAP should be set to get the dirty bitmap -+ * before unmapping IO virtual addresses. When this flag is set, the user must -+ * provide a struct vfio_bitmap in data[]. User must provide zero-allocated -+ * memory via vfio_bitmap.data and its size in the vfio_bitmap.size field. -+ * A bit in the bitmap represents one page, of user provided page size in -+ * vfio_bitmap.pgsize field, consecutively starting from iova offset. Bit set -+ * indicates that the page at that offset from iova is dirty. A Bitmap of the -+ * pages in the range of unmapped size is returned in the user-provided -+ * vfio_bitmap.data. - */ - struct vfio_iommu_type1_dma_unmap { - __u32 argsz; - __u32 flags; -+#define VFIO_DMA_UNMAP_FLAG_GET_DIRTY_BITMAP (1 << 0) - __u64 iova; /* IO virtual address */ - __u64 size; /* Size of mapping (bytes) */ -+ __u8 data[]; - }; - - #define VFIO_IOMMU_UNMAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 14) -@@ -763,6 +1102,57 @@ struct vfio_iommu_type1_dma_unmap { - #define VFIO_IOMMU_ENABLE _IO(VFIO_TYPE, VFIO_BASE + 15) - #define VFIO_IOMMU_DISABLE _IO(VFIO_TYPE, VFIO_BASE + 16) - -+/** -+ * VFIO_IOMMU_DIRTY_PAGES - _IOWR(VFIO_TYPE, VFIO_BASE + 17, -+ * struct vfio_iommu_type1_dirty_bitmap) -+ * IOCTL is used for dirty pages logging. -+ * Caller should set flag depending on which operation to perform, details as -+ * below: -+ * -+ * Calling the IOCTL with VFIO_IOMMU_DIRTY_PAGES_FLAG_START flag set, instructs -+ * the IOMMU driver to log pages that are dirtied or potentially dirtied by -+ * the device; designed to be used when a migration is in progress. Dirty pages -+ * are logged until logging is disabled by user application by calling the IOCTL -+ * with VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP flag. -+ * -+ * Calling the IOCTL with VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP flag set, instructs -+ * the IOMMU driver to stop logging dirtied pages. -+ * -+ * Calling the IOCTL with VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP flag set -+ * returns the dirty pages bitmap for IOMMU container for a given IOVA range. -+ * The user must specify the IOVA range and the pgsize through the structure -+ * vfio_iommu_type1_dirty_bitmap_get in the data[] portion. This interface -+ * supports getting a bitmap of the smallest supported pgsize only and can be -+ * modified in future to get a bitmap of any specified supported pgsize. The -+ * user must provide a zeroed memory area for the bitmap memory and specify its -+ * size in bitmap.size. One bit is used to represent one page consecutively -+ * starting from iova offset. The user should provide page size in bitmap.pgsize -+ * field. A bit set in the bitmap indicates that the page at that offset from -+ * iova is dirty. The caller must set argsz to a value including the size of -+ * structure vfio_iommu_type1_dirty_bitmap_get, but excluding the size of the -+ * actual bitmap. If dirty pages logging is not enabled, an error will be -+ * returned. -+ * -+ * Only one of the flags _START, _STOP and _GET may be specified at a time. -+ * -+ */ -+struct vfio_iommu_type1_dirty_bitmap { -+ __u32 argsz; -+ __u32 flags; -+#define VFIO_IOMMU_DIRTY_PAGES_FLAG_START (1 << 0) -+#define VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP (1 << 1) -+#define VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP (1 << 2) -+ __u8 data[]; -+}; -+ -+struct vfio_iommu_type1_dirty_bitmap_get { -+ __u64 iova; /* IO virtual address */ -+ __u64 size; /* Size of iova range */ -+ struct vfio_bitmap bitmap; -+}; -+ -+#define VFIO_IOMMU_DIRTY_PAGES _IO(VFIO_TYPE, VFIO_BASE + 17) -+ - /* -------- Additional API for SPAPR TCE (Server POWERPC) IOMMU -------- */ - - /* --- -2.27.0 - diff --git a/linux-headers-update-against-5.10-and-manual-clear-v.patch b/linux-headers-update-against-5.10-and-manual-clear-v.patch index 0315fc2c1a30be23b4643c30d783e5259ef11931..93d300675cb54678121161bfb63e0a35bfaffc6f 100644 --- a/linux-headers-update-against-5.10-and-manual-clear-v.patch +++ b/linux-headers-update-against-5.10-and-manual-clear-v.patch @@ -1,4 +1,4 @@ -From 79efeccd41d761b68946df68e5431eff399ccbd5 Mon Sep 17 00:00:00 2001 +From 40512773625a4f8ddd96a5af924f119b89a14706 Mon Sep 17 00:00:00 2001 From: Zenghui Yu Date: Sat, 8 May 2021 17:31:03 +0800 Subject: [PATCH] linux-headers: update against 5.10 and manual clear vfio @@ -12,16 +12,16 @@ the kernel, update the header to add them. Signed-off-by: Zenghui Yu Signed-off-by: Kunkun Jiang --- - linux-headers/linux/vfio.h | 37 ++++++++++++++++++++++++++++++++++++- - 1 file changed, 36 insertions(+), 1 deletion(-) + linux-headers/linux/vfio.h | 36 +++++++++++++++++++++++++++++++++++- + 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h -index a90672494d..120387ba58 100644 +index e680594f27..f4ff038e8c 100644 --- a/linux-headers/linux/vfio.h +++ b/linux-headers/linux/vfio.h -@@ -46,6 +46,16 @@ - */ - #define VFIO_NOIOMMU_IOMMU 8 +@@ -52,6 +52,16 @@ + /* Supports the vaddr flag for DMA map and unmap */ + #define VFIO_UPDATE_VADDR 10 +/* + * The vfio_iommu driver may support user clears dirty log manually, which means @@ -36,15 +36,7 @@ index a90672494d..120387ba58 100644 /* * The IOCTL interface is designed for extensibility by embedding the * structure length (argsz) and flags into structures passed between -@@ -1074,6 +1084,7 @@ struct vfio_bitmap { - * field. No guarantee is made to the user that arbitrary unmaps of iova - * or size different from those used in the original mapping call will - * succeed. -+ * - * VFIO_DMA_UNMAP_FLAG_GET_DIRTY_BITMAP should be set to get the dirty bitmap - * before unmapping IO virtual addresses. When this flag is set, the user must - * provide a struct vfio_bitmap in data[]. User must provide zero-allocated -@@ -1133,8 +1144,30 @@ struct vfio_iommu_type1_dma_unmap { +@@ -1196,8 +1206,30 @@ struct vfio_iommu_type1_dma_unmap { * actual bitmap. If dirty pages logging is not enabled, an error will be * returned. * @@ -76,7 +68,7 @@ index a90672494d..120387ba58 100644 */ struct vfio_iommu_type1_dirty_bitmap { __u32 argsz; -@@ -1142,6 +1175,8 @@ struct vfio_iommu_type1_dirty_bitmap { +@@ -1205,6 +1237,8 @@ struct vfio_iommu_type1_dirty_bitmap { #define VFIO_IOMMU_DIRTY_PAGES_FLAG_START (1 << 0) #define VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP (1 << 1) #define VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP (1 << 2) diff --git a/linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch b/linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch deleted file mode 100644 index 731d06a74024c81bcc1ececeb79da2b873c2546f..0000000000000000000000000000000000000000 --- a/linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 27a9f40b308efd8ddcb81e286441865b5a0cb541 Mon Sep 17 00:00:00 2001 -From: Zenghui Yu -Date: Tue, 14 Apr 2020 21:52:42 +0800 -Subject: [PATCH] linux headers: update against "KVM/ARM: Fix >256 vcpus" - -This is part of upstream commit f363d039e883 ("linux headers: update -against v5.4-rc1"), authored by Eric Auger . - -Signed-off-by: Zenghui Yu ---- - linux-headers/asm-arm/kvm.h | 4 +++- - linux-headers/asm-arm64/kvm.h | 4 +++- - linux-headers/linux/kvm.h | 1 + - 3 files changed, 7 insertions(+), 2 deletions(-) - -diff --git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h -index e1f8b745..137a2730 100644 ---- a/linux-headers/asm-arm/kvm.h -+++ b/linux-headers/asm-arm/kvm.h -@@ -254,8 +254,10 @@ struct kvm_vcpu_events { - #define KVM_DEV_ARM_ITS_CTRL_RESET 4 - - /* KVM_IRQ_LINE irq field index values */ -+#define KVM_ARM_IRQ_VCPU2_SHIFT 28 -+#define KVM_ARM_IRQ_VCPU2_MASK 0xf - #define KVM_ARM_IRQ_TYPE_SHIFT 24 --#define KVM_ARM_IRQ_TYPE_MASK 0xff -+#define KVM_ARM_IRQ_TYPE_MASK 0xf - #define KVM_ARM_IRQ_VCPU_SHIFT 16 - #define KVM_ARM_IRQ_VCPU_MASK 0xff - #define KVM_ARM_IRQ_NUM_SHIFT 0 -diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h -index 2431ec35..cdfd5f33 100644 ---- a/linux-headers/asm-arm64/kvm.h -+++ b/linux-headers/asm-arm64/kvm.h -@@ -308,8 +308,10 @@ struct kvm_vcpu_events { - #define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1 - - /* KVM_IRQ_LINE irq field index values */ -+#define KVM_ARM_IRQ_VCPU2_SHIFT 28 -+#define KVM_ARM_IRQ_VCPU2_MASK 0xf - #define KVM_ARM_IRQ_TYPE_SHIFT 24 --#define KVM_ARM_IRQ_TYPE_MASK 0xff -+#define KVM_ARM_IRQ_TYPE_MASK 0xf - #define KVM_ARM_IRQ_VCPU_SHIFT 16 - #define KVM_ARM_IRQ_VCPU_MASK 0xff - #define KVM_ARM_IRQ_NUM_SHIFT 0 -diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h -index c8423e76..744e888e 100644 ---- a/linux-headers/linux/kvm.h -+++ b/linux-headers/linux/kvm.h -@@ -988,6 +988,7 @@ struct kvm_ppc_resize_hpt { - #define KVM_CAP_ARM_VM_IPA_SIZE 165 - #define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166 /* Obsolete */ - #define KVM_CAP_HYPERV_CPUID 167 -+#define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174 - #define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 168 - #define KVM_CAP_PPC_IRQ_XIVE 169 - #define KVM_CAP_ARM_SVE 170 --- -2.23.0 diff --git a/linux-user-mmap.c-fix-integer-underflow-in-target_mr.patch b/linux-user-mmap.c-fix-integer-underflow-in-target_mr.patch deleted file mode 100644 index 2d0c6abf3d233a0694cec23a2097011c39d4fd1f..0000000000000000000000000000000000000000 --- a/linux-user-mmap.c-fix-integer-underflow-in-target_mr.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 7b4aded3f772ef43e2b600594f755eadd5da5958 Mon Sep 17 00:00:00 2001 -From: Jonathan Marler -Date: Sat, 2 May 2020 10:12:25 -0600 -Subject: [PATCH 3/5] linux-user/mmap.c: fix integer underflow in target_mremap - -Fixes: https://bugs.launchpad.net/bugs/1876373 - -This code path in mmap occurs when a page size is decreased with mremap. When a section of pages is shrunk, qemu calls mmap_reserve on the pages that were released. However, it has the diff operation reversed, subtracting the larger old_size from the smaller new_size. Instead, it should be subtracting the smaller new_size from the larger old_size. You can also see in the previous line of the change that this mmap_reserve call only occurs when old_size > new_size. - -Bug: https://bugs.launchpad.net/qemu/+bug/1876373 -Signed-off-by: Jonathan Marler -Reviewded-by: Laurent Vivier -Message-Id: <20200502161225.14346-1-johnnymarler@gmail.com> -Signed-off-by: Laurent Vivier ---- - linux-user/mmap.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/linux-user/mmap.c b/linux-user/mmap.c -index 46a6e3a7..2a9ca0c3 100644 ---- a/linux-user/mmap.c -+++ b/linux-user/mmap.c -@@ -740,7 +740,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, - if (prot == 0) { - host_addr = mremap(g2h(old_addr), old_size, new_size, flags); - if (host_addr != MAP_FAILED && reserved_va && old_size > new_size) { -- mmap_reserve(old_addr + old_size, new_size - old_size); -+ mmap_reserve(old_addr + old_size, old_size - new_size); - } - } else { - errno = ENOMEM; --- -2.23.0 - diff --git a/lm32-do-not-leak-memory-on-object_new-object_unref.patch b/lm32-do-not-leak-memory-on-object_new-object_unref.patch deleted file mode 100644 index 7ccc53684bb3d3224757209a4c1710883214fcc8..0000000000000000000000000000000000000000 --- a/lm32-do-not-leak-memory-on-object_new-object_unref.patch +++ /dev/null @@ -1,77 +0,0 @@ -From d50be5295c49be1b6024f5902948b52e683b4c23 Mon Sep 17 00:00:00 2001 -From: lizhengui -Date: Wed, 9 Sep 2020 14:18:35 +0800 -Subject: [PATCH] lm32: do not leak memory on object_new/object_unref -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Bottom halves and ptimers are malloced, but nothing in these -files is freeing memory allocated by instance_init. Since -these are sysctl devices that are never unrealized, just moving -the allocations to realize is enough to avoid the leak in -practice (and also to avoid upsetting asan when running -device-introspect-test). - -Signed-off-by: Paolo Bonzini -Reviewed-by: Philippe Mathieu-Daudé ---- - hw/timer/lm32_timer.c | 6 +++--- - hw/timer/milkymist-sysctl.c | 10 +++++----- - 2 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c -index 6ce876c6..13f15825 100644 ---- a/hw/timer/lm32_timer.c -+++ b/hw/timer/lm32_timer.c -@@ -184,9 +184,6 @@ static void lm32_timer_init(Object *obj) - - sysbus_init_irq(dev, &s->irq); - -- s->bh = qemu_bh_new(timer_hit, s); -- s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT); -- - memory_region_init_io(&s->iomem, obj, &timer_ops, s, - "timer", R_MAX * 4); - sysbus_init_mmio(dev, &s->iomem); -@@ -196,6 +193,9 @@ static void lm32_timer_realize(DeviceState *dev, Error **errp) - { - LM32TimerState *s = LM32_TIMER(dev); - -+ s->bh = qemu_bh_new(timer_hit, s); -+ s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT); -+ - ptimer_set_freq(s->ptimer, s->freq_hz); - } - -diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c -index a9d25087..2f1ecc6d 100644 ---- a/hw/timer/milkymist-sysctl.c -+++ b/hw/timer/milkymist-sysctl.c -@@ -280,11 +280,6 @@ static void milkymist_sysctl_init(Object *obj) - sysbus_init_irq(dev, &s->timer0_irq); - sysbus_init_irq(dev, &s->timer1_irq); - -- s->bh0 = qemu_bh_new(timer0_hit, s); -- s->bh1 = qemu_bh_new(timer1_hit, s); -- s->ptimer0 = ptimer_init(s->bh0, PTIMER_POLICY_DEFAULT); -- s->ptimer1 = ptimer_init(s->bh1, PTIMER_POLICY_DEFAULT); -- - memory_region_init_io(&s->regs_region, obj, &sysctl_mmio_ops, s, - "milkymist-sysctl", R_MAX * 4); - sysbus_init_mmio(dev, &s->regs_region); -@@ -294,6 +289,11 @@ static void milkymist_sysctl_realize(DeviceState *dev, Error **errp) - { - MilkymistSysctlState *s = MILKYMIST_SYSCTL(dev); - -+ s->bh0 = qemu_bh_new(timer0_hit, s); -+ s->bh1 = qemu_bh_new(timer1_hit, s); -+ s->ptimer0 = ptimer_init(s->bh0, PTIMER_POLICY_DEFAULT); -+ s->ptimer1 = ptimer_init(s->bh1, PTIMER_POLICY_DEFAULT); -+ - ptimer_set_freq(s->ptimer0, s->freq_hz); - ptimer_set_freq(s->ptimer1, s->freq_hz); - } --- -2.19.1 - diff --git a/log-Add-log-at-boot-cpu-init-for-aarch64.patch b/log-Add-log-at-boot-cpu-init-for-aarch64.patch new file mode 100644 index 0000000000000000000000000000000000000000..7e76bcffa4e89fbb6182946802ef38c08b9c9722 --- /dev/null +++ b/log-Add-log-at-boot-cpu-init-for-aarch64.patch @@ -0,0 +1,67 @@ +From 2d3abbcc8f6c6db582d931ba194b26dd7148849f Mon Sep 17 00:00:00 2001 +From: "wanghaibin.wang" +Date: Mon, 16 Oct 2017 18:01:59 +0800 +Subject: [PATCH 1/3] log: Add log at boot & cpu init for aarch64 + +Add log at boot & cpu init for aarch64 + +Signed-off-by: miaoyubo +Signed-off-by: Jingyi Wang +--- + hw/arm/boot.c | 4 ++++ + hw/arm/virt.c | 3 +++ + 2 files changed, 7 insertions(+) + +diff --git a/hw/arm/boot.c b/hw/arm/boot.c +index 74ad397b1f..21024f7999 100644 +--- a/hw/arm/boot.c ++++ b/hw/arm/boot.c +@@ -12,6 +12,7 @@ + #include "qemu/datadir.h" + #include "qemu/error-report.h" + #include "qapi/error.h" ++#include "qemu/log.h" + #include + #include "hw/arm/boot.h" + #include "hw/arm/linux-boot-if.h" +@@ -1317,6 +1318,9 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info) + * doesn't support secure. + */ + assert(!(info->secure_board_setup && kvm_enabled())); ++ ++ qemu_log("load the kernel\n"); ++ + info->kernel_filename = ms->kernel_filename; + info->kernel_cmdline = ms->kernel_cmdline; + info->initrd_filename = ms->initrd_filename; +diff --git a/hw/arm/virt.c b/hw/arm/virt.c +index 0538d258fa..47e98f09e8 100644 +--- a/hw/arm/virt.c ++++ b/hw/arm/virt.c +@@ -33,6 +33,7 @@ + #include "qemu/datadir.h" + #include "qemu/units.h" + #include "qemu/option.h" ++#include "qemu/log.h" + #include "monitor/qdev.h" + #include "qapi/error.h" + #include "hw/sysbus.h" +@@ -971,6 +972,7 @@ static void virt_powerdown_req(Notifier *n, void *opaque) + { + VirtMachineState *s = container_of(n, VirtMachineState, powerdown_notifier); + ++ qemu_log("send powerdown to vm.\n"); + if (s->acpi_dev) { + acpi_send_event(s->acpi_dev, ACPI_POWER_DOWN_STATUS); + } else { +@@ -2072,6 +2074,7 @@ static void machvirt_init(MachineState *machine) + } + + create_fdt(vms); ++ qemu_log("cpu init start\n"); + + possible_cpus = mc->possible_cpu_arch_ids(machine); + assert(possible_cpus->len == max_cpus); +-- +2.30.0 + diff --git a/log-Add-some-logs-on-VM-runtime-path.patch b/log-Add-some-logs-on-VM-runtime-path.patch index 80eb8c39b4bcc4884c5a8fbfa43f28b808efb912..90408a3a2a9971f29abee70b9907aa1e45ad22cf 100644 --- a/log-Add-some-logs-on-VM-runtime-path.patch +++ b/log-Add-some-logs-on-VM-runtime-path.patch @@ -1,25 +1,25 @@ -From 0c83403e6e3ab21a01941be4ec57b02388eeb9c4 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Fri, 22 May 2020 18:56:09 +0800 +From d0ed3afacd2af1cbfcfb615471ade3c8c4185c00 Mon Sep 17 00:00:00 2001 +From: Yan Wang +Date: Tue, 8 Feb 2022 15:48:01 +0800 Subject: [PATCH] log: Add some logs on VM runtime path Add logs on VM runtime path, to make it easier to do trouble shooting. Signed-off-by: Ying Fang +Signed-off-by: Yan Wang +--- + hw/virtio/virtio-pci.c | 2 ++ + hw/virtio/virtio.c | 14 ++++++++++++-- + monitor/monitor.c | 9 +++++++++ + qapi/qmp-dispatch.c | 15 +++++++++++++++ + softmmu/qdev-monitor.c | 4 +++- + 5 files changed, 41 insertions(+), 3 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c -index f6d2223..b4b0ed2 100644 +index 750aa47ec1..38a5dc1ba8 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c -@@ -32,6 +32,7 @@ - #include "qemu/range.h" - #include "hw/virtio/virtio-bus.h" - #include "qapi/visitor.h" -+#include "qemu/log.h" - - #define VIRTIO_PCI_REGION_SIZE(dev) VIRTIO_PCI_CONFIG_OFF(msix_present(dev)) - -@@ -1659,7 +1660,9 @@ static void virtio_pci_device_unplugged(DeviceState *d) +@@ -1772,7 +1772,9 @@ static void virtio_pci_device_unplugged(DeviceState *d) VirtIOPCIProxy *proxy = VIRTIO_PCI(d); bool modern = virtio_pci_modern(proxy); bool modern_pio = proxy->flags & VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY; @@ -30,10 +30,10 @@ index f6d2223..b4b0ed2 100644 if (modern) { diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c -index 7c3822c..79c2dcf 100644 +index ea7c079fb0..9b4ac58a16 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c -@@ -1172,7 +1172,14 @@ int virtio_set_status(VirtIODevice *vdev, uint8_t val) +@@ -1945,7 +1945,14 @@ int virtio_set_status(VirtIODevice *vdev, uint8_t val) k->set_status(vdev, val); } vdev->status = val; @@ -49,7 +49,7 @@ index 7c3822c..79c2dcf 100644 return 0; } -@@ -1614,8 +1621,11 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, +@@ -2389,8 +2396,11 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, break; } @@ -63,62 +63,60 @@ index 7c3822c..79c2dcf 100644 vdev->vq[i].vring.num = queue_size; vdev->vq[i].vring.num_default = queue_size; diff --git a/monitor/monitor.c b/monitor/monitor.c -index 3ef2817..6f726e8 100644 +index 21c7a68758..013c628695 100644 --- a/monitor/monitor.c +++ b/monitor/monitor.c -@@ -28,6 +28,7 @@ +@@ -29,6 +29,7 @@ #include "qapi/qapi-emit-events.h" + #include "qapi/qapi-visit-control.h" #include "qapi/qmp/qdict.h" - #include "qapi/qmp/qstring.h" +#include "qapi/qmp/qjson.h" #include "qemu/error-report.h" #include "qemu/option.h" #include "sysemu/qtest.h" -@@ -254,6 +255,7 @@ static void monitor_qapi_event_emit(QAPIEvent event, QDict *qdict) +@@ -318,6 +319,7 @@ static void monitor_qapi_event_emit(QAPIEvent event, QDict *qdict) { Monitor *mon; MonitorQMP *qmp_mon; -+ QString *json; ++ GString *json; trace_monitor_protocol_event_emit(event, qdict); QTAILQ_FOREACH(mon, &mon_list, entry) { -@@ -264,6 +266,13 @@ static void monitor_qapi_event_emit(QAPIEvent event, QDict *qdict) +@@ -328,6 +330,13 @@ static void monitor_qapi_event_emit(QAPIEvent event, QDict *qdict) qmp_mon = container_of(mon, MonitorQMP, common); if (qmp_mon->commands != &qmp_cap_negotiation_commands) { qmp_send_response(qmp_mon, qdict); + json = qobject_to_json(QOBJECT(qdict)); + if (json) { -+ if (!strstr(json->string, "RTC_CHANGE")) { -+ qemu_log("%s\n", qstring_get_str(json)); ++ if (!strstr(json->str, "RTC_CHANGE")) { ++ qemu_log("%s\n", json->str); + } -+ qobject_unref(json); ++ g_string_free(json, true); + } } } } diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c -index e2c366e..6dfdad5 100644 +index d378bccac7..bb005594d3 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c -@@ -17,7 +17,9 @@ - #include "qapi/qmp/qdict.h" - #include "qapi/qmp/qjson.h" +@@ -25,6 +25,7 @@ #include "qapi/qmp/qbool.h" -+#include "qapi/qmp/qstring.h" - #include "sysemu/sysemu.h" + #include "qemu/coroutine.h" + #include "qemu/main-loop.h" +#include "qemu/log.h" - static QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oob, - Error **errp) -@@ -83,6 +85,7 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request, - const char *command; - QDict *args, *dict; - QmpCommand *cmd; -+ QString *json; + Visitor *qobject_input_visitor_new_qmp(QObject *obj) + { +@@ -147,6 +148,7 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, + QObject *id; QObject *ret = NULL; + QDict *rsp = NULL; ++ GString *json; - dict = qmp_dispatch_check_obj(request, allow_oob, errp); -@@ -128,6 +131,19 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request, + dict = qobject_to(QDict, request); + if (!dict) { +@@ -204,6 +206,19 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, qobject_ref(args); } @@ -130,27 +128,27 @@ index e2c366e..6dfdad5 100644 + && (strcmp(command, "query-balloon") != 0) + && (strcmp(command, "set_password") != 0)) { + qemu_log("qmp_cmd_name: %s, arguments: %s\n", -+ command, qstring_get_str(json)); ++ command, json->str); + } -+ qobject_unref(json); ++ g_string_free(json, true); + } + - cmd->fn(args, &ret, &local_err); - if (local_err) { - error_propagate(errp, local_err); -diff --git a/qdev-monitor.c b/qdev-monitor.c -index 58222c2..c6c1d3f 100644 ---- a/qdev-monitor.c -+++ b/qdev-monitor.c -@@ -34,6 +34,7 @@ + assert(!(oob && qemu_in_coroutine())); + assert(monitor_cur() == NULL); + if (!!(cmd->options & QCO_COROUTINE) == qemu_in_coroutine()) { +diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c +index 01f3834db5..dfd6429bf3 100644 +--- a/softmmu/qdev-monitor.c ++++ b/softmmu/qdev-monitor.c +@@ -36,6 +36,7 @@ + #include "qemu/option.h" #include "qemu/qemu-print.h" + #include "qemu/option_int.h" ++#include "qemu/log.h" #include "sysemu/block-backend.h" #include "migration/misc.h" -+#include "qemu/log.h" - - /* - * Aliases were a bad idea from the start. Let's keep them -@@ -586,6 +587,7 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) + #include "migration/migration.h" +@@ -635,6 +636,7 @@ DeviceState *qdev_device_add_from_qdict(const QDict *opts, if (path != NULL) { bus = qbus_find(path, errp); if (!bus) { @@ -158,24 +156,15 @@ index 58222c2..c6c1d3f 100644 return NULL; } if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) { -@@ -627,6 +629,8 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) - - /* set properties */ - if (qemu_opt_foreach(opts, set_property, dev, &err)) { -+ error_setg(errp, "the bus %s -driver %s set property failed", -+ bus ? bus->name : "None", driver); +@@ -707,7 +709,7 @@ DeviceState *qdev_device_add_from_qdict(const QDict *opts, + if (*errp) { goto err_del_dev; } - -@@ -636,6 +640,8 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) - dev->opts = NULL; +- ++ qemu_log("add qdev %s:%s success\n", driver, dev->id ? dev->id : "none"); + if (!qdev_realize(DEVICE(dev), bus, errp)) { goto err_del_dev; } -+ qemu_log("add qdev %s:%s success\n", driver, -+ qemu_opts_id(opts) ? qemu_opts_id(opts) : "none"); - return dev; - - err_del_dev: -- -1.8.3.1 +2.27.0 diff --git a/log-Delete-redudant-qemu_log.patch b/log-Delete-redudant-qemu_log.patch new file mode 100644 index 0000000000000000000000000000000000000000..cc9baab1c5be346226688063c857804ccbc8844f --- /dev/null +++ b/log-Delete-redudant-qemu_log.patch @@ -0,0 +1,40 @@ +From 4b195103bc1e38c05eb67cd230051463b6dff03f Mon Sep 17 00:00:00 2001 +From: Jingyi Wang +Date: Mon, 14 Feb 2022 14:42:05 +0800 +Subject: [PATCH] log: Delete redudant qemu_log + +Delete redudant qemu_log in qmp_dispatch() + +Signed-off-by: Jingyi Wang +--- + qapi/qmp-dispatch.c | 14 -------------- + 1 file changed, 14 deletions(-) + +diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c +index 392ddb097c..e9ea5a70d4 100644 +--- a/qapi/qmp-dispatch.c ++++ b/qapi/qmp-dispatch.c +@@ -222,20 +222,6 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, + + assert(!(oob && qemu_in_coroutine())); + assert(monitor_cur() == NULL); +- +- json = qobject_to_json(QOBJECT(args)); +- if (json) { +- if ((strcmp(command, "query-block-jobs") != 0) +- && (strcmp(command, "query-migrate") != 0) +- && (strcmp(command, "query-blockstats") != 0) +- && (strcmp(command, "query-balloon") != 0) +- && (strcmp(command, "set_password") != 0)) { +- qemu_log("qmp_cmd_name: %s, arguments: %s\n", +- command, json->str); +- } +- g_string_free(json, true); +- } +- + if (!!(cmd->options & QCO_COROUTINE) == qemu_in_coroutine()) { + monitor_set_cur(qemu_coroutine_self(), cur_mon); + cmd->fn(args, &ret, &err); +-- +2.27.0 + diff --git a/make-check-unit-use-after-free-in-test-opts-visitor.patch b/make-check-unit-use-after-free-in-test-opts-visitor.patch deleted file mode 100644 index 590970004769b464b68977639a0e5e823bb9b9ac..0000000000000000000000000000000000000000 --- a/make-check-unit-use-after-free-in-test-opts-visitor.patch +++ /dev/null @@ -1,102 +0,0 @@ -From e3dfb5d2848975e9e947cb894afac87ce386a2bc Mon Sep 17 00:00:00 2001 -From: lizhengui -Date: Wed, 9 Sep 2020 15:18:52 +0800 -Subject: [PATCH] make check-unit: use after free in test-opts-visitor - -In the struct OptsVisitor, the 'repeated_opts' member points to a list -in the 'unprocessed_opts' hash table after the list has been destroyed. -A subsequent call to visit_type_int() references the deleted list. -It results in use-after-free issue reproduced by running the test case -under the Valgrind: valgrind tests/test-opts-visitor. -A new mode ListMode::LM_TRAVERSED is declared to mark the list -traversal completed. - -Suggested-by: Markus Armbruster -Signed-off-by: Andrey Shinkevich -Message-Id: <1565024586-387112-1-git-send-email-andrey.shinkevich@virtuozzo.com> ---- - qapi/opts-visitor.c | 26 ++++++++++++++++++++++---- - 1 file changed, 22 insertions(+), 4 deletions(-) - -diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c -index 324b1974..42d87df6 100644 ---- a/qapi/opts-visitor.c -+++ b/qapi/opts-visitor.c -@@ -24,7 +24,8 @@ enum ListMode - { - LM_NONE, /* not traversing a list of repeated options */ - -- LM_IN_PROGRESS, /* opts_next_list() ready to be called. -+ LM_IN_PROGRESS, /* -+ * opts_next_list() ready to be called. - * - * Generating the next list link will consume the most - * recently parsed QemuOpt instance of the repeated -@@ -36,7 +37,8 @@ enum ListMode - * LM_UNSIGNED_INTERVAL. - */ - -- LM_SIGNED_INTERVAL, /* opts_next_list() has been called. -+ LM_SIGNED_INTERVAL, /* -+ * opts_next_list() has been called. - * - * Generating the next list link will consume the most - * recently stored element from the signed interval, -@@ -48,7 +50,14 @@ enum ListMode - * next element of the signed interval. - */ - -- LM_UNSIGNED_INTERVAL /* Same as above, only for an unsigned interval. */ -+ LM_UNSIGNED_INTERVAL, /* Same as above, only for an unsigned interval. */ -+ -+ LM_TRAVERSED /* -+ * opts_next_list() has been called. -+ * -+ * No more QemuOpt instance in the list. -+ * The traversal has been completed. -+ */ - }; - - typedef enum ListMode ListMode; -@@ -238,6 +247,8 @@ opts_next_list(Visitor *v, GenericList *tail, size_t size) - OptsVisitor *ov = to_ov(v); - - switch (ov->list_mode) { -+ case LM_TRAVERSED: -+ return NULL; - case LM_SIGNED_INTERVAL: - case LM_UNSIGNED_INTERVAL: - if (ov->list_mode == LM_SIGNED_INTERVAL) { -@@ -258,6 +269,8 @@ opts_next_list(Visitor *v, GenericList *tail, size_t size) - opt = g_queue_pop_head(ov->repeated_opts); - if (g_queue_is_empty(ov->repeated_opts)) { - g_hash_table_remove(ov->unprocessed_opts, opt->name); -+ ov->repeated_opts = NULL; -+ ov->list_mode = LM_TRAVERSED; - return NULL; - } - break; -@@ -289,7 +302,8 @@ opts_end_list(Visitor *v, void **obj) - - assert(ov->list_mode == LM_IN_PROGRESS || - ov->list_mode == LM_SIGNED_INTERVAL || -- ov->list_mode == LM_UNSIGNED_INTERVAL); -+ ov->list_mode == LM_UNSIGNED_INTERVAL || -+ ov->list_mode == LM_TRAVERSED); - ov->repeated_opts = NULL; - ov->list_mode = LM_NONE; - } -@@ -306,6 +320,10 @@ lookup_scalar(const OptsVisitor *ov, const char *name, Error **errp) - list = lookup_distinct(ov, name, errp); - return list ? g_queue_peek_tail(list) : NULL; - } -+ if (ov->list_mode == LM_TRAVERSED) { -+ error_setg(errp, "Fewer list elements than expected"); -+ return NULL; -+ } - assert(ov->list_mode == LM_IN_PROGRESS); - return g_queue_peek_head(ov->repeated_opts); - } --- -2.19.1 - diff --git a/make-release-pull-in-edk2-submodules-so-we-can-build.patch b/make-release-pull-in-edk2-submodules-so-we-can-build.patch deleted file mode 100644 index 70bcc864d0fd976919e540165bc7167e5026c46e..0000000000000000000000000000000000000000 --- a/make-release-pull-in-edk2-submodules-so-we-can-build.patch +++ /dev/null @@ -1,60 +0,0 @@ -From c5c9b1362d1652a9d0f79f6d9ae2f80d4b5fe432 Mon Sep 17 00:00:00 2001 -From: Michael Roth -Date: Thu, 12 Sep 2019 18:12:01 -0500 -Subject: [PATCH] make-release: pull in edk2 submodules so we can build it from - tarballs -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The `make efi` target added by 536d2173 is built from the roms/edk2 -submodule, which in turn relies on additional submodules nested under -roms/edk2. - -The make-release script currently only pulls in top-level submodules, -so these nested submodules are missing in the resulting tarball. - -We could try to address this situation more generally by recursively -pulling in all submodules, but this doesn't necessarily ensure the -end-result will build properly (this case also required other changes). - -Additionally, due to the nature of submodules, we may not always have -control over how these sorts of things are dealt with, so for now we -continue to handle it on a case-by-case in the make-release script. - -Cc: Laszlo Ersek -Cc: Bruce Rogers -Cc: qemu-stable@nongnu.org # v4.1.0 -Reported-by: Bruce Rogers -Reviewed-by: Philippe Mathieu-Daudé -Tested-by: Philippe Mathieu-Daudé -Signed-off-by: Michael Roth -Message-Id: <20190912231202.12327-2-mdroth@linux.vnet.ibm.com> -Signed-off-by: Philippe Mathieu-Daudé -(cherry picked from commit 45c61c6c23918e3b05ed9ecac5b2328ebae5f774) -Signed-off-by: Michael Roth ---- - scripts/make-release | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/scripts/make-release b/scripts/make-release -index b4af9c9e52..a2a8cda33c 100755 ---- a/scripts/make-release -+++ b/scripts/make-release -@@ -20,6 +20,14 @@ git checkout "v${version}" - git submodule update --init - (cd roms/seabios && git describe --tags --long --dirty > .version) - (cd roms/skiboot && ./make_version.sh > .version) -+# Fetch edk2 submodule's submodules, since it won't have access to them via -+# the tarball later. -+# -+# A more uniform way to handle this sort of situation would be nice, but we -+# don't necessarily have much control over how a submodule handles its -+# submodule dependencies, so we continue to handle these on a case-by-case -+# basis for now. -+(cd roms/edk2 && git submodule update --init) - popd - tar --exclude=.git -cjf ${destination}.tar.bz2 ${destination} - rm -rf ${destination} --- -2.23.0 diff --git a/mcf5208-fix-leak-from-qemu_allocate_irqs.patch b/mcf5208-fix-leak-from-qemu_allocate_irqs.patch deleted file mode 100644 index 7e254f577e4f08bc332bb94dda769ce9a584c623..0000000000000000000000000000000000000000 --- a/mcf5208-fix-leak-from-qemu_allocate_irqs.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 07b7cdb648124748c34be299fbfdfe3b6e38a521 Mon Sep 17 00:00:00 2001 -From: lizhengui -Date: Wed, 9 Sep 2020 14:53:00 +0800 -Subject: [PATCH] mcf5208: fix leak from qemu_allocate_irqs - -The array returned by qemu_allocate_irqs is malloced, free it. - -Signed-off-by: Paolo Bonzini -Reviewed-by: Thomas Huth ---- - hw/m68k/mcf5208.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c -index 6f6efae9..cc765eac 100644 ---- a/hw/m68k/mcf5208.c -+++ b/hw/m68k/mcf5208.c -@@ -270,6 +270,8 @@ static void mcf5208evb_init(MachineState *machine) - 0xfc030000, pic + 36); - } - -+ g_free(pic); -+ - /* 0xfc000000 SCM. */ - /* 0xfc004000 XBS. */ - /* 0xfc008000 FlexBus CS. */ --- -2.19.1 - diff --git a/megasas-avoid-NULL-pointer-dereference.patch b/megasas-avoid-NULL-pointer-dereference.patch deleted file mode 100644 index c7bc95901d82110b49e65ccab6cd9a84dc562aa0..0000000000000000000000000000000000000000 --- a/megasas-avoid-NULL-pointer-dereference.patch +++ /dev/null @@ -1,36 +0,0 @@ -From cf7f42b21aaa7694c6232a9a5027de9df341f299 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Thu, 14 May 2020 00:55:39 +0530 -Subject: [PATCH 5/9] megasas: avoid NULL pointer dereference - -While in megasas_handle_frame(), megasas_enqueue_frame() may -set a NULL frame into MegasasCmd object for a given 'frame_addr' -address. Add check to avoid a NULL pointer dereference issue. - -Reported-by: Alexander Bulekov -Fixes: https://bugs.launchpad.net/qemu/+bug/1878259 -Signed-off-by: Prasad J Pandit -Acked-by: Alexander Bulekov -Reviewed-by: Darren Kenny -Message-Id: <20200513192540.1583887-3-ppandit@redhat.com> -Signed-off-by: Paolo Bonzini ---- - 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 7ee331d9da..5923ffbd22 100644 ---- a/hw/scsi/megasas.c -+++ b/hw/scsi/megasas.c -@@ -503,7 +503,7 @@ static MegasasCmd *megasas_enqueue_frame(MegasasState *s, - cmd->pa = frame; - /* Map all possible frames */ - cmd->frame = pci_dma_map(pcid, frame, &frame_size_p, 0); -- if (frame_size_p != frame_size) { -+ if (!cmd->frame || frame_size_p != frame_size) { - trace_megasas_qf_map_failed(cmd->index, (unsigned long)frame); - if (cmd->frame) { - megasas_unmap_frame(s, cmd); --- -2.25.1 - diff --git a/megasas-use-unsigned-type-for-positive-numeric-field.patch b/megasas-use-unsigned-type-for-positive-numeric-field.patch deleted file mode 100644 index 7e194395193623e061917b0a5e6315d6b8564a61..0000000000000000000000000000000000000000 --- a/megasas-use-unsigned-type-for-positive-numeric-field.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 7bad515189482d289d3efe4133c8af9f184662e4 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Thu, 14 May 2020 00:55:40 +0530 -Subject: [PATCH 6/9] megasas: use unsigned type for positive numeric fields - -Use unsigned type for the MegasasState fields which hold positive -numeric values. - -Signed-off-by: Prasad J Pandit -Reviewed-by: Darren Kenny -Message-Id: <20200513192540.1583887-4-ppandit@redhat.com> -Signed-off-by: Paolo Bonzini ---- - hw/scsi/megasas.c | 38 +++++++++++++++++++------------------- - 1 file changed, 19 insertions(+), 19 deletions(-) - -diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c -index 5923ffbd22..94469e8169 100644 ---- a/hw/scsi/megasas.c -+++ b/hw/scsi/megasas.c -@@ -85,34 +85,34 @@ typedef struct MegasasState { - MemoryRegion queue_io; - uint32_t frame_hi; - -- int fw_state; -+ uint32_t fw_state; - uint32_t fw_sge; - uint32_t fw_cmds; - uint32_t flags; -- int fw_luns; -- int intr_mask; -- int doorbell; -- int busy; -- int diag; -- int adp_reset; -+ uint32_t fw_luns; -+ uint32_t intr_mask; -+ uint32_t doorbell; -+ uint32_t busy; -+ uint32_t diag; -+ uint32_t adp_reset; - OnOffAuto msi; - OnOffAuto msix; - - MegasasCmd *event_cmd; -- int event_locale; -+ uint16_t event_locale; - int event_class; -- int event_count; -- int shutdown_event; -- int boot_event; -+ uint32_t event_count; -+ uint32_t shutdown_event; -+ uint32_t boot_event; - - uint64_t sas_addr; - char *hba_serial; - - uint64_t reply_queue_pa; - void *reply_queue; -- int reply_queue_len; -+ uint16_t reply_queue_len; - uint16_t reply_queue_head; -- int reply_queue_tail; -+ uint16_t reply_queue_tail; - uint64_t consumer_pa; - uint64_t producer_pa; - -@@ -2258,9 +2258,9 @@ static const VMStateDescription vmstate_megasas_gen1 = { - VMSTATE_PCI_DEVICE(parent_obj, MegasasState), - VMSTATE_MSIX(parent_obj, MegasasState), - -- VMSTATE_INT32(fw_state, MegasasState), -- VMSTATE_INT32(intr_mask, MegasasState), -- VMSTATE_INT32(doorbell, MegasasState), -+ VMSTATE_UINT32(fw_state, MegasasState), -+ VMSTATE_UINT32(intr_mask, MegasasState), -+ VMSTATE_UINT32(doorbell, MegasasState), - VMSTATE_UINT64(reply_queue_pa, MegasasState), - VMSTATE_UINT64(consumer_pa, MegasasState), - VMSTATE_UINT64(producer_pa, MegasasState), -@@ -2277,9 +2277,9 @@ static const VMStateDescription vmstate_megasas_gen2 = { - VMSTATE_PCI_DEVICE(parent_obj, MegasasState), - VMSTATE_MSIX(parent_obj, MegasasState), - -- VMSTATE_INT32(fw_state, MegasasState), -- VMSTATE_INT32(intr_mask, MegasasState), -- VMSTATE_INT32(doorbell, MegasasState), -+ VMSTATE_UINT32(fw_state, MegasasState), -+ VMSTATE_UINT32(intr_mask, MegasasState), -+ VMSTATE_UINT32(doorbell, MegasasState), - VMSTATE_UINT64(reply_queue_pa, MegasasState), - VMSTATE_UINT64(consumer_pa, MegasasState), - VMSTATE_UINT64(producer_pa, MegasasState), --- -2.25.1 - diff --git a/megasas-use-unsigned-type-for-reply_queue_head-and-c.patch b/megasas-use-unsigned-type-for-reply_queue_head-and-c.patch deleted file mode 100644 index 507aeafb6911562d542f06f91c75a3dd90f43478..0000000000000000000000000000000000000000 --- a/megasas-use-unsigned-type-for-reply_queue_head-and-c.patch +++ /dev/null @@ -1,51 +0,0 @@ -From e081fb1058e357d4d7adc30201013a46123fe2ae Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Thu, 14 May 2020 00:55:38 +0530 -Subject: [PATCH 4/9] megasas: use unsigned type for reply_queue_head and check - index - -A guest user may set 'reply_queue_head' field of MegasasState to -a negative value. Later in 'megasas_lookup_frame' it is used to -index into s->frames[] array. Use unsigned type to avoid OOB -access issue. - -Also check that 'index' value stays within s->frames[] bounds -through the while() loop in 'megasas_lookup_frame' to avoid OOB -access. - -Reported-by: Ren Ding -Reported-by: Hanqing Zhao -Reported-by: Alexander Bulekov -Signed-off-by: Prasad J Pandit -Acked-by: Alexander Bulekov -Message-Id: <20200513192540.1583887-2-ppandit@redhat.com> -Signed-off-by: Paolo Bonzini ---- - hw/scsi/megasas.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c -index 0c4399930a..7ee331d9da 100644 ---- a/hw/scsi/megasas.c -+++ b/hw/scsi/megasas.c -@@ -111,7 +111,7 @@ typedef struct MegasasState { - uint64_t reply_queue_pa; - void *reply_queue; - int reply_queue_len; -- int reply_queue_head; -+ uint16_t reply_queue_head; - int reply_queue_tail; - uint64_t consumer_pa; - uint64_t producer_pa; -@@ -444,7 +444,7 @@ static MegasasCmd *megasas_lookup_frame(MegasasState *s, - - index = s->reply_queue_head; - -- while (num < s->fw_cmds) { -+ while (num < s->fw_cmds && index < MEGASAS_MAX_FRAMES) { - if (s->frames[index].pa && s->frames[index].pa == frame) { - cmd = &s->frames[index]; - break; --- -2.25.1 - diff --git a/memory-Add-IOMMU_ATTR_MSI_TRANSLATE-IOMMU-memory-reg.patch b/memory-Add-IOMMU_ATTR_MSI_TRANSLATE-IOMMU-memory-reg.patch index c67de46045dcbdca04a8a78d8ca0d44b27a794c2..b06bc2514357ceda3aeff221ef2095f43885ada1 100644 --- a/memory-Add-IOMMU_ATTR_MSI_TRANSLATE-IOMMU-memory-reg.patch +++ b/memory-Add-IOMMU_ATTR_MSI_TRANSLATE-IOMMU-memory-reg.patch @@ -1,4 +1,4 @@ -From b7f4f3b71a179a21a90ca32ef7d6ea000fb0e3bd Mon Sep 17 00:00:00 2001 +From 062923fd4e6d11e1b724f2dd059f8b0c6e65bf7a Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Mon, 25 Mar 2019 16:35:05 +0100 Subject: [PATCH] memory: Add IOMMU_ATTR_MSI_TRANSLATE IOMMU memory region @@ -16,17 +16,17 @@ Signed-off-by: Kunkun Jiang 1 file changed, 1 insertion(+) diff --git a/include/exec/memory.h b/include/exec/memory.h -index 74606e14aa..716b07e115 100644 +index 864bcaeb01..76ef99ed27 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h -@@ -242,6 +242,7 @@ struct MemoryRegionOps { +@@ -323,6 +323,7 @@ typedef struct MemoryRegionClass { enum IOMMUMemoryRegionAttr { IOMMU_ATTR_SPAPR_TCE_FD, IOMMU_ATTR_VFIO_NESTED, + IOMMU_ATTR_MSI_TRANSLATE, }; - /** + /* -- 2.27.0 diff --git a/memory-Add-IOMMU_ATTR_VFIO_NESTED-IOMMU-memory-regio.patch b/memory-Add-IOMMU_ATTR_VFIO_NESTED-IOMMU-memory-regio.patch index 3932161dc8aeb2377a64f77c1ccc2e8a5c0d9a6a..bb27247096c8d16f63ff7c55a7cb2a6827dccd16 100644 --- a/memory-Add-IOMMU_ATTR_VFIO_NESTED-IOMMU-memory-regio.patch +++ b/memory-Add-IOMMU_ATTR_VFIO_NESTED-IOMMU-memory-regio.patch @@ -1,4 +1,4 @@ -From 5f4291f431add76b8754a5fb2d62ab4108ece73f Mon Sep 17 00:00:00 2001 +From b380e3e0c30fb68dbbfb1397f3c374adfff77ac4 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Mon, 1 Jul 2019 11:30:30 +0200 Subject: [PATCH] memory: Add IOMMU_ATTR_VFIO_NESTED IOMMU memory region @@ -24,11 +24,11 @@ Signed-off-by: Kunkun Jiang 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c -index 0ef1ca376c..55eed5189e 100644 +index da5dac1ba5..9b87d16217 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c -@@ -1531,6 +1531,17 @@ static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu, - } +@@ -1589,6 +1589,17 @@ static int smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu, + return 0; } +static int smmuv3_get_attr(IOMMUMemoryRegion *iommu, @@ -45,7 +45,7 @@ index 0ef1ca376c..55eed5189e 100644 static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass, void *data) { -@@ -1538,6 +1549,7 @@ static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass, +@@ -1596,6 +1607,7 @@ static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass, imrc->translate = smmuv3_translate; imrc->notify_flag_changed = smmuv3_notify_flag_changed; @@ -54,11 +54,11 @@ index 0ef1ca376c..55eed5189e 100644 static const TypeInfo smmuv3_type_info = { diff --git a/include/exec/memory.h b/include/exec/memory.h -index 3c5206dce6..74606e14aa 100644 +index c3180075e1..864bcaeb01 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h -@@ -240,7 +240,8 @@ struct MemoryRegionOps { - }; +@@ -321,7 +321,8 @@ typedef struct MemoryRegionClass { + enum IOMMUMemoryRegionAttr { - IOMMU_ATTR_SPAPR_TCE_FD @@ -66,7 +66,7 @@ index 3c5206dce6..74606e14aa 100644 + IOMMU_ATTR_VFIO_NESTED, }; - /** + /* -- 2.27.0 diff --git a/memory-Add-new-fields-in-IOTLBEntry.patch b/memory-Add-new-fields-in-IOTLBEntry.patch index d76ff3bcd7321b32c9a57b6862f68b19f1216daa..5a85dbfd61ecea58ff1942d24a004b2ed82e6fdd 100644 --- a/memory-Add-new-fields-in-IOTLBEntry.patch +++ b/memory-Add-new-fields-in-IOTLBEntry.patch @@ -1,4 +1,4 @@ -From 5a77056573d946eb9220b90dd1edce1f6f925c42 Mon Sep 17 00:00:00 2001 +From da97cef20d4ee5a8f3942953836b35e7f7dd974f Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 4 Sep 2018 08:43:05 -0400 Subject: [PATCH] memory: Add new fields in IOTLBEntry @@ -19,17 +19,117 @@ translation are required to be invalidated. A flag field is introduced to inform whether those fields are set. +To enforce all existing users do not use those new fields, +initialize the IOMMUTLBEvents when needed. + Signed-off-by: Eric Auger Signed-off-by: Kunkun Jiang --- - include/exec/memory.h | 36 +++++++++++++++++++++++++++++++++++- - 1 file changed, 35 insertions(+), 1 deletion(-) + hw/arm/smmu-common.c | 2 +- + hw/arm/smmuv3.c | 2 +- + hw/i386/intel_iommu.c | 6 +++--- + hw/ppc/spapr_iommu.c | 2 +- + hw/virtio/virtio-iommu.c | 4 ++-- + include/exec/memory.h | 36 +++++++++++++++++++++++++++++++++++- + 6 files changed, 43 insertions(+), 9 deletions(-) +diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c +index 0459850a93..3a1ecf81d6 100644 +--- a/hw/arm/smmu-common.c ++++ b/hw/arm/smmu-common.c +@@ -470,7 +470,7 @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid) + /* Unmap the whole notifier's range */ + static void smmu_unmap_notifier_range(IOMMUNotifier *n) + { +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + + event.type = IOMMU_NOTIFIER_UNMAP; + event.entry.target_as = &address_space_memory; +diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c +index 01b60bee49..94e2c658f8 100644 +--- a/hw/arm/smmuv3.c ++++ b/hw/arm/smmuv3.c +@@ -802,7 +802,7 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, + uint8_t tg, uint64_t num_pages) + { + SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu); +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + uint8_t granule; + + if (!tg) { +diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c +index f584449d8d..fae282ef5e 100644 +--- a/hw/i386/intel_iommu.c ++++ b/hw/i386/intel_iommu.c +@@ -1193,7 +1193,7 @@ static int vtd_page_walk_level(dma_addr_t addr, uint64_t start, + uint32_t offset; + uint64_t slpte; + uint64_t subpage_size, subpage_mask; +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + uint64_t iova = start; + uint64_t iova_next; + int ret = 0; +@@ -2425,7 +2425,7 @@ static bool vtd_process_device_iotlb_desc(IntelIOMMUState *s, + VTDInvDesc *inv_desc) + { + VTDAddressSpace *vtd_dev_as; +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + struct VTDBus *vtd_bus; + hwaddr addr; + uint64_t sz; +@@ -3481,7 +3481,7 @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n) + size = remain = end - start + 1; + + while (remain >= VTD_PAGE_SIZE) { +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + uint64_t mask = dma_aligned_pow2_mask(start, end, s->aw_bits); + uint64_t size = mask + 1; + +diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c +index db01071858..454df25d44 100644 +--- a/hw/ppc/spapr_iommu.c ++++ b/hw/ppc/spapr_iommu.c +@@ -449,7 +449,7 @@ static void spapr_tce_reset(DeviceState *dev) + static target_ulong put_tce_emu(SpaprTceTable *tcet, target_ulong ioba, + target_ulong tce) + { +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + hwaddr page_mask = IOMMU_PAGE_MASK(tcet->page_shift); + unsigned long index = (ioba - tcet->bus_offset) >> tcet->page_shift; + +diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c +index 1b23e8e18c..83ed2b82e6 100644 +--- a/hw/virtio/virtio-iommu.c ++++ b/hw/virtio/virtio-iommu.c +@@ -129,7 +129,7 @@ static void virtio_iommu_notify_map(IOMMUMemoryRegion *mr, hwaddr virt_start, + hwaddr virt_end, hwaddr paddr, + uint32_t flags) + { +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + IOMMUAccessFlags perm = IOMMU_ACCESS_FLAG(flags & VIRTIO_IOMMU_MAP_F_READ, + flags & VIRTIO_IOMMU_MAP_F_WRITE); + +@@ -154,7 +154,7 @@ static void virtio_iommu_notify_map(IOMMUMemoryRegion *mr, hwaddr virt_start, + static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start, + hwaddr virt_end) + { +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + uint64_t delta = virt_end - virt_start; + + if (!(mr->iommu_notify_flags & IOMMU_NOTIFIER_UNMAP)) { diff --git a/include/exec/memory.h b/include/exec/memory.h -index dca8184277..3c5206dce6 100644 +index 20f1b27377..c3180075e1 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h -@@ -66,14 +66,48 @@ typedef enum { +@@ -113,14 +113,48 @@ typedef enum { IOMMU_RW = 3, } IOMMUAccessFlags; @@ -43,7 +143,7 @@ index dca8184277..3c5206dce6 100644 #define IOMMU_ACCESS_FLAG(r, w) (((r) ? IOMMU_RO : 0) | ((w) ? IOMMU_WO : 0)) +/** -+ * IOMMUTLBEntry - IOMMU TLB entry ++ * struct IOMMUTLBEntry - IOMMU TLB entry + * + * Structure used when performing a translation or when notifying MAP or + * UNMAP (invalidation) events diff --git a/memory-Align-MemoryRegionSections-fields.patch b/memory-Align-MemoryRegionSections-fields.patch deleted file mode 100644 index c363a026a5f2d071950d6d9749511166432d59e4..0000000000000000000000000000000000000000 --- a/memory-Align-MemoryRegionSections-fields.patch +++ /dev/null @@ -1,45 +0,0 @@ -From aebd98d0799d6dd9bb4dd4bf73f0b75c5f4e665d Mon Sep 17 00:00:00 2001 -From: "Dr. David Alan Gilbert" -Date: Wed, 14 Aug 2019 18:55:33 +0100 -Subject: [PATCH] memory: Align MemoryRegionSections fields -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -MemoryRegionSection includes an Int128 'size' field; -on some platforms the compiler causes an alignment of this to -a 128bit boundary, leaving 8 bytes of dead space. -This deadspace can be filled with junk. - -Move the size field to the top avoiding unnecessary alignment. - -Signed-off-by: Dr. David Alan Gilbert -Reviewed-by: Philippe Mathieu-Daudé -Message-Id: <20190814175535.2023-2-dgilbert@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry picked from commit 44f85d3276397cfa2cfa379c61430405dad4e644) -Signed-off-by: Michael Roth ---- - include/exec/memory.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/include/exec/memory.h b/include/exec/memory.h -index 1625913..f0f0767 100644 ---- a/include/exec/memory.h -+++ b/include/exec/memory.h -@@ -484,10 +484,10 @@ static inline FlatView *address_space_to_flatview(AddressSpace *as) - * @nonvolatile: this section is non-volatile - */ - struct MemoryRegionSection { -+ Int128 size; - MemoryRegion *mr; - FlatView *fv; - hwaddr offset_within_region; -- Int128 size; - hwaddr offset_within_address_space; - bool readonly; - bool nonvolatile; --- -1.8.3.1 - diff --git a/memory-Introduce-IOMMU-Memory-Region-inject_faults-A.patch b/memory-Introduce-IOMMU-Memory-Region-inject_faults-A.patch index 7cecd31a9765fb0926a4de993b38e0d5e68dfd6b..e541d9e69d716560a8d5636a25d072b3d05c765f 100644 --- a/memory-Introduce-IOMMU-Memory-Region-inject_faults-A.patch +++ b/memory-Introduce-IOMMU-Memory-Region-inject_faults-A.patch @@ -1,4 +1,4 @@ -From 497e055ed89e3cb5286dde2b05b7d7fd67e69331 Mon Sep 17 00:00:00 2001 +From d2dce19165f133935ff72e209f19bc43ab4d1421 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 13 Sep 2018 14:13:04 +0200 Subject: [PATCH] memory: Introduce IOMMU Memory Region inject_faults API @@ -9,16 +9,16 @@ the IOMMU memory region. Signed-off-by: Eric Auger Signed-off-by: Kunkun Jiang --- - include/exec/memory.h | 25 +++++++++++++++++++++++++ - memory.c | 10 ++++++++++ - 2 files changed, 35 insertions(+) + include/exec/memory.h | 24 ++++++++++++++++++++++++ + softmmu/memory.c | 10 ++++++++++ + 2 files changed, 34 insertions(+) diff --git a/include/exec/memory.h b/include/exec/memory.h -index 716b07e115..ffd4282f14 100644 +index 76ef99ed27..3e84d62e40 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h -@@ -56,6 +56,8 @@ struct MemoryRegionMmio { - CPUWriteMemoryFunc *write[3]; +@@ -103,6 +103,8 @@ struct MemoryRegionSection { + bool nonvolatile; }; +struct iommu_fault; @@ -26,10 +26,10 @@ index 716b07e115..ffd4282f14 100644 typedef struct IOMMUTLBEntry IOMMUTLBEntry; /* See address_space_translate: bit 0 is read, bit 1 is write. */ -@@ -378,6 +380,19 @@ typedef struct IOMMUMemoryRegionClass { - * @iommu: the IOMMUMemoryRegion - */ - int (*num_indexes)(IOMMUMemoryRegion *iommu); +@@ -523,6 +525,19 @@ struct IOMMUMemoryRegionClass { + int (*iommu_set_page_size_mask)(IOMMUMemoryRegion *iommu, + uint64_t page_size_mask, + Error **errp); + + /* + * Inject @count faults into the IOMMU memory region @@ -43,13 +43,13 @@ index 716b07e115..ffd4282f14 100644 + */ + int (*inject_faults)(IOMMUMemoryRegion *iommu, int count, + struct iommu_fault *buf); - } IOMMUMemoryRegionClass; - - typedef struct CoalescedMemoryRange CoalescedMemoryRange; -@@ -1182,6 +1197,16 @@ int memory_region_iommu_attrs_to_index(IOMMUMemoryRegion *iommu_mr, - */ - int memory_region_iommu_num_indexes(IOMMUMemoryRegion *iommu_mr); + }; + typedef struct RamDiscardListener RamDiscardListener; +@@ -1819,6 +1834,15 @@ int memory_region_iommu_num_indexes(IOMMUMemoryRegion *iommu_mr); + int memory_region_iommu_set_page_size_mask(IOMMUMemoryRegion *iommu_mr, + uint64_t page_size_mask, + Error **errp); +/** + * memory_region_inject_faults : inject @count faults stored in @buf + * @@ -59,16 +59,15 @@ index 716b07e115..ffd4282f14 100644 + */ +int memory_region_inject_faults(IOMMUMemoryRegion *iommu_mr, int count, + struct iommu_fault *buf); -+ + /** * memory_region_name: get a memory region's name - * -diff --git a/memory.c b/memory.c -index 708b3dff3d..623f89baa4 100644 ---- a/memory.c -+++ b/memory.c -@@ -2017,6 +2017,16 @@ int memory_region_iommu_num_indexes(IOMMUMemoryRegion *iommu_mr) - return imrc->num_indexes(iommu_mr); +diff --git a/softmmu/memory.c b/softmmu/memory.c +index 7340e19ff5..9f98209ab2 100644 +--- a/softmmu/memory.c ++++ b/softmmu/memory.c +@@ -2111,6 +2111,16 @@ void ram_discard_manager_unregister_listener(RamDiscardManager *rdm, + rdmc->unregister_listener(rdm, rdl); } +int memory_region_inject_faults(IOMMUMemoryRegion *iommu_mr, int count, diff --git a/memory-Provide-an-equality-function-for-MemoryRegion.patch b/memory-Provide-an-equality-function-for-MemoryRegion.patch deleted file mode 100644 index 9d81f489a7fc516ba95aa411bccbc0a67397d389..0000000000000000000000000000000000000000 --- a/memory-Provide-an-equality-function-for-MemoryRegion.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 026ef4aabd2d533d1d2f206bd3312fb1b1674058 Mon Sep 17 00:00:00 2001 -From: "Dr. David Alan Gilbert" -Date: Wed, 14 Aug 2019 18:55:34 +0100 -Subject: [PATCH] memory: Provide an equality function for MemoryRegionSections -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Provide a comparison function that checks all the fields are the same. - -Signed-off-by: Dr. David Alan Gilbert -Reviewed-by: Philippe Mathieu-Daudé -Message-Id: <20190814175535.2023-3-dgilbert@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry picked from commit 9366cf02e4e31c2a8128904d4d8290a0fad5f888) -Signed-off-by: Michael Roth ---- - include/exec/memory.h | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/include/exec/memory.h b/include/exec/memory.h -index f0f0767..ba0ce25 100644 ---- a/include/exec/memory.h -+++ b/include/exec/memory.h -@@ -493,6 +493,18 @@ struct MemoryRegionSection { - bool nonvolatile; - }; - -+static inline bool MemoryRegionSection_eq(MemoryRegionSection *a, -+ MemoryRegionSection *b) -+{ -+ return a->mr == b->mr && -+ a->fv == b->fv && -+ a->offset_within_region == b->offset_within_region && -+ a->offset_within_address_space == b->offset_within_address_space && -+ int128_eq(a->size, b->size) && -+ a->readonly == b->readonly && -+ a->nonvolatile == b->nonvolatile; -+} -+ - /** - * memory_region_init: Initialize a memory region - * --- -1.8.3.1 - diff --git a/memory-Set-DIRTY_MEMORY_MIGRATION-when-IOMMU-is-enab.patch b/memory-Set-DIRTY_MEMORY_MIGRATION-when-IOMMU-is-enab.patch deleted file mode 100644 index 2c4052639c2c104de23c1a6d99674ec036e675af..0000000000000000000000000000000000000000 --- a/memory-Set-DIRTY_MEMORY_MIGRATION-when-IOMMU-is-enab.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0ae8b3e05294fee99870efa9b58e22e16f31caf9 Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:20 +0530 -Subject: [PATCH] memory: Set DIRTY_MEMORY_MIGRATION when IOMMU is enabled - -mr->ram_block is NULL when mr->is_iommu is true, then fr.dirty_log_mask -wasn't set correctly due to which memory listener's log_sync doesn't -get called. -This patch returns log_mask with DIRTY_MEMORY_MIGRATION set when -IOMMU is enabled. - -Signed-off-by: Kirti Wankhede -Reviewed-by: Yan Zhao -Acked-by: Paolo Bonzini -Signed-off-by: Alex Williamson ---- - memory.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/memory.c b/memory.c -index 5d8c9a9234..44713efc66 100644 ---- a/memory.c -+++ b/memory.c -@@ -1825,7 +1825,7 @@ bool memory_region_is_ram_device(MemoryRegion *mr) - uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr) - { - uint8_t mask = mr->dirty_log_mask; -- if (global_dirty_log && mr->ram_block) { -+ if (global_dirty_log && (mr->ram_block || memory_region_is_iommu(mr))) { - mask |= (1 << DIRTY_MEMORY_MIGRATION); - } - return mask; --- -2.27.0 - diff --git a/memory-Skip-dirty-tracking-for-un-migratable-memory-.patch b/memory-Skip-dirty-tracking-for-un-migratable-memory-.patch deleted file mode 100644 index 8a25d177e1349ef0faca9b9280e70bb43dfd2837..0000000000000000000000000000000000000000 --- a/memory-Skip-dirty-tracking-for-un-migratable-memory-.patch +++ /dev/null @@ -1,42 +0,0 @@ -From d0d816682b790b7d8a9caf17c32eadde7756ac9c Mon Sep 17 00:00:00 2001 -From: Zenghui Yu -Date: Mon, 16 Nov 2020 21:22:10 +0800 -Subject: [PATCH] memory: Skip dirty tracking for un-migratable memory regions - -It makes no sense to track dirty pages for those un-migratable memory -regions (e.g., Memory BAR region of the VFIO PCI device) and doing so -will potentially lead to some unpleasant issues during migration [1]. - -Skip dirty tracking for those regions by evaluating if the region is -migratable before setting dirty_log_mask (DIRTY_MEMORY_MIGRATION). - -[1] https://lists.gnu.org/archive/html/qemu-devel/2020-11/msg03757.html - -Signed-off-by: Zenghui Yu -Message-Id: <20201116132210.1730-1-yuzenghui@huawei.com> -Reviewed-by: Cornelia Huck -Signed-off-by: Paolo Bonzini -Signed-off-by: Kunkun Jiang ---- - memory.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/memory.c b/memory.c -index 44713efc66..708b3dff3d 100644 ---- a/memory.c -+++ b/memory.c -@@ -1825,7 +1825,10 @@ bool memory_region_is_ram_device(MemoryRegion *mr) - uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr) - { - uint8_t mask = mr->dirty_log_mask; -- if (global_dirty_log && (mr->ram_block || memory_region_is_iommu(mr))) { -+ RAMBlock *rb = mr->ram_block; -+ -+ if (global_dirty_log && ((rb && qemu_ram_is_migratable(rb)) || -+ memory_region_is_iommu(mr))) { - mask |= (1 << DIRTY_MEMORY_MIGRATION); - } - return mask; --- -2.27.0 - diff --git a/memory-clamp-cached-translation-in-case-it-points-to.patch b/memory-clamp-cached-translation-in-case-it-points-to.patch deleted file mode 100644 index c4f74d4e094c937f8b415683dc06997c3ce6cc90..0000000000000000000000000000000000000000 --- a/memory-clamp-cached-translation-in-case-it-points-to.patch +++ /dev/null @@ -1,72 +0,0 @@ -From e07e9fc9d97e9cae3d6316b7286b504398a6fc80 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Wed, 13 Jan 2021 14:50:59 +0800 -Subject: [PATCH] memory: clamp cached translation in case it points to an MMIO - region - -In using the address_space_translate_internal API, address_space_cache_init -forgot one piece of advice that can be found in the code for -address_space_translate_internal: - - /* MMIO registers can be expected to perform full-width accesses based only - * on their address, without considering adjacent registers that could - * decode to completely different MemoryRegions. When such registers - * exist (e.g. I/O ports 0xcf8 and 0xcf9 on most PC chipsets), MMIO - * regions overlap wildly. For this reason we cannot clamp the accesses - * here. - * - * If the length is small (as is the case for address_space_ldl/stl), - * everything works fine. If the incoming length is large, however, - * the caller really has to do the clamping through memory_access_size. - */ - -address_space_cache_init is exactly one such case where "the incoming length -is large", therefore we need to clamp the resulting length---not to -memory_access_size though, since we are not doing an access yet, but to -the size of the resulting section. This ensures that subsequent accesses -to the cached MemoryRegionSection will be in range. - -With this patch, the enclosed testcase notices that the used ring does -not fit into the MSI-X table and prints a "qemu-system-x86_64: Cannot map used" -error. - -Signed-off-by: Paolo Bonzini -(cherry-picked from 4bfb024b) -Fix CVE-2020-27821 -Signed-off-by: Alex Chen ---- - exec.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/exec.c b/exec.c -index 85c6d80353..8822c241d8 100644 ---- a/exec.c -+++ b/exec.c -@@ -3834,6 +3834,7 @@ int64_t address_space_cache_init(MemoryRegionCache *cache, - AddressSpaceDispatch *d; - hwaddr l; - MemoryRegion *mr; -+ Int128 diff; - - assert(len > 0); - -@@ -3842,6 +3843,16 @@ int64_t address_space_cache_init(MemoryRegionCache *cache, - d = flatview_to_dispatch(cache->fv); - cache->mrs = *address_space_translate_internal(d, addr, &cache->xlat, &l, true); - -+ /* -+ * cache->xlat is now relative to cache->mrs.mr, not to the section itself. -+ * Take that into account to compute how many bytes are there between -+ * cache->xlat and the end of the section. -+ */ -+ -+ diff = int128_sub(cache->mrs.size, -+ int128_make64(cache->xlat - cache->mrs.offset_within_region)); -+ l = int128_get64(int128_min(diff, int128_make64(l))); -+ - mr = cache->mrs.mr; - memory_region_ref(mr); - if (memory_access_is_direct(mr, is_write)) { --- -2.27.0 - diff --git a/microblaze-fix-leak-of-fdevice-tree-blob.patch b/microblaze-fix-leak-of-fdevice-tree-blob.patch deleted file mode 100644 index dd845e80cef5f3315e44417f3b7eeaa60ce6b8bb..0000000000000000000000000000000000000000 --- a/microblaze-fix-leak-of-fdevice-tree-blob.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 2ff9c28e2b72cd359a0c4e931412e355baee8e1e Mon Sep 17 00:00:00 2001 -From: lizhengui -Date: Wed, 9 Sep 2020 14:55:11 +0800 -Subject: [PATCH] microblaze: fix leak of fdevice tree blob -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The device tree blob returned by load_device_tree is malloced. -Free it before returning. - -Signed-off-by: Paolo Bonzini -Reviewed-by: Philippe Mathieu-Daudé ---- - hw/microblaze/boot.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c -index a7af4c07..0fcc4e9d 100644 ---- a/hw/microblaze/boot.c -+++ b/hw/microblaze/boot.c -@@ -99,6 +99,7 @@ static int microblaze_load_dtb(hwaddr addr, - } - - cpu_physical_memory_write(addr, fdt, fdt_size); -+ g_free(fdt); - return fdt_size; - } - --- -2.19.1 - diff --git a/migration-Add-compress_level-sanity-check.patch b/migration-Add-compress_level-sanity-check.patch index 8513384f438612de27e6c4508d3f38d22edcd897..0839f6a467edb5b0f9adfd457edbcf8604a4f8d3 100644 --- a/migration-Add-compress_level-sanity-check.patch +++ b/migration-Add-compress_level-sanity-check.patch @@ -1,23 +1,24 @@ -From 90c8ce0b3bcf4a3140bc4b500da9b55a694e1bde Mon Sep 17 00:00:00 2001 -From: Zeyu Jin +From 84780210ac31e430d59b0c6d3d9f522c626b6380 Mon Sep 17 00:00:00 2001 +From: Chuan Zheng Date: Sat, 30 Jan 2021 16:23:15 +0800 -Subject: [PATCH] migration: Add compress_level sanity check +Subject: [PATCH 13/14] migration: Add compress_level sanity check Zlib compression has level from 1 to 9. However Zstd compression has level from 1 to 22 (level >= 20 not recommanded). Let's do sanity check here to make sure a vaild compress_level is given by user. +Signed-off-by: Chuan Zheng Signed-off-by: Zeyu Jin Signed-off-by: Ying Fang --- - migration/migration.c | 32 ++++++++++++++++++++++++++++---- - 1 file changed, 28 insertions(+), 4 deletions(-) + migration/migration.c | 30 ++++++++++++++++++++++++++++-- + 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/migration/migration.c b/migration/migration.c -index 67425fde7a..17a5c16c79 100644 +index 07dc059251..f86dd8cccd 100644 --- a/migration/migration.c +++ b/migration/migration.c -@@ -1111,16 +1111,40 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, +@@ -1320,14 +1320,40 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, } } @@ -56,12 +57,10 @@ index 67425fde7a..17a5c16c79 100644 { - if (params->has_compress_level && - (params->compress_level > 9)) { -- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "compress_level", -- "is invalid, it should be in the range of 0 to 9"); + if (params->has_compress_level && !compress_level_check(params, errp)) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "compress_level", + "a value between 0 and 9"); return false; - } - -- 2.27.0 diff --git a/migration-Add-multi-thread-compress-method.patch b/migration-Add-multi-thread-compress-method.patch index e900a729ea9779862318e0d2c192f88d8cf81c44..b25d78785979829b5ff7c75d3cea72ee87cdbc3b 100644 --- a/migration-Add-multi-thread-compress-method.patch +++ b/migration-Add-multi-thread-compress-method.patch @@ -1,74 +1,31 @@ -From b0cabc67e16d9b4e1e749b0359dd8f3874e0968d Mon Sep 17 00:00:00 2001 -From: Zeyu Jin +From 39d851b5d5517fbcecc8d16229ae72ca152899b7 Mon Sep 17 00:00:00 2001 +From: Chuan Zheng Date: Sat, 30 Jan 2021 14:57:54 +0800 -Subject: [PATCH] migration: Add multi-thread compress method +Subject: [PATCH 09/14] migration: Add multi-thread compress method A multi-thread compress method parameter is added to hold the method we are going to use. By default the 'zlib' method is used to maintain the compatibility as before. +Signed-off-by: Chuan Zheng Signed-off-by: Zeyu Jin Signed-off-by: Ying Fang --- - hw/core/qdev-prop-internal.h | 18 ++++++++++++++++++ - hw/core/qdev-properties-system.c | 13 +++++++++++++ - hw/core/qdev-properties.c | 14 +++++++++++--- + hw/core/qdev-properties-system.c | 11 +++++++++++ include/hw/qdev-properties.h | 4 ++++ - migration/migration.c | 15 +++++++++++++++ - migration/qemu-file.c | 9 +++++++++ + migration/migration.c | 11 +++++++++++ monitor/hmp-cmds.c | 13 +++++++++++++ qapi/migration.json | 26 +++++++++++++++++++++++++- - 8 files changed, 108 insertions(+), 4 deletions(-) - create mode 100644 hw/core/qdev-prop-internal.h + 5 files changed, 64 insertions(+), 1 deletion(-) -diff --git a/hw/core/qdev-prop-internal.h b/hw/core/qdev-prop-internal.h -new file mode 100644 -index 0000000000..a4a7eaf078 ---- /dev/null -+++ b/hw/core/qdev-prop-internal.h -@@ -0,0 +1,18 @@ -+/* -+ * qdev property parsing -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#ifndef HW_CORE_QDEV_PROP_INTERNAL_H -+#define HW_CORE_QDEV_PROP_INTERNAL_H -+ -+void get_enum(Object *obj, Visitor *v, const char *name, void *opaque, -+ Error **errp); -+void set_enum(Object *obj, Visitor *v, const char *name, void *opaque, -+ Error **errp); -+ -+void set_default_value_enum(Object *obj, const Property *prop); -+ -+#endif diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c -index ba412dd2ca..67ed89b406 100644 +index a91f60567a..8c265bed6f 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c -@@ -15,6 +15,7 @@ - #include "hw/qdev.h" - #include "qapi/error.h" - #include "qapi/qmp/qerror.h" -+#include "qapi/qapi-types-migration.h" - #include "sysemu/block-backend.h" - #include "sysemu/blockdev.h" - #include "hw/block/block.h" -@@ -23,6 +24,7 @@ - #include "chardev/char-fe.h" - #include "sysemu/iothread.h" - #include "sysemu/tpm_backend.h" -+#include "qdev-prop-internal.h" - - static void get_pointer(Object *obj, Visitor *v, Property *prop, - char *(*print)(void *ptr), -@@ -399,3 +401,14 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) - } - nd->instantiated = 1; - } +@@ -1119,3 +1119,14 @@ const PropertyInfo qdev_prop_uuid = { + .set = set_uuid, + .set_default_value = set_default_uuid_auto, + }; + +/* --- CompressMethod --- */ +const PropertyInfo qdev_prop_compress_method = { @@ -76,107 +33,54 @@ index ba412dd2ca..67ed89b406 100644 + .description = "multi-thread compression method, " + "zlib", + .enum_table = &CompressMethod_lookup, -+ .get = get_enum, -+ .set = set_enum, -+ .set_default_value = set_default_value_enum, ++ .get = qdev_propinfo_get_enum, ++ .set = qdev_propinfo_set_enum, ++ .set_default_value = qdev_propinfo_set_default_value_enum, +}; -diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c -index 81c97f48a7..709f9e0f9d 100644 ---- a/hw/core/qdev-properties.c -+++ b/hw/core/qdev-properties.c -@@ -11,6 +11,7 @@ - #include "qapi/visitor.h" - #include "chardev/char.h" - #include "qemu/uuid.h" -+#include "qdev-prop-internal.h" - - void qdev_prop_set_after_realize(DeviceState *dev, const char *name, - Error **errp) -@@ -46,7 +47,7 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) - return ptr; - } - --static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque, -+void get_enum(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) - { - DeviceState *dev = DEVICE(obj); -@@ -56,7 +57,7 @@ static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque, - visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp); - } - --static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque, -+void set_enum(Object *obj, Visitor *v, const char *name, void *opaque, - Error **errp) - { - DeviceState *dev = DEVICE(obj); -@@ -71,7 +72,7 @@ static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque, - visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp); - } - --static void set_default_value_enum(Object *obj, const Property *prop) -+void set_default_value_enum(Object *obj, const Property *prop) - { - object_property_set_str(obj, - qapi_enum_lookup(prop->info->enum_table, -@@ -79,6 +80,13 @@ static void set_default_value_enum(Object *obj, const Property *prop) - prop->name, &error_abort); - } - -+const PropertyInfo qdev_prop_enum = { -+ .name = "enum", -+ .get = get_enum, -+ .set = set_enum, -+ .set_default_value = set_default_value_enum, -+}; -+ - /* Bit */ - - static uint32_t qdev_get_prop_mask(Property *prop) diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h -index 1eae5ab056..a22a532eb8 100644 +index f7925f67d0..ea129d65a6 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h -@@ -23,6 +23,7 @@ extern const PropertyInfo qdev_prop_tpm; - extern const PropertyInfo qdev_prop_ptr; - extern const PropertyInfo qdev_prop_macaddr; +@@ -58,6 +58,7 @@ extern const PropertyInfo qdev_prop_int64; + extern const PropertyInfo qdev_prop_size; + extern const PropertyInfo qdev_prop_string; extern const PropertyInfo qdev_prop_on_off_auto; +extern const PropertyInfo qdev_prop_compress_method; - extern const PropertyInfo qdev_prop_losttickpolicy; - extern const PropertyInfo qdev_prop_blockdev_on_error; - extern const PropertyInfo qdev_prop_bios_chs_trans; -@@ -205,6 +206,9 @@ extern const PropertyInfo qdev_prop_pcie_link_width; - DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr) + extern const PropertyInfo qdev_prop_size32; + extern const PropertyInfo qdev_prop_arraylen; + extern const PropertyInfo qdev_prop_link; +@@ -161,6 +162,9 @@ extern const PropertyInfo qdev_prop_link; + DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*) #define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_on_off_auto, OnOffAuto) +#define DEFINE_PROP_COMPRESS_METHOD(_n, _s, _f, _d) \ + DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_compress_method, \ + CompressMethod) - #define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \ - DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_losttickpolicy, \ - LostTickPolicy) + #define DEFINE_PROP_SIZE32(_n, _s, _f, _d) \ + DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_size32, uint32_t) + diff --git a/migration/migration.c b/migration/migration.c -index 0e396f22b4..c79bf09269 100644 +index abaf6f9e3d..fa3db87d75 100644 --- a/migration/migration.c +++ b/migration/migration.c -@@ -71,6 +71,7 @@ +@@ -83,6 +83,7 @@ #define DEFAULT_MIGRATE_DECOMPRESS_THREAD_COUNT 2 /*0: means nocompress, 1: best speed, ... 9: best compress ratio */ #define DEFAULT_MIGRATE_COMPRESS_LEVEL 1 +#define DEFAULT_MIGRATE_COMPRESS_METHOD COMPRESS_METHOD_ZLIB /* Define default autoconverge cpu throttle migration parameters */ + #define DEFAULT_MIGRATE_THROTTLE_TRIGGER_THRESHOLD 50 #define DEFAULT_MIGRATE_CPU_THROTTLE_INITIAL 20 - #define DEFAULT_MIGRATE_CPU_THROTTLE_INCREMENT 10 -@@ -748,6 +749,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) +@@ -855,6 +856,8 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) params->compress_wait_thread = s->parameters.compress_wait_thread; params->has_decompress_threads = true; params->decompress_threads = s->parameters.decompress_threads; + params->has_compress_method = true; + params->compress_method = s->parameters.compress_method; + params->has_throttle_trigger_threshold = true; + params->throttle_trigger_threshold = s->parameters.throttle_trigger_threshold; params->has_cpu_throttle_initial = true; - params->cpu_throttle_initial = s->parameters.cpu_throttle_initial; - params->has_cpu_throttle_increment = true; -@@ -1250,6 +1253,10 @@ static void migrate_params_test_apply(MigrateSetParameters *params, +@@ -1491,6 +1494,10 @@ static void migrate_params_test_apply(MigrateSetParameters *params, dest->decompress_threads = params->decompress_threads; } @@ -184,81 +88,50 @@ index 0e396f22b4..c79bf09269 100644 + dest->compress_method = params->compress_method; + } + - if (params->has_cpu_throttle_initial) { - dest->cpu_throttle_initial = params->cpu_throttle_initial; + if (params->has_throttle_trigger_threshold) { + dest->throttle_trigger_threshold = params->throttle_trigger_threshold; } -@@ -1331,6 +1338,10 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp) - s->parameters.decompress_threads = params->decompress_threads; - } - -+ if (params->has_compress_method) { -+ s->parameters.compress_method = params->compress_method; -+ } -+ - if (params->has_cpu_throttle_initial) { - s->parameters.cpu_throttle_initial = params->cpu_throttle_initial; - } -@@ -3436,6 +3447,9 @@ static Property migration_properties[] = { +@@ -4159,6 +4166,9 @@ static Property migration_properties[] = { DEFINE_PROP_UINT8("x-decompress-threads", MigrationState, parameters.decompress_threads, DEFAULT_MIGRATE_DECOMPRESS_THREAD_COUNT), + DEFINE_PROP_COMPRESS_METHOD("compress-method", MigrationState, + parameters.compress_method, + DEFAULT_MIGRATE_COMPRESS_METHOD), - DEFINE_PROP_UINT8("x-cpu-throttle-initial", MigrationState, - parameters.cpu_throttle_initial, - DEFAULT_MIGRATE_CPU_THROTTLE_INITIAL), -@@ -3535,6 +3549,7 @@ static void migration_instance_init(Object *obj) + DEFINE_PROP_UINT8("x-throttle-trigger-threshold", MigrationState, + parameters.throttle_trigger_threshold, + DEFAULT_MIGRATE_THROTTLE_TRIGGER_THRESHOLD), +@@ -4275,6 +4285,7 @@ static void migration_instance_init(Object *obj) params->has_compress_level = true; params->has_compress_threads = true; params->has_decompress_threads = true; + params->has_compress_method = true; + params->has_throttle_trigger_threshold = true; params->has_cpu_throttle_initial = true; params->has_cpu_throttle_increment = true; - params->has_max_bandwidth = true; -diff --git a/migration/qemu-file.c b/migration/qemu-file.c -index cd96d04e9a..be0d6c8ca8 100644 ---- a/migration/qemu-file.c -+++ b/migration/qemu-file.c -@@ -382,6 +382,15 @@ static void add_to_iovec(QEMUFile *f, const uint8_t *buf, size_t size, - } - } - -+static void add_buf_to_iovec(QEMUFile *f, size_t len) -+{ -+ add_to_iovec(f, f->buf + f->buf_index, len, false); -+ f->buf_index += len; -+ if (f->buf_index == IO_BUF_SIZE) { -+ qemu_fflush(f); -+ } -+} -+ - void qemu_put_buffer_async(QEMUFile *f, const uint8_t *buf, size_t size, - bool may_free) - { diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c -index fc5d6b92c4..e5a7a88ba2 100644 +index 9c91bf93e9..294652034e 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c -@@ -41,6 +41,7 @@ - #include "qapi/qapi-commands-tpm.h" - #include "qapi/qapi-commands-ui.h" +@@ -45,6 +45,7 @@ #include "qapi/qapi-visit-net.h" -+#include "qapi/qapi-visit-migration.h" + #include "qapi/qapi-visit-migration.h" #include "qapi/qmp/qdict.h" ++#include "qapi/qapi-visit-migration.h" #include "qapi/qmp/qerror.h" #include "qapi/string-input-visitor.h" -@@ -426,6 +427,9 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) + #include "qapi/string-output-visitor.h" +@@ -429,6 +430,9 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) MigrationParameter_str(MIGRATION_PARAMETER_DECOMPRESS_THREADS), params->decompress_threads); - assert(params->has_cpu_throttle_initial); + assert(params->has_throttle_trigger_threshold); + monitor_printf(mon, "%s: %s\n", + MigrationParameter_str(MIGRATION_PARAMETER_COMPRESS_METHOD), + CompressMethod_str(params->compress_method)); monitor_printf(mon, "%s: %u\n", - MigrationParameter_str(MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL), - params->cpu_throttle_initial); -@@ -1756,6 +1760,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) + MigrationParameter_str(MIGRATION_PARAMETER_THROTTLE_TRIGGER_THRESHOLD), + params->throttle_trigger_threshold); +@@ -1191,6 +1195,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) MigrateSetParameters *p = g_new0(MigrateSetParameters, 1); uint64_t valuebw = 0; uint64_t cache_size; @@ -266,9 +139,9 @@ index fc5d6b92c4..e5a7a88ba2 100644 Error *err = NULL; int val, ret; -@@ -1781,6 +1786,14 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) +@@ -1216,6 +1221,14 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) p->has_decompress_threads = true; - visit_type_int(v, param, &p->decompress_threads, &err); + visit_type_uint8(v, param, &p->decompress_threads, &err); break; + case MIGRATION_PARAMETER_COMPRESS_METHOD: + p->has_compress_method = true; @@ -278,16 +151,16 @@ index fc5d6b92c4..e5a7a88ba2 100644 + } + p->compress_method = compress_method; + break; - case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL: - p->has_cpu_throttle_initial = true; - visit_type_int(v, param, &p->cpu_throttle_initial, &err); + case MIGRATION_PARAMETER_THROTTLE_TRIGGER_THRESHOLD: + p->has_throttle_trigger_threshold = true; + visit_type_uint8(v, param, &p->throttle_trigger_threshold, &err); diff --git a/qapi/migration.json b/qapi/migration.json -index 6844ddfab3..b0e8c493ee 100644 +index bbfd48cf0b..3a76907ea9 100644 --- a/qapi/migration.json +++ b/qapi/migration.json -@@ -482,6 +482,19 @@ - ## - { 'command': 'query-migrate-capabilities', 'returns': ['MigrationCapabilityStatus']} +@@ -596,6 +596,19 @@ + 'bitmaps': [ 'BitmapMigrationBitmapAlias' ] + } } +## +# @CompressMethod: @@ -305,61 +178,61 @@ index 6844ddfab3..b0e8c493ee 100644 ## # @MigrationParameter: # -@@ -518,6 +531,9 @@ - # compression, so set the decompress-threads to the number about 1/4 - # of compress-threads is adequate. +@@ -632,6 +645,9 @@ + # compression, so set the decompress-threads to the number about 1/4 + # of compress-threads is adequate. # +# @compress-method: Which multi-thread compression method to use. +# Defaults to none. (Since 5.0) +# - # @cpu-throttle-initial: Initial percentage of time guest cpus are throttled - # when migration auto-converge is activated. The - # default value is 20. (Since 2.7) -@@ -586,7 +602,7 @@ + # @throttle-trigger-threshold: The ratio of bytes_dirty_period and bytes_xfer_period + # to trigger throttling. It is expressed as percentage. + # The default value is 50. (Since 5.0) +@@ -758,7 +774,7 @@ 'data': ['announce-initial', 'announce-max', 'announce-rounds', 'announce-step', 'compress-level', 'compress-threads', 'decompress-threads', -- 'compress-wait-thread', -+ 'compress-wait-thread', 'compress-method', +- 'compress-wait-thread', 'throttle-trigger-threshold', ++ 'compress-wait-thread', 'compress-method', 'throttle-trigger-threshold', 'cpu-throttle-initial', 'cpu-throttle-increment', + 'cpu-throttle-tailslow', 'tls-creds', 'tls-hostname', 'tls-authz', 'max-bandwidth', - 'downtime-limit', 'x-checkpoint-delay', 'block-incremental', -@@ -620,6 +636,9 @@ +@@ -797,6 +813,9 @@ # # @decompress-threads: decompression thread count # +# @compress-method: Set compression method to use in multi-thread compression. +# Defaults to none. (Since 5.0) +# - # @cpu-throttle-initial: Initial percentage of time guest cpus are - # throttled when migration auto-converge is activated. - # The default value is 20. (Since 2.7) -@@ -695,6 +714,7 @@ - '*compress-threads': 'int', + # @throttle-trigger-threshold: The ratio of bytes_dirty_period and bytes_xfer_period + # to trigger throttling. It is expressed as percentage. + # The default value is 50. (Since 5.0) +@@ -930,6 +949,7 @@ + '*compress-threads': 'uint8', '*compress-wait-thread': 'bool', - '*decompress-threads': 'int', + '*decompress-threads': 'uint8', + '*compress-method': 'CompressMethod', - '*cpu-throttle-initial': 'int', - '*cpu-throttle-increment': 'int', - '*tls-creds': 'StrOrNull', -@@ -753,6 +773,9 @@ + '*throttle-trigger-threshold': 'uint8', + '*cpu-throttle-initial': 'uint8', + '*cpu-throttle-increment': 'uint8', +@@ -995,6 +1015,9 @@ # # @decompress-threads: decompression thread count # +# @compress-method: Which multi-thread compression method to use. +# Defaults to none. (Since 5.0) +# - # @cpu-throttle-initial: Initial percentage of time guest cpus are - # throttled when migration auto-converge is activated. - # (Since 2.7) -@@ -828,6 +851,7 @@ + # @throttle-trigger-threshold: The ratio of bytes_dirty_period and bytes_xfer_period + # to trigger throttling. It is expressed as percentage. + # The default value is 50. (Since 5.0) +@@ -1128,6 +1151,7 @@ '*compress-threads': 'uint8', '*compress-wait-thread': 'bool', '*decompress-threads': 'uint8', + '*compress-method': 'CompressMethod', + '*throttle-trigger-threshold': 'uint8', '*cpu-throttle-initial': 'uint8', '*cpu-throttle-increment': 'uint8', - '*tls-creds': 'str', -- 2.27.0 diff --git a/migration-Add-multi-thread-compress-ops.patch b/migration-Add-multi-thread-compress-ops.patch index 043d9f9b3379a4664e01b9153ccc7ecf3a702c6d..6e3b6c178ae40a9b16df95dab7859a0434663d38 100644 --- a/migration-Add-multi-thread-compress-ops.patch +++ b/migration-Add-multi-thread-compress-ops.patch @@ -1,11 +1,12 @@ -From 99fddf2ffeefc99ab15b3428dbd2b46476be3e7e Mon Sep 17 00:00:00 2001 -From: Zeyu Jin +From 5e4bc7ceaf81a4932c92e479e9add947b698395b Mon Sep 17 00:00:00 2001 +From: Chuan Zheng Date: Sat, 30 Jan 2021 15:57:31 +0800 -Subject: [PATCH] migration: Add multi-thread compress ops +Subject: [PATCH 11/14] migration: Add multi-thread compress ops Add the MigrationCompressOps and MigrationDecompressOps structures to make the compression method configurable for multi-thread compression migration. +Signed-off-by: Chuan Zheng Signed-off-by: Zeyu Jin Signed-off-by: Ying Fang --- @@ -15,10 +16,10 @@ Signed-off-by: Ying Fang 3 files changed, 201 insertions(+), 78 deletions(-) diff --git a/migration/migration.c b/migration/migration.c -index c79bf09269..67425fde7a 100644 +index fa3db87d75..07dc059251 100644 --- a/migration/migration.c +++ b/migration/migration.c -@@ -2143,6 +2143,15 @@ int migrate_decompress_threads(void) +@@ -2456,6 +2456,15 @@ int migrate_decompress_threads(void) return s->parameters.decompress_threads; } @@ -35,19 +36,19 @@ index c79bf09269..67425fde7a 100644 { MigrationState *s; diff --git a/migration/migration.h b/migration/migration.h -index f2bd4ebe33..4aa72297fc 100644 +index 8130b703eb..4ed4f555da 100644 --- a/migration/migration.h +++ b/migration/migration.h -@@ -319,6 +319,7 @@ int migrate_compress_level(void); +@@ -355,6 +355,7 @@ int migrate_compress_level(void); int migrate_compress_threads(void); int migrate_compress_wait_thread(void); int migrate_decompress_threads(void); +CompressMethod migrate_compress_method(void); bool migrate_use_events(void); bool migrate_postcopy_blocktime(void); - + bool migrate_background_snapshot(void); diff --git a/migration/ram.c b/migration/ram.c -index f78a681ca2..3ed808a4ca 100644 +index 1176816fba..069560e7f9 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -417,6 +417,9 @@ struct CompressParam { @@ -288,7 +289,7 @@ index f78a681ca2..3ed808a4ca 100644 g_free(comp_param[i].originbuf); goto exit; } -@@ -2208,50 +2385,6 @@ static int ram_save_multifd_page(RAMState *rs, RAMBlock *block, +@@ -1338,50 +1515,6 @@ static int ram_save_multifd_page(RAMState *rs, RAMBlock *block, return 1; } @@ -339,7 +340,7 @@ index f78a681ca2..3ed808a4ca 100644 static bool do_compress_ram_page(CompressParam *param, RAMBlock *block) { RAMState *rs = ram_state; -@@ -2274,7 +2407,7 @@ static bool do_compress_ram_page(CompressParam *param, RAMBlock *block) +@@ -1404,7 +1537,7 @@ static bool do_compress_ram_page(CompressParam *param, RAMBlock *block) * decompression */ memcpy(param->originbuf, p, TARGET_PAGE_SIZE); @@ -348,7 +349,7 @@ index f78a681ca2..3ed808a4ca 100644 if (ret < 0) { qemu_file_set_error(migrate_get_current()->to_dst_file, ret); error_report("compressed data failed!"); -@@ -3965,32 +4098,6 @@ void ram_handle_compressed(void *host, uint8_t ch, uint64_t size) +@@ -3413,32 +3546,6 @@ void ram_handle_compressed(void *host, uint8_t ch, uint64_t size) } } @@ -381,7 +382,7 @@ index f78a681ca2..3ed808a4ca 100644 static void *do_data_decompress(void *opaque) { DecompressParam *param = opaque; -@@ -4004,7 +4111,7 @@ static void *do_data_decompress(void *opaque) +@@ -3452,7 +3559,7 @@ static void *do_data_decompress(void *opaque) param->des = 0; qemu_mutex_unlock(¶m->mutex); @@ -390,7 +391,7 @@ index f78a681ca2..3ed808a4ca 100644 if (ret < 0 && migrate_get_current()->decompress_error_check) { error_report("decompress data failed"); qemu_file_set_error(decomp_file, ret); -@@ -4074,7 +4181,7 @@ static void compress_threads_load_cleanup(void) +@@ -3522,7 +3629,7 @@ static void compress_threads_load_cleanup(void) qemu_thread_join(decompress_threads + i); qemu_mutex_destroy(&decomp_param[i].mutex); qemu_cond_destroy(&decomp_param[i].cond); @@ -399,7 +400,7 @@ index f78a681ca2..3ed808a4ca 100644 g_free(decomp_param[i].compbuf); decomp_param[i].compbuf = NULL; } -@@ -4083,6 +4190,7 @@ static void compress_threads_load_cleanup(void) +@@ -3531,6 +3638,7 @@ static void compress_threads_load_cleanup(void) decompress_threads = NULL; decomp_param = NULL; decomp_file = NULL; @@ -407,7 +408,7 @@ index f78a681ca2..3ed808a4ca 100644 } static int compress_threads_load_setup(QEMUFile *f) -@@ -4093,6 +4201,11 @@ static int compress_threads_load_setup(QEMUFile *f) +@@ -3541,6 +3649,11 @@ static int compress_threads_load_setup(QEMUFile *f) return 0; } @@ -419,7 +420,7 @@ index f78a681ca2..3ed808a4ca 100644 thread_count = migrate_decompress_threads(); decompress_threads = g_new0(QemuThread, thread_count); decomp_param = g_new0(DecompressParam, thread_count); -@@ -4100,7 +4213,7 @@ static int compress_threads_load_setup(QEMUFile *f) +@@ -3548,7 +3661,7 @@ static int compress_threads_load_setup(QEMUFile *f) qemu_cond_init(&decomp_done_cond); decomp_file = f; for (i = 0; i < thread_count; i++) { @@ -428,7 +429,7 @@ index f78a681ca2..3ed808a4ca 100644 goto exit; } -@@ -4642,7 +4755,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) +@@ -4156,7 +4269,7 @@ static int ram_load_precopy(QEMUFile *f) case RAM_SAVE_FLAG_COMPRESS_PAGE: len = qemu_get_be32(f); diff --git a/migration-Add-zstd-support-in-multi-thread-compressi.patch b/migration-Add-zstd-support-in-multi-thread-compressi.patch index a84bb368ebe5a81e223c805c151ea4896ccc4e51..416e2becfe69b9f00a9fa89a0fe5f998405274df 100644 --- a/migration-Add-zstd-support-in-multi-thread-compressi.patch +++ b/migration-Add-zstd-support-in-multi-thread-compressi.patch @@ -1,47 +1,49 @@ -From 54a1b546e0bd0cc41669bf7ade806c6c777c96ad Mon Sep 17 00:00:00 2001 -From: Zeyu Jin +From bafba05f7405ba31213120d99679cc4b6c1be68e Mon Sep 17 00:00:00 2001 +From: Chuan Zheng Date: Sat, 30 Jan 2021 16:15:10 +0800 -Subject: [PATCH] migration: Add zstd support in multi-thread compression +Subject: [PATCH 12/14] migration: Add zstd support in multi-thread compression This patch enables zstd option in multi-thread compression. +Signed-off-by: Chuan Zheng Signed-off-by: Zeyu Jin Signed-off-by: Ying Fang --- hw/core/qdev-properties-system.c | 2 +- - migration/ram.c | 130 ++++++++++++++++++++++++++++++- - qapi/migration.json | 2 +- - 3 files changed, 130 insertions(+), 4 deletions(-) + migration/ram.c | 131 ++++++++++++++++++++++++++++++- + qapi/migration.json | 3 +- + 3 files changed, 132 insertions(+), 4 deletions(-) diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c -index 67ed89b406..6d48903c87 100644 +index 8c265bed6f..6a6ff03be7 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c -@@ -406,7 +406,7 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) +@@ -1124,7 +1124,7 @@ const PropertyInfo qdev_prop_uuid = { const PropertyInfo qdev_prop_compress_method = { .name = "CompressMethod", .description = "multi-thread compression method, " - "zlib", + "zlib/zstd", .enum_table = &CompressMethod_lookup, - .get = get_enum, - .set = set_enum, + .get = qdev_propinfo_get_enum, + .set = qdev_propinfo_set_enum, diff --git a/migration/ram.c b/migration/ram.c -index 3ed808a4ca..ba1e729c39 100644 +index 069560e7f9..c3484ee1a9 100644 --- a/migration/ram.c +++ b/migration/ram.c -@@ -59,6 +59,10 @@ - #include "savevm.h" - #include "qemu/iov.h" +@@ -62,6 +62,11 @@ + #include "qemu/userfaultfd.h" + #endif /* defined(__linux__) */ +#ifdef CONFIG_ZSTD +#include +#include +#endif ++ /***********************************************************/ /* ram save/restore */ -@@ -415,11 +419,16 @@ struct CompressParam { +@@ -415,11 +420,16 @@ struct CompressParam { ram_addr_t offset; /* internally used fields */ @@ -59,7 +61,7 @@ index 3ed808a4ca..ba1e729c39 100644 }; typedef struct CompressParam CompressParam; -@@ -434,6 +443,11 @@ struct DecompressParam { +@@ -434,6 +444,11 @@ struct DecompressParam { /* for zlib compression */ z_stream stream; @@ -71,7 +73,7 @@ index 3ed808a4ca..ba1e729c39 100644 }; typedef struct DecompressParam DecompressParam; -@@ -482,7 +496,7 @@ static int zlib_save_setup(CompressParam *param) +@@ -482,7 +497,7 @@ static int zlib_save_setup(CompressParam *param) } static ssize_t zlib_compress_data(CompressParam *param, size_t size) @@ -80,7 +82,7 @@ index 3ed808a4ca..ba1e729c39 100644 int err; uint8_t *dest = NULL; z_stream *stream = ¶m->stream; -@@ -567,6 +581,103 @@ static int zlib_check_len(int len) +@@ -567,6 +582,103 @@ static int zlib_check_len(int len) return len < 0 || len > compressBound(TARGET_PAGE_SIZE); } @@ -184,7 +186,7 @@ index 3ed808a4ca..ba1e729c39 100644 static int set_compress_ops(void) { compress_ops = g_new0(MigrationCompressOps, 1); -@@ -577,6 +688,13 @@ static int set_compress_ops(void) +@@ -577,6 +689,13 @@ static int set_compress_ops(void) compress_ops->save_cleanup = zlib_save_cleanup; compress_ops->compress_data = zlib_compress_data; break; @@ -198,7 +200,7 @@ index 3ed808a4ca..ba1e729c39 100644 default: return -1; } -@@ -595,6 +713,14 @@ static int set_decompress_ops(void) +@@ -595,6 +714,14 @@ static int set_decompress_ops(void) decompress_ops->decompress_data = zlib_decompress_data; decompress_ops->check_len = zlib_check_len; break; @@ -214,15 +216,21 @@ index 3ed808a4ca..ba1e729c39 100644 return -1; } diff --git a/qapi/migration.json b/qapi/migration.json -index b0e8c493ee..587ef65872 100644 +index 3a76907ea9..d4ebc5f028 100644 --- a/qapi/migration.json +++ b/qapi/migration.json -@@ -493,7 +493,7 @@ +@@ -602,12 +602,13 @@ + # An enumeration of multi-thread compression methods. + # + # @zlib: use zlib compression method. ++# @zstd: use zstd compression method. + # + # Since: 5.0 # ## { 'enum': 'CompressMethod', - 'data': [ 'zlib' ] } -+ 'data': [ 'zlib', { 'name': 'zstd', 'if': 'defined(CONFIG_ZSTD)' } ] } ++ 'data': [ 'zlib', { 'name': 'zstd', 'if': 'CONFIG_ZSTD' } ] } ## # @MigrationParameter: diff --git a/migration-Change-SaveStateEntry.instance_id-into-uin.patch b/migration-Change-SaveStateEntry.instance_id-into-uin.patch deleted file mode 100644 index 3eb83b3996ccd7b934d7ca5c65800ead9c0ae3bd..0000000000000000000000000000000000000000 --- a/migration-Change-SaveStateEntry.instance_id-into-uin.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 2eadc5c611ca8cc916f74c0f393f1fd942903ef7 Mon Sep 17 00:00:00 2001 -From: Peter Xu -Date: Wed, 16 Oct 2019 10:29:31 +0800 -Subject: [PATCH 6/8] migration: Change SaveStateEntry.instance_id into - uint32_t - -It was always used as 32bit, so define it as used to be clear. -Instead of using -1 as the auto-gen magic value, we switch to -UINT32_MAX. We also make sure that we don't auto-gen this value to -avoid overflowed instance IDs without being noticed. - -Suggested-by: Juan Quintela -Signed-off-by: Peter Xu -Reviewed-by: Juan Quintela -Signed-off-by: Juan Quintela ---- - hw/intc/apic_common.c | 2 +- - include/migration/register.h | 2 +- - include/migration/vmstate.h | 2 +- - migration/savevm.c | 18 ++++++++++-------- - stubs/vmstate.c | 2 +- - 5 files changed, 14 insertions(+), 12 deletions(-) - -diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c -index faea1af..07adba0 100644 ---- a/hw/intc/apic_common.c -+++ b/hw/intc/apic_common.c -@@ -313,7 +313,7 @@ static void apic_common_realize(DeviceState *dev, Error **errp) - APICCommonState *s = APIC_COMMON(dev); - APICCommonClass *info; - static DeviceState *vapic; -- int instance_id = s->id; -+ uint32_t instance_id = s->id; - - info = APIC_COMMON_GET_CLASS(s); - info->realize(dev, errp); -diff --git a/include/migration/register.h b/include/migration/register.h -index 3d0b983..8b2bc5b 100644 ---- a/include/migration/register.h -+++ b/include/migration/register.h -@@ -70,7 +70,7 @@ typedef struct SaveVMHandlers { - - int register_savevm_live(DeviceState *dev, - const char *idstr, -- int instance_id, -+ uint32_t instance_id, - int version_id, - const SaveVMHandlers *ops, - void *opaque); -diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h -index 92f531a..8abd2e3 100644 ---- a/include/migration/vmstate.h -+++ b/include/migration/vmstate.h -@@ -1117,7 +1117,7 @@ bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque); - #define VMSTATE_INSTANCE_ID_ANY -1 - - /* Returns: 0 on success, -1 on failure */ --int vmstate_register_with_alias_id(DeviceState *dev, int instance_id, -+int vmstate_register_with_alias_id(DeviceState *dev, uint32_t instance_id, - const VMStateDescription *vmsd, - void *base, int alias_id, - int required_for_version, -diff --git a/migration/savevm.c b/migration/savevm.c -index 62552ab..7d89c57 100644 ---- a/migration/savevm.c -+++ b/migration/savevm.c -@@ -229,7 +229,7 @@ typedef struct CompatEntry { - typedef struct SaveStateEntry { - QTAILQ_ENTRY(SaveStateEntry) entry; - char idstr[256]; -- int instance_id; -+ uint32_t instance_id; - int alias_id; - int version_id; - /* version id read from the stream */ -@@ -616,10 +616,10 @@ void dump_vmstate_json_to_file(FILE *out_file) - fclose(out_file); - } - --static int calculate_new_instance_id(const char *idstr) -+static uint32_t calculate_new_instance_id(const char *idstr) - { - SaveStateEntry *se; -- int instance_id = 0; -+ uint32_t instance_id = 0; - - QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { - if (strcmp(idstr, se->idstr) == 0 -@@ -627,6 +627,8 @@ static int calculate_new_instance_id(const char *idstr) - instance_id = se->instance_id + 1; - } - } -+ /* Make sure we never loop over without being noticed */ -+ assert(instance_id != VMSTATE_INSTANCE_ID_ANY); - return instance_id; - } - -@@ -682,7 +684,7 @@ static void savevm_state_handler_insert(SaveStateEntry *nse) - distinguishing id for all instances of your device class. */ - int register_savevm_live(DeviceState *dev, - const char *idstr, -- int instance_id, -+ uint32_t instance_id, - int version_id, - const SaveVMHandlers *ops, - void *opaque) -@@ -756,7 +758,7 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque) - } - } - --int vmstate_register_with_alias_id(DeviceState *dev, int instance_id, -+int vmstate_register_with_alias_id(DeviceState *dev, uint32_t instance_id, - const VMStateDescription *vmsd, - void *opaque, int alias_id, - int required_for_version, -@@ -1507,7 +1509,7 @@ int qemu_save_device_state(QEMUFile *f) - return qemu_file_get_error(f); - } - --static SaveStateEntry *find_se(const char *idstr, int instance_id) -+static SaveStateEntry *find_se(const char *idstr, uint32_t instance_id) - { - SaveStateEntry *se; - -@@ -2187,7 +2189,7 @@ qemu_loadvm_section_start_full(QEMUFile *f, MigrationIncomingState *mis) - /* Find savevm section */ - se = find_se(idstr, instance_id); - if (se == NULL) { -- error_report("Unknown savevm section or instance '%s' %d. " -+ error_report("Unknown savevm section or instance '%s' %"PRIu32". " - "Make sure that your current VM setup matches your " - "saved VM setup, including any hotplugged devices", - idstr, instance_id); -@@ -2211,7 +2213,7 @@ qemu_loadvm_section_start_full(QEMUFile *f, MigrationIncomingState *mis) - - ret = vmstate_load(f, se); - if (ret < 0) { -- error_report("error while loading state for instance 0x%x of" -+ error_report("error while loading state for instance 0x%"PRIx32" of" - " device '%s'", instance_id, idstr); - return ret; - } -diff --git a/stubs/vmstate.c b/stubs/vmstate.c -index e1e89b8..4ed5cc6 100644 ---- a/stubs/vmstate.c -+++ b/stubs/vmstate.c -@@ -4,7 +4,7 @@ - const VMStateDescription vmstate_dummy = {}; - - int vmstate_register_with_alias_id(DeviceState *dev, -- int instance_id, -+ uint32_t instance_id, - const VMStateDescription *vmsd, - void *base, int alias_id, - int required_for_version, --- -1.8.3.1 - diff --git a/migration-Compat-virtual-timer-adjust-for-v4.0.1-and.patch b/migration-Compat-virtual-timer-adjust-for-v4.0.1-and.patch deleted file mode 100644 index 79548949d7f449db1c57df2b747e347d7b220db5..0000000000000000000000000000000000000000 --- a/migration-Compat-virtual-timer-adjust-for-v4.0.1-and.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 79d722679731233ccb1aa775d896a4bf21e13d44 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 27 May 2020 10:02:06 +0800 -Subject: [PATCH] migration: Compat virtual timer adjust for v4.0.1 and v4.1.0 - -Vtimer adjust is used in openEuler qemu-4.0.1, however kvm_adjvtime -is introduced in openEuler qemu-4.1.0. To maintain the compatibility -and enable cross version migration, let's enable vtimer adjust only -if kvm_adjvtime is not enabled, otherwise there may be conflicts -between vtimer adjust and kvm_adjvtime. - -After this modification: -1: openEuler qemu-4.0.1 use vtimer as the default virtual timer -2: openEuler qemu-4.1.0 use kvm_adjvtime as the defaut virtual timer - -Migration from openEuler qemu-4.0.1 to openEuler qemu-4.1.0 will -be ok, but migration path from upstream qemu-4.0.1 to openEuler -qemu-4..0.1 will be broken. - -Since openEuler qemu-4.1.0, kvm_adjvtime is used as the default -virtual timer. So please upgrade to openEuler qemu-4.1.0 and -use the virt-4.1 machine. - -Signed-off-by: Ying Fang - -diff --git a/cpus.c b/cpus.c -index b9aa51f8..6a28bdef 100644 ---- a/cpus.c -+++ b/cpus.c -@@ -1067,6 +1067,12 @@ void cpu_synchronize_all_pre_loadvm(void) - } - - #ifdef __aarch64__ -+static bool kvm_adjvtime_enabled(CPUState *cs) -+{ -+ ARMCPU *cpu = ARM_CPU(cs); -+ return cpu->kvm_adjvtime == true; -+} -+ - static void get_vcpu_timer_tick(CPUState *cs) - { - CPUARMState *env = &ARM_CPU(cs)->env; -@@ -1096,7 +1102,13 @@ static int do_vm_stop(RunState state, bool send_stop) - cpu_disable_ticks(); - pause_all_vcpus(); - #ifdef __aarch64__ -- if (first_cpu) { -+ /* vtimer adjust is used in openEuler qemu-4.0.1, however kvm_adjvtime -+ * is introduced in openEuler qemu-4.1.0. To maintain the compatibility -+ * and enable cross version migration, let's enable vtimer adjust only -+ * if kvm_adjvtime is not enabled, otherwise there may be conflicts -+ * between vtimer adjust and kvm_adjvtime. -+ */ -+ if (first_cpu && !kvm_adjvtime_enabled(first_cpu)) { - get_vcpu_timer_tick(first_cpu); - } - #endif -@@ -1946,6 +1958,7 @@ void cpu_resume(CPUState *cpu) - } - - #ifdef __aarch64__ -+ - static void set_vcpu_timer_tick(CPUState *cs) - { - CPUARMState *env = &ARM_CPU(cs)->env; -@@ -1977,7 +1990,10 @@ void resume_all_vcpus(void) - - qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true); - #ifdef __aarch64__ -- if (first_cpu) { -+ /* Enable vtimer adjust only if kvm_adjvtime is not enabled, otherwise -+ * there may be conflicts between vtimer adjust and kvm_adjvtime. -+ */ -+ if (first_cpu && !kvm_adjvtime_enabled(first_cpu)) { - set_vcpu_timer_tick(first_cpu); - } - #endif --- -2.23.0 - diff --git a/migration-Count-new_dirty-instead-of-real_dirty.patch b/migration-Count-new_dirty-instead-of-real_dirty.patch deleted file mode 100644 index a9ff297ffac9fb42ce63ef8a256e648adf1166dd..0000000000000000000000000000000000000000 --- a/migration-Count-new_dirty-instead-of-real_dirty.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 63320ae36834e4ff2f0d139f205c464caa3887b4 Mon Sep 17 00:00:00 2001 -From: Keqian Zhu -Date: Mon, 22 Jun 2020 11:20:37 +0800 -Subject: [PATCH 04/11] migration: Count new_dirty instead of real_dirty - -real_dirty_pages becomes equal to total ram size after dirty log sync -in ram_init_bitmaps, the reason is that the bitmap of ramblock is -initialized to be all set, so old path counts them as "real dirty" at -beginning. - -This causes wrong dirty rate and false positive throttling. - -Signed-off-by: Keqian Zhu -Message-Id: <20200622032037.31112-1-zhukeqian1@huawei.com> -Reviewed-by: Dr. David Alan Gilbert -Signed-off-by: Dr. David Alan Gilbert -Signed-off-by: BiaoXiang Ye ---- - include/exec/ram_addr.h | 5 +---- - migration/ram.c | 8 +++++--- - 2 files changed, 6 insertions(+), 7 deletions(-) - -diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h -index b7b2e60f..52344066 100644 ---- a/include/exec/ram_addr.h -+++ b/include/exec/ram_addr.h -@@ -485,8 +485,7 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, - static inline - uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb, - ram_addr_t start, -- ram_addr_t length, -- uint64_t *real_dirty_pages) -+ ram_addr_t length) - { - ram_addr_t addr; - unsigned long word = BIT_WORD((start + rb->offset) >> TARGET_PAGE_BITS); -@@ -512,7 +511,6 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb, - if (src[idx][offset]) { - unsigned long bits = atomic_xchg(&src[idx][offset], 0); - unsigned long new_dirty; -- *real_dirty_pages += ctpopl(bits); - new_dirty = ~dest[k]; - dest[k] |= bits; - new_dirty &= bits; -@@ -545,7 +543,6 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(RAMBlock *rb, - start + addr + offset, - TARGET_PAGE_SIZE, - DIRTY_MEMORY_MIGRATION)) { -- *real_dirty_pages += 1; - long k = (start + addr) >> TARGET_PAGE_BITS; - if (!test_and_set_bit(k, dest)) { - num_dirty++; -diff --git a/migration/ram.c b/migration/ram.c -index 840e3548..83cabec6 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1765,9 +1765,11 @@ static inline bool migration_bitmap_clear_dirty(RAMState *rs, - static void migration_bitmap_sync_range(RAMState *rs, RAMBlock *rb, - ram_addr_t length) - { -- rs->migration_dirty_pages += -- cpu_physical_memory_sync_dirty_bitmap(rb, 0, length, -- &rs->num_dirty_pages_period); -+ uint64_t new_dirty_pages = -+ cpu_physical_memory_sync_dirty_bitmap(rb, 0, rb->used_length); -+ -+ rs->migration_dirty_pages += new_dirty_pages; -+ rs->num_dirty_pages_period += new_dirty_pages; - } - - /** --- -2.27.0.dirty - diff --git a/migration-Create-migration_is_running.patch b/migration-Create-migration_is_running.patch deleted file mode 100644 index 86f0e6d3db2a2a51c25ebe9d6f0f4d6c48dc2de0..0000000000000000000000000000000000000000 --- a/migration-Create-migration_is_running.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 3d75adce1b9b465c45a9e841d285b3524e19cd7d Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 2 Dec 2020 14:39:46 +0800 -Subject: [PATCH] migration: Create migration_is_running() - -This function returns true if we are in the middle of a migration. -It is like migration_is_setup_or_active() with CANCELLING and COLO. -Adapt all callers that are needed. - -Signed-off-by: Juan Quintela -Reviewed-by: Dr. David Alan Gilbert ---- - migration/migration.c | 28 +++++++++++++++++++++++----- - migration/migration.h | 1 + - migration/savevm.c | 4 +--- - 3 files changed, 25 insertions(+), 8 deletions(-) - -diff --git a/migration/migration.c b/migration/migration.c -index 993d77b7d6..923a1d9d3f 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -822,6 +822,26 @@ bool migration_is_setup_or_active(int state) - } - } - -+bool migration_is_running(int state) -+{ -+ switch (state) { -+ case MIGRATION_STATUS_ACTIVE: -+ case MIGRATION_STATUS_POSTCOPY_ACTIVE: -+ case MIGRATION_STATUS_POSTCOPY_PAUSED: -+ case MIGRATION_STATUS_POSTCOPY_RECOVER: -+ case MIGRATION_STATUS_SETUP: -+ case MIGRATION_STATUS_PRE_SWITCHOVER: -+ case MIGRATION_STATUS_DEVICE: -+ case MIGRATION_STATUS_CANCELLING: -+ case MIGRATION_STATUS_COLO: -+ return true; -+ -+ default: -+ return false; -+ -+ } -+} -+ - static void populate_ram_info(MigrationInfo *info, MigrationState *s) - { - info->has_ram = true; -@@ -1074,7 +1094,7 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, - MigrationCapabilityStatusList *cap; - bool cap_list[MIGRATION_CAPABILITY__MAX]; - -- if (migration_is_setup_or_active(s->state)) { -+ if (migration_is_running(s->state)) { - error_setg(errp, QERR_MIGRATION_ACTIVE); - return; - } -@@ -1588,7 +1608,7 @@ static void migrate_fd_cancel(MigrationState *s) - - do { - old_state = s->state; -- if (!migration_is_setup_or_active(old_state)) { -+ if (!migration_is_running(old_state)) { - break; - } - /* If the migration is paused, kick it out of the pause */ -@@ -1873,9 +1893,7 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc, - return true; - } - -- if (migration_is_setup_or_active(s->state) || -- s->state == MIGRATION_STATUS_CANCELLING || -- s->state == MIGRATION_STATUS_COLO) { -+ if (migration_is_running(s->state)) { - error_setg(errp, QERR_MIGRATION_ACTIVE); - return false; - } -diff --git a/migration/migration.h b/migration/migration.h -index e5aaf2ef70..f2bd4ebe33 100644 ---- a/migration/migration.h -+++ b/migration/migration.h -@@ -282,6 +282,7 @@ void migrate_fd_error(MigrationState *s, const Error *error); - void migrate_fd_connect(MigrationState *s, Error *error_in); - - bool migration_is_setup_or_active(int state); -+bool migration_is_running(int state); - - void migrate_init(MigrationState *s); - bool migration_is_blocked(Error **errp); -diff --git a/migration/savevm.c b/migration/savevm.c -index 8163de7f21..f0974380e5 100644 ---- a/migration/savevm.c -+++ b/migration/savevm.c -@@ -1414,9 +1414,7 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp) - MigrationState *ms = migrate_get_current(); - MigrationStatus status; - -- if (migration_is_setup_or_active(ms->state) || -- ms->state == MIGRATION_STATUS_CANCELLING || -- ms->state == MIGRATION_STATUS_COLO) { -+ if (migration_is_running(ms->state)) { - error_setg(errp, QERR_MIGRATION_ACTIVE); - return -EINVAL; - } --- -2.27.0 - diff --git a/migration-Define-VMSTATE_INSTANCE_ID_ANY.patch b/migration-Define-VMSTATE_INSTANCE_ID_ANY.patch deleted file mode 100644 index cd32b04997c14345aa7f488cd1a960a106d9aa15..0000000000000000000000000000000000000000 --- a/migration-Define-VMSTATE_INSTANCE_ID_ANY.patch +++ /dev/null @@ -1,237 +0,0 @@ -From 21e049e2941b108df45c9089cbf7539caae538e6 Mon Sep 17 00:00:00 2001 -From: Peter Xu -Date: Wed, 16 Oct 2019 10:29:30 +0800 -Subject: [PATCH 5/8] migration: Define VMSTATE_INSTANCE_ID_ANY - -Define the new macro VMSTATE_INSTANCE_ID_ANY for callers who wants to -auto-generate the vmstate instance ID. Previously it was hard coded -as -1 instead of this macro. It helps to change this default value in -the follow up patches. No functional change. - -Signed-off-by: Peter Xu -Reviewed-by: Juan Quintela -Signed-off-by: Juan Quintela ---- - hw/arm/stellaris.c | 2 +- - hw/core/qdev.c | 4 +++- - hw/display/ads7846.c | 2 +- - hw/i2c/core.c | 2 +- - hw/input/stellaris_input.c | 3 ++- - hw/intc/apic_common.c | 2 +- - hw/misc/max111x.c | 3 ++- - hw/net/eepro100.c | 3 ++- - hw/pci/pci.c | 2 +- - hw/ppc/spapr.c | 2 +- - hw/timer/arm_timer.c | 2 +- - hw/tpm/tpm_emulator.c | 3 ++- - include/migration/vmstate.h | 2 ++ - migration/savevm.c | 8 ++++---- - 14 files changed, 24 insertions(+), 16 deletions(-) - -diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c -index 499035f..3432033 100644 ---- a/hw/arm/stellaris.c -+++ b/hw/arm/stellaris.c -@@ -705,7 +705,7 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq, - memory_region_init_io(&s->iomem, NULL, &ssys_ops, s, "ssys", 0x00001000); - memory_region_add_subregion(get_system_memory(), base, &s->iomem); - ssys_reset(s); -- vmstate_register(NULL, -1, &vmstate_stellaris_sys, s); -+ vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_stellaris_sys, s); - return 0; - } - -diff --git a/hw/core/qdev.c b/hw/core/qdev.c -index 94ebc0a..4b32f2f 100644 ---- a/hw/core/qdev.c -+++ b/hw/core/qdev.c -@@ -848,7 +848,9 @@ static void device_set_realized(Object *obj, bool value, Error **errp) - dev->canonical_path = object_get_canonical_path(OBJECT(dev)); - - if (qdev_get_vmsd(dev)) { -- if (vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev, -+ if (vmstate_register_with_alias_id(dev, -+ VMSTATE_INSTANCE_ID_ANY, -+ qdev_get_vmsd(dev), dev, - dev->instance_id_alias, - dev->alias_required_for_version, - &local_err) < 0) { -diff --git a/hw/display/ads7846.c b/hw/display/ads7846.c -index 1a97e97..be1802e 100644 ---- a/hw/display/ads7846.c -+++ b/hw/display/ads7846.c -@@ -152,7 +152,7 @@ static void ads7846_realize(SSISlave *d, Error **errp) - - ads7846_int_update(s); - -- vmstate_register(NULL, -1, &vmstate_ads7846, s); -+ vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_ads7846, s); - } - - static void ads7846_class_init(ObjectClass *klass, void *data) -diff --git a/hw/i2c/core.c b/hw/i2c/core.c -index 20f36f1..186702b 100644 ---- a/hw/i2c/core.c -+++ b/hw/i2c/core.c -@@ -59,7 +59,7 @@ I2CBus *i2c_init_bus(DeviceState *parent, const char *name) - - bus = I2C_BUS(qbus_create(TYPE_I2C_BUS, parent, name)); - QLIST_INIT(&bus->current_devs); -- vmstate_register(NULL, -1, &vmstate_i2c_bus, bus); -+ vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_i2c_bus, bus); - return bus; - } - -diff --git a/hw/input/stellaris_input.c b/hw/input/stellaris_input.c -index 3a666d6..6c5b6d8 100644 ---- a/hw/input/stellaris_input.c -+++ b/hw/input/stellaris_input.c -@@ -86,5 +86,6 @@ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode) - } - s->num_buttons = n; - qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s); -- vmstate_register(NULL, -1, &vmstate_stellaris_gamepad, s); -+ vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, -+ &vmstate_stellaris_gamepad, s); - } -diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c -index e764a2b..faea1af 100644 ---- a/hw/intc/apic_common.c -+++ b/hw/intc/apic_common.c -@@ -329,7 +329,7 @@ static void apic_common_realize(DeviceState *dev, Error **errp) - } - - if (s->legacy_instance_id) { -- instance_id = -1; -+ instance_id = VMSTATE_INSTANCE_ID_ANY; - } - vmstate_register_with_alias_id(NULL, instance_id, &vmstate_apic_common, - s, -1, 0, NULL); -diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c -index d373ece..364cb01 100644 ---- a/hw/misc/max111x.c -+++ b/hw/misc/max111x.c -@@ -144,7 +144,8 @@ static int max111x_init(SSISlave *d, int inputs) - s->input[7] = 0x80; - s->com = 0; - -- vmstate_register(dev, -1, &vmstate_max111x, s); -+ vmstate_register(dev, VMSTATE_INSTANCE_ID_ANY, -+ &vmstate_max111x, s); - return 0; - } - -diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c -index 6607c91..03edd25 100644 ---- a/hw/net/eepro100.c -+++ b/hw/net/eepro100.c -@@ -1872,7 +1872,8 @@ static void e100_nic_realize(PCIDevice *pci_dev, Error **errp) - - s->vmstate = g_memdup(&vmstate_eepro100, sizeof(vmstate_eepro100)); - s->vmstate->name = qemu_get_queue(s->nic)->model; -- vmstate_register(&pci_dev->qdev, -1, s->vmstate, s); -+ vmstate_register(&pci_dev->qdev, VMSTATE_INSTANCE_ID_ANY, -+ s->vmstate, s); - } - - static void eepro100_instance_init(Object *obj) -diff --git a/hw/pci/pci.c b/hw/pci/pci.c -index 8076a80..e74143c 100644 ---- a/hw/pci/pci.c -+++ b/hw/pci/pci.c -@@ -118,7 +118,7 @@ static void pci_bus_realize(BusState *qbus, Error **errp) - bus->machine_done.notify = pcibus_machine_done; - qemu_add_machine_init_done_notifier(&bus->machine_done); - -- vmstate_register(NULL, -1, &vmstate_pcibus, bus); -+ vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_pcibus, bus); - } - - static void pcie_bus_realize(BusState *qbus, Error **errp) -diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c -index 12ed4b0..b0f37c3 100644 ---- a/hw/ppc/spapr.c -+++ b/hw/ppc/spapr.c -@@ -3069,7 +3069,7 @@ static void spapr_machine_init(MachineState *machine) - * interface, this is a legacy from the sPAPREnvironment structure - * which predated MachineState but had a similar function */ - vmstate_register(NULL, 0, &vmstate_spapr, spapr); -- register_savevm_live(NULL, "spapr/htab", -1, 1, -+ register_savevm_live(NULL, "spapr/htab", VMSTATE_INSTANCE_ID_ANY, 1, - &savevm_htab_handlers, spapr); - - qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine), -diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c -index f0a7534..1ce4e01 100644 ---- a/hw/timer/arm_timer.c -+++ b/hw/timer/arm_timer.c -@@ -172,7 +172,7 @@ static arm_timer_state *arm_timer_init(uint32_t freq) - - bh = qemu_bh_new(arm_timer_tick, s); - s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT); -- vmstate_register(NULL, -1, &vmstate_arm_timer, s); -+ vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_arm_timer, s); - return s; - } - -diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c -index 38bf5fd..836c489 100644 ---- a/hw/tpm/tpm_emulator.c -+++ b/hw/tpm/tpm_emulator.c -@@ -914,7 +914,8 @@ static void tpm_emulator_inst_init(Object *obj) - tpm_emu->cur_locty_number = ~0; - qemu_mutex_init(&tpm_emu->mutex); - -- vmstate_register(NULL, -1, &vmstate_tpm_emulator, obj); -+ vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, -+ &vmstate_tpm_emulator, obj); - } - - /* -diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h -index c2bfa7a..92f531a 100644 ---- a/include/migration/vmstate.h -+++ b/include/migration/vmstate.h -@@ -1114,6 +1114,8 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd, - - bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque); - -+#define VMSTATE_INSTANCE_ID_ANY -1 -+ - /* Returns: 0 on success, -1 on failure */ - int vmstate_register_with_alias_id(DeviceState *dev, int instance_id, - const VMStateDescription *vmsd, -diff --git a/migration/savevm.c b/migration/savevm.c -index 480c511..62552ab 100644 ---- a/migration/savevm.c -+++ b/migration/savevm.c -@@ -722,7 +722,7 @@ int register_savevm_live(DeviceState *dev, - } - pstrcat(se->idstr, sizeof(se->idstr), idstr); - -- if (instance_id == -1) { -+ if (instance_id == VMSTATE_INSTANCE_ID_ANY) { - se->instance_id = calculate_new_instance_id(se->idstr); - } else { - se->instance_id = instance_id; -@@ -789,14 +789,14 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id, - - se->compat = g_new0(CompatEntry, 1); - pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), vmsd->name); -- se->compat->instance_id = instance_id == -1 ? -+ se->compat->instance_id = instance_id == VMSTATE_INSTANCE_ID_ANY ? - calculate_compat_instance_id(vmsd->name) : instance_id; -- instance_id = -1; -+ instance_id = VMSTATE_INSTANCE_ID_ANY; - } - } - pstrcat(se->idstr, sizeof(se->idstr), vmsd->name); - -- if (instance_id == -1) { -+ if (instance_id == VMSTATE_INSTANCE_ID_ANY) { - se->instance_id = calculate_new_instance_id(se->idstr); - } else { - se->instance_id = instance_id; --- -1.8.3.1 - diff --git a/migration-Don-t-send-data-if-we-have-stopped.patch b/migration-Don-t-send-data-if-we-have-stopped.patch deleted file mode 100644 index 08d5d3bbbdd0b8a6f7d3dbc485cc3814a830e483..0000000000000000000000000000000000000000 --- a/migration-Don-t-send-data-if-we-have-stopped.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 855404b4766ddda851035587aa1b84768abbaf11 Mon Sep 17 00:00:00 2001 -From: Juan Quintela -Date: Wed, 22 Jan 2020 11:36:12 +0100 -Subject: [PATCH] migration: Don't send data if we have stopped - -If we do a cancel, we got out without one error, but we can't do the -rest of the output as in a normal situation. - -Signed-off-by: Juan Quintela -Reviewed-by: Dr. David Alan Gilbert ---- - migration/ram.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/migration/ram.c b/migration/ram.c -index b74929542d..dc9831d7f3 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -3686,7 +3686,8 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) - ram_control_after_iterate(f, RAM_CONTROL_ROUND); - - out: -- if (ret >= 0) { -+ if (ret >= 0 -+ && migration_is_setup_or_active(migrate_get_current()->state)) { - multifd_send_sync_main(rs); - qemu_put_be64(f, RAM_SAVE_FLAG_EOS); - qemu_fflush(f); --- -2.27.0 - diff --git a/migration-Make-global-sem_sync-semaphore-by-channel.patch b/migration-Make-global-sem_sync-semaphore-by-channel.patch deleted file mode 100644 index d9dbab23e4f83d88595956668c61385618864fd7..0000000000000000000000000000000000000000 --- a/migration-Make-global-sem_sync-semaphore-by-channel.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 8c3794d709eefdae777477bef7ff3511d55bf418 Mon Sep 17 00:00:00 2001 -From: Juan Quintela -Date: Wed, 14 Aug 2019 04:02:14 +0200 -Subject: [PATCH 05/10] migration: Make global sem_sync semaphore by channel - -This makes easy to debug things because when you want for all threads -to arrive at that semaphore, you know which one your are waiting for. - -Change-Id: I533af8cdc68f619b68eff8e4e573c4de371a3954 -Signed-off-by: Juan Quintela -Message-Id: <20190814020218.1868-3-quintela@redhat.com> -Reviewed-by: Dr. David Alan Gilbert -Signed-off-by: Dr. David Alan Gilbert ---- - migration/ram.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/migration/ram.c b/migration/ram.c -index c75716bb..51811c2d 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -661,6 +661,8 @@ typedef struct { - uint64_t num_packets; - /* pages sent through this channel */ - uint64_t num_pages; -+ /* syncs main thread and channels */ -+ QemuSemaphore sem_sync; - } MultiFDSendParams; - - typedef struct { -@@ -896,8 +898,6 @@ struct { - MultiFDSendParams *params; - /* array of pages to sent */ - MultiFDPages_t *pages; -- /* syncs main thread and channels */ -- QemuSemaphore sem_sync; - /* global number of generated multifd packets */ - uint64_t packet_num; - /* send channels ready */ -@@ -1037,6 +1037,7 @@ void multifd_save_cleanup(void) - p->c = NULL; - qemu_mutex_destroy(&p->mutex); - qemu_sem_destroy(&p->sem); -+ qemu_sem_destroy(&p->sem_sync); - g_free(p->name); - p->name = NULL; - multifd_pages_clear(p->pages); -@@ -1046,7 +1047,6 @@ void multifd_save_cleanup(void) - p->packet = NULL; - } - qemu_sem_destroy(&multifd_send_state->channels_ready); -- qemu_sem_destroy(&multifd_send_state->sem_sync); - g_free(multifd_send_state->params); - multifd_send_state->params = NULL; - multifd_pages_clear(multifd_send_state->pages); -@@ -1096,7 +1096,7 @@ static void multifd_send_sync_main(RAMState *rs) - MultiFDSendParams *p = &multifd_send_state->params[i]; - - trace_multifd_send_sync_main_wait(p->id); -- qemu_sem_wait(&multifd_send_state->sem_sync); -+ qemu_sem_wait(&p->sem_sync); - } - trace_multifd_send_sync_main(multifd_send_state->packet_num); - } -@@ -1156,7 +1156,7 @@ static void *multifd_send_thread(void *opaque) - qemu_mutex_unlock(&p->mutex); - - if (flags & MULTIFD_FLAG_SYNC) { -- qemu_sem_post(&multifd_send_state->sem_sync); -+ qemu_sem_post(&p->sem_sync); - } - qemu_sem_post(&multifd_send_state->channels_ready); - } else if (p->quit) { -@@ -1179,7 +1179,7 @@ out: - */ - if (ret != 0) { - if (flags & MULTIFD_FLAG_SYNC) { -- qemu_sem_post(&multifd_send_state->sem_sync); -+ qemu_sem_post(&p->sem_sync); - } - qemu_sem_post(&multifd_send_state->channels_ready); - } -@@ -1225,7 +1225,6 @@ int multifd_save_setup(void) - multifd_send_state = g_malloc0(sizeof(*multifd_send_state)); - multifd_send_state->params = g_new0(MultiFDSendParams, thread_count); - multifd_send_state->pages = multifd_pages_init(page_count); -- qemu_sem_init(&multifd_send_state->sem_sync, 0); - qemu_sem_init(&multifd_send_state->channels_ready, 0); - - for (i = 0; i < thread_count; i++) { -@@ -1233,6 +1232,7 @@ int multifd_save_setup(void) - - qemu_mutex_init(&p->mutex); - qemu_sem_init(&p->sem, 0); -+ qemu_sem_init(&p->sem_sync, 0); - p->quit = false; - p->pending_job = 0; - p->id = i; --- -2.19.1 diff --git a/migration-Make-sure-that-we-don-t-call-write-in-case.patch b/migration-Make-sure-that-we-don-t-call-write-in-case.patch deleted file mode 100644 index 73e3fe41d0ee74e22d7e5434ca89b421bbce0708..0000000000000000000000000000000000000000 --- a/migration-Make-sure-that-we-don-t-call-write-in-case.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 2898f8669445d38d4a6a8986c1e6d94381a7e869 Mon Sep 17 00:00:00 2001 -From: Juan Quintela -Date: Tue, 3 Mar 2020 14:51:35 +0000 -Subject: [PATCH] migration: Make sure that we don't call write() in case of - error - -RH-Author: Juan Quintela -Message-id: <20200303145143.149290-3-quintela@redhat.com> -Patchwork-id: 94113 -O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH v2 02/10] migration: Make sure that we don't call write() in case of error -Bugzilla: 1738451 -RH-Acked-by: Laurent Vivier -RH-Acked-by: Peter Xu -RH-Acked-by: Dr. David Alan Gilbert - -If we are exiting due to an error/finish/.... Just don't try to even -touch the channel with one IO operation. - -Signed-off-by: Juan Quintela -Reviewed-by: Dr. David Alan Gilbert -Signed-off-by: Juan Quintela -(cherry picked from commit 4d65a6216bfc44891ac298b74a6921d479805131) -Signed-off-by: Danilo C. L. de Paula ---- - migration/ram.c | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - -diff --git a/migration/ram.c b/migration/ram.c -index d4ac696899..27585a4f3e 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1195,6 +1195,12 @@ struct { - uint64_t packet_num; - /* send channels ready */ - QemuSemaphore channels_ready; -+ /* -+ * Have we already run terminate threads. There is a race when it -+ * happens that we got one error while we are exiting. -+ * We will use atomic operations. Only valid values are 0 and 1. -+ */ -+ int exiting; - } *multifd_send_state; - - /* -@@ -1223,6 +1229,10 @@ static int multifd_send_pages(RAMState *rs) - MultiFDPages_t *pages = multifd_send_state->pages; - uint64_t transferred; - -+ if (atomic_read(&multifd_send_state->exiting)) { -+ return -1; -+ } -+ - qemu_sem_wait(&multifd_send_state->channels_ready); - /* - * next_channel can remain from a previous migration that was -@@ -1308,6 +1318,16 @@ static void multifd_send_terminate_threads(Error *err) - } - } - -+ /* -+ * We don't want to exit each threads twice. Depending on where -+ * we get the error, or if there are two independent errors in two -+ * threads at the same time, we can end calling this function -+ * twice. -+ */ -+ if (atomic_xchg(&multifd_send_state->exiting, 1)) { -+ return; -+ } -+ - for (i = 0; i < migrate_multifd_channels(); i++) { - MultiFDSendParams *p = &multifd_send_state->params[i]; - -@@ -1425,6 +1445,10 @@ static void *multifd_send_thread(void *opaque) - - while (true) { - qemu_sem_wait(&p->sem); -+ -+ if (atomic_read(&multifd_send_state->exiting)) { -+ break; -+ } - qemu_mutex_lock(&p->mutex); - - if (p->pending_job) { -@@ -1655,6 +1679,7 @@ int multifd_save_setup(void) - multifd_send_state->params = g_new0(MultiFDSendParams, thread_count); - multifd_send_state->pages = multifd_pages_init(page_count); - qemu_sem_init(&multifd_send_state->channels_ready, 0); -+ atomic_set(&multifd_send_state->exiting, 0); - - for (i = 0; i < thread_count; i++) { - MultiFDSendParams *p = &multifd_send_state->params[i]; --- -2.27.0 - diff --git a/migration-Maybe-VM-is-paused-when-migration-is-cance.patch b/migration-Maybe-VM-is-paused-when-migration-is-cance.patch deleted file mode 100644 index 6c918f3c17ca619dfb88e1856d3d26625419f465..0000000000000000000000000000000000000000 --- a/migration-Maybe-VM-is-paused-when-migration-is-cance.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 5e99e1329fa52dce8ab784a960e64a3e19b429aa Mon Sep 17 00:00:00 2001 -From: Zhimin Feng -Date: Tue, 14 Jan 2020 17:43:09 +0800 -Subject: [PATCH 07/10] migration: Maybe VM is paused when migration is - cancelled - -If the migration is cancelled when it is in the completion phase, -the migration state is set to MIGRATION_STATUS_CANCELLING. -The VM maybe wait for the 'pause_sem' semaphore in migration_maybe_pause -function, so that VM always is paused. - -Change-Id: Ib2f2f42ee1edbb14da269ee19ba1fe16dd363822 -Reported-by: Euler Robot -Signed-off-by: Zhimin Feng -Reviewed-by: Juan Quintela -Signed-off-by: Juan Quintela ---- - migration/migration.c | 24 ++++++++++++++++-------- - 1 file changed, 16 insertions(+), 8 deletions(-) - -diff --git a/migration/migration.c b/migration/migration.c -index bea9b1d7..114c33a1 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -2731,14 +2731,22 @@ static int migration_maybe_pause(MigrationState *s, - /* This block intentionally left blank */ - } - -- qemu_mutex_unlock_iothread(); -- migrate_set_state(&s->state, *current_active_state, -- MIGRATION_STATUS_PRE_SWITCHOVER); -- qemu_sem_wait(&s->pause_sem); -- migrate_set_state(&s->state, MIGRATION_STATUS_PRE_SWITCHOVER, -- new_state); -- *current_active_state = new_state; -- qemu_mutex_lock_iothread(); -+ /* -+ * If the migration is cancelled when it is in the completion phase, -+ * the migration state is set to MIGRATION_STATUS_CANCELLING. -+ * So we don't need to wait a semaphore, otherwise we would always -+ * wait for the 'pause_sem' semaphore. -+ */ -+ if (s->state != MIGRATION_STATUS_CANCELLING) { -+ qemu_mutex_unlock_iothread(); -+ migrate_set_state(&s->state, *current_active_state, -+ MIGRATION_STATUS_PRE_SWITCHOVER); -+ qemu_sem_wait(&s->pause_sem); -+ migrate_set_state(&s->state, MIGRATION_STATUS_PRE_SWITCHOVER, -+ new_state); -+ *current_active_state = new_state; -+ qemu_mutex_lock_iothread(); -+ } - - return s->state == new_state ? 0 : -EINVAL; - } --- -2.19.1 diff --git a/migration-Rate-limit-inside-host-pages.patch b/migration-Rate-limit-inside-host-pages.patch deleted file mode 100644 index 17eb46f82ce18a6e2e17583ea6a77879178bc9bc..0000000000000000000000000000000000000000 --- a/migration-Rate-limit-inside-host-pages.patch +++ /dev/null @@ -1,173 +0,0 @@ -From 3e8a587b055f0e3cabf91921fca0777fe7e349f5 Mon Sep 17 00:00:00 2001 -From: Laurent Vivier -Date: Tue, 17 Mar 2020 17:05:18 +0000 -Subject: [PATCH] migration: Rate limit inside host pages - -RH-Author: Laurent Vivier -Message-id: <20200317170518.9303-1-lvivier@redhat.com> -Patchwork-id: 94374 -O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH] migration: Rate limit inside host pages -Bugzilla: 1814336 -RH-Acked-by: Peter Xu -RH-Acked-by: Juan Quintela -RH-Acked-by: Dr. David Alan Gilbert - -From: "Dr. David Alan Gilbert" - -When using hugepages, rate limiting is necessary within each huge -page, since a 1G huge page can take a significant time to send, so -you end up with bursty behaviour. - -Fixes: 4c011c37ecb3 ("postcopy: Send whole huge pages") -Reported-by: Lin Ma -Signed-off-by: Dr. David Alan Gilbert -Reviewed-by: Juan Quintela -Reviewed-by: Peter Xu -Signed-off-by: Juan Quintela -(cherry picked from commit 97e1e06780e70f6e98a0d2df881e0c0927d3aeb6) -Signed-off-by: Laurent Vivier - -BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1814336 -BRANCH: rhel-av-8.2.0 -UPSTREAM: Merged -BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=27283241 -TESTED: Tested that the migration abort doesn't trigger an error message in - the kernel logs on P9 - -Signed-off-by: Danilo C. L. de Paula ---- - migration/migration.c | 57 ++++++++++++++++++++++++------------------ - migration/migration.h | 1 + - migration/ram.c | 2 ++ - migration/trace-events | 4 +-- - 4 files changed, 37 insertions(+), 27 deletions(-) - -diff --git a/migration/migration.c b/migration/migration.c -index fd7d81d4b6..b0b9430822 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -3260,6 +3260,37 @@ void migration_consume_urgent_request(void) - qemu_sem_wait(&migrate_get_current()->rate_limit_sem); - } - -+/* Returns true if the rate limiting was broken by an urgent request */ -+bool migration_rate_limit(void) -+{ -+ int64_t now = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); -+ MigrationState *s = migrate_get_current(); -+ -+ bool urgent = false; -+ migration_update_counters(s, now); -+ if (qemu_file_rate_limit(s->to_dst_file)) { -+ /* -+ * Wait for a delay to do rate limiting OR -+ * something urgent to post the semaphore. -+ */ -+ int ms = s->iteration_start_time + BUFFER_DELAY - now; -+ trace_migration_rate_limit_pre(ms); -+ if (qemu_sem_timedwait(&s->rate_limit_sem, ms) == 0) { -+ /* -+ * We were woken by one or more urgent things but -+ * the timedwait will have consumed one of them. -+ * The service routine for the urgent wake will dec -+ * the semaphore itself for each item it consumes, -+ * so add this one we just eat back. -+ */ -+ qemu_sem_post(&s->rate_limit_sem); -+ urgent = true; -+ } -+ trace_migration_rate_limit_post(urgent); -+ } -+ return urgent; -+} -+ - /* - * Master migration thread on the source VM. - * It drives the migration and pumps the data down the outgoing channel. -@@ -3313,8 +3344,6 @@ static void *migration_thread(void *opaque) - trace_migration_thread_setup_complete(); - - while (migration_is_active(s)) { -- int64_t current_time; -- - if (urgent || !qemu_file_rate_limit(s->to_dst_file)) { - MigIterateState iter_state = migration_iteration_run(s); - if (iter_state == MIG_ITERATE_SKIP) { -@@ -3341,29 +3370,7 @@ static void *migration_thread(void *opaque) - update_iteration_initial_status(s); - } - -- current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); -- -- migration_update_counters(s, current_time); -- -- urgent = false; -- if (qemu_file_rate_limit(s->to_dst_file)) { -- /* Wait for a delay to do rate limiting OR -- * something urgent to post the semaphore. -- */ -- int ms = s->iteration_start_time + BUFFER_DELAY - current_time; -- trace_migration_thread_ratelimit_pre(ms); -- if (qemu_sem_timedwait(&s->rate_limit_sem, ms) == 0) { -- /* We were worken by one or more urgent things but -- * the timedwait will have consumed one of them. -- * The service routine for the urgent wake will dec -- * the semaphore itself for each item it consumes, -- * so add this one we just eat back. -- */ -- qemu_sem_post(&s->rate_limit_sem); -- urgent = true; -- } -- trace_migration_thread_ratelimit_post(urgent); -- } -+ urgent = migration_rate_limit(); - } - - trace_migration_thread_after_loop(); -diff --git a/migration/migration.h b/migration/migration.h -index 4aa72297fc..ff8a0bf12d 100644 ---- a/migration/migration.h -+++ b/migration/migration.h -@@ -345,6 +345,7 @@ int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque); - - void migration_make_urgent_request(void); - void migration_consume_urgent_request(void); -+bool migration_rate_limit(void); - - int migration_send_initial_packet(QIOChannel *c, uint8_t id, Error **errp); - int migration_recv_initial_packet(QIOChannel *c, Error **errp); -diff --git a/migration/ram.c b/migration/ram.c -index 27585a4f3e..d6657a8093 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -3076,6 +3076,8 @@ static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss, - } - - pss->page++; -+ /* Allow rate limiting to happen in the middle of huge pages */ -+ migration_rate_limit(); - } while ((pss->page & (pagesize_bits - 1)) && - offset_in_ramblock(pss->block, pss->page << TARGET_PAGE_BITS)); - -diff --git a/migration/trace-events b/migration/trace-events -index c0640cd424..b4d85229d9 100644 ---- a/migration/trace-events -+++ b/migration/trace-events -@@ -131,12 +131,12 @@ migrate_send_rp_recv_bitmap(char *name, int64_t size) "block '%s' size 0x%"PRIi6 - migration_completion_file_err(void) "" - migration_completion_postcopy_end(void) "" - migration_completion_postcopy_end_after_complete(void) "" -+migration_rate_limit_pre(int ms) "%d ms" -+migration_rate_limit_post(int urgent) "urgent: %d" - migration_return_path_end_before(void) "" - migration_return_path_end_after(int rp_error) "%d" - migration_thread_after_loop(void) "" - migration_thread_file_err(void) "" --migration_thread_ratelimit_pre(int ms) "%d ms" --migration_thread_ratelimit_post(int urgent) "urgent: %d" - migration_thread_setup_complete(void) "" - open_return_path_on_source(void) "" - open_return_path_on_source_continue(void) "" --- -2.27.0 - diff --git a/migration-Refactoring-multi-thread-compress-migratio.patch b/migration-Refactoring-multi-thread-compress-migratio.patch index d3ab4d0d97a8a1cf1c945a38b97b47a33277ab9b..35f697bd5b2bbe079e4fd3886365064c5b710be4 100644 --- a/migration-Refactoring-multi-thread-compress-migratio.patch +++ b/migration-Refactoring-multi-thread-compress-migratio.patch @@ -1,7 +1,7 @@ -From 524d8cee48006918cf181f2817e4ec3ce5a3bb12 Mon Sep 17 00:00:00 2001 -From: Zeyu Jin +From b871594aa1798ddcc7f5124e5b3e1c5d858c155c Mon Sep 17 00:00:00 2001 +From: Chuan Zheng Date: Sat, 30 Jan 2021 15:21:17 +0800 -Subject: [PATCH] migration: Refactoring multi-thread compress migration +Subject: [PATCH 10/14] migration: Refactoring multi-thread compress migration Code refactor for the compression procedure which includes: @@ -13,19 +13,20 @@ with qemu-file. Besides, the decompression code is located at ram.c only. Wrap the input into the param structure which already exists. This change also makes the function much more flexible for other compression methods. +Signed-off-by: Chuan Zheng Signed-off-by: Zeyu Jin Signed-off-by: Ying Fang --- - migration/qemu-file.c | 78 ++++++--------------------------------- + migration/qemu-file.c | 61 ++++++------------------------- migration/qemu-file.h | 4 +- migration/ram.c | 85 +++++++++++++++++++++++++++++++------------ - 3 files changed, 75 insertions(+), 92 deletions(-) + 3 files changed, 75 insertions(+), 75 deletions(-) diff --git a/migration/qemu-file.c b/migration/qemu-file.c -index be0d6c8ca8..3bba694ed4 100644 +index 6338d8e2ff..e07026da4f 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c -@@ -695,72 +695,6 @@ uint64_t qemu_get_be64(QEMUFile *f) +@@ -745,55 +745,6 @@ uint64_t qemu_get_be64(QEMUFile *f) return v; } @@ -56,11 +57,8 @@ index be0d6c8ca8..3bba694ed4 100644 -/* Compress size bytes of data start at p and store the compressed - * data to the buffer of f. - * -- * When f is not writable, return -1 if f has no space to save the -- * compressed data. -- * When f is wirtable and it has no space to save the compressed data, -- * do fflush first, if f still has no space to save the compressed -- * data, return -1. +- * Since the file is dummy file with empty_ops, return -1 if f has no space to +- * save the compressed data. - */ -ssize_t qemu_put_compression_data(QEMUFile *f, z_stream *stream, - const uint8_t *p, size_t size) @@ -68,14 +66,7 @@ index be0d6c8ca8..3bba694ed4 100644 - ssize_t blen = IO_BUF_SIZE - f->buf_index - sizeof(int32_t); - - if (blen < compressBound(size)) { -- if (!qemu_file_is_writable(f)) { -- return -1; -- } -- qemu_fflush(f); -- blen = IO_BUF_SIZE - sizeof(int32_t); -- if (blen < compressBound(size)) { -- return -1; -- } +- return -1; - } - - blen = qemu_compress_data(stream, f->buf + f->buf_index + sizeof(int32_t), @@ -85,22 +76,15 @@ index be0d6c8ca8..3bba694ed4 100644 - } - - qemu_put_be32(f, blen); -- if (f->ops->writev_buffer) { -- add_to_iovec(f, f->buf + f->buf_index, blen, false); -- } -- f->buf_index += blen; -- if (f->buf_index == IO_BUF_SIZE) { -- qemu_fflush(f); -- } +- add_buf_to_iovec(f, blen); - return blen + sizeof(int32_t); -} -- + /* Put the data in the buffer of f_src to the buffer of f_des, and * then reset the buf_index of f_src to 0. - */ -@@ -820,3 +754,15 @@ void qemu_file_set_blocking(QEMUFile *f, bool block) - f->ops->set_blocking(f->opaque, block); - } +@@ -866,3 +817,15 @@ QIOChannel *qemu_file_get_ioc(QEMUFile *file) + { + return file->has_ioc ? QIO_CHANNEL(file->opaque) : NULL; } + +ssize_t qemu_put_compress_start(QEMUFile *f, uint8_t **dest_ptr) @@ -115,10 +99,10 @@ index be0d6c8ca8..3bba694ed4 100644 + add_buf_to_iovec(f, v); +} diff --git a/migration/qemu-file.h b/migration/qemu-file.h -index 5de9fa2e96..6570e53e13 100644 +index 3f36d4dc8c..617a1373ad 100644 --- a/migration/qemu-file.h +++ b/migration/qemu-file.h -@@ -134,8 +134,6 @@ bool qemu_file_is_writable(QEMUFile *f); +@@ -139,8 +139,6 @@ bool qemu_file_is_writable(QEMUFile *f); size_t qemu_peek_buffer(QEMUFile *f, uint8_t **buf, size_t size, size_t offset); size_t qemu_get_buffer_in_place(QEMUFile *f, uint8_t **buf, size_t size); @@ -127,7 +111,7 @@ index 5de9fa2e96..6570e53e13 100644 int qemu_put_qemu_file(QEMUFile *f_des, QEMUFile *f_src); /* -@@ -162,6 +160,8 @@ void ram_control_before_iterate(QEMUFile *f, uint64_t flags); +@@ -167,6 +165,8 @@ void ram_control_before_iterate(QEMUFile *f, uint64_t flags); void ram_control_after_iterate(QEMUFile *f, uint64_t flags); void ram_control_load_hook(QEMUFile *f, uint64_t flags, void *data); @@ -137,7 +121,7 @@ index 5de9fa2e96..6570e53e13 100644 * will be passed to ram_control_load_hook in the incoming-migration * side. This lets before_ram_iterate/after_ram_iterate add diff --git a/migration/ram.c b/migration/ram.c -index 92ce1a53e7..f78a681ca2 100644 +index 863035d235..1176816fba 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -449,26 +449,22 @@ static QemuThread *decompress_threads; @@ -169,7 +153,7 @@ index 92ce1a53e7..f78a681ca2 100644 qemu_mutex_lock(&comp_done_lock); param->done = true; -@@ -2212,28 +2208,73 @@ static int ram_save_multifd_page(RAMState *rs, RAMBlock *block, +@@ -1342,28 +1338,73 @@ static int ram_save_multifd_page(RAMState *rs, RAMBlock *block, return 1; } @@ -249,7 +233,7 @@ index 92ce1a53e7..f78a681ca2 100644 if (ret < 0) { qemu_file_set_error(migrate_get_current()->to_dst_file, ret); error_report("compressed data failed!"); -@@ -3926,19 +3967,20 @@ void ram_handle_compressed(void *host, uint8_t ch, uint64_t size) +@@ -3374,19 +3415,20 @@ void ram_handle_compressed(void *host, uint8_t ch, uint64_t size) /* return the size after decompression, or negative value on error */ static int @@ -275,7 +259,7 @@ index 92ce1a53e7..f78a681ca2 100644 stream->next_out = dest; err = inflate(stream, Z_NO_FLUSH); -@@ -3952,22 +3994,17 @@ qemu_uncompress_data(z_stream *stream, uint8_t *dest, size_t dest_len, +@@ -3400,22 +3442,17 @@ qemu_uncompress_data(z_stream *stream, uint8_t *dest, size_t dest_len, static void *do_data_decompress(void *opaque) { DecompressParam *param = opaque; diff --git a/migration-add-qemu_file_update_transfer-interface.patch b/migration-add-qemu_file_update_transfer-interface.patch deleted file mode 100644 index 4222fd0adb202051cd57a3f0cab01e5ad52f8248..0000000000000000000000000000000000000000 --- a/migration-add-qemu_file_update_transfer-interface.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 7572495245a437da717e6829a9ce852cc3f229c9 Mon Sep 17 00:00:00 2001 -From: Zheng Chuan -Date: Mon, 20 Apr 2020 15:13:47 +0800 -Subject: [PATCH 02/10] migration: add qemu_file_update_transfer interface - -Add qemu_file_update_transfer for just update bytes_xfer for speed -limitation. This will be used for further migration feature such as -multifd migration. - -Change-Id: I969aa15305c961254b6fb9805b0ed2d65826cc5d -Signed-off-by: Ivan Ren -Reviewed-by: Wei Yang -Reviewed-by: Juan Quintela -Message-Id: <1564464816-21804-2-git-send-email-ivanren@tencent.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/qemu-file.c | 5 +++++ - migration/qemu-file.h | 1 + - 2 files changed, 6 insertions(+) - -diff --git a/migration/qemu-file.c b/migration/qemu-file.c -index 04315855..18f48052 100644 ---- a/migration/qemu-file.c -+++ b/migration/qemu-file.c -@@ -615,6 +615,11 @@ void qemu_file_reset_rate_limit(QEMUFile *f) - f->bytes_xfer = 0; - } - -+void qemu_file_update_transfer(QEMUFile *f, int64_t len) -+{ -+ f->bytes_xfer += len; -+} -+ - void qemu_put_be16(QEMUFile *f, unsigned int v) - { - qemu_put_byte(f, v >> 8); -diff --git a/migration/qemu-file.h b/migration/qemu-file.h -index 13baf896..5de9fa2e 100644 ---- a/migration/qemu-file.h -+++ b/migration/qemu-file.h -@@ -147,6 +147,7 @@ int qemu_peek_byte(QEMUFile *f, int offset); - void qemu_file_skip(QEMUFile *f, int size); - void qemu_update_position(QEMUFile *f, size_t size); - void qemu_file_reset_rate_limit(QEMUFile *f); -+void qemu_file_update_transfer(QEMUFile *f, int64_t len); - void qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate); - int64_t qemu_file_get_rate_limit(QEMUFile *f); - void qemu_file_set_error(QEMUFile *f, int ret); --- -2.19.1 diff --git a/migration-add-speed-limit-for-multifd-migration.patch b/migration-add-speed-limit-for-multifd-migration.patch deleted file mode 100644 index 690d9c9cf095cafdb2ff18025d70ee57a2527de2..0000000000000000000000000000000000000000 --- a/migration-add-speed-limit-for-multifd-migration.patch +++ /dev/null @@ -1,127 +0,0 @@ -From bc5780480db9e38699df0b4697e60a9f36258dc4 Mon Sep 17 00:00:00 2001 -From: Ivan Ren -Date: Tue, 30 Jul 2019 13:33:35 +0800 -Subject: [PATCH 03/10] migration: add speed limit for multifd migration - -Limit the speed of multifd migration through common speed limitation -qemu file. - -Change-Id: Id2abfc7ea85679bd53130a43043cc70179a52e87 -Signed-off-by: Ivan Ren -Message-Id: <1564464816-21804-3-git-send-email-ivanren@tencent.com> -Reviewed-by: Wei Yang -Reviewed-by: Juan Quintela -Signed-off-by: Dr. David Alan Gilbert ---- - migration/ram.c | 22 ++++++++++++---------- - 1 file changed, 12 insertions(+), 10 deletions(-) - -diff --git a/migration/ram.c b/migration/ram.c -index 889148dd..88ddd2bb 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -922,7 +922,7 @@ struct { - * false. - */ - --static int multifd_send_pages(void) -+static int multifd_send_pages(RAMState *rs) - { - int i; - static int next_channel; -@@ -954,6 +954,7 @@ static int multifd_send_pages(void) - multifd_send_state->pages = p->pages; - p->pages = pages; - transferred = ((uint64_t) pages->used) * TARGET_PAGE_SIZE + p->packet_len; -+ qemu_file_update_transfer(rs->f, transferred); - ram_counters.multifd_bytes += transferred; - ram_counters.transferred += transferred;; - qemu_mutex_unlock(&p->mutex); -@@ -962,7 +963,7 @@ static int multifd_send_pages(void) - return 1; - } - --static int multifd_queue_page(RAMBlock *block, ram_addr_t offset) -+static int multifd_queue_page(RAMState *rs, RAMBlock *block, ram_addr_t offset) - { - MultiFDPages_t *pages = multifd_send_state->pages; - -@@ -981,12 +982,12 @@ static int multifd_queue_page(RAMBlock *block, ram_addr_t offset) - } - } - -- if (multifd_send_pages() < 0) { -+ if (multifd_send_pages(rs) < 0) { - return -1; - } - - if (pages->block != block) { -- return multifd_queue_page(block, offset); -+ return multifd_queue_page(rs, block, offset); - } - - return 1; -@@ -1054,7 +1055,7 @@ void multifd_save_cleanup(void) - multifd_send_state = NULL; - } - --static void multifd_send_sync_main(void) -+static void multifd_send_sync_main(RAMState *rs) - { - int i; - -@@ -1062,7 +1063,7 @@ static void multifd_send_sync_main(void) - return; - } - if (multifd_send_state->pages->used) { -- if (multifd_send_pages() < 0) { -+ if (multifd_send_pages(rs) < 0) { - error_report("%s: multifd_send_pages fail", __func__); - return; - } -@@ -1083,6 +1084,7 @@ static void multifd_send_sync_main(void) - p->packet_num = multifd_send_state->packet_num++; - p->flags |= MULTIFD_FLAG_SYNC; - p->pending_job++; -+ qemu_file_update_transfer(rs->f, p->packet_len); - qemu_mutex_unlock(&p->mutex); - qemu_sem_post(&p->sem); - } -@@ -2079,7 +2081,7 @@ static int ram_save_page(RAMState *rs, PageSearchStatus *pss, bool last_stage) - static int ram_save_multifd_page(RAMState *rs, RAMBlock *block, - ram_addr_t offset) - { -- if (multifd_queue_page(block, offset) < 0) { -+ if (multifd_queue_page(rs, block, offset) < 0) { - return -1; - } - ram_counters.normal++; -@@ -3482,7 +3484,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) - ram_control_before_iterate(f, RAM_CONTROL_SETUP); - ram_control_after_iterate(f, RAM_CONTROL_SETUP); - -- multifd_send_sync_main(); -+ multifd_send_sync_main(*rsp); - qemu_put_be64(f, RAM_SAVE_FLAG_EOS); - qemu_fflush(f); - -@@ -3570,7 +3572,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) - ram_control_after_iterate(f, RAM_CONTROL_ROUND); - - out: -- multifd_send_sync_main(); -+ multifd_send_sync_main(rs); - qemu_put_be64(f, RAM_SAVE_FLAG_EOS); - qemu_fflush(f); - ram_counters.transferred += 8; -@@ -3629,7 +3631,7 @@ static int ram_save_complete(QEMUFile *f, void *opaque) - - rcu_read_unlock(); - -- multifd_send_sync_main(); -+ multifd_send_sync_main(rs); - qemu_put_be64(f, RAM_SAVE_FLAG_EOS); - qemu_fflush(f); - --- -2.19.1 diff --git a/migration-always-initialise-ram_counters-for-a-new-m.patch b/migration-always-initialise-ram_counters-for-a-new-m.patch deleted file mode 100644 index ccd0db9ab87204ca41e17c1120618748eb4383fe..0000000000000000000000000000000000000000 --- a/migration-always-initialise-ram_counters-for-a-new-m.patch +++ /dev/null @@ -1,125 +0,0 @@ -From af2aa4f553565ae6b2248204c154748f38ec4746 Mon Sep 17 00:00:00 2001 -From: Ivan Ren -Date: Fri, 2 Aug 2019 18:18:41 +0800 -Subject: [PATCH 01/10] migration: always initialise ram_counters for a new - migration - -This patch fix a multifd migration bug in migration speed calculation, this -problem can be reproduced as follows: -1. start a vm and give a heavy memory write stress to prevent the vm be - successfully migrated to destination -2. begin a migration with multifd -3. migrate for a long time [actually, this can be measured by transferred bytes] -4. migrate cancel -5. begin a new migration with multifd, the migration will directly run into - migration_completion phase - -Reason as follows: - -Migration update bandwidth and s->threshold_size in function -migration_update_counters after BUFFER_DELAY time: - - current_bytes = migration_total_bytes(s); - transferred = current_bytes - s->iteration_initial_bytes; - time_spent = current_time - s->iteration_start_time; - bandwidth = (double)transferred / time_spent; - s->threshold_size = bandwidth * s->parameters.downtime_limit; - -In multifd migration, migration_total_bytes function return -qemu_ftell(s->to_dst_file) + ram_counters.multifd_bytes. -s->iteration_initial_bytes will be initialized to 0 at every new migration, -but ram_counters is a global variable, and history migration data will be -accumulated. So if the ram_counters.multifd_bytes is big enough, it may lead -pending_size >= s->threshold_size become false in migration_iteration_run -after the first migration_update_counters. - -Change-Id: Ib153d8676a5b82650bfb1156060e09f0d29f3ac6 -Signed-off-by: Ivan Ren -Reviewed-by: Juan Quintela -Reviewed-by: Wei Yang -Suggested-by: Wei Yang -Message-Id: <1564741121-1840-1-git-send-email-ivanren@tencent.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/migration.c | 25 +++++++++++++++++++------ - migration/savevm.c | 1 + - 2 files changed, 20 insertions(+), 6 deletions(-) - -diff --git a/migration/migration.c b/migration/migration.c -index 8a607fe1..bea9b1d7 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -1908,6 +1908,11 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc, - } - - migrate_init(s); -+ /* -+ * set ram_counters memory to zero for a -+ * new migration -+ */ -+ memset(&ram_counters, 0, sizeof(ram_counters)); - - return true; - } -@@ -3025,6 +3030,17 @@ static void migration_calculate_complete(MigrationState *s) - } - } - -+static void update_iteration_initial_status(MigrationState *s) -+{ -+ /* -+ * Update these three fields at the same time to avoid mismatch info lead -+ * wrong speed calculation. -+ */ -+ s->iteration_start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); -+ s->iteration_initial_bytes = migration_total_bytes(s); -+ s->iteration_initial_pages = ram_get_total_transferred_pages(); -+} -+ - static void migration_update_counters(MigrationState *s, - int64_t current_time) - { -@@ -3060,9 +3076,7 @@ static void migration_update_counters(MigrationState *s, - - qemu_file_reset_rate_limit(s->to_dst_file); - -- s->iteration_start_time = current_time; -- s->iteration_initial_bytes = current_bytes; -- s->iteration_initial_pages = ram_get_total_transferred_pages(); -+ update_iteration_initial_status(s); - - trace_migrate_transferred(transferred, time_spent, - bandwidth, s->threshold_size); -@@ -3186,7 +3200,7 @@ static void *migration_thread(void *opaque) - rcu_register_thread(); - - object_ref(OBJECT(s)); -- s->iteration_start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); -+ update_iteration_initial_status(s); - - qemu_savevm_state_header(s->to_dst_file); - -@@ -3251,8 +3265,7 @@ static void *migration_thread(void *opaque) - * the local variables. This is important to avoid - * breaking transferred_bytes and bandwidth calculation - */ -- s->iteration_start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); -- s->iteration_initial_bytes = 0; -+ update_iteration_initial_status(s); - } - - current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); -diff --git a/migration/savevm.c b/migration/savevm.c -index 79ed44d4..480c511b 100644 ---- a/migration/savevm.c -+++ b/migration/savevm.c -@@ -1424,6 +1424,7 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp) - } - - migrate_init(ms); -+ memset(&ram_counters, 0, sizeof(ram_counters)); - ms->to_dst_file = f; - - qemu_mutex_unlock_iothread(); --- -2.19.1 diff --git a/migration-colo-fix-use-after-free-of-local_err.patch b/migration-colo-fix-use-after-free-of-local_err.patch deleted file mode 100644 index c03ceb5120bc3069ac123cc9c2702653c4d2da17..0000000000000000000000000000000000000000 --- a/migration-colo-fix-use-after-free-of-local_err.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 663e9b5f25d22834260a0686f77a27c957cd7b2f Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Tue, 24 Mar 2020 18:36:28 +0300 -Subject: [PATCH 07/14] migration/colo: fix use after free of local_err - -local_err is used again in secondary_vm_do_failover() after -replication_stop_all(), so we must zero it. Otherwise try to set -non-NULL local_err will crash. - -Signed-off-by: Vladimir Sementsov-Ogievskiy -Message-Id: <20200324153630.11882-5-vsementsov@virtuozzo.com> -Reviewed-by: Dr. David Alan Gilbert -Signed-off-by: Dr. David Alan Gilbert -Signed-off-by: Peng Liang ---- - migration/colo.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/migration/colo.c b/migration/colo.c -index 9f84b1fa3c0f..761b3544d472 100644 ---- a/migration/colo.c -+++ b/migration/colo.c -@@ -89,6 +89,7 @@ static void secondary_vm_do_failover(void) - replication_stop_all(true, &local_err); - if (local_err) { - error_report_err(local_err); -+ local_err = NULL; - } - - /* Notify all filters of all NIC to do checkpoint */ --- -2.26.2 - diff --git a/migration-dirtyrate-Add-RamblockDirtyInfo-to-store-s.patch b/migration-dirtyrate-Add-RamblockDirtyInfo-to-store-s.patch deleted file mode 100644 index 8028a29dd7141ce2fc2e139559c1a54661b31109..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-Add-RamblockDirtyInfo-to-store-s.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 17b0582ebba622afbd8f454bbee8141ed2785f13 Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Wed, 16 Sep 2020 14:21:58 +0800 -Subject: [PATCH] migration/dirtyrate: Add RamblockDirtyInfo to store sampled - page info - -Add RamblockDirtyInfo to store sampled page info of each ramblock. - -Signed-off-by: Chuan Zheng -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: David Edmondson -Reviewed-by: Li Qiang -Message-Id: <1600237327-33618-4-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/dirtyrate.h | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - -diff --git a/migration/dirtyrate.h b/migration/dirtyrate.h -index 84ab9409ac..8707df852d 100644 ---- a/migration/dirtyrate.h -+++ b/migration/dirtyrate.h -@@ -19,10 +19,28 @@ - */ - #define DIRTYRATE_DEFAULT_SAMPLE_PAGES 512 - -+/* -+ * Record ramblock idstr -+ */ -+#define RAMBLOCK_INFO_MAX_LEN 256 -+ - struct DirtyRateConfig { - uint64_t sample_pages_per_gigabytes; /* sample pages per GB */ - int64_t sample_period_seconds; /* time duration between two sampling */ - }; - -+/* -+ * Store dirtypage info for each ramblock. -+ */ -+struct RamblockDirtyInfo { -+ char idstr[RAMBLOCK_INFO_MAX_LEN]; /* idstr for each ramblock */ -+ uint8_t *ramblock_addr; /* base address of ramblock we measure */ -+ uint64_t ramblock_pages; /* ramblock size in TARGET_PAGE_SIZE */ -+ uint64_t *sample_page_vfn; /* relative offset address for sampled page */ -+ uint64_t sample_pages_count; /* count of sampled pages */ -+ uint64_t sample_dirty_count; /* count of dirty pages we measure */ -+ uint32_t *hash_result; /* array of hash result for sampled pages */ -+}; -+ - void *get_dirtyrate_thread(void *arg); - #endif --- -2.27.0 - diff --git a/migration-dirtyrate-Add-dirtyrate-statistics-series-.patch b/migration-dirtyrate-Add-dirtyrate-statistics-series-.patch deleted file mode 100644 index 1d56f8029ca9b35243e87984538c93113cd4513a..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-Add-dirtyrate-statistics-series-.patch +++ /dev/null @@ -1,93 +0,0 @@ -From d1340703e127c02e9a586143039507ba10d73cfb Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Wed, 16 Sep 2020 14:21:59 +0800 -Subject: [PATCH] migration/dirtyrate: Add dirtyrate statistics series - functions - -Add dirtyrate statistics functions to record/update dirtyrate info. - -Signed-off-by: Chuan Zheng -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: Li Qiang -Message-Id: <1600237327-33618-5-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/dirtyrate.c | 32 ++++++++++++++++++++++++++++++++ - migration/dirtyrate.h | 12 ++++++++++++ - 2 files changed, 44 insertions(+) - -diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c -index 44a60bf10d..cbb323d6ec 100644 ---- a/migration/dirtyrate.c -+++ b/migration/dirtyrate.c -@@ -23,6 +23,7 @@ - #include "dirtyrate.h" - - static int CalculatingState = DIRTY_RATE_STATUS_UNSTARTED; -+static struct DirtyRateStat DirtyStat; - - static int dirtyrate_set_state(int *state, int old_state, int new_state) - { -@@ -34,6 +35,37 @@ static int dirtyrate_set_state(int *state, int old_state, int new_state) - } - } - -+static void reset_dirtyrate_stat(void) -+{ -+ DirtyStat.total_dirty_samples = 0; -+ DirtyStat.total_sample_count = 0; -+ DirtyStat.total_block_mem_MB = 0; -+ DirtyStat.dirty_rate = -1; -+ DirtyStat.start_time = 0; -+ DirtyStat.calc_time = 0; -+} -+ -+static void update_dirtyrate_stat(struct RamblockDirtyInfo *info) -+{ -+ DirtyStat.total_dirty_samples += info->sample_dirty_count; -+ DirtyStat.total_sample_count += info->sample_pages_count; -+ /* size of total pages in MB */ -+ DirtyStat.total_block_mem_MB += (info->ramblock_pages * -+ TARGET_PAGE_SIZE) >> 20; -+} -+ -+static void update_dirtyrate(uint64_t msec) -+{ -+ uint64_t dirtyrate; -+ uint64_t total_dirty_samples = DirtyStat.total_dirty_samples; -+ uint64_t total_sample_count = DirtyStat.total_sample_count; -+ uint64_t total_block_mem_MB = DirtyStat.total_block_mem_MB; -+ -+ dirtyrate = total_dirty_samples * total_block_mem_MB * -+ 1000 / (total_sample_count * msec); -+ -+ DirtyStat.dirty_rate = dirtyrate; -+} - - static void calculate_dirtyrate(struct DirtyRateConfig config) - { -diff --git a/migration/dirtyrate.h b/migration/dirtyrate.h -index 8707df852d..312debca6f 100644 ---- a/migration/dirtyrate.h -+++ b/migration/dirtyrate.h -@@ -42,5 +42,17 @@ struct RamblockDirtyInfo { - uint32_t *hash_result; /* array of hash result for sampled pages */ - }; - -+/* -+ * Store calculation statistics for each measure. -+ */ -+struct DirtyRateStat { -+ uint64_t total_dirty_samples; /* total dirty sampled page */ -+ uint64_t total_sample_count; /* total sampled pages */ -+ uint64_t total_block_mem_MB; /* size of total sampled pages in MB */ -+ int64_t dirty_rate; /* dirty rate in MB/s */ -+ int64_t start_time; /* calculation start time in units of second */ -+ int64_t calc_time; /* time duration of two sampling in units of second */ -+}; -+ - void *get_dirtyrate_thread(void *arg); - #endif --- -2.27.0 - diff --git a/migration-dirtyrate-Add-trace_calls-to-make-it-easie.patch b/migration-dirtyrate-Add-trace_calls-to-make-it-easie.patch deleted file mode 100644 index 79d825c8a34d1229876b03e1ca64e464d7e0d91c..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-Add-trace_calls-to-make-it-easie.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 8a36332d38c0c0ba6b7d8c096367a4ec7c94e522 Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Wed, 16 Sep 2020 14:22:07 +0800 -Subject: [PATCH] migration/dirtyrate: Add trace_calls to make it easier to - debug - -Add trace_calls to make it easier to debug - -Signed-off-by: Chuan Zheng -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: David Edmondson -Message-Id: <1600237327-33618-13-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/dirtyrate.c | 9 +++++++++ - migration/trace-events | 8 ++++++++ - 2 files changed, 17 insertions(+) - -diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c -index 9d9155f8ab..80936a4ca6 100644 ---- a/migration/dirtyrate.c -+++ b/migration/dirtyrate.c -@@ -22,6 +22,7 @@ - #include "qapi/qapi-commands-migration.h" - #include "migration.h" - #include "ram.h" -+#include "trace.h" - #include "dirtyrate.h" - - static int CalculatingState = DIRTY_RATE_STATUS_UNSTARTED; -@@ -54,6 +55,7 @@ static bool is_sample_period_valid(int64_t sec) - static int dirtyrate_set_state(int *state, int old_state, int new_state) - { - assert(new_state < DIRTY_RATE_STATUS__MAX); -+ trace_dirtyrate_set_state(DirtyRateStatus_str(new_state)); - if (atomic_cmpxchg(state, old_state, new_state) == old_state) { - return 0; - } else { -@@ -76,6 +78,8 @@ static struct DirtyRateInfo *query_dirty_rate_info(void) - info->start_time = DirtyStat.start_time; - info->calc_time = DirtyStat.calc_time; - -+ trace_query_dirty_rate_info(DirtyRateStatus_str(CalculatingState)); -+ - return info; - } - -@@ -123,6 +127,7 @@ static uint32_t get_ramblock_vfn_hash(struct RamblockDirtyInfo *info, - crc = crc32(0, (info->ramblock_addr + - vfn * TARGET_PAGE_SIZE), TARGET_PAGE_SIZE); - -+ trace_get_ramblock_vfn_hash(info->idstr, vfn, crc); - return crc; - } - -@@ -201,6 +206,8 @@ static bool skip_sample_ramblock(RAMBlock *block) - * Sample only blocks larger than MIN_RAMBLOCK_SIZE. - */ - if (qemu_ram_get_used_length(block) < (MIN_RAMBLOCK_SIZE << 10)) { -+ trace_skip_sample_ramblock(block->idstr, -+ qemu_ram_get_used_length(block)); - return true; - } - -@@ -260,6 +267,7 @@ static void calc_page_dirty_rate(struct RamblockDirtyInfo *info) - for (i = 0; i < info->sample_pages_count; i++) { - crc = get_ramblock_vfn_hash(info, info->sample_page_vfn[i]); - if (crc != info->hash_result[i]) { -+ trace_calc_page_dirty_rate(info->idstr, crc, info->hash_result[i]); - info->sample_dirty_count++; - } - } -@@ -285,6 +293,7 @@ find_block_matched(RAMBlock *block, int count, - if (infos[i].ramblock_addr != qemu_ram_get_host_addr(block) || - infos[i].ramblock_pages != - (qemu_ram_get_used_length(block) >> TARGET_PAGE_BITS)) { -+ trace_find_page_matched(block->idstr); - return NULL; - } - -diff --git a/migration/trace-events b/migration/trace-events -index d8e54c367a..69620c43c2 100644 ---- a/migration/trace-events -+++ b/migration/trace-events -@@ -296,3 +296,11 @@ dirty_bitmap_load_bits_zeroes(void) "" - dirty_bitmap_load_header(uint32_t flags) "flags 0x%x" - dirty_bitmap_load_enter(void) "" - dirty_bitmap_load_success(void) "" -+ -+# dirtyrate.c -+dirtyrate_set_state(const char *new_state) "new state %s" -+query_dirty_rate_info(const char *new_state) "current state %s" -+get_ramblock_vfn_hash(const char *idstr, uint64_t vfn, uint32_t crc) "ramblock name: %s, vfn: %"PRIu64 ", crc: %" PRIu32 -+calc_page_dirty_rate(const char *idstr, uint32_t new_crc, uint32_t old_crc) "ramblock name: %s, new crc: %" PRIu32 ", old crc: %" PRIu32 -+skip_sample_ramblock(const char *idstr, uint64_t ramblock_size) "ramblock name: %s, ramblock size: %" PRIu64 -+find_page_matched(const char *idstr) "ramblock %s addr or size changed" --- -2.27.0 - diff --git a/migration-dirtyrate-Compare-page-hash-results-for-re.patch b/migration-dirtyrate-Compare-page-hash-results-for-re.patch deleted file mode 100644 index b9277d5faa65a35cc1d044023683ea37e452fc65..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-Compare-page-hash-results-for-re.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 949612c5bbc5414970aed7d7ec9390a058ee2246 Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Wed, 16 Sep 2020 14:22:02 +0800 -Subject: [PATCH] migration/dirtyrate: Compare page hash results for recorded - sampled page - -Compare page hash results for recorded sampled page. - -Signed-off-by: Chuan Zheng -Signed-off-by: YanYing Zhuang -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: Li Qiang -Message-Id: <1600237327-33618-8-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/dirtyrate.c | 63 +++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 63 insertions(+) - -diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c -index f93601f8ab..0412f825dc 100644 ---- a/migration/dirtyrate.c -+++ b/migration/dirtyrate.c -@@ -177,6 +177,69 @@ out: - return ret; - } - -+static void calc_page_dirty_rate(struct RamblockDirtyInfo *info) -+{ -+ uint32_t crc; -+ int i; -+ -+ for (i = 0; i < info->sample_pages_count; i++) { -+ crc = get_ramblock_vfn_hash(info, info->sample_page_vfn[i]); -+ if (crc != info->hash_result[i]) { -+ info->sample_dirty_count++; -+ } -+ } -+} -+ -+static struct RamblockDirtyInfo * -+find_block_matched(RAMBlock *block, int count, -+ struct RamblockDirtyInfo *infos) -+{ -+ int i; -+ struct RamblockDirtyInfo *matched; -+ -+ for (i = 0; i < count; i++) { -+ if (!strcmp(infos[i].idstr, qemu_ram_get_idstr(block))) { -+ break; -+ } -+ } -+ -+ if (i == count) { -+ return NULL; -+ } -+ -+ if (infos[i].ramblock_addr != qemu_ram_get_host_addr(block) || -+ infos[i].ramblock_pages != -+ (qemu_ram_get_used_length(block) >> TARGET_PAGE_BITS)) { -+ return NULL; -+ } -+ -+ matched = &infos[i]; -+ -+ return matched; -+} -+ -+static bool compare_page_hash_info(struct RamblockDirtyInfo *info, -+ int block_count) -+{ -+ struct RamblockDirtyInfo *block_dinfo = NULL; -+ RAMBlock *block = NULL; -+ -+ RAMBLOCK_FOREACH_MIGRATABLE(block) { -+ block_dinfo = find_block_matched(block, block_count, info); -+ if (block_dinfo == NULL) { -+ continue; -+ } -+ calc_page_dirty_rate(block_dinfo); -+ update_dirtyrate_stat(block_dinfo); -+ } -+ -+ if (DirtyStat.total_sample_count == 0) { -+ return false; -+ } -+ -+ return true; -+} -+ - static void calculate_dirtyrate(struct DirtyRateConfig config) - { - /* todo */ --- -2.27.0 - diff --git a/migration-dirtyrate-Implement-calculate_dirtyrate-fu.patch b/migration-dirtyrate-Implement-calculate_dirtyrate-fu.patch deleted file mode 100644 index 1fcb2c07c2bfd83d91ee582ec79c39d759c8335b..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-Implement-calculate_dirtyrate-fu.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 18102266fb18c4bfcdd4760e7111ca03a7520588 Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Wed, 16 Sep 2020 14:22:05 +0800 -Subject: [PATCH] migration/dirtyrate: Implement calculate_dirtyrate() function - -Implement calculate_dirtyrate() function. - -Signed-off-by: Chuan Zheng -Signed-off-by: YanYing Zhuang -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: Li Qiang -Message-Id: <1600237327-33618-11-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/dirtyrate.c | 45 +++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 43 insertions(+), 2 deletions(-) - -diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c -index 485d6467c9..c7a389a527 100644 ---- a/migration/dirtyrate.c -+++ b/migration/dirtyrate.c -@@ -162,6 +162,21 @@ static void get_ramblock_dirty_info(RAMBlock *block, - strcpy(info->idstr, qemu_ram_get_idstr(block)); - } - -+static void free_ramblock_dirty_info(struct RamblockDirtyInfo *infos, int count) -+{ -+ int i; -+ -+ if (!infos) { -+ return; -+ } -+ -+ for (i = 0; i < count; i++) { -+ g_free(infos[i].sample_page_vfn); -+ g_free(infos[i].hash_result); -+ } -+ g_free(infos); -+} -+ - static bool skip_sample_ramblock(RAMBlock *block) - { - /* -@@ -287,8 +302,34 @@ static bool compare_page_hash_info(struct RamblockDirtyInfo *info, - - static void calculate_dirtyrate(struct DirtyRateConfig config) - { -- /* todo */ -- return; -+ struct RamblockDirtyInfo *block_dinfo = NULL; -+ int block_count = 0; -+ int64_t msec = 0; -+ int64_t initial_time; -+ -+ rcu_register_thread(); -+ reset_dirtyrate_stat(); -+ rcu_read_lock(); -+ initial_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); -+ if (!record_ramblock_hash_info(&block_dinfo, config, &block_count)) { -+ goto out; -+ } -+ rcu_read_unlock(); -+ -+ msec = config.sample_period_seconds * 1000; -+ msec = set_sample_page_period(msec, initial_time); -+ -+ rcu_read_lock(); -+ if (!compare_page_hash_info(block_dinfo, block_count)) { -+ goto out; -+ } -+ -+ update_dirtyrate(msec); -+ -+out: -+ rcu_read_unlock(); -+ free_ramblock_dirty_info(block_dinfo, block_count); -+ rcu_unregister_thread(); - } - - void *get_dirtyrate_thread(void *arg) --- -2.27.0 - diff --git a/migration-dirtyrate-Implement-qmp_cal_dirty_rate-qmp.patch b/migration-dirtyrate-Implement-qmp_cal_dirty_rate-qmp.patch deleted file mode 100644 index 04893d36e579d9c4b78dfa9d1bd488d3a842cddb..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-Implement-qmp_cal_dirty_rate-qmp.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 1f5f7156988cee6e678eff253df0e79788c950d7 Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Wed, 16 Sep 2020 14:22:06 +0800 -Subject: [PATCH] migration/dirtyrate: Implement - qmp_cal_dirty_rate()/qmp_get_dirty_rate() function - -Implement qmp_cal_dirty_rate()/qmp_get_dirty_rate() function which could be called - -Signed-off-by: Chuan Zheng -Message-Id: <1600237327-33618-12-git-send-email-zhengchuan@huawei.com> -Reviewed-by: Dr. David Alan Gilbert -Signed-off-by: Dr. David Alan Gilbert - atomic function fixup - Wording fixup in migration.json based on Eric's review ---- - migration/dirtyrate.c | 62 +++++++++++++++++++++++++++++++++++++++++++ - qapi/migration.json | 50 ++++++++++++++++++++++++++++++++++ - 2 files changed, 112 insertions(+) - -diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c -index c7a389a527..9d9155f8ab 100644 ---- a/migration/dirtyrate.c -+++ b/migration/dirtyrate.c -@@ -61,6 +61,24 @@ static int dirtyrate_set_state(int *state, int old_state, int new_state) - } - } - -+static struct DirtyRateInfo *query_dirty_rate_info(void) -+{ -+ int64_t dirty_rate = DirtyStat.dirty_rate; -+ struct DirtyRateInfo *info = g_malloc0(sizeof(DirtyRateInfo)); -+ -+ if (atomic_read(&CalculatingState) == DIRTY_RATE_STATUS_MEASURED) { -+ info->dirty_rate = dirty_rate; -+ } else { -+ info->dirty_rate = -1; -+ } -+ -+ info->status = CalculatingState; -+ info->start_time = DirtyStat.start_time; -+ info->calc_time = DirtyStat.calc_time; -+ -+ return info; -+} -+ - static void reset_dirtyrate_stat(void) - { - DirtyStat.total_dirty_samples = 0; -@@ -318,6 +336,8 @@ static void calculate_dirtyrate(struct DirtyRateConfig config) - - msec = config.sample_period_seconds * 1000; - msec = set_sample_page_period(msec, initial_time); -+ DirtyStat.start_time = initial_time / 1000; -+ DirtyStat.calc_time = msec / 1000; - - rcu_read_lock(); - if (!compare_page_hash_info(block_dinfo, block_count)) { -@@ -353,3 +373,45 @@ void *get_dirtyrate_thread(void *arg) - } - return NULL; - } -+ -+void qmp_calc_dirty_rate(int64_t calc_time, Error **errp) -+{ -+ static struct DirtyRateConfig config; -+ QemuThread thread; -+ int ret; -+ -+ /* -+ * If the dirty rate is already being measured, don't attempt to start. -+ */ -+ if (atomic_read(&CalculatingState) == DIRTY_RATE_STATUS_MEASURING) { -+ error_setg(errp, "the dirty rate is already being measured."); -+ return; -+ } -+ -+ if (!is_sample_period_valid(calc_time)) { -+ error_setg(errp, "calc-time is out of range[%d, %d].", -+ MIN_FETCH_DIRTYRATE_TIME_SEC, -+ MAX_FETCH_DIRTYRATE_TIME_SEC); -+ return; -+ } -+ -+ /* -+ * Init calculation state as unstarted. -+ */ -+ ret = dirtyrate_set_state(&CalculatingState, CalculatingState, -+ DIRTY_RATE_STATUS_UNSTARTED); -+ if (ret == -1) { -+ error_setg(errp, "init dirty rate calculation state failed."); -+ return; -+ } -+ -+ config.sample_period_seconds = calc_time; -+ config.sample_pages_per_gigabytes = DIRTYRATE_DEFAULT_SAMPLE_PAGES; -+ qemu_thread_create(&thread, "get_dirtyrate", get_dirtyrate_thread, -+ (void *)&config, QEMU_THREAD_DETACHED); -+} -+ -+struct DirtyRateInfo *qmp_query_dirty_rate(Error **errp) -+{ -+ return query_dirty_rate_info(); -+} -diff --git a/qapi/migration.json b/qapi/migration.json -index fdddde0af7..76f5b42493 100644 ---- a/qapi/migration.json -+++ b/qapi/migration.json -@@ -1462,3 +1462,53 @@ - ## - { 'enum': 'DirtyRateStatus', - 'data': [ 'unstarted', 'measuring', 'measured'] } -+ -+## -+# @DirtyRateInfo: -+# -+# Information about current dirty page rate of vm. -+# -+# @dirty-rate: @dirtyrate describing the dirty page rate of vm -+# in units of MB/s. -+# If this field returns '-1', it means querying has not -+# yet started or completed. -+# -+# @status: status containing dirtyrate query status includes -+# 'unstarted' or 'measuring' or 'measured' -+# -+# @start-time: start time in units of second for calculation -+# -+# @calc-time: time in units of second for sample dirty pages -+# -+# Since: 5.2 -+# -+## -+{ 'struct': 'DirtyRateInfo', -+ 'data': {'dirty-rate': 'int64', -+ 'status': 'DirtyRateStatus', -+ 'start-time': 'int64', -+ 'calc-time': 'int64'} } -+ -+## -+# @calc-dirty-rate: -+# -+# start calculating dirty page rate for vm -+# -+# @calc-time: time in units of second for sample dirty pages -+# -+# Since: 5.2 -+# -+# Example: -+# {"command": "calc-dirty-rate", "data": {"calc-time": 1} } -+# -+## -+{ 'command': 'calc-dirty-rate', 'data': {'calc-time': 'int64'} } -+ -+## -+# @query-dirty-rate: -+# -+# query dirty page rate in units of MB/s for vm -+# -+# Since: 5.2 -+## -+{ 'command': 'query-dirty-rate', 'returns': 'DirtyRateInfo' } --- -2.27.0 - diff --git a/migration-dirtyrate-Implement-set_sample_page_period.patch b/migration-dirtyrate-Implement-set_sample_page_period.patch deleted file mode 100644 index fdb9c22431a0d74a4055f01839a42beaa2fa1f51..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-Implement-set_sample_page_period.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 905082a502e0600d40e784df2443ae99948cf52d Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Wed, 16 Sep 2020 14:22:04 +0800 -Subject: [PATCH] migration/dirtyrate: Implement set_sample_page_period() and - is_sample_period_valid() - -Implement is_sample_period_valid() to check if the sample period is vaild and -do set_sample_page_period() to sleep specific time between sample actions. - -Signed-off-by: Chuan Zheng -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: David Edmondson -Reviewed-by: Li Qiang -Message-Id: <1600237327-33618-10-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/dirtyrate.c | 24 ++++++++++++++++++++++++ - migration/dirtyrate.h | 6 ++++++ - 2 files changed, 30 insertions(+) - -diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c -index 97bb883850..485d6467c9 100644 ---- a/migration/dirtyrate.c -+++ b/migration/dirtyrate.c -@@ -27,6 +27,30 @@ - static int CalculatingState = DIRTY_RATE_STATUS_UNSTARTED; - static struct DirtyRateStat DirtyStat; - -+static int64_t set_sample_page_period(int64_t msec, int64_t initial_time) -+{ -+ int64_t current_time; -+ -+ current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); -+ if ((current_time - initial_time) >= msec) { -+ msec = current_time - initial_time; -+ } else { -+ g_usleep((msec + initial_time - current_time) * 1000); -+ } -+ -+ return msec; -+} -+ -+static bool is_sample_period_valid(int64_t sec) -+{ -+ if (sec < MIN_FETCH_DIRTYRATE_TIME_SEC || -+ sec > MAX_FETCH_DIRTYRATE_TIME_SEC) { -+ return false; -+ } -+ -+ return true; -+} -+ - static int dirtyrate_set_state(int *state, int old_state, int new_state) - { - assert(new_state < DIRTY_RATE_STATUS__MAX); -diff --git a/migration/dirtyrate.h b/migration/dirtyrate.h -index be5b8ec2b1..6ec429534d 100644 ---- a/migration/dirtyrate.h -+++ b/migration/dirtyrate.h -@@ -29,6 +29,12 @@ - */ - #define MIN_RAMBLOCK_SIZE 128 - -+/* -+ * Take 1s as minimum time for calculation duration -+ */ -+#define MIN_FETCH_DIRTYRATE_TIME_SEC 1 -+#define MAX_FETCH_DIRTYRATE_TIME_SEC 60 -+ - struct DirtyRateConfig { - uint64_t sample_pages_per_gigabytes; /* sample pages per GB */ - int64_t sample_period_seconds; /* time duration between two sampling */ --- -2.27.0 - diff --git a/migration-dirtyrate-Record-hash-results-for-each-sam.patch b/migration-dirtyrate-Record-hash-results-for-each-sam.patch deleted file mode 100644 index 5a5a8a9476155c56c740941143b899e80b5a2472..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-Record-hash-results-for-each-sam.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 751dbc44b4ac0e0c0bce2f53d2ee79a6e6318188 Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Wed, 16 Sep 2020 14:22:01 +0800 -Subject: [PATCH] migration/dirtyrate: Record hash results for each sampled - page - -Record hash results for each sampled page, crc32 is taken to calculate -hash results for each sampled length in TARGET_PAGE_SIZE. - -Signed-off-by: Chuan Zheng -Signed-off-by: YanYing Zhuang -Reviewed-by: David Edmondson -Reviewed-by: Li Qiang -Message-Id: <1600237327-33618-7-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/dirtyrate.c | 109 ++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 109 insertions(+) - -diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c -index 1ccc71077d..f93601f8ab 100644 ---- a/migration/dirtyrate.c -+++ b/migration/dirtyrate.c -@@ -10,6 +10,7 @@ - * See the COPYING file in the top-level directory. - */ - -+#include - #include "qemu/osdep.h" - #include "qapi/error.h" - #include "cpu.h" -@@ -68,6 +69,114 @@ static void update_dirtyrate(uint64_t msec) - DirtyStat.dirty_rate = dirtyrate; - } - -+/* -+ * get hash result for the sampled memory with length of TARGET_PAGE_SIZE -+ * in ramblock, which starts from ramblock base address. -+ */ -+static uint32_t get_ramblock_vfn_hash(struct RamblockDirtyInfo *info, -+ uint64_t vfn) -+{ -+ uint32_t crc; -+ -+ crc = crc32(0, (info->ramblock_addr + -+ vfn * TARGET_PAGE_SIZE), TARGET_PAGE_SIZE); -+ -+ return crc; -+} -+ -+static bool save_ramblock_hash(struct RamblockDirtyInfo *info) -+{ -+ unsigned int sample_pages_count; -+ int i; -+ GRand *rand; -+ -+ sample_pages_count = info->sample_pages_count; -+ -+ /* ramblock size less than one page, return success to skip this ramblock */ -+ if (unlikely(info->ramblock_pages == 0 || sample_pages_count == 0)) { -+ return true; -+ } -+ -+ info->hash_result = g_try_malloc0_n(sample_pages_count, -+ sizeof(uint32_t)); -+ if (!info->hash_result) { -+ return false; -+ } -+ -+ info->sample_page_vfn = g_try_malloc0_n(sample_pages_count, -+ sizeof(uint64_t)); -+ if (!info->sample_page_vfn) { -+ g_free(info->hash_result); -+ return false; -+ } -+ -+ rand = g_rand_new(); -+ for (i = 0; i < sample_pages_count; i++) { -+ info->sample_page_vfn[i] = g_rand_int_range(rand, 0, -+ info->ramblock_pages - 1); -+ info->hash_result[i] = get_ramblock_vfn_hash(info, -+ info->sample_page_vfn[i]); -+ } -+ g_rand_free(rand); -+ -+ return true; -+} -+ -+static void get_ramblock_dirty_info(RAMBlock *block, -+ struct RamblockDirtyInfo *info, -+ struct DirtyRateConfig *config) -+{ -+ uint64_t sample_pages_per_gigabytes = config->sample_pages_per_gigabytes; -+ -+ /* Right shift 30 bits to calc ramblock size in GB */ -+ info->sample_pages_count = (qemu_ram_get_used_length(block) * -+ sample_pages_per_gigabytes) >> 30; -+ /* Right shift TARGET_PAGE_BITS to calc page count */ -+ info->ramblock_pages = qemu_ram_get_used_length(block) >> -+ TARGET_PAGE_BITS; -+ info->ramblock_addr = qemu_ram_get_host_addr(block); -+ strcpy(info->idstr, qemu_ram_get_idstr(block)); -+} -+ -+static bool record_ramblock_hash_info(struct RamblockDirtyInfo **block_dinfo, -+ struct DirtyRateConfig config, -+ int *block_count) -+{ -+ struct RamblockDirtyInfo *info = NULL; -+ struct RamblockDirtyInfo *dinfo = NULL; -+ RAMBlock *block = NULL; -+ int total_count = 0; -+ int index = 0; -+ bool ret = false; -+ -+ RAMBLOCK_FOREACH_MIGRATABLE(block) { -+ total_count++; -+ } -+ -+ dinfo = g_try_malloc0_n(total_count, sizeof(struct RamblockDirtyInfo)); -+ if (dinfo == NULL) { -+ goto out; -+ } -+ -+ RAMBLOCK_FOREACH_MIGRATABLE(block) { -+ if (index >= total_count) { -+ break; -+ } -+ info = &dinfo[index]; -+ get_ramblock_dirty_info(block, info, &config); -+ if (!save_ramblock_hash(info)) { -+ goto out; -+ } -+ index++; -+ } -+ ret = true; -+ -+out: -+ *block_count = index; -+ *block_dinfo = dinfo; -+ return ret; -+} -+ - static void calculate_dirtyrate(struct DirtyRateConfig config) - { - /* todo */ --- -2.27.0 - diff --git a/migration-dirtyrate-add-DirtyRateStatus-to-denote-ca.patch b/migration-dirtyrate-add-DirtyRateStatus-to-denote-ca.patch deleted file mode 100644 index e0ebb2a70e3771da65a340b081094e63318d42fe..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-add-DirtyRateStatus-to-denote-ca.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 466b3eee340f022e53478e706e8d4dc02136b1e1 Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Wed, 16 Sep 2020 14:21:57 +0800 -Subject: [PATCH] migration/dirtyrate: add DirtyRateStatus to denote - calculation status - -add DirtyRateStatus to denote calculating status. - -Signed-off-by: Chuan Zheng -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: Li Qiang -Message-Id: <1600237327-33618-3-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert - atomic name fixup ---- - migration/dirtyrate.c | 26 ++++++++++++++++++++++++++ - qapi/migration.json | 17 +++++++++++++++++ - 2 files changed, 43 insertions(+) - -diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c -index 29ef663acb..44a60bf10d 100644 ---- a/migration/dirtyrate.c -+++ b/migration/dirtyrate.c -@@ -22,6 +22,19 @@ - #include "migration.h" - #include "dirtyrate.h" - -+static int CalculatingState = DIRTY_RATE_STATUS_UNSTARTED; -+ -+static int dirtyrate_set_state(int *state, int old_state, int new_state) -+{ -+ assert(new_state < DIRTY_RATE_STATUS__MAX); -+ if (atomic_cmpxchg(state, old_state, new_state) == old_state) { -+ return 0; -+ } else { -+ return -1; -+ } -+} -+ -+ - static void calculate_dirtyrate(struct DirtyRateConfig config) - { - /* todo */ -@@ -31,8 +44,21 @@ static void calculate_dirtyrate(struct DirtyRateConfig config) - void *get_dirtyrate_thread(void *arg) - { - struct DirtyRateConfig config = *(struct DirtyRateConfig *)arg; -+ int ret; -+ -+ ret = dirtyrate_set_state(&CalculatingState, DIRTY_RATE_STATUS_UNSTARTED, -+ DIRTY_RATE_STATUS_MEASURING); -+ if (ret == -1) { -+ error_report("change dirtyrate state failed."); -+ return NULL; -+ } - - calculate_dirtyrate(config); - -+ ret = dirtyrate_set_state(&CalculatingState, DIRTY_RATE_STATUS_MEASURING, -+ DIRTY_RATE_STATUS_MEASURED); -+ if (ret == -1) { -+ error_report("change dirtyrate state failed."); -+ } - return NULL; - } -diff --git a/qapi/migration.json b/qapi/migration.json -index 9cfbaf8c6c..fdddde0af7 100644 ---- a/qapi/migration.json -+++ b/qapi/migration.json -@@ -1445,3 +1445,20 @@ - # Since: 3.0 - ## - { 'command': 'migrate-pause', 'allow-oob': true } -+ -+## -+# @DirtyRateStatus: -+# -+# An enumeration of dirtyrate status. -+# -+# @unstarted: the dirtyrate thread has not been started. -+# -+# @measuring: the dirtyrate thread is measuring. -+# -+# @measured: the dirtyrate thread has measured and results are available. -+# -+# Since: 5.2 -+# -+## -+{ 'enum': 'DirtyRateStatus', -+ 'data': [ 'unstarted', 'measuring', 'measured'] } --- -2.27.0 - diff --git a/migration-dirtyrate-move-RAMBLOCK_FOREACH_MIGRATABLE.patch b/migration-dirtyrate-move-RAMBLOCK_FOREACH_MIGRATABLE.patch deleted file mode 100644 index 16660d7dd46f4ec3712f9714de37c41a3c3554f4..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-move-RAMBLOCK_FOREACH_MIGRATABLE.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 1cee10fe37193c6b5ed4e765a2a6d1e6c1411922 Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Wed, 16 Sep 2020 14:22:00 +0800 -Subject: [PATCH] migration/dirtyrate: move RAMBLOCK_FOREACH_MIGRATABLE into - ram.h - -RAMBLOCK_FOREACH_MIGRATABLE is need in dirtyrate measure, -move the existing definition up into migration/ram.h - -Signed-off-by: Chuan Zheng -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: David Edmondson -Reviewed-by: Li Qiang -Message-Id: <1600237327-33618-6-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/dirtyrate.c | 1 + - migration/ram.c | 11 +---------- - migration/ram.h | 10 ++++++++++ - 3 files changed, 12 insertions(+), 10 deletions(-) - -diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c -index cbb323d6ec..1ccc71077d 100644 ---- a/migration/dirtyrate.c -+++ b/migration/dirtyrate.c -@@ -20,6 +20,7 @@ - #include "qemu/rcu_queue.h" - #include "qapi/qapi-commands-migration.h" - #include "migration.h" -+#include "ram.h" - #include "dirtyrate.h" - - static int CalculatingState = DIRTY_RATE_STATUS_UNSTARTED; -diff --git a/migration/ram.c b/migration/ram.c -index 848059d9fb..1a33c7b3e2 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -159,21 +159,12 @@ out: - return ret; - } - --static bool ramblock_is_ignored(RAMBlock *block) -+bool ramblock_is_ignored(RAMBlock *block) - { - return !qemu_ram_is_migratable(block) || - (migrate_ignore_shared() && qemu_ram_is_shared(block)); - } - --/* Should be holding either ram_list.mutex, or the RCU lock. */ --#define RAMBLOCK_FOREACH_NOT_IGNORED(block) \ -- INTERNAL_RAMBLOCK_FOREACH(block) \ -- if (ramblock_is_ignored(block)) {} else -- --#define RAMBLOCK_FOREACH_MIGRATABLE(block) \ -- INTERNAL_RAMBLOCK_FOREACH(block) \ -- if (!qemu_ram_is_migratable(block)) {} else -- - #undef RAMBLOCK_FOREACH - - int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque) -diff --git a/migration/ram.h b/migration/ram.h -index a788ff0e8e..565ec86b1f 100644 ---- a/migration/ram.h -+++ b/migration/ram.h -@@ -37,6 +37,16 @@ extern MigrationStats ram_counters; - extern XBZRLECacheStats xbzrle_counters; - extern CompressionStats compression_counters; - -+bool ramblock_is_ignored(RAMBlock *block); -+/* Should be holding either ram_list.mutex, or the RCU lock. */ -+#define RAMBLOCK_FOREACH_NOT_IGNORED(block) \ -+ INTERNAL_RAMBLOCK_FOREACH(block) \ -+ if (ramblock_is_ignored(block)) {} else -+ -+#define RAMBLOCK_FOREACH_MIGRATABLE(block) \ -+ INTERNAL_RAMBLOCK_FOREACH(block) \ -+ if (!qemu_ram_is_migratable(block)) {} else -+ - int xbzrle_cache_resize(int64_t new_size, Error **errp); - uint64_t ram_bytes_remaining(void); - uint64_t ram_bytes_total(void); --- -2.27.0 - diff --git a/migration-dirtyrate-present-dirty-rate-only-when-que.patch b/migration-dirtyrate-present-dirty-rate-only-when-que.patch deleted file mode 100644 index d6d5dd423913c89888c29e530b18009bf1f63f50..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-present-dirty-rate-only-when-que.patch +++ /dev/null @@ -1,69 +0,0 @@ -From ba399ad806d195f31d0b76fa55363a4147459a5b Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Tue, 29 Sep 2020 11:42:18 +0800 -Subject: [PATCH] migration/dirtyrate: present dirty rate only when querying - the rate has completed - -Make dirty_rate field optional, present dirty rate only when querying -the rate has completed. -The qmp results is shown as follow: -@unstarted: -{"return":{"status":"unstarted","start-time":0,"calc-time":0},"id":"libvirt-12"} -@measuring: -{"return":{"status":"measuring","start-time":102931,"calc-time":1},"id":"libvirt-85"} -@measured: -{"return":{"status":"measured","dirty-rate":4,"start-time":150146,"calc-time":1},"id":"libvirt-15"} - -Signed-off-by: Chuan Zheng -Reviewed-by: David Edmondson -Message-Id: <1601350938-128320-3-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/dirtyrate.c | 3 +-- - qapi/migration.json | 8 +++----- - 2 files changed, 4 insertions(+), 7 deletions(-) - -diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c -index f1c007d569..00c8085456 100644 ---- a/migration/dirtyrate.c -+++ b/migration/dirtyrate.c -@@ -69,9 +69,8 @@ static struct DirtyRateInfo *query_dirty_rate_info(void) - struct DirtyRateInfo *info = g_malloc0(sizeof(DirtyRateInfo)); - - if (atomic_read(&CalculatingState) == DIRTY_RATE_STATUS_MEASURED) { -+ info->has_dirty_rate = true; - info->dirty_rate = dirty_rate; -- } else { -- info->dirty_rate = -1; - } - - info->status = CalculatingState; -diff --git a/qapi/migration.json b/qapi/migration.json -index 76f5b42493..6844ddfab3 100644 ---- a/qapi/migration.json -+++ b/qapi/migration.json -@@ -1468,10 +1468,8 @@ - # - # Information about current dirty page rate of vm. - # --# @dirty-rate: @dirtyrate describing the dirty page rate of vm --# in units of MB/s. --# If this field returns '-1', it means querying has not --# yet started or completed. -+# @dirty-rate: an estimate of the dirty page rate of the VM in units of -+# MB/s, present only when estimating the rate has completed. - # - # @status: status containing dirtyrate query status includes - # 'unstarted' or 'measuring' or 'measured' -@@ -1484,7 +1482,7 @@ - # - ## - { 'struct': 'DirtyRateInfo', -- 'data': {'dirty-rate': 'int64', -+ 'data': {'*dirty-rate': 'int64', - 'status': 'DirtyRateStatus', - 'start-time': 'int64', - 'calc-time': 'int64'} } --- -2.27.0 - diff --git a/migration-dirtyrate-record-start_time-and-calc_time-.patch b/migration-dirtyrate-record-start_time-and-calc_time-.patch deleted file mode 100644 index a4a4fed2c90eb99565d7712a6565c2284331b29c..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-record-start_time-and-calc_time-.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 5de3e40a6c1a4afcc2612ac109326956e7cded63 Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Tue, 29 Sep 2020 11:42:17 +0800 -Subject: [PATCH] migration/dirtyrate: record start_time and calc_time while at - the measuring state - -Querying could include both the start-time and the calc-time while at the measuring -state, allowing a caller to determine when they should expect to come back looking -for a result. - -Signed-off-by: Chuan Zheng -Message-Id: <1601350938-128320-2-git-send-email-zhengchuan@huawei.com> -Reviewed-by: David Edmondson -Signed-off-by: Dr. David Alan Gilbert ---- - migration/dirtyrate.c | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - -diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c -index 80936a4ca6..f1c007d569 100644 ---- a/migration/dirtyrate.c -+++ b/migration/dirtyrate.c -@@ -83,14 +83,14 @@ static struct DirtyRateInfo *query_dirty_rate_info(void) - return info; - } - --static void reset_dirtyrate_stat(void) -+static void init_dirtyrate_stat(int64_t start_time, int64_t calc_time) - { - DirtyStat.total_dirty_samples = 0; - DirtyStat.total_sample_count = 0; - DirtyStat.total_block_mem_MB = 0; - DirtyStat.dirty_rate = -1; -- DirtyStat.start_time = 0; -- DirtyStat.calc_time = 0; -+ DirtyStat.start_time = start_time; -+ DirtyStat.calc_time = calc_time; - } - - static void update_dirtyrate_stat(struct RamblockDirtyInfo *info) -@@ -335,7 +335,6 @@ static void calculate_dirtyrate(struct DirtyRateConfig config) - int64_t initial_time; - - rcu_register_thread(); -- reset_dirtyrate_stat(); - rcu_read_lock(); - initial_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); - if (!record_ramblock_hash_info(&block_dinfo, config, &block_count)) { -@@ -365,6 +364,8 @@ void *get_dirtyrate_thread(void *arg) - { - struct DirtyRateConfig config = *(struct DirtyRateConfig *)arg; - int ret; -+ int64_t start_time; -+ int64_t calc_time; - - ret = dirtyrate_set_state(&CalculatingState, DIRTY_RATE_STATUS_UNSTARTED, - DIRTY_RATE_STATUS_MEASURING); -@@ -373,6 +374,10 @@ void *get_dirtyrate_thread(void *arg) - return NULL; - } - -+ start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000; -+ calc_time = config.sample_period_seconds; -+ init_dirtyrate_stat(start_time, calc_time); -+ - calculate_dirtyrate(config); - - ret = dirtyrate_set_state(&CalculatingState, DIRTY_RATE_STATUS_MEASURING, --- -2.27.0 - diff --git a/migration-dirtyrate-setup-up-query-dirtyrate-framwor.patch b/migration-dirtyrate-setup-up-query-dirtyrate-framwor.patch deleted file mode 100644 index f4a2b4ff12bf88e0f37211df631867d0ee6f6a6d..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-setup-up-query-dirtyrate-framwor.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 18dbd0efc14aa190b2f4c364fa614b0994af5af0 Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Wed, 16 Sep 2020 14:21:56 +0800 -Subject: [PATCH] migration/dirtyrate: setup up query-dirtyrate framwork - -Add get_dirtyrate_thread() functions to setup query-dirtyrate -framework. - -Signed-off-by: Chuan Zheng -Signed-off-by: YanYing Zhuang -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: David Edmondson -Reviewed-by: Li Qiang -Message-Id: <1600237327-33618-2-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - Makefile.target | 1 + - migration/dirtyrate.c | 38 ++++++++++++++++++++++++++++++++++++++ - migration/dirtyrate.h | 28 ++++++++++++++++++++++++++++ - 3 files changed, 67 insertions(+) - create mode 100644 migration/dirtyrate.c - create mode 100644 migration/dirtyrate.h - -diff --git a/Makefile.target b/Makefile.target -index 933b27453a..5ea840964c 100644 ---- a/Makefile.target -+++ b/Makefile.target -@@ -161,6 +161,7 @@ obj-y += qapi/ - obj-y += memory.o - obj-y += memory_mapping.o - obj-y += migration/ram.o -+obj-y += migration/dirtyrate.o - LIBS := $(libs_softmmu) $(LIBS) - - # Hardware support -diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c -new file mode 100644 -index 0000000000..29ef663acb ---- /dev/null -+++ b/migration/dirtyrate.c -@@ -0,0 +1,38 @@ -+/* -+ * Dirtyrate implement code -+ * -+ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO.,LTD. -+ * -+ * Authors: -+ * Chuan Zheng -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#include "qemu/osdep.h" -+#include "qapi/error.h" -+#include "cpu.h" -+#include "qemu/config-file.h" -+#include "exec/memory.h" -+#include "exec/ram_addr.h" -+#include "exec/target_page.h" -+#include "qemu/rcu_queue.h" -+#include "qapi/qapi-commands-migration.h" -+#include "migration.h" -+#include "dirtyrate.h" -+ -+static void calculate_dirtyrate(struct DirtyRateConfig config) -+{ -+ /* todo */ -+ return; -+} -+ -+void *get_dirtyrate_thread(void *arg) -+{ -+ struct DirtyRateConfig config = *(struct DirtyRateConfig *)arg; -+ -+ calculate_dirtyrate(config); -+ -+ return NULL; -+} -diff --git a/migration/dirtyrate.h b/migration/dirtyrate.h -new file mode 100644 -index 0000000000..84ab9409ac ---- /dev/null -+++ b/migration/dirtyrate.h -@@ -0,0 +1,28 @@ -+/* -+ * Dirtyrate common functions -+ * -+ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD. -+ * -+ * Authors: -+ * Chuan Zheng -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#ifndef QEMU_MIGRATION_DIRTYRATE_H -+#define QEMU_MIGRATION_DIRTYRATE_H -+ -+/* -+ * Sample 512 pages per GB as default. -+ * TODO: Make it configurable. -+ */ -+#define DIRTYRATE_DEFAULT_SAMPLE_PAGES 512 -+ -+struct DirtyRateConfig { -+ uint64_t sample_pages_per_gigabytes; /* sample pages per GB */ -+ int64_t sample_period_seconds; /* time duration between two sampling */ -+}; -+ -+void *get_dirtyrate_thread(void *arg); -+#endif --- -2.27.0 - diff --git a/migration-dirtyrate-simplify-includes-in-dirtyrate.c.patch b/migration-dirtyrate-simplify-includes-in-dirtyrate.c.patch deleted file mode 100644 index 3bdb51b5d936d3a51bc9321815f98b742070b3ab..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-simplify-includes-in-dirtyrate.c.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 91eed005e1af25f49ab38732cd3c9ea8071331b0 Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Fri, 30 Oct 2020 11:58:01 +0800 -Subject: [PATCH] migration/dirtyrate: simplify includes in dirtyrate.c - -Remove redundant blank line which is left by Commit 662770af7c6e8c, -also take this opportunity to remove redundant includes in dirtyrate.c. - -Signed-off-by: Chuan Zheng -Message-Id: <1604030281-112946-1-git-send-email-zhengchuan@huawei.com> -Reviewed-by: Dr. David Alan Gilbert -Signed-off-by: Dr. David Alan Gilbert ---- - migration/dirtyrate.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c -index 00c8085456..9a6d0e2cc6 100644 ---- a/migration/dirtyrate.c -+++ b/migration/dirtyrate.c -@@ -10,17 +10,16 @@ - * See the COPYING file in the top-level directory. - */ - --#include - #include "qemu/osdep.h" -+#include - #include "qapi/error.h" - #include "cpu.h" --#include "qemu/config-file.h" - #include "exec/memory.h" - #include "exec/ram_addr.h" - #include "exec/target_page.h" - #include "qemu/rcu_queue.h" -+#include "qemu/error-report.h" - #include "qapi/qapi-commands-migration.h" --#include "migration.h" - #include "ram.h" - #include "trace.h" - #include "dirtyrate.h" --- -2.27.0 - diff --git a/migration-dirtyrate-skip-sampling-ramblock-with-size.patch b/migration-dirtyrate-skip-sampling-ramblock-with-size.patch deleted file mode 100644 index 0e649e3cdef1a3283d1ed0fde909902d5f3274a7..0000000000000000000000000000000000000000 --- a/migration-dirtyrate-skip-sampling-ramblock-with-size.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0fcff073292e78e08ee24eb784783156b2974f4a Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Wed, 16 Sep 2020 14:22:03 +0800 -Subject: [PATCH] migration/dirtyrate: skip sampling ramblock with size below - MIN_RAMBLOCK_SIZE - -In order to sample real RAM, skip ramblock with size below MIN_RAMBLOCK_SIZE -which is set as 128M. - -Signed-off-by: Chuan Zheng -Reviewed-by: David Edmondson -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: Li Qiang -Message-Id: <1600237327-33618-9-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/dirtyrate.c | 21 +++++++++++++++++++++ - migration/dirtyrate.h | 5 +++++ - 2 files changed, 26 insertions(+) - -diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c -index 0412f825dc..97bb883850 100644 ---- a/migration/dirtyrate.c -+++ b/migration/dirtyrate.c -@@ -138,6 +138,18 @@ static void get_ramblock_dirty_info(RAMBlock *block, - strcpy(info->idstr, qemu_ram_get_idstr(block)); - } - -+static bool skip_sample_ramblock(RAMBlock *block) -+{ -+ /* -+ * Sample only blocks larger than MIN_RAMBLOCK_SIZE. -+ */ -+ if (qemu_ram_get_used_length(block) < (MIN_RAMBLOCK_SIZE << 10)) { -+ return true; -+ } -+ -+ return false; -+} -+ - static bool record_ramblock_hash_info(struct RamblockDirtyInfo **block_dinfo, - struct DirtyRateConfig config, - int *block_count) -@@ -150,6 +162,9 @@ static bool record_ramblock_hash_info(struct RamblockDirtyInfo **block_dinfo, - bool ret = false; - - RAMBLOCK_FOREACH_MIGRATABLE(block) { -+ if (skip_sample_ramblock(block)) { -+ continue; -+ } - total_count++; - } - -@@ -159,6 +174,9 @@ static bool record_ramblock_hash_info(struct RamblockDirtyInfo **block_dinfo, - } - - RAMBLOCK_FOREACH_MIGRATABLE(block) { -+ if (skip_sample_ramblock(block)) { -+ continue; -+ } - if (index >= total_count) { - break; - } -@@ -225,6 +243,9 @@ static bool compare_page_hash_info(struct RamblockDirtyInfo *info, - RAMBlock *block = NULL; - - RAMBLOCK_FOREACH_MIGRATABLE(block) { -+ if (skip_sample_ramblock(block)) { -+ continue; -+ } - block_dinfo = find_block_matched(block, block_count, info); - if (block_dinfo == NULL) { - continue; -diff --git a/migration/dirtyrate.h b/migration/dirtyrate.h -index 312debca6f..be5b8ec2b1 100644 ---- a/migration/dirtyrate.h -+++ b/migration/dirtyrate.h -@@ -24,6 +24,11 @@ - */ - #define RAMBLOCK_INFO_MAX_LEN 256 - -+/* -+ * Minimum RAMBlock size to sample, in megabytes. -+ */ -+#define MIN_RAMBLOCK_SIZE 128 -+ - struct DirtyRateConfig { - uint64_t sample_pages_per_gigabytes; /* sample pages per GB */ - int64_t sample_period_seconds; /* time duration between two sampling */ --- -2.27.0 - diff --git a/migration-fix-COLO-broken-caused-by-a-previous-commi.patch b/migration-fix-COLO-broken-caused-by-a-previous-commi.patch deleted file mode 100644 index 3ac65d9c79a43e8233c80d633dc02835e9f8344c..0000000000000000000000000000000000000000 --- a/migration-fix-COLO-broken-caused-by-a-previous-commi.patch +++ /dev/null @@ -1,39 +0,0 @@ -From c635692b4e75db3f9547f6d4ed9d73d1cdb34989 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 2 Dec 2020 14:43:45 +0800 -Subject: [PATCH] migration: fix COLO broken caused by a previous commit - -This commit "migration: Create migration_is_running()" broke -COLO. Becuase there is a process broken by this commit. - -colo_process_checkpoint - ->colo_do_checkpoint_transaction - ->migrate_set_block_enabled - ->qmp_migrate_set_capabilities - -It can be fixed by make COLO process as an exception, -Maybe we need a better way to fix it. - -Cc: Juan Quintela -Signed-off-by: zhanghailiang -Reviewed-by: Juan Quintela -Signed-off-by: Juan Quintela ---- - migration/migration.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/migration/migration.c b/migration/migration.c -index 923a1d9d3f..0e396f22b4 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -833,7 +833,6 @@ bool migration_is_running(int state) - case MIGRATION_STATUS_PRE_SWITCHOVER: - case MIGRATION_STATUS_DEVICE: - case MIGRATION_STATUS_CANCELLING: -- case MIGRATION_STATUS_COLO: - return true; - - default: --- -2.27.0 - diff --git a/migration-fix-cleanup_bh-leak-on-resume.patch b/migration-fix-cleanup_bh-leak-on-resume.patch deleted file mode 100644 index 6b75ed01b8faa4c3d5b9d1e17e6d3d205daa2396..0000000000000000000000000000000000000000 --- a/migration-fix-cleanup_bh-leak-on-resume.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 1d7c227bbb24665cea03f96a984ad6be223ac40c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Wed, 25 Mar 2020 19:47:21 +0100 -Subject: [PATCH 2/5] migration: fix cleanup_bh leak on resume -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Since commit 8c6b0356b53977bcfdea5299db07884915425b0c ("util/async: -make bh_aio_poll() O(1)"), migration-test reveals a leak: - -QTEST_QEMU_BINARY=x86_64-softmmu/qemu-system-x86_64 -tests/qtest/migration-test -p /x86_64/migration/postcopy/recovery -tests/qtest/libqtest.c:140: kill_qemu() tried to terminate QEMU -process but encountered exit status 1 (expected 0) - -================================================================= -==2082571==ERROR: LeakSanitizer: detected memory leaks - -Direct leak of 40 byte(s) in 1 object(s) allocated from: - #0 0x7f25971dfc58 in __interceptor_malloc (/lib64/libasan.so.5+0x10dc58) - #1 0x7f2596d08358 in g_malloc (/lib64/libglib-2.0.so.0+0x57358) - #2 0x560970d006f8 in qemu_bh_new /home/elmarco/src/qemu/util/main-loop.c:532 - #3 0x5609704afa02 in migrate_fd_connect -/home/elmarco/src/qemu/migration/migration.c:3407 - #4 0x5609704b6b6f in migration_channel_connect -/home/elmarco/src/qemu/migration/channel.c:92 - #5 0x5609704b2bfb in socket_outgoing_migration -/home/elmarco/src/qemu/migration/socket.c:108 - #6 0x560970b9bd6c in qio_task_complete /home/elmarco/src/qemu/io/task.c:196 - #7 0x560970b9aa97 in qio_task_thread_result -/home/elmarco/src/qemu/io/task.c:111 - #8 0x7f2596cfee3a (/lib64/libglib-2.0.so.0+0x4de3a) - -Signed-off-by: Marc-André Lureau -Message-Id: <20200325184723.2029630-2-marcandre.lureau@redhat.com> -Reviewed-by: Juan Quintela -Signed-off-by: Paolo Bonzini -Signed-off-by: Zhenyu Ye ---- - migration/migration.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/migration/migration.c b/migration/migration.c -index 8f2fc2b4..7949f2a4 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -3313,7 +3313,12 @@ void migrate_fd_connect(MigrationState *s, Error *error_in) - bool resume = s->state == MIGRATION_STATUS_POSTCOPY_PAUSED; - - s->expected_downtime = s->parameters.downtime_limit; -- s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup_bh, s); -+ if (resume) { -+ assert(s->cleanup_bh); -+ } else { -+ assert(!s->cleanup_bh); -+ s->cleanup_bh = qemu_bh_new(migrate_fd_cleanup_bh, s); -+ } - if (error_in) { - migrate_fd_error(s, error_in); - migrate_fd_cleanup(s); --- -2.22.0.windows.1 - diff --git a/migration-fix-memory-leak-in-qmp_migrate_set_paramet.patch b/migration-fix-memory-leak-in-qmp_migrate_set_paramet.patch deleted file mode 100644 index 46775ae5ee200005e5d56f10ccd2c02e75685c7a..0000000000000000000000000000000000000000 --- a/migration-fix-memory-leak-in-qmp_migrate_set_paramet.patch +++ /dev/null @@ -1,78 +0,0 @@ -From d65b5b20f4ada9e6c5af37b0fb59fa4709c4bdc9 Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Fri, 5 Mar 2021 16:06:52 +0800 -Subject: [PATCH] migration: fix memory leak in qmp_migrate_set_parameters - -"tmp.tls_hostname" and "tmp.tls_creds" allocated by migrate_params_test_apply() -is forgot to free at the end of qmp_migrate_set_parameters(). Fix that. - -The leak stack: -Direct leak of 2 byte(s) in 2 object(s) allocated from: - #0 0xffffb597c20b in __interceptor_malloc (/usr/lib64/libasan.so.4+0xd320b) - #1 0xffffb52dcb1b in g_malloc (/usr/lib64/libglib-2.0.so.0+0x58b1b) - #2 0xffffb52f8143 in g_strdup (/usr/lib64/libglib-2.0.so.0+0x74143) - #3 0xaaaac52447fb in migrate_params_test_apply (/usr/src/debug/qemu-4.1.0/migration/migration.c:1377) - #4 0xaaaac52fdca7 in qmp_migrate_set_parameters (/usr/src/debug/qemu-4.1.0/qapi/qapi-commands-migration.c:192) - #5 0xaaaac551d543 in qmp_dispatch (/usr/src/debug/qemu-4.1.0/qapi/qmp-dispatch.c:165) - #6 0xaaaac52a0a8f in qmp_dispatch (/usr/src/debug/qemu-4.1.0/monitor/qmp.c:125) - #7 0xaaaac52a1c7f in monitor_qmp_dispatch (/usr/src/debug/qemu-4.1.0/monitor/qmp.c:214) - #8 0xaaaac55cb0cf in aio_bh_call (/usr/src/debug/qemu-4.1.0/util/async.c:117) - #9 0xaaaac55d4543 in aio_bh_poll (/usr/src/debug/qemu-4.1.0/util/aio-posix.c:459) - #10 0xaaaac55cae0f in aio_dispatch (/usr/src/debug/qemu-4.1.0/util/async.c:268) - #11 0xffffb52d6a7b in g_main_context_dispatch (/usr/lib64/libglib-2.0.so.0+0x52a7b) - #12 0xaaaac55d1e3b(/usr/bin/qemu-kvm-4.1.0+0x1622e3b) - #13 0xaaaac4e314bb(/usr/bin/qemu-kvm-4.1.0+0xe824bb) - #14 0xaaaac47f45ef(/usr/bin/qemu-kvm-4.1.0+0x8455ef) - #15 0xffffb4bfef3f in __libc_start_main (/usr/lib64/libc.so.6+0x23f3f) - #16 0xaaaac47ffacb(/usr/bin/qemu-kvm-4.1.0+0x850acb) - -Direct leak of 2 byte(s) in 2 object(s) allocated from: - #0 0xffffb597c20b in __interceptor_malloc (/usr/lib64/libasan.so.4+0xd320b) - #1 0xffffb52dcb1b in g_malloc (/usr/lib64/libglib-2.0.so.0+0x58b1b) - #2 0xffffb52f8143 in g_strdup (/usr/lib64/libglib-2.0.so.0+0x74143) - #3 0xaaaac5244893 in migrate_params_test_apply (/usr/src/debug/qemu-4.1.0/migration/migration.c:1382) - #4 0xaaaac52fdca7 in qmp_migrate_set_parameters (/usr/src/debug/qemu-4.1.0/qapi/qapi-commands-migration.c:192) - #5 0xaaaac551d543 in qmp_dispatch (/usr/src/debug/qemu-4.1.0/qapi/qmp-dispatch.c) - #6 0xaaaac52a0a8f in qmp_dispatch (/usr/src/debug/qemu-4.1.0/monitor/qmp.c:125) - #7 0xaaaac52a1c7f in monitor_qmp_dispatch (/usr/src/debug/qemu-4.1.0/monitor/qmp.c:214) - #8 0xaaaac55cb0cf in aio_bh_call (/usr/src/debug/qemu-4.1.0/util/async.c:117) - #9 0xaaaac55d4543 in aio_bh_poll (/usr/src/debug/qemu-4.1.0/util/aio-posix.c:459) - #10 0xaaaac55cae0f in in aio_dispatch (/usr/src/debug/qemu-4.1.0/util/async.c:268) - #11 0xffffb52d6a7b in g_main_context_dispatch (/usr/lib64/libglib-2.0.so.0+0x52a7b) - #12 0xaaaac55d1e3b(/usr/bin/qemu-kvm-4.1.0+0x1622e3b) - #13 0xaaaac4e314bb(/usr/bin/qemu-kvm-4.1.0+0xe824bb) - #14 0xaaaac47f45ef (/usr/bin/qemu-kvm-4.1.0+0x8455ef) - #15 0xffffb4bfef3f in __libc_start_main (/usr/lib64/libc.so.6+0x23f3f) - #16 0xaaaac47ffacb(/usr/bin/qemu-kvm-4.1.0+0x850acb) - -Signed-off-by: Chuan Zheng -Reviewed-by: KeQian Zhu -Reviewed-by: HaiLiang -Reviewed-by: Juan Quintela -Signed-off-by: Juan Quintela ---- - migration/migration.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/migration/migration.c b/migration/migration.c -index 17a5c16c79..9b40380d7c 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -1291,12 +1291,12 @@ static void migrate_params_test_apply(MigrateSetParameters *params, - - if (params->has_tls_creds) { - assert(params->tls_creds->type == QTYPE_QSTRING); -- dest->tls_creds = g_strdup(params->tls_creds->u.s); -+ dest->tls_creds = params->tls_creds->u.s; - } - - if (params->has_tls_hostname) { - assert(params->tls_hostname->type == QTYPE_QSTRING); -- dest->tls_hostname = g_strdup(params->tls_hostname->u.s); -+ dest->tls_hostname = params->tls_hostname->u.s; - } - - if (params->has_max_bandwidth) { --- -2.27.0 - diff --git a/migration-fix-multifd_send_pages-next-channel.patch b/migration-fix-multifd_send_pages-next-channel.patch deleted file mode 100644 index 4bb113c644c4175386636e02a5d7188e8c2e408c..0000000000000000000000000000000000000000 --- a/migration-fix-multifd_send_pages-next-channel.patch +++ /dev/null @@ -1,50 +0,0 @@ -From c11a23b92334ae86eddfdc2b155d404293891985 Mon Sep 17 00:00:00 2001 -From: alexchen -Date: Tue, 8 Sep 2020 11:18:50 +0000 -Subject: [PATCH 08/11] migration: fix multifd_send_pages() next channel - -multifd_send_pages() loops around the available channels, -the next channel to use between two calls to multifd_send_pages() is stored -inside a local static variable, next_channel. - -It works well, except if the number of channels decreases between two calls -to multifd_send_pages(). In this case, the loop can try to access the -data of a channel that doesn't exist anymore. - -The problem can be triggered if we start a migration with a given number of -channels and then we cancel the migration to restart it with a lower number. -This ends generally with an error like: -qemu-system-ppc64: .../util/qemu-thread-posix.c:77: qemu_mutex_lock_impl: Assertion `mutex->initialized' failed. - -This patch fixes the error by capping next_channel with the current number -of channels before using it. - -Signed-off-by: Laurent Vivier -Message-Id: <20200617113154.593233-1-lvivier@redhat.com> -Reviewed-by: Juan Quintela -Signed-off-by: Dr. David Alan Gilbert -Signed-off-by: BiaoXiang Ye ---- - migration/ram.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/migration/ram.c b/migration/ram.c -index 83cabec6..ac033f22 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -931,6 +931,12 @@ static int multifd_send_pages(RAMState *rs) - uint64_t transferred; - - qemu_sem_wait(&multifd_send_state->channels_ready); -+ /* -+ * next_channel can remain from a previous migration that was -+ * using more channels, so ensure it doesn't overflow if the -+ * limit is lower now. -+ */ -+ next_channel %= migrate_multifd_channels(); - for (i = next_channel;; i = (i + 1) % migrate_multifd_channels()) { - p = &multifd_send_state->params[i]; - --- -2.27.0.dirty - diff --git a/migration-multifd-clean-pages-after-filling-packet.patch b/migration-multifd-clean-pages-after-filling-packet.patch deleted file mode 100644 index 596c5244691dc0a60a486598a74e23466a62645b..0000000000000000000000000000000000000000 --- a/migration-multifd-clean-pages-after-filling-packet.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 0f7e704a4faa661583ea6d82659f206e561f23d4 Mon Sep 17 00:00:00 2001 -From: Wei Yang -Date: Sat, 26 Oct 2019 07:19:59 +0800 -Subject: [PATCH 3/8] migration/multifd: clean pages after filling packet - -This is a preparation for the next patch: - - not use multifd during postcopy. - -Without enabling postcopy, everything looks good. While after enabling -postcopy, migration may fail even not use multifd during postcopy. The -reason is the pages is not properly cleared and *old* target page will -continue to be transferred. - -After clean pages, migration succeeds. - -Signed-off-by: Wei Yang -Reviewed-by: Juan Quintela -Signed-off-by: Juan Quintela ---- - migration/ram.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/migration/ram.c b/migration/ram.c -index 840e354..c2eb1ed 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -947,10 +947,10 @@ static int multifd_send_pages(RAMState *rs) - } - qemu_mutex_unlock(&p->mutex); - } -- p->pages->used = 0; -+ assert(!p->pages->used); -+ assert(!p->pages->block); - - p->packet_num = multifd_send_state->packet_num++; -- p->pages->block = NULL; - multifd_send_state->pages = p->pages; - p->pages = pages; - transferred = ((uint64_t) pages->used) * TARGET_PAGE_SIZE + p->packet_len; -@@ -1137,6 +1137,7 @@ static void *multifd_send_thread(void *opaque) - p->num_packets++; - p->num_pages += used; - p->pages->used = 0; -+ p->pages->block = NULL; - qemu_mutex_unlock(&p->mutex); - - trace_multifd_send(p->id, packet_num, used, flags, --- -1.8.3.1 - diff --git a/migration-multifd-fix-destroyed-mutex-access-in-term.patch b/migration-multifd-fix-destroyed-mutex-access-in-term.patch deleted file mode 100644 index a927ea533c253ff242c5867cde1055453668c1c5..0000000000000000000000000000000000000000 --- a/migration-multifd-fix-destroyed-mutex-access-in-term.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 34d797aa134a33c1d67ca85d9d9f996d58162276 Mon Sep 17 00:00:00 2001 -From: Jiahui Cen -Date: Wed, 23 Oct 2019 11:47:37 +0800 -Subject: [PATCH 09/10] migration/multifd: fix destroyed mutex access in - terminating multifd threads - -One multifd will lock all the other multifds' IOChannel mutex to inform them -to quit by setting p->quit or shutting down p->c. In this senario, if some -multifds had already been terminated and multifd_load_cleanup/multifd_save_cleanup -had destroyed their mutex, it could cause destroyed mutex access when trying -lock their mutex. - -Here is the coredump stack: - #0 0x00007f81a2794437 in raise () from /usr/lib64/libc.so.6 - #1 0x00007f81a2795b28 in abort () from /usr/lib64/libc.so.6 - #2 0x00007f81a278d1b6 in __assert_fail_base () from /usr/lib64/libc.so.6 - #3 0x00007f81a278d262 in __assert_fail () from /usr/lib64/libc.so.6 - #4 0x000055eb1bfadbd3 in qemu_mutex_lock_impl (mutex=0x55eb1e2d1988, file=, line=) at util/qemu-thread-posix.c:64 - #5 0x000055eb1bb4564a in multifd_send_terminate_threads (err=) at migration/ram.c:1015 - #6 0x000055eb1bb4bb7f in multifd_send_thread (opaque=0x55eb1e2d19f8) at migration/ram.c:1171 - #7 0x000055eb1bfad628 in qemu_thread_start (args=0x55eb1e170450) at util/qemu-thread-posix.c:502 - #8 0x00007f81a2b36df5 in start_thread () from /usr/lib64/libpthread.so.0 - #9 0x00007f81a286048d in clone () from /usr/lib64/libc.so.6 - -To fix it up, let's destroy the mutex after all the other multifd threads had -been terminated. - -Change-Id: I4124d43e8558ba302052bdc53fdae7cfcf9d8687 -Signed-off-by: Jiahui Cen -Signed-off-by: Ying Fang -Reviewed-by: Juan Quintela -Signed-off-by: Juan Quintela ---- - migration/ram.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/migration/ram.c b/migration/ram.c -index 029f1cdf..d7d2d5ec 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1033,6 +1033,10 @@ void multifd_save_cleanup(void) - if (p->running) { - qemu_thread_join(&p->thread); - } -+ } -+ for (i = 0; i < migrate_multifd_channels(); i++) { -+ MultiFDSendParams *p = &multifd_send_state->params[i]; -+ - socket_send_channel_destroy(p->c); - p->c = NULL; - qemu_mutex_destroy(&p->mutex); -@@ -1306,6 +1310,10 @@ int multifd_load_cleanup(Error **errp) - qemu_sem_post(&p->sem_sync); - qemu_thread_join(&p->thread); - } -+ } -+ for (i = 0; i < migrate_multifd_channels(); i++) { -+ MultiFDRecvParams *p = &multifd_recv_state->params[i]; -+ - object_unref(OBJECT(p->c)); - p->c = NULL; - qemu_mutex_destroy(&p->mutex); --- -2.19.1 diff --git a/migration-multifd-fix-hangup-with-TLS-Multifd-due-to.patch b/migration-multifd-fix-hangup-with-TLS-Multifd-due-to.patch deleted file mode 100644 index 021fbcf8a6e4053b5e051ce3885b677d678259ca..0000000000000000000000000000000000000000 --- a/migration-multifd-fix-hangup-with-TLS-Multifd-due-to.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 26ffadd08711aa4ef62932ac0ecf5048518b2801 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 2 Dec 2020 14:50:12 +0800 -Subject: [PATCH] migration/multifd: fix hangup with TLS-Multifd due to - blocking handshake -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The qemu main loop could hang up forever when we enable TLS+Multifd. -The Src multifd_send_0 invokes tls handshake, it sends hello to sever -and wait response. -However, the Dst main qemu loop has been waiting recvmsg() for multifd_recv_1. -Both of Src and Dst main qemu loop are blocking and waiting for reponse which -results in hanging up forever. - -Src: (multifd_send_0) Dst: (multifd_recv_1) -multifd_channel_connect migration_channel_process_incoming - multifd_tls_channel_connect migration_tls_channel_process_incoming - multifd_tls_channel_connect qio_channel_tls_handshake_task - qio_channel_tls_handshake gnutls_handshake - qio_channel_tls_handshake_task ... - qcrypto_tls_session_handshake ... - gnutls_handshake ... - ... ... - recvmsg (Blocking I/O waiting for response) recvmsg (Blocking I/O waiting for response) - -Fix this by offloadinig handshake work to a background thread. - -Reported-by: Yan Jin -Suggested-by: Daniel P. Berrangé -Signed-off-by: Chuan Zheng -Message-Id: <1604643893-8223-1-git-send-email-zhengchuan@huawei.com> -Reviewed-by: Daniel P. Berrangé -Signed-off-by: Dr. David Alan Gilbert ---- - migration/ram.c | 23 +++++++++++++++++------ - 1 file changed, 17 insertions(+), 6 deletions(-) - -diff --git a/migration/ram.c b/migration/ram.c -index dc9831d7f3..a37dbfc049 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1220,6 +1220,19 @@ static void multifd_tls_outgoing_handshake(QIOTask *task, - multifd_channel_connect(p, ioc, err); - } - -+static void *multifd_tls_handshake_thread(void *opaque) -+{ -+ MultiFDSendParams *p = opaque; -+ QIOChannelTLS *tioc = QIO_CHANNEL_TLS(p->c); -+ -+ qio_channel_tls_handshake(tioc, -+ multifd_tls_outgoing_handshake, -+ p, -+ NULL, -+ NULL); -+ return NULL; -+} -+ - static void multifd_tls_channel_connect(MultiFDSendParams *p, - QIOChannel *ioc, - Error **errp) -@@ -1235,12 +1248,10 @@ static void multifd_tls_channel_connect(MultiFDSendParams *p, - - trace_multifd_tls_outgoing_handshake_start(ioc, tioc, hostname); - qio_channel_set_name(QIO_CHANNEL(tioc), "multifd-tls-outgoing"); -- qio_channel_tls_handshake(tioc, -- multifd_tls_outgoing_handshake, -- p, -- NULL, -- NULL); -- -+ p->c = QIO_CHANNEL(tioc); -+ qemu_thread_create(&p->thread, "multifd-tls-handshake-worker", -+ multifd_tls_handshake_thread, p, -+ QEMU_THREAD_JOINABLE); - } - - static bool multifd_channel_connect(MultiFDSendParams *p, --- -2.27.0 - diff --git a/migration-multifd-fix-nullptr-access-in-multifd_send.patch b/migration-multifd-fix-nullptr-access-in-multifd_send.patch deleted file mode 100644 index f2d278a135434e3b0838be7876b1fe2a616816cd..0000000000000000000000000000000000000000 --- a/migration-multifd-fix-nullptr-access-in-multifd_send.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 6a08ee257a95d9f2514bd995e90ddf46d3f78b41 Mon Sep 17 00:00:00 2001 -From: Zheng Chuan -Date: Tue, 21 Apr 2020 19:49:26 +0800 -Subject: [PATCH 10/10] migration/multifd: fix nullptr access in - multifd_send_terminate_threads - -If the multifd_send_threads is not created when migration is failed, -multifd_save_cleanup would be called twice. In this senario, the -multifd_send_state is accessed after it has been released, the result -is that the source VM is crashing down. - -Here is the coredump stack: - Program received signal SIGSEGV, Segmentation fault. - 0x00005629333a78ef in multifd_send_terminate_threads (err=err@entry=0x0) at migration/ram.c:1012 - 1012 MultiFDSendParams *p = &multifd_send_state->params[i]; - #0 0x00005629333a78ef in multifd_send_terminate_threads (err=err@entry=0x0) at migration/ram.c:1012 - #1 0x00005629333ab8a9 in multifd_save_cleanup () at migration/ram.c:1028 - #2 0x00005629333abaea in multifd_new_send_channel_async (task=0x562935450e70, opaque=) at migration/ram.c:1202 - #3 0x000056293373a562 in qio_task_complete (task=task@entry=0x562935450e70) at io/task.c:196 - #4 0x000056293373a6e0 in qio_task_thread_result (opaque=0x562935450e70) at io/task.c:111 - #5 0x00007f475d4d75a7 in g_idle_dispatch () from /usr/lib64/libglib-2.0.so.0 - #6 0x00007f475d4da9a9 in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0 - #7 0x0000562933785b33 in glib_pollfds_poll () at util/main-loop.c:219 - #8 os_host_main_loop_wait (timeout=) at util/main-loop.c:242 - #9 main_loop_wait (nonblocking=nonblocking@entry=0) at util/main-loop.c:518 - #10 0x00005629334c5acf in main_loop () at vl.c:1810 - #11 0x000056293334d7bb in main (argc=, argv=, envp=) at vl.c:4471 - -If the multifd_send_threads is not created when migration is failed. -In this senario, we don't call multifd_save_cleanup in multifd_new_send_channel_async. - -Change-Id: I7441efe2ed542054ecd2a4da8146e2652824b452 -Signed-off-by: Zhimin Feng -Reviewed-by: Juan Quintela -Signed-off-by: Juan Quintela ---- - migration/ram.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/migration/ram.c b/migration/ram.c -index d7d2d5ec..1858d66c 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1205,7 +1205,15 @@ static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque) - - if (qio_task_propagate_error(task, &local_err)) { - migrate_set_error(migrate_get_current(), local_err); -- multifd_save_cleanup(); -+ /* Error happen, we need to tell who pay attention to me */ -+ qemu_sem_post(&multifd_send_state->channels_ready); -+ qemu_sem_post(&p->sem_sync); -+ /* -+ * Although multifd_send_thread is not created, but main migration -+ * thread neet to judge whether it is running, so we need to mark -+ * its status. -+ */ -+ p->quit = true; - } else { - p->c = QIO_CHANNEL(sioc); - qio_channel_set_delay(p->c, false); --- -2.19.1 diff --git a/migration-multifd-fix-nullptr-access-in-terminating-m.patch b/migration-multifd-fix-nullptr-access-in-terminating-m.patch deleted file mode 100644 index d403b28f28a708a94d7799618053e53c7d75b939..0000000000000000000000000000000000000000 --- a/migration-multifd-fix-nullptr-access-in-terminating-m.patch +++ /dev/null @@ -1,75 +0,0 @@ -From d9a847f0982fcca6f63031215065c346fcc27bbc Mon Sep 17 00:00:00 2001 -From: Zheng Chuan -Date: Fri, 24 Apr 2020 11:58:33 +0800 -Subject: [PATCH 06/10] migration/multifd: fix nullptr access in terminating - multifd threads - -One multifd channel will shutdown all the other multifd's IOChannel when it -fails to receive an IOChannel. In this senario, if some multifds had not -received its IOChannel yet, it would try to shutdown its IOChannel which could -cause nullptr access at qio_channel_shutdown. - -Here is the coredump stack: - #0 object_get_class (obj=obj@entry=0x0) at qom/object.c:908 - #1 0x00005563fdbb8f4a in qio_channel_shutdown (ioc=0x0, how=QIO_CHANNEL_SHUTDOWN_BOTH, errp=0x0) at io/channel.c:355 - #2 0x00005563fd7b4c5f in multifd_recv_terminate_threads (err=) at migration/ram.c:1280 - #3 0x00005563fd7bc019 in multifd_recv_new_channel (ioc=ioc@entry=0x556400255610, errp=errp@entry=0x7ffec07dce00) at migration/ram.c:1478 - #4 0x00005563fda82177 in migration_ioc_process_incoming (ioc=ioc@entry=0x556400255610, errp=errp@entry=0x7ffec07dce30) at migration/migration.c:605 - #5 0x00005563fda8567d in migration_channel_process_incoming (ioc=0x556400255610) at migration/channel.c:44 - #6 0x00005563fda83ee0 in socket_accept_incoming_migration (listener=0x5563fff6b920, cioc=0x556400255610, opaque=) at migration/socket -.c:166 - #7 0x00005563fdbc25cd in qio_net_listener_channel_func (ioc=, condition=, opaque=) at io/net-listener.c:54 - #8 0x00007f895b6fe9a9 in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0 - #9 0x00005563fdc18136 in glib_pollfds_poll () at util/main-loop.c:218 - #10 0x00005563fdc181b5 in os_host_main_loop_wait (timeout=1000000000) at util/main-loop.c:241 - #11 0x00005563fdc183a2 in main_loop_wait (nonblocking=nonblocking@entry=0) at util/main-loop.c:517 - #12 0x00005563fd8edb37 in main_loop () at vl.c:1791 - #13 0x00005563fd74fd45 in main (argc=, argv=, envp=) at vl.c:4473 - -To fix it up, let's check p->c before calling qio_channel_shutdown. - -Change-Id: Ib36c1b3d866a3ad92d1460512df840cfb8736ab6 -Signed-off-by: Jiahui Cen -Signed-off-by: Ying Fang -Reviewed-by: Juan Quintela -Signed-off-by: Juan Quintela ---- - migration/ram.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/migration/ram.c b/migration/ram.c -index 51811c2d..756a525f 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1112,6 +1112,7 @@ static void *multifd_send_thread(void *opaque) - rcu_register_thread(); - - if (multifd_send_initial_packet(p, &local_err) < 0) { -+ ret = -1; - goto out; - } - /* initial packet */ -@@ -1178,9 +1179,7 @@ out: - * who pay attention to me. - */ - if (ret != 0) { -- if (flags & MULTIFD_FLAG_SYNC) { -- qemu_sem_post(&p->sem_sync); -- } -+ qemu_sem_post(&p->sem_sync); - qemu_sem_post(&multifd_send_state->channels_ready); - } - -@@ -1279,7 +1278,9 @@ static void multifd_recv_terminate_threads(Error *err) - - normal quit, i.e. everything went fine, just finished - - error quit: We close the channels so the channel threads - finish the qio_channel_read_all_eof() */ -- qio_channel_shutdown(p->c, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); -+ if (p->c) { -+ qio_channel_shutdown(p->c, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); -+ } - qemu_mutex_unlock(&p->mutex); - } - } --- -2.19.1 diff --git a/migration-multifd-fix-potential-wrong-acception-orde.patch b/migration-multifd-fix-potential-wrong-acception-orde.patch deleted file mode 100644 index 6b8f18ce71abccf8987fb9261817654b3b10d631..0000000000000000000000000000000000000000 --- a/migration-multifd-fix-potential-wrong-acception-orde.patch +++ /dev/null @@ -1,302 +0,0 @@ -From 71f3e496c128b46f803cc4776154b02a5e505cb2 Mon Sep 17 00:00:00 2001 -From: Zheng Chuan -Date: Wed, 22 Apr 2020 13:45:39 +0800 -Subject: [PATCH] migration/multifd: fix potential wrong acception order of - IOChannel - -Multifd assumes the migration thread IOChannel is always established before -the multifd IOChannels, but this assumption will be broken in many situations -like network packet loss. - -For example: -Step1: Source (migration thread IOChannel) --SYN--> Destination -Step2: Source (migration thread IOChannel) <--SYNACK Destination -Step3: Source (migration thread IOChannel, lost) --ACK-->X Destination -Step4: Source (multifd IOChannel) --SYN--> Destination -Step5: Source (multifd IOChannel) <--SYNACK Destination -Step6: Source (multifd IOChannel, ESTABLISHED) --ACK--> Destination -Step7: Destination accepts multifd IOChannel -Step8: Source (migration thread IOChannel, ESTABLISHED) -ACK,DATA-> Destination -Step9: Destination accepts migration thread IOChannel - -The above situation can be reproduced by creating a weak network environment, -such as "tc qdisc add dev eth0 root netem loss 50%". The wrong acception order -will cause magic check failure and thus lead to migration failure. - -This patch fixes this issue by sending a migration IOChannel initial packet with -a unique id when using multifd migration. Since the multifd IOChannels will also -send initial packets, the destination can judge whether the processing IOChannel -belongs to multifd by checking the id in the initial packet. This mechanism can -ensure that different IOChannels will go to correct branches in our test. - -Change-Id: I63d1c32c7b66063bd6a3c5e7d63500555bd148b9 -Signed-off-by: Jiahui Cen -Signed-off-by: Ying Fang - -diff --git a/migration/channel.c b/migration/channel.c -index 20e4c8e2..74621814 100644 ---- a/migration/channel.c -+++ b/migration/channel.c -@@ -82,6 +82,15 @@ void migration_channel_connect(MigrationState *s, - return; - } - } else { -+ if (migrate_use_multifd()) { -+ /* multifd migration cannot distinguish migration IOChannel -+ * from multifd IOChannels, so we need to send an initial packet -+ * to show it is migration IOChannel -+ */ -+ migration_send_initial_packet(ioc, -+ migrate_multifd_channels(), -+ &error); -+ } - QEMUFile *f = qemu_fopen_channel_output(ioc); - - qemu_mutex_lock(&s->qemu_file_lock); -diff --git a/migration/migration.c b/migration/migration.c -index 114c33a1..8f2fc2b4 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -517,12 +517,6 @@ static void migration_incoming_setup(QEMUFile *f) - { - MigrationIncomingState *mis = migration_incoming_get_current(); - -- if (multifd_load_setup() != 0) { -- /* We haven't been able to create multifd threads -- nothing better to do */ -- exit(EXIT_FAILURE); -- } -- - if (!mis->from_src_file) { - mis->from_src_file = f; - } -@@ -580,36 +574,41 @@ void migration_fd_process_incoming(QEMUFile *f) - void migration_ioc_process_incoming(QIOChannel *ioc, Error **errp) - { - MigrationIncomingState *mis = migration_incoming_get_current(); -- bool start_migration; -- -- if (!mis->from_src_file) { -- /* The first connection (multifd may have multiple) */ -- QEMUFile *f = qemu_fopen_channel_input(ioc); -+ Error *local_err = NULL; -+ int id = 0; - -- /* If it's a recovery, we're done */ -- if (postcopy_try_recover(f)) { -- return; -- } -+ if (migrate_use_multifd()) { -+ id = migration_recv_initial_packet(ioc, &local_err); -+ } -+ if (!migrate_use_multifd() || id == migrate_multifd_channels()) { -+ if (!mis->from_src_file) { -+ /* The migration connection (multifd may have multiple) */ -+ QEMUFile *f = qemu_fopen_channel_input(ioc); - -- migration_incoming_setup(f); -+ /* If it's a recovery, we're done */ -+ if (postcopy_try_recover(f)) { -+ return; -+ } - -- /* -- * Common migration only needs one channel, so we can start -- * right now. Multifd needs more than one channel, we wait. -- */ -- start_migration = !migrate_use_multifd(); -- } else { -- Error *local_err = NULL; -+ migration_incoming_setup(f); -+ } -+ } else if (id >= 0) { - /* Multiple connections */ - assert(migrate_use_multifd()); -- start_migration = multifd_recv_new_channel(ioc, &local_err); -+ multifd_recv_new_channel(ioc, id, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } -+ } else { -+ /* Bad connections */ -+ multifd_recv_terminate_threads(local_err); -+ error_propagate(errp, local_err); -+ return; - } - -- if (start_migration) { -+ /* Once we have all the channels we need, we can start migration */ -+ if (migration_has_all_channels()) { - migration_incoming_process(); - } - } -diff --git a/migration/migration.h b/migration/migration.h -index 1fdd7b21..feb34430 100644 ---- a/migration/migration.h -+++ b/migration/migration.h -@@ -339,4 +339,7 @@ int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque); - void migration_make_urgent_request(void); - void migration_consume_urgent_request(void); - -+int migration_send_initial_packet(QIOChannel *c, uint8_t id, Error **errp); -+int migration_recv_initial_packet(QIOChannel *c, Error **errp); -+ - #endif -diff --git a/migration/ram.c b/migration/ram.c -index 756a525f..029f1cdf 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -593,7 +593,7 @@ typedef struct { - uint8_t id; - uint8_t unused1[7]; /* Reserved for future use */ - uint64_t unused2[4]; /* Reserved for future use */ --} __attribute__((packed)) MultiFDInit_t; -+} __attribute__((packed)) MigrationInit_t; - - typedef struct { - uint32_t magic; -@@ -702,26 +702,26 @@ typedef struct { - QemuSemaphore sem_sync; - } MultiFDRecvParams; - --static int multifd_send_initial_packet(MultiFDSendParams *p, Error **errp) -+int migration_send_initial_packet(QIOChannel *c, uint8_t id, Error **errp) - { -- MultiFDInit_t msg; -+ MigrationInit_t msg; - int ret; - - msg.magic = cpu_to_be32(MULTIFD_MAGIC); - msg.version = cpu_to_be32(MULTIFD_VERSION); -- msg.id = p->id; -+ msg.id = id; - memcpy(msg.uuid, &qemu_uuid.data, sizeof(msg.uuid)); - -- ret = qio_channel_write_all(p->c, (char *)&msg, sizeof(msg), errp); -+ ret = qio_channel_write_all(c, (char *)&msg, sizeof(msg), errp); - if (ret != 0) { - return -1; - } - return 0; - } - --static int multifd_recv_initial_packet(QIOChannel *c, Error **errp) -+int migration_recv_initial_packet(QIOChannel *c, Error **errp) - { -- MultiFDInit_t msg; -+ MigrationInit_t msg; - int ret; - - ret = qio_channel_read_all(c, (char *)&msg, sizeof(msg), errp); -@@ -756,8 +756,8 @@ static int multifd_recv_initial_packet(QIOChannel *c, Error **errp) - } - - if (msg.id > migrate_multifd_channels()) { -- error_setg(errp, "multifd: received channel version %d " -- "expected %d", msg.version, MULTIFD_VERSION); -+ error_setg(errp, "multifd: received channel id %d " -+ "expected [0-%d]", msg.id, migrate_multifd_channels()); - return -1; - } - -@@ -1111,7 +1111,7 @@ static void *multifd_send_thread(void *opaque) - trace_multifd_send_thread_start(p->id); - rcu_register_thread(); - -- if (multifd_send_initial_packet(p, &local_err) < 0) { -+ if (migration_send_initial_packet(p->c, p->id, &local_err) < 0) { - ret = -1; - goto out; - } -@@ -1255,7 +1255,7 @@ struct { - uint64_t packet_num; - } *multifd_recv_state; - --static void multifd_recv_terminate_threads(Error *err) -+void multifd_recv_terminate_threads(Error *err) - { - int i; - -@@ -1470,21 +1470,10 @@ bool multifd_recv_all_channels_created(void) - * - Return false and do not set @errp when correctly receiving the current one; - * - Return false and set @errp when failing to receive the current channel. - */ --bool multifd_recv_new_channel(QIOChannel *ioc, Error **errp) -+void multifd_recv_new_channel(QIOChannel *ioc, int id, Error **errp) - { - MultiFDRecvParams *p; - Error *local_err = NULL; -- int id; -- -- id = multifd_recv_initial_packet(ioc, &local_err); -- if (id < 0) { -- multifd_recv_terminate_threads(local_err); -- error_propagate_prepend(errp, local_err, -- "failed to receive packet" -- " via multifd channel %d: ", -- atomic_read(&multifd_recv_state->count)); -- return false; -- } - - p = &multifd_recv_state->params[id]; - if (p->c != NULL) { -@@ -1492,7 +1481,7 @@ bool multifd_recv_new_channel(QIOChannel *ioc, Error **errp) - id); - multifd_recv_terminate_threads(local_err); - error_propagate(errp, local_err); -- return false; -+ return; - } - p->c = ioc; - object_ref(OBJECT(ioc)); -@@ -1503,8 +1492,6 @@ bool multifd_recv_new_channel(QIOChannel *ioc, Error **errp) - qemu_thread_create(&p->thread, p->name, multifd_recv_thread, p, - QEMU_THREAD_JOINABLE); - atomic_inc(&multifd_recv_state->count); -- return atomic_read(&multifd_recv_state->count) == -- migrate_multifd_channels(); - } - - /** -diff --git a/migration/ram.h b/migration/ram.h -index bd0eee79..a788ff0e 100644 ---- a/migration/ram.h -+++ b/migration/ram.h -@@ -46,7 +46,8 @@ void multifd_save_cleanup(void); - int multifd_load_setup(void); - int multifd_load_cleanup(Error **errp); - bool multifd_recv_all_channels_created(void); --bool multifd_recv_new_channel(QIOChannel *ioc, Error **errp); -+void multifd_recv_new_channel(QIOChannel *ioc, int id, Error **errp); -+void multifd_recv_terminate_threads(Error *err); - - uint64_t ram_pagesize_summary(void); - int ram_save_queue_pages(const char *rbname, ram_addr_t start, ram_addr_t len); -diff --git a/migration/socket.c b/migration/socket.c -index 98efdc02..093b956b 100644 ---- a/migration/socket.c -+++ b/migration/socket.c -@@ -22,6 +22,7 @@ - #include "channel.h" - #include "socket.h" - #include "migration.h" -+#include "ram.h" - #include "qemu-file.h" - #include "io/channel-socket.h" - #include "io/net-listener.h" -@@ -181,6 +182,12 @@ static void socket_start_incoming_migration(SocketAddress *saddr, - - qio_net_listener_set_name(listener, "migration-socket-listener"); - -+ if (multifd_load_setup() != 0) { -+ /* We haven't been able to create multifd threads -+ nothing better to do */ -+ exit(EXIT_FAILURE); -+ } -+ - if (qio_net_listener_open_sync(listener, saddr, errp) < 0) { - object_unref(OBJECT(listener)); - return; --- -2.23.0 diff --git a/migration-multifd-not-use-multifd-during-postcopy.patch b/migration-multifd-not-use-multifd-during-postcopy.patch deleted file mode 100644 index 6df61bfdd8d637854acea0e13e787db04dbdeca2..0000000000000000000000000000000000000000 --- a/migration-multifd-not-use-multifd-during-postcopy.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 7331554bd6ab230404b20d612aed20a95c20eba6 Mon Sep 17 00:00:00 2001 -From: Wei Yang -Date: Sat, 26 Oct 2019 07:20:00 +0800 -Subject: [PATCH 4/8] migration/multifd: not use multifd during postcopy - -We don't support multifd during postcopy, but user still could enable -both multifd and postcopy. This leads to migration failure. - -Skip multifd during postcopy. - -Signed-off-by: Wei Yang -Reviewed-by: Juan Quintela -Signed-off-by: Juan Quintela ---- - migration/ram.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/migration/ram.c b/migration/ram.c -index c2eb1ed..aace3a5 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -2571,10 +2571,13 @@ static int ram_save_target_page(RAMState *rs, PageSearchStatus *pss, - } - - /* -- * do not use multifd for compression as the first page in the new -- * block should be posted out before sending the compressed page -+ * Do not use multifd for: -+ * 1. Compression as the first page in the new block should be posted out -+ * before sending the compressed page -+ * 2. In postcopy as one whole host page should be placed - */ -- if (!save_page_use_compression(rs) && migrate_use_multifd()) { -+ if (!save_page_use_compression(rs) && migrate_use_multifd() -+ && !migration_in_postcopy()) { - return ram_save_multifd_page(rs, block, offset); - } - --- -1.8.3.1 - diff --git a/migration-ram-Do-error_free-after-migrate_set_error-.patch b/migration-ram-Do-error_free-after-migrate_set_error-.patch deleted file mode 100644 index 0039f43d86d5506bfca2953904a215d3f178526a..0000000000000000000000000000000000000000 --- a/migration-ram-Do-error_free-after-migrate_set_error-.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 05d1fbd2390d441e5acb606dba3d308d506a8eb1 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Tue, 5 May 2020 11:44:20 +0800 -Subject: [PATCH 1/3] migration/ram: Do error_free after migrate_set_error to - avoid memleaks - -If local_err is not NULL, it use error_copy to set migrate error in -multifd_send_terminate_threads. Thus, we should free it. - -Similarly, fix another leak in multifd_recv_thread. - -The leak stack: -Direct leak of 96 byte(s) in 2 object(s) allocated from: - #0 0xfffdd97fe938 in __interceptor_calloc (/lib64/libasan.so.4+0xee938) - #1 0xfffdd85a8bb0 in g_malloc0 (/lib64/libglib-2.0.so.0+0x58bb0) - #2 0xaaadfc6e41c4 in error_setv util/error.c:61 - #3 0xaaadfc6e4880 in error_setg_errno_internal util/error.c:109 - #4 0xaaadfc6192a8 in qio_channel_socket_writev io/channel-socket.c:552 - #5 0xaaadfc614604 in qio_channel_writev_all io/channel.c:171 - #6 0xaaadfc6147ec in qio_channel_write_all io/channel.c:257 - #7 0xaaadfbaec5fc in multifd_send_thread /usr/src/debug/qemu-4.1.0-4_asan.aarch64/migration/ram.c:1145 - #8 0xaaadfc6db768 in qemu_thread_start util/qemu-thread-posix.c:502 - #9 0xfffdd79a88c8 (/lib64/libpthread.so.0+0x88c8) - #10 0xfffdd78e9578 (/lib64/libc.so.6+0xd9578) - -Indirect leak of 104 byte(s) in 2 object(s) allocated from: - #0 0xfffdd97feb40 in realloc (/lib64/libasan.so.4+0xeeb40) - #1 0xfffdd78fa6e0 in __vasprintf_chk (/lib64/libc.so.6+0xea6e0) - #2 0xfffdd85ee710 in g_vasprintf (/lib64/libglib-2.0.so.0+0x9e710) - #3 0xfffdd85c45c4 in g_strdup_vprintf (/lib64/libglib-2.0.so.0+0x745c4) - #4 0xfffdd85c4674 in g_strdup_printf (/lib64/libglib-2.0.so.0+0x74674) - #5 0xaaadfc6e4214 in error_setv util/error.c:65 - #6 0xaaadfc6e4880 in error_setg_errno_internal util/error.c:109 - #7 0xaaadfc6192a8 in qio_channel_socket_writev io/channel-socket.c:552 - #8 0xaaadfc614604 in qio_channel_writev_all io/channel.c:171 - #9 0xaaadfc6147ec in qio_channel_write_all io/channel.c:257 - #10 0xaaadfbaec5fc in multifd_send_thread /usr/src/debug/qemu-4.1.0-4_asan.aarch64/migration/ram.c:1145 - #11 0xaaadfc6db768 in qemu_thread_start util/qemu-thread-posix.c:502 - #12 0xfffdd79a88c8 (/lib64/libpthread.so.0+0x88c8) - #13 0xfffdd78e9578 (/lib64/libc.so.6+0xd9578) - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan ---- - migration/ram.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/migration/ram.c b/migration/ram.c -index 1858d66c..6baf1412 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1176,6 +1176,7 @@ static void *multifd_send_thread(void *opaque) - out: - if (local_err) { - multifd_send_terminate_threads(local_err); -+ error_free(local_err); - } - - /* -@@ -1427,6 +1428,7 @@ static void *multifd_recv_thread(void *opaque) - - if (local_err) { - multifd_recv_terminate_threads(local_err); -+ error_free(local_err); - } - qemu_mutex_lock(&p->mutex); - p->running = false; --- -2.23.0 diff --git a/migration-ram-Optimize-ram_save_host_page.patch b/migration-ram-Optimize-ram_save_host_page.patch deleted file mode 100644 index c58a6dcb6a5f3dc85be056f1c6ffd3a0bf3ba972..0000000000000000000000000000000000000000 --- a/migration-ram-Optimize-ram_save_host_page.patch +++ /dev/null @@ -1,95 +0,0 @@ -From ae1a8506aa45266f2bf77a8d428f5ccd970a9b13 Mon Sep 17 00:00:00 2001 -From: Kunkun Jiang -Date: Tue, 16 Mar 2021 20:57:16 +0800 -Subject: [PATCH] migration/ram: Optimize ram_save_host_page() - -Starting from pss->page, ram_save_host_page() will check every page -and send the dirty pages up to the end of the current host page or -the boundary of used_length of the block. If the host page size is -a huge page, the step "check" will take a lot of time. - -It will improve performance to use migration_bitmap_find_dirty(). - -Tested on Kunpeng 920; VM parameters: 1U 4G (page size 1G) -The time of ram_save_host_page() in the last round of ram saving: -before optimize: 9250us after optimize: 34us - -Signed-off-by: Keqian Zhu -Signed-off-by: Kunkun Jiang -Reviewed-by: Peter Xu -Message-Id: <20210316125716.1243-3-jiangkunkun@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/ram.c | 43 +++++++++++++++++++++---------------------- - 1 file changed, 21 insertions(+), 22 deletions(-) - -diff --git a/migration/ram.c b/migration/ram.c -index 22063e00b4..1bd99ff9e5 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -3052,6 +3052,8 @@ static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss, - int tmppages, pages = 0; - size_t pagesize_bits = - qemu_ram_pagesize(pss->block) >> TARGET_PAGE_BITS; -+ unsigned long hostpage_boundary = -+ QEMU_ALIGN_UP(pss->page + 1, pagesize_bits); - - if (ramblock_is_ignored(pss->block)) { - error_report("block %s should not be migrated !", pss->block->idstr); -@@ -3060,34 +3062,31 @@ static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss, - - do { - /* Check the pages is dirty and if it is send it */ -- if (!migration_bitmap_clear_dirty(rs, pss->block, pss->page)) { -- pss->page++; -- continue; -- } -- -- tmppages = ram_save_target_page(rs, pss, last_stage); -- if (tmppages < 0) { -- return tmppages; -- } -+ if (migration_bitmap_clear_dirty(rs, pss->block, pss->page)) { -+ tmppages = ram_save_target_page(rs, pss, last_stage); -+ if (tmppages < 0) { -+ return tmppages; -+ } - -- pages += tmppages; -- if (pss->block->unsentmap) { -- clear_bit(pss->page, pss->block->unsentmap); -- } -+ pages += tmppages; -+ if (pss->block->unsentmap) { -+ clear_bit(pss->page, pss->block->unsentmap); -+ } - -- pss->page++; -- /* -- * Allow rate limiting to happen in the middle of huge pages if -- * something is sent in the current iteration. -- */ -- if (pagesize_bits > 1 && tmppages > 0) { -- migration_rate_limit(); -+ /* -+ * Allow rate limiting to happen in the middle of huge pages if -+ * something is sent in the current iteration. -+ */ -+ if (pagesize_bits > 1 && tmppages > 0) { -+ migration_rate_limit(); -+ } - } -+ pss->page = migration_bitmap_find_dirty(rs, pss->block, pss->page); - } while ((pss->page & (pagesize_bits - 1)) && - offset_in_ramblock(pss->block, pss->page << TARGET_PAGE_BITS)); - -- /* The offset we leave with is the last one we looked at */ -- pss->page--; -+ /* The offset we leave with is the min boundary of host page and block */ -+ pss->page = MIN(pss->page, hostpage_boundary) - 1; - return pages; - } - --- -2.27.0 - diff --git a/migration-ram-Reduce-unnecessary-rate-limiting.patch b/migration-ram-Reduce-unnecessary-rate-limiting.patch deleted file mode 100644 index 64374dd3e255224e650c8de3e93669db04a6c413..0000000000000000000000000000000000000000 --- a/migration-ram-Reduce-unnecessary-rate-limiting.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 338d691c985ad5b3624ef36e4beaac82982c8f0a Mon Sep 17 00:00:00 2001 -From: Kunkun Jiang -Date: Tue, 16 Mar 2021 20:57:15 +0800 -Subject: [PATCH] migration/ram: Reduce unnecessary rate limiting - -When the host page is a huge page and something is sent in the -current iteration, migration_rate_limit() should be executed. -If not, it can be omitted. - -Signed-off-by: Keqian Zhu -Signed-off-by: Kunkun Jiang -Reviewed-by: David Edmondson -Reviewed-by: Dr. David Alan Gilbert -Message-Id: <20210316125716.1243-2-jiangkunkun@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/ram.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/migration/ram.c b/migration/ram.c -index 2077ba5be4..22063e00b4 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -3076,8 +3076,13 @@ static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss, - } - - pss->page++; -- /* Allow rate limiting to happen in the middle of huge pages */ -- migration_rate_limit(); -+ /* -+ * Allow rate limiting to happen in the middle of huge pages if -+ * something is sent in the current iteration. -+ */ -+ if (pagesize_bits > 1 && tmppages > 0) { -+ migration_rate_limit(); -+ } - } while ((pss->page & (pagesize_bits - 1)) && - offset_in_ramblock(pss->block, pss->page << TARGET_PAGE_BITS)); - --- -2.27.0 - diff --git a/migration-ram-fix-memleaks-in-multifd_new_send_chann.patch b/migration-ram-fix-memleaks-in-multifd_new_send_chann.patch deleted file mode 100644 index f9cb2bf652b90968144c673fd6c59655acfd785f..0000000000000000000000000000000000000000 --- a/migration-ram-fix-memleaks-in-multifd_new_send_chann.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 4d456b243a41a8e91535b2820fd6ed4f6fb4a194 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Tue, 5 May 2020 15:50:54 +0800 -Subject: [PATCH 2/3] migration/ram: fix memleaks in - multifd_new_send_channel_async - -When error happen in multifd_new_send_channel_async, 'sioc' will not be used -to create the multifd_send_thread. Let's free it to avoid a memleak. And also -do error_free after migrate_set_error() to avoid another leak in the same place. - -The leak stack: -Direct leak of 2160 byte(s) in 6 object(s) allocated from: - #0 0xfffdd97fe754 in malloc (/lib64/libasan.so.4+0xee754) - #1 0xfffdd85a8b48 in g_malloc (/lib64/libglib-2.0.so.0+0x58b48) - #2 0xaaadfc4e2b10 in object_new_with_type qom/object.c:634 - #3 0xaaadfc619468 in qio_channel_socket_new io/channel-socket.c:56 - #4 0xaaadfc3d3e74 in socket_send_channel_create migration/socket.c:37 - #5 0xaaadfbaed6f4 in multifd_save_setup /usr/src/debug/qemu-4.1.0-4_asan.aarch64/migration/ram.c:1255 - #6 0xaaadfc3d2f78 in migrate_fd_connect migration/migration.c:3359 - #7 0xaaadfc3d6240 in migration_channel_connect migration/channel.c:101 - #8 0xaaadfc3d3590 in socket_outgoing_migration migration/socket.c:108 - #9 0xaaadfc625a64 in qio_task_complete io/task.c:195 - #10 0xaaadfc625ed0 in qio_task_thread_result io/task.c:111 - #11 0xfffdd859edec (/lib64/libglib-2.0.so.0+0x4edec) - #12 0xfffdd85a2a78 in g_main_context_dispatch (/lib64/libglib-2.0.so.0+0x52a78) - #13 0xaaadfc6d3b84 in glib_pollfds_poll util/main-loop.c:218 - #14 0xaaadfc6d3b84 in os_host_main_loop_wait util/main-loop.c:241 - #15 0xaaadfc6d3b84 in main_loop_wait util/main-loop.c:517 - #16 0xaaadfbf9206c in main_loop /usr/src/debug/qemu-4.1.0-4_asan.aarch64/vl.c:1791 - #17 0xaaadfba1b124 in main /usr/src/debug/qemu-4.1.0-4_asan.aarch64/vl.c:4473 - #18 0xfffdd7833f5c in __libc_start_main (/lib64/libc.so.6+0x23f5c) - #19 0xaaadfba26360 (/usr/libexec/qemu-kvm+0x886360) - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan ---- - migration/ram.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/migration/ram.c b/migration/ram.c -index 6baf1412..840e3548 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1215,6 +1215,8 @@ static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque) - * its status. - */ - p->quit = true; -+ object_unref(OBJECT(sioc)); -+ error_free(local_err); - } else { - p->c = QIO_CHANNEL(sioc); - qio_channel_set_delay(p->c, false); --- -2.23.0 diff --git a/migration-ram-fix-use-after-free-of-local_err.patch b/migration-ram-fix-use-after-free-of-local_err.patch deleted file mode 100644 index f74e3b18df98ae0e5a88ff9224fa06c8ea24197a..0000000000000000000000000000000000000000 --- a/migration-ram-fix-use-after-free-of-local_err.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 019526f7f7b42a7d1b8a74e1db6a8050adf9e1fb Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Tue, 24 Mar 2020 18:36:29 +0300 -Subject: [PATCH 08/14] migration/ram: fix use after free of local_err - -local_err is used again in migration_bitmap_sync_precopy() after -precopy_notify(), so we must zero it. Otherwise try to set -non-NULL local_err will crash. - -Signed-off-by: Vladimir Sementsov-Ogievskiy -Message-Id: <20200324153630.11882-6-vsementsov@virtuozzo.com> -Reviewed-by: Dr. David Alan Gilbert -Signed-off-by: Dr. David Alan Gilbert -Signed-off-by: Peng Liang ---- - migration/ram.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/migration/ram.c b/migration/ram.c -index 840e35480b04..5d1ae7570018 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1912,6 +1912,7 @@ static void migration_bitmap_sync_precopy(RAMState *rs) - */ - if (precopy_notify(PRECOPY_NOTIFY_BEFORE_BITMAP_SYNC, &local_err)) { - error_report_err(local_err); -+ local_err = NULL; - } - - migration_bitmap_sync(rs); --- -2.26.2 - diff --git a/migration-rdma-cleanup-rdma-context-before-g_free-to.patch b/migration-rdma-cleanup-rdma-context-before-g_free-to.patch deleted file mode 100644 index a39894ada540a713645b0735b719eb4d5a3edbff..0000000000000000000000000000000000000000 --- a/migration-rdma-cleanup-rdma-context-before-g_free-to.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 9867dc6fc3f131324b73664b9617376270d8d013 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Fri, 8 May 2020 06:07:55 -0400 -Subject: [PATCH 4/5] migration/rdma: cleanup rdma context before g_free to - avoid memleaks - -When error happen in initializing 'rdma_return_path', we should cleanup rdma context -before g_free(rdma) to avoid some memleaks. This patch fix that. - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan -Message-Id: <20200508100755.7875-3-pannengyuan@huawei.com> -Reviewed-by: Juan Quintela -Signed-off-by: Dr. David Alan Gilbert ---- - migration/rdma.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/migration/rdma.c b/migration/rdma.c -index 3036221e..bb24dac5 100644 ---- a/migration/rdma.c -+++ b/migration/rdma.c -@@ -4103,20 +4103,20 @@ void rdma_start_outgoing_migration(void *opaque, - rdma_return_path = qemu_rdma_data_init(host_port, errp); - - if (rdma_return_path == NULL) { -- goto err; -+ goto return_path_err; - } - - ret = qemu_rdma_source_init(rdma_return_path, - s->enabled_capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL], errp); - - if (ret) { -- goto err; -+ goto return_path_err; - } - - ret = qemu_rdma_connect(rdma_return_path, errp); - - if (ret) { -- goto err; -+ goto return_path_err; - } - - rdma->return_path = rdma_return_path; -@@ -4129,6 +4129,8 @@ void rdma_start_outgoing_migration(void *opaque, - s->to_dst_file = qemu_fopen_rdma(rdma, "wb"); - migrate_fd_connect(s, NULL); - return; -+return_path_err: -+ qemu_rdma_cleanup(rdma); - err: - g_free(rdma); - g_free(rdma_return_path); --- -2.23.0 - diff --git a/migration-rdma-fix-a-memleak-on-error-path-in-rdma_s.patch b/migration-rdma-fix-a-memleak-on-error-path-in-rdma_s.patch deleted file mode 100644 index 5e0fb101d827377551a7858f225cf365367e12b7..0000000000000000000000000000000000000000 --- a/migration-rdma-fix-a-memleak-on-error-path-in-rdma_s.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 8ae2e3b8be812bcbdeb6151c685026bcaedd4a4b Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Sat, 9 May 2020 15:25:42 +0800 -Subject: [PATCH 3/3] migration/rdma: fix a memleak on error path in - rdma_start_incoming_migration - -'rdma->host' is malloced in qemu_rdma_data_init, but forgot to free on the error -path in rdma_start_incoming_migration(), this patch fix that. - -Direct leak of 2 byte(s) in 1 object(s) allocated from: - #0 0xfffce56d34fb in __interceptor_malloc (/lib64/libasan.so.4+0xd34fb) - #1 0xfffce5158aa3 in g_malloc (/lib64/libglib-2.0.so.0+0x58aa3) - #2 0xfffce5174213 in g_strdup (/lib64/libglib-2.0.so.0+0x74213) - #3 0xaaad7c569ddf in qemu_rdma_data_init /Images/qemu/migration/rdma.c:2647 - #4 0xaaad7c57c99f in rdma_start_incoming_migration /Images/qemu/migration/rdma.c:4020 - #5 0xaaad7c52b35f in qemu_start_incoming_migration /Images/qemu/migration/migration.c:371 - #6 0xaaad7be173bf in qemu_init /Images/qemu/softmmu/vl.c:4464 - #7 0xaaad7bb29843 in main /Images/qemu/softmmu/main.c:48 - #8 0xfffce3713f5f in __libc_start_main (/lib64/libc.so.6+0x23f5f) - #9 0xaaad7bb2bf73 (/Images/qemu/build/aarch64-softmmu/qemu-system-aarch64+0x8fbf73) - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan ---- - migration/rdma.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/migration/rdma.c b/migration/rdma.c -index 3036221e..b5fdb6a7 100644 ---- a/migration/rdma.c -+++ b/migration/rdma.c -@@ -4068,6 +4068,9 @@ void rdma_start_incoming_migration(const char *host_port, Error **errp) - return; - err: - error_propagate(errp, local_err); -+ if (rdma) { -+ g_free(rdma->host); -+ } - g_free(rdma); - g_free(rdma_return_path); - } --- -2.23.0 diff --git a/migration-register_savevm_live-doesn-t-need-dev.patch b/migration-register_savevm_live-doesn-t-need-dev.patch deleted file mode 100644 index a980deccbcac98d709a35e62f41c7d52e39b0d11..0000000000000000000000000000000000000000 --- a/migration-register_savevm_live-doesn-t-need-dev.patch +++ /dev/null @@ -1,201 +0,0 @@ -From 0f7cde69416f85ec3d3f57769ae38db3d72fda8c Mon Sep 17 00:00:00 2001 -From: "Dr. David Alan Gilbert" -Date: Thu, 22 Aug 2019 12:54:33 +0100 -Subject: [PATCH] migration: register_savevm_live doesn't need dev - -Commit 78dd48df3 removed the last caller of register_savevm_live for an -instantiable device (rather than a single system wide device); -so trim out the parameter. - -Signed-off-by: Dr. David Alan Gilbert -Message-Id: <20190822115433.12070-1-dgilbert@redhat.com> -Reviewed-by: Stefan Hajnoczi -Reviewed-by: Cornelia Huck -Signed-off-by: Dr. David Alan Gilbert ---- - docs/devel/migration.rst | 3 +-- - hw/ppc/spapr.c | 2 +- - hw/s390x/s390-skeys.c | 2 +- - hw/s390x/s390-stattrib.c | 2 +- - hw/s390x/tod.c | 2 +- - include/migration/register.h | 3 +-- - migration/block-dirty-bitmap.c | 2 +- - migration/block.c | 2 +- - migration/ram.c | 2 +- - migration/savevm.c | 23 +---------------------- - net/slirp.c | 2 +- - 11 files changed, 11 insertions(+), 34 deletions(-) - -diff --git a/docs/devel/migration.rst b/docs/devel/migration.rst -index 220059679a..cc6f839fce 100644 ---- a/docs/devel/migration.rst -+++ b/docs/devel/migration.rst -@@ -183,8 +183,7 @@ another to load the state back. - - .. code:: c - -- int register_savevm_live(DeviceState *dev, -- const char *idstr, -+ int register_savevm_live(const char *idstr, - int instance_id, - int version_id, - SaveVMHandlers *ops, -diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c -index b0f37c34a4..289967c3de 100644 ---- a/hw/ppc/spapr.c -+++ b/hw/ppc/spapr.c -@@ -3069,7 +3069,7 @@ static void spapr_machine_init(MachineState *machine) - * interface, this is a legacy from the sPAPREnvironment structure - * which predated MachineState but had a similar function */ - vmstate_register(NULL, 0, &vmstate_spapr, spapr); -- register_savevm_live(NULL, "spapr/htab", VMSTATE_INSTANCE_ID_ANY, 1, -+ register_savevm_live("spapr/htab", VMSTATE_INSTANCE_ID_ANY, 1, - &savevm_htab_handlers, spapr); - - qbus_set_hotplug_handler(sysbus_get_default(), OBJECT(machine), -diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c -index e5bd92c0c7..fb7d57865d 100644 ---- a/hw/s390x/s390-skeys.c -+++ b/hw/s390x/s390-skeys.c -@@ -388,7 +388,7 @@ static inline void s390_skeys_set_migration_enabled(Object *obj, bool value, - ss->migration_enabled = value; - - if (ss->migration_enabled) { -- register_savevm_live(NULL, TYPE_S390_SKEYS, 0, 1, -+ register_savevm_live(TYPE_S390_SKEYS, 0, 1, - &savevm_s390_storage_keys, ss); - } else { - unregister_savevm(DEVICE(ss), TYPE_S390_SKEYS, ss); -diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c -index 766f2015a4..5ee15d5e82 100644 ---- a/hw/s390x/s390-stattrib.c -+++ b/hw/s390x/s390-stattrib.c -@@ -382,7 +382,7 @@ static void s390_stattrib_instance_init(Object *obj) - { - S390StAttribState *sas = S390_STATTRIB(obj); - -- register_savevm_live(NULL, TYPE_S390_STATTRIB, 0, 0, -+ register_savevm_live(TYPE_S390_STATTRIB, 0, 0, - &savevm_s390_stattrib_handlers, sas); - - object_property_add_bool(obj, "migration-enabled", -diff --git a/hw/s390x/tod.c b/hw/s390x/tod.c -index a9fca8eb0b..d6b22bb966 100644 ---- a/hw/s390x/tod.c -+++ b/hw/s390x/tod.c -@@ -100,7 +100,7 @@ static void s390_tod_realize(DeviceState *dev, Error **errp) - S390TODState *td = S390_TOD(dev); - - /* Legacy migration interface */ -- register_savevm_live(NULL, "todclock", 0, 1, &savevm_tod, td); -+ register_savevm_live("todclock", 0, 1, &savevm_tod, td); - } - - static void s390_tod_class_init(ObjectClass *oc, void *data) -diff --git a/include/migration/register.h b/include/migration/register.h -index 8b2bc5b129..f3ba10b6ef 100644 ---- a/include/migration/register.h -+++ b/include/migration/register.h -@@ -68,8 +68,7 @@ typedef struct SaveVMHandlers { - int (*resume_prepare)(MigrationState *s, void *opaque); - } SaveVMHandlers; - --int register_savevm_live(DeviceState *dev, -- const char *idstr, -+int register_savevm_live(const char *idstr, - uint32_t instance_id, - int version_id, - const SaveVMHandlers *ops, -diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c -index 4a896a09eb..11e8feb595 100644 ---- a/migration/block-dirty-bitmap.c -+++ b/migration/block-dirty-bitmap.c -@@ -733,7 +733,7 @@ void dirty_bitmap_mig_init(void) - { - QSIMPLEQ_INIT(&dirty_bitmap_mig_state.dbms_list); - -- register_savevm_live(NULL, "dirty-bitmap", 0, 1, -+ register_savevm_live("dirty-bitmap", 0, 1, - &savevm_dirty_bitmap_handlers, - &dirty_bitmap_mig_state); - } -diff --git a/migration/block.c b/migration/block.c -index 91f98ef44a..ec15d1d6b3 100644 ---- a/migration/block.c -+++ b/migration/block.c -@@ -1030,6 +1030,6 @@ void blk_mig_init(void) - QSIMPLEQ_INIT(&block_mig_state.blk_list); - qemu_mutex_init(&block_mig_state.lock); - -- register_savevm_live(NULL, "block", 0, 1, &savevm_block_handlers, -+ register_savevm_live("block", 0, 1, &savevm_block_handlers, - &block_mig_state); - } -diff --git a/migration/ram.c b/migration/ram.c -index d6657a8093..2077ba5be4 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -5125,5 +5125,5 @@ static SaveVMHandlers savevm_ram_handlers = { - void ram_mig_init(void) - { - qemu_mutex_init(&XBZRLE.lock); -- register_savevm_live(NULL, "ram", 0, 4, &savevm_ram_handlers, &ram_state); -+ register_savevm_live("ram", 0, 4, &savevm_ram_handlers, &ram_state); - } -diff --git a/migration/savevm.c b/migration/savevm.c -index f0974380e5..cdb79222a4 100644 ---- a/migration/savevm.c -+++ b/migration/savevm.c -@@ -683,8 +683,7 @@ static void savevm_state_handler_insert(SaveStateEntry *nse) - of the system, so instance_id should be removed/replaced. - Meanwhile pass -1 as instance_id if you do not already have a clearly - distinguishing id for all instances of your device class. */ --int register_savevm_live(DeviceState *dev, -- const char *idstr, -+int register_savevm_live(const char *idstr, - uint32_t instance_id, - int version_id, - const SaveVMHandlers *ops, -@@ -703,26 +702,6 @@ int register_savevm_live(DeviceState *dev, - se->is_ram = 1; - } - -- if (dev) { -- char *id = qdev_get_dev_path(dev); -- if (id) { -- if (snprintf(se->idstr, sizeof(se->idstr), "%s/", id) >= -- sizeof(se->idstr)) { -- error_report("Path too long for VMState (%s)", id); -- g_free(id); -- g_free(se); -- -- return -1; -- } -- g_free(id); -- -- se->compat = g_new0(CompatEntry, 1); -- pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), idstr); -- se->compat->instance_id = instance_id == -1 ? -- calculate_compat_instance_id(idstr) : instance_id; -- instance_id = -1; -- } -- } - pstrcat(se->idstr, sizeof(se->idstr), idstr); - - if (instance_id == VMSTATE_INSTANCE_ID_ANY) { -diff --git a/net/slirp.c b/net/slirp.c -index b34cb29276..f42f496641 100644 ---- a/net/slirp.c -+++ b/net/slirp.c -@@ -576,7 +576,7 @@ static int net_slirp_init(NetClientState *peer, const char *model, - * specific version? - */ - g_assert(slirp_state_version() == 4); -- register_savevm_live(NULL, "slirp", 0, slirp_state_version(), -+ register_savevm_live("slirp", 0, slirp_state_version(), - &savevm_slirp_state, s->slirp); - - s->poll_notifier.notify = net_slirp_poll_notify; --- -2.27.0 - diff --git a/migration-savevm-release-gslist-after-dump_vmstate_j.patch b/migration-savevm-release-gslist-after-dump_vmstate_j.patch deleted file mode 100644 index d5ec9b881005dc21ec927a9f4b37f57999c89c1f..0000000000000000000000000000000000000000 --- a/migration-savevm-release-gslist-after-dump_vmstate_j.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 0d8c145e986d4f500f065d2d8645e95175324e62 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Wed, 19 Feb 2020 17:47:05 +0800 -Subject: [PATCH 8/9] migration/savevm: release gslist after dump_vmstate_json - -'list' forgot to free at the end of dump_vmstate_json_to_file(), although it's called only once, but seems like a clean code. - -Fix the leak as follow: -Direct leak of 16 byte(s) in 1 object(s) allocated from: - #0 0x7fb946abd768 in __interceptor_malloc (/lib64/libasan.so.5+0xef768) - #1 0x7fb945eca445 in g_malloc (/lib64/libglib-2.0.so.0+0x52445) - #2 0x7fb945ee2066 in g_slice_alloc (/lib64/libglib-2.0.so.0+0x6a066) - #3 0x7fb945ee3139 in g_slist_prepend (/lib64/libglib-2.0.so.0+0x6b139) - #4 0x5585db591581 in object_class_get_list_tramp /mnt/sdb/qemu-new/qemu/qom/object.c:1084 - #5 0x5585db590f66 in object_class_foreach_tramp /mnt/sdb/qemu-new/qemu/qom/object.c:1028 - #6 0x7fb945eb35f7 in g_hash_table_foreach (/lib64/libglib-2.0.so.0+0x3b5f7) - #7 0x5585db59110c in object_class_foreach /mnt/sdb/qemu-new/qemu/qom/object.c:1038 - #8 0x5585db5916b6 in object_class_get_list /mnt/sdb/qemu-new/qemu/qom/object.c:1092 - #9 0x5585db335ca0 in dump_vmstate_json_to_file /mnt/sdb/qemu-new/qemu/migration/savevm.c:638 - #10 0x5585daa5bcbf in main /mnt/sdb/qemu-new/qemu/vl.c:4420 - #11 0x7fb941204812 in __libc_start_main ../csu/libc-start.c:308 - #12 0x5585da29420d in _start (/mnt/sdb/qemu-new/qemu/build/x86_64-softmmu/qemu-system-x86_64+0x27f020d) - -Indirect leak of 7472 byte(s) in 467 object(s) allocated from: - #0 0x7fb946abd768 in __interceptor_malloc (/lib64/libasan.so.5+0xef768) - #1 0x7fb945eca445 in g_malloc (/lib64/libglib-2.0.so.0+0x52445) - #2 0x7fb945ee2066 in g_slice_alloc (/lib64/libglib-2.0.so.0+0x6a066) - #3 0x7fb945ee3139 in g_slist_prepend (/lib64/libglib-2.0.so.0+0x6b139) - #4 0x5585db591581 in object_class_get_list_tramp /mnt/sdb/qemu-new/qemu/qom/object.c:1084 - #5 0x5585db590f66 in object_class_foreach_tramp /mnt/sdb/qemu-new/qemu/qom/object.c:1028 - #6 0x7fb945eb35f7 in g_hash_table_foreach (/lib64/libglib-2.0.so.0+0x3b5f7) - #7 0x5585db59110c in object_class_foreach /mnt/sdb/qemu-new/qemu/qom/object.c:1038 - #8 0x5585db5916b6 in object_class_get_list /mnt/sdb/qemu-new/qemu/qom/object.c:1092 - #9 0x5585db335ca0 in dump_vmstate_json_to_file /mnt/sdb/qemu-new/qemu/migration/savevm.c:638 - #10 0x5585daa5bcbf in main /mnt/sdb/qemu-new/qemu/vl.c:4420 - #11 0x7fb941204812 in __libc_start_main ../csu/libc-start.c:308 - #12 0x5585da29420d in _start (/mnt/sdb/qemu-new/qemu/build/x86_64-softmmu/qemu-system-x86_64+0x27f020d) - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan -Reviewed-by: Juan Quintela -Reviewed-by: Dr. David Alan Gilbert -Signed-off-by: Juan Quintela -Signed-off-by: AlexChen ---- - migration/savevm.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/migration/savevm.c b/migration/savevm.c -index 7d89c57..8163de7 100644 ---- a/migration/savevm.c -+++ b/migration/savevm.c -@@ -614,6 +614,7 @@ void dump_vmstate_json_to_file(FILE *out_file) - } - fprintf(out_file, "\n}\n"); - fclose(out_file); -+ g_slist_free(list); - } - - static uint32_t calculate_new_instance_id(const char *idstr) --- -1.8.3.1 - diff --git a/migration-skip-cache_drop-for-bios-bootloader-and-nv.patch b/migration-skip-cache_drop-for-bios-bootloader-and-nv.patch new file mode 100644 index 0000000000000000000000000000000000000000..d7f90b3e2cf859fecaf55cffaa886a08297ff5d4 --- /dev/null +++ b/migration-skip-cache_drop-for-bios-bootloader-and-nv.patch @@ -0,0 +1,47 @@ +From d9fef6139e17976db194d73848baff543c4a2590 Mon Sep 17 00:00:00 2001 +From: Chuan Zheng +Date: Wed, 9 Feb 2022 08:49:41 +0800 +Subject: [PATCH 10/15] migration: skip cache_drop for bios bootloader and + nvram template + +Qemu enabled page cache dropping for raw device on the destionation host +during shared storage migration. +However, fsync may take 300ms to multiple seconds to return in multiple-migration +scene, because all domains in a host share bios bootloader file, skip cache_drop +for bios bootloader and nvram template to avoid downtime increase. +--- + block.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/block.c b/block.c +index 0ac5b163d2..91f123a354 100644 +--- a/block.c ++++ b/block.c +@@ -67,6 +67,9 @@ + + #define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */ + ++#define DEFAULT_BIOS_BOOT_LOADER_DIR "/usr/share/edk2" ++#define DEFAULT_NVRAM_TEMPLATE_DIR "/var/lib/libvirt/qemu/nvram" ++ + static QTAILQ_HEAD(, BlockDriverState) graph_bdrv_states = + QTAILQ_HEAD_INITIALIZER(graph_bdrv_states); + +@@ -6432,7 +6435,13 @@ int coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, Error **errp) + return ret; + } + +- if (bs->drv->bdrv_co_invalidate_cache) { ++ /* ++ * It's not necessary for bios bootloader and nvram template to drop cache ++ * when migration, skip this step for them to avoid dowtime increase. ++ */ ++ if (bs->drv->bdrv_co_invalidate_cache && ++ !strstr(bs->filename, DEFAULT_BIOS_BOOT_LOADER_DIR) && ++ !strstr(bs->filename, DEFAULT_NVRAM_TEMPLATE_DIR)) { + bs->drv->bdrv_co_invalidate_cache(bs, &local_err); + if (local_err) { + bs->open_flags |= BDRV_O_INACTIVE; +-- +2.27.0 + diff --git a/migration-tls-add-error-handling-in-multifd_tls_hand.patch b/migration-tls-add-error-handling-in-multifd_tls_hand.patch deleted file mode 100644 index de444af35d9713e092f98a89485a8a8c590a2203..0000000000000000000000000000000000000000 --- a/migration-tls-add-error-handling-in-multifd_tls_hand.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 4bf84b63bf1b2fba031fc6c3f4948785d534df3b Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Fri, 5 Mar 2021 16:10:57 +0800 -Subject: [PATCH] migration/tls: add error handling in - multifd_tls_handshake_thread - -If any error happens during multifd send thread creating (e.g. channel broke -because new domain is destroyed by the dst), multifd_tls_handshake_thread -may exit silently, leaving main migration thread hanging (ram_save_setup -> -multifd_send_sync_main -> qemu_sem_wait(&p->sem_sync)). -Fix that by adding error handling in multifd_tls_handshake_thread. - -Signed-off-by: Hao Wang ---- - migration/ram.c | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - -diff --git a/migration/ram.c b/migration/ram.c -index 3338363e9d..d4ac696899 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1516,7 +1516,16 @@ static void multifd_tls_outgoing_handshake(QIOTask *task, - } else { - trace_multifd_tls_outgoing_handshake_complete(ioc); - } -- multifd_channel_connect(p, ioc, err); -+ -+ if (!multifd_channel_connect(p, ioc, err)) { -+ /* -+ * Error happen, mark multifd_send_thread status as 'quit' although it -+ * is not created, and then tell who pay attention to me. -+ */ -+ p->quit = true; -+ qemu_sem_post(&multifd_send_state->channels_ready); -+ qemu_sem_post(&p->sem_sync); -+ } - } - - static void *multifd_tls_handshake_thread(void *opaque) --- -2.27.0 - diff --git a/migration-tls-add-support-for-multifd-tls-handshake.patch b/migration-tls-add-support-for-multifd-tls-handshake.patch deleted file mode 100644 index f81bb6194cdd98b8a83046cc6cfc831d108d5aae..0000000000000000000000000000000000000000 --- a/migration-tls-add-support-for-multifd-tls-handshake.patch +++ /dev/null @@ -1,125 +0,0 @@ -From e283c7dab15fed5af2904480230f86cf81b67aed Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 2 Dec 2020 11:38:37 +0800 -Subject: [PATCH] migration/tls: add support for multifd tls-handshake -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Similar like migration main thread, we need to do handshake -for each multifd thread. - -Signed-off-by: Chuan Zheng -Signed-off-by: Yan Jin -Reviewed-by: Daniel P. Berrangé -Message-Id: <1600139042-104593-6-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/ram.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 75 insertions(+), 2 deletions(-) - -diff --git a/migration/ram.c b/migration/ram.c -index 2b9d00745c..b82c0e6562 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -38,6 +38,7 @@ - #include "ram.h" - #include "migration.h" - #include "socket.h" -+#include "tls.h" - #include "migration/register.h" - #include "migration/misc.h" - #include "qemu-file.h" -@@ -1200,6 +1201,77 @@ out: - return NULL; - } - -+static bool multifd_channel_connect(MultiFDSendParams *p, -+ QIOChannel *ioc, -+ Error *error); -+ -+static void multifd_tls_outgoing_handshake(QIOTask *task, -+ gpointer opaque) -+{ -+ MultiFDSendParams *p = opaque; -+ QIOChannel *ioc = QIO_CHANNEL(qio_task_get_source(task)); -+ Error *err = NULL; -+ -+ qio_task_propagate_error(task, &err); -+ multifd_channel_connect(p, ioc, err); -+} -+ -+static void multifd_tls_channel_connect(MultiFDSendParams *p, -+ QIOChannel *ioc, -+ Error **errp) -+{ -+ MigrationState *s = migrate_get_current(); -+ const char *hostname = p->tls_hostname; -+ QIOChannelTLS *tioc; -+ -+ tioc = migration_tls_client_create(s, ioc, hostname, errp); -+ if (!tioc) { -+ return; -+ } -+ -+ qio_channel_set_name(QIO_CHANNEL(tioc), "multifd-tls-outgoing"); -+ qio_channel_tls_handshake(tioc, -+ multifd_tls_outgoing_handshake, -+ p, -+ NULL, -+ NULL); -+ -+} -+ -+static bool multifd_channel_connect(MultiFDSendParams *p, -+ QIOChannel *ioc, -+ Error *error) -+{ -+ MigrationState *s = migrate_get_current(); -+ -+ if (!error) { -+ if (s->parameters.tls_creds && -+ *s->parameters.tls_creds && -+ !object_dynamic_cast(OBJECT(ioc), -+ TYPE_QIO_CHANNEL_TLS)) { -+ multifd_tls_channel_connect(p, ioc, &error); -+ if (!error) { -+ /* -+ * tls_channel_connect will call back to this -+ * function after the TLS handshake, -+ * so we mustn't call multifd_send_thread until then -+ */ -+ return false; -+ } else { -+ return true; -+ } -+ } else { -+ /* update for tls qio channel */ -+ p->c = ioc; -+ qemu_thread_create(&p->thread, p->name, multifd_send_thread, p, -+ QEMU_THREAD_JOINABLE); -+ } -+ return false; -+ } -+ -+ return true; -+} -+ - static void multifd_new_send_channel_cleanup(MultiFDSendParams *p, - QIOChannel *ioc, Error *err) - { -@@ -1229,8 +1301,9 @@ static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque) - p->c = QIO_CHANNEL(sioc); - qio_channel_set_delay(p->c, false); - p->running = true; -- qemu_thread_create(&p->thread, p->name, multifd_send_thread, p, -- QEMU_THREAD_JOINABLE); -+ if (multifd_channel_connect(p, sioc, local_err)) { -+ goto cleanup; -+ } - return; - } - --- -2.27.0 - diff --git a/migration-tls-add-tls_hostname-into-MultiFDSendParam.patch b/migration-tls-add-tls_hostname-into-MultiFDSendParam.patch deleted file mode 100644 index 3b06a42fad428d20035072601afbcd139b77c291..0000000000000000000000000000000000000000 --- a/migration-tls-add-tls_hostname-into-MultiFDSendParam.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0aff29297923b32e919ce944030a043e0826d9aa Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 2 Dec 2020 11:25:44 +0800 -Subject: [PATCH] migration/tls: add tls_hostname into MultiFDSendParams -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Since multifd creation is async with migration_channel_connect, we should -pass the hostname from MigrationState to MultiFDSendParams. - -Signed-off-by: Chuan Zheng -Signed-off-by: Yan Jin -Message-Id: <1600139042-104593-4-git-send-email-zhengchuan@huawei.com> -Reviewed-by: Daniel P. Berrangé -Signed-off-by: Dr. David Alan Gilbert ---- - migration/ram.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/migration/ram.c b/migration/ram.c -index 1a33c7b3e2..bb8f383c3b 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -621,6 +621,8 @@ typedef struct { - uint8_t id; - /* channel thread name */ - char *name; -+ /* tls hostname */ -+ char *tls_hostname; - /* channel thread id */ - QemuThread thread; - /* communication channel */ -@@ -1041,6 +1043,8 @@ void multifd_save_cleanup(void) - qemu_sem_destroy(&p->sem_sync); - g_free(p->name); - p->name = NULL; -+ g_free(p->tls_hostname); -+ p->tls_hostname = NULL; - multifd_pages_clear(p->pages); - p->pages = NULL; - p->packet_len = 0; -@@ -1229,10 +1233,12 @@ int multifd_save_setup(void) - int thread_count; - uint32_t page_count = MULTIFD_PACKET_SIZE / qemu_target_page_size(); - uint8_t i; -+ MigrationState *s; - - if (!migrate_use_multifd()) { - return 0; - } -+ s = migrate_get_current(); - thread_count = migrate_multifd_channels(); - multifd_send_state = g_malloc0(sizeof(*multifd_send_state)); - multifd_send_state->params = g_new0(MultiFDSendParams, thread_count); -@@ -1253,6 +1259,7 @@ int multifd_save_setup(void) - + sizeof(ram_addr_t) * page_count; - p->packet = g_malloc0(p->packet_len); - p->name = g_strdup_printf("multifdsend_%d", i); -+ p->tls_hostname = g_strdup(s->hostname); - socket_send_channel_create(multifd_new_send_channel_async, p); - } - return 0; --- -2.27.0 - diff --git a/migration-tls-add-trace-points-for-multifd-tls.patch b/migration-tls-add-trace-points-for-multifd-tls.patch deleted file mode 100644 index a49ef1faad30e725b45c01e10812df9b7b72b7b3..0000000000000000000000000000000000000000 --- a/migration-tls-add-trace-points-for-multifd-tls.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 83cbd3a645e9376a25cd359e8f12f8db025bf071 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 2 Dec 2020 13:56:11 +0800 -Subject: [PATCH] migration/tls: add trace points for multifd-tls -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -add trace points for multifd-tls for debug. - -Signed-off-by: Chuan Zheng -Signed-off-by: Yan Jin -Reviewed-by: Daniel P. Berrangé -Message-Id: <1600139042-104593-7-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/ram.c | 10 +++++++++- - migration/trace-events | 4 ++++ - 2 files changed, 13 insertions(+), 1 deletion(-) - -diff --git a/migration/ram.c b/migration/ram.c -index b82c0e6562..3ded38c0be 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1212,7 +1212,11 @@ static void multifd_tls_outgoing_handshake(QIOTask *task, - QIOChannel *ioc = QIO_CHANNEL(qio_task_get_source(task)); - Error *err = NULL; - -- qio_task_propagate_error(task, &err); -+ if (qio_task_propagate_error(task, &err)) { -+ trace_multifd_tls_outgoing_handshake_error(ioc, error_get_pretty(err)); -+ } else { -+ trace_multifd_tls_outgoing_handshake_complete(ioc); -+ } - multifd_channel_connect(p, ioc, err); - } - -@@ -1229,6 +1233,7 @@ static void multifd_tls_channel_connect(MultiFDSendParams *p, - return; - } - -+ trace_multifd_tls_outgoing_handshake_start(ioc, tioc, hostname); - qio_channel_set_name(QIO_CHANNEL(tioc), "multifd-tls-outgoing"); - qio_channel_tls_handshake(tioc, - multifd_tls_outgoing_handshake, -@@ -1244,6 +1249,9 @@ static bool multifd_channel_connect(MultiFDSendParams *p, - { - MigrationState *s = migrate_get_current(); - -+ trace_multifd_set_outgoing_channel( -+ ioc, object_get_typename(OBJECT(ioc)), p->tls_hostname, error); -+ - if (!error) { - if (s->parameters.tls_creds && - *s->parameters.tls_creds && -diff --git a/migration/trace-events b/migration/trace-events -index 69620c43c2..c0640cd424 100644 ---- a/migration/trace-events -+++ b/migration/trace-events -@@ -93,6 +93,10 @@ multifd_send_sync_main_signal(uint8_t id) "channel %d" - multifd_send_sync_main_wait(uint8_t id) "channel %d" - multifd_send_thread_end(uint8_t id, uint64_t packets, uint64_t pages) "channel %d packets %" PRIu64 " pages %" PRIu64 - multifd_send_thread_start(uint8_t id) "%d" -+multifd_tls_outgoing_handshake_start(void *ioc, void *tioc, const char *hostname) "ioc=%p tioc=%p hostname=%s" -+multifd_tls_outgoing_handshake_error(void *ioc, const char *err) "ioc=%p err=%s" -+multifd_tls_outgoing_handshake_complete(void *ioc) "ioc=%p" -+multifd_set_outgoing_channel(void *ioc, const char *ioctype, const char *hostname, void *err) "ioc=%p ioctype=%s hostname=%s err=%p" - ram_discard_range(const char *rbname, uint64_t start, size_t len) "%s: start: %" PRIx64 " %zx" - ram_load_loop(const char *rbname, uint64_t addr, int flags, void *host) "%s: addr: 0x%" PRIx64 " flags: 0x%x host: %p" - ram_load_postcopy_loop(uint64_t addr, int flags) "@%" PRIx64 " %x" --- -2.27.0 - diff --git a/migration-tls-extract-cleanup-function-for-common-us.patch b/migration-tls-extract-cleanup-function-for-common-us.patch deleted file mode 100644 index 5ac83e9200020300060317065bfbfeca0ebf84e2..0000000000000000000000000000000000000000 --- a/migration-tls-extract-cleanup-function-for-common-us.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 29914b97b20a6415476095c913607412a3f7572f Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 2 Dec 2020 11:32:44 +0800 -Subject: [PATCH] migration/tls: extract cleanup function for common-use -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -multifd channel cleanup is need if multifd handshake failed, -let's extract it. - -Signed-off-by: Chuan Zheng -Signed-off-by: Yan Jin -Reviewed-by: Daniel P. Berrangé -Message-Id: <1600139042-104593-5-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/ram.c | 34 ++++++++++++++++++++++------------ - 1 file changed, 22 insertions(+), 12 deletions(-) - -diff --git a/migration/ram.c b/migration/ram.c -index bb8f383c3b..2b9d00745c 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1200,6 +1200,23 @@ out: - return NULL; - } - -+static void multifd_new_send_channel_cleanup(MultiFDSendParams *p, -+ QIOChannel *ioc, Error *err) -+{ -+ migrate_set_error(migrate_get_current(), err); -+ /* Error happen, we need to tell who pay attention to me */ -+ qemu_sem_post(&multifd_send_state->channels_ready); -+ qemu_sem_post(&p->sem_sync); -+ /* -+ * Although multifd_send_thread is not created, but main migration -+ * thread neet to judge whether it is running, so we need to mark -+ * its status. -+ */ -+ p->quit = true; -+ object_unref(OBJECT(ioc)); -+ error_free(err); -+} -+ - static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque) - { - MultiFDSendParams *p = opaque; -@@ -1207,25 +1224,18 @@ static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque) - Error *local_err = NULL; - - if (qio_task_propagate_error(task, &local_err)) { -- migrate_set_error(migrate_get_current(), local_err); -- /* Error happen, we need to tell who pay attention to me */ -- qemu_sem_post(&multifd_send_state->channels_ready); -- qemu_sem_post(&p->sem_sync); -- /* -- * Although multifd_send_thread is not created, but main migration -- * thread neet to judge whether it is running, so we need to mark -- * its status. -- */ -- p->quit = true; -- object_unref(OBJECT(sioc)); -- error_free(local_err); -+ goto cleanup; - } else { - p->c = QIO_CHANNEL(sioc); - qio_channel_set_delay(p->c, false); - p->running = true; - qemu_thread_create(&p->thread, p->name, multifd_send_thread, p, - QEMU_THREAD_JOINABLE); -+ return; - } -+ -+cleanup: -+ multifd_new_send_channel_cleanup(p, sioc, local_err); - } - - int multifd_save_setup(void) --- -2.27.0 - diff --git a/migration-tls-extract-migration_tls_client_create-fo.patch b/migration-tls-extract-migration_tls_client_create-fo.patch deleted file mode 100644 index 7f538332241d60313f87533cff62785c11e98f39..0000000000000000000000000000000000000000 --- a/migration-tls-extract-migration_tls_client_create-fo.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 4ffa2ea3749066a0444b69ef16ec4e4d6cdad0e1 Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Tue, 15 Sep 2020 11:03:58 +0800 -Subject: [PATCH] migration/tls: extract migration_tls_client_create for - common-use -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -migration_tls_client_create will be used in multifd-tls, let's -extract it. - -Signed-off-by: Chuan Zheng -Signed-off-by: Yan Jin -Reviewed-by: Daniel P. Berrangé -Message-Id: <1600139042-104593-3-git-send-email-zhengchuan@huawei.com> -Signed-off-by: Dr. David Alan Gilbert ---- - migration/tls.c | 26 ++++++++++++++++++-------- - migration/tls.h | 6 ++++++ - 2 files changed, 24 insertions(+), 8 deletions(-) - -diff --git a/migration/tls.c b/migration/tls.c -index a0eb553e14..1d5b571d8e 100644 ---- a/migration/tls.c -+++ b/migration/tls.c -@@ -22,7 +22,6 @@ - #include "channel.h" - #include "migration.h" - #include "tls.h" --#include "io/channel-tls.h" - #include "crypto/tlscreds.h" - #include "qemu/error-report.h" - #include "qapi/error.h" -@@ -126,11 +125,10 @@ static void migration_tls_outgoing_handshake(QIOTask *task, - object_unref(OBJECT(ioc)); - } - -- --void migration_tls_channel_connect(MigrationState *s, -- QIOChannel *ioc, -- const char *hostname, -- Error **errp) -+QIOChannelTLS *migration_tls_client_create(MigrationState *s, -+ QIOChannel *ioc, -+ const char *hostname, -+ Error **errp) - { - QCryptoTLSCreds *creds; - QIOChannelTLS *tioc; -@@ -138,7 +136,7 @@ void migration_tls_channel_connect(MigrationState *s, - creds = migration_tls_get_creds( - s, QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT, errp); - if (!creds) { -- return; -+ return NULL; - } - - if (s->parameters.tls_hostname && *s->parameters.tls_hostname) { -@@ -146,11 +144,23 @@ void migration_tls_channel_connect(MigrationState *s, - } - if (!hostname) { - error_setg(errp, "No hostname available for TLS"); -- return; -+ return NULL; - } - - tioc = qio_channel_tls_new_client( - ioc, creds, hostname, errp); -+ -+ return tioc; -+} -+ -+void migration_tls_channel_connect(MigrationState *s, -+ QIOChannel *ioc, -+ const char *hostname, -+ Error **errp) -+{ -+ QIOChannelTLS *tioc; -+ -+ tioc = migration_tls_client_create(s, ioc, hostname, errp); - if (!tioc) { - return; - } -diff --git a/migration/tls.h b/migration/tls.h -index cdd70001ed..0cfbe368ba 100644 ---- a/migration/tls.h -+++ b/migration/tls.h -@@ -22,11 +22,17 @@ - #define QEMU_MIGRATION_TLS_H - - #include "io/channel.h" -+#include "io/channel-tls.h" - - void migration_tls_channel_process_incoming(MigrationState *s, - QIOChannel *ioc, - Error **errp); - -+QIOChannelTLS *migration_tls_client_create(MigrationState *s, -+ QIOChannel *ioc, -+ const char *hostname, -+ Error **errp); -+ - void migration_tls_channel_connect(MigrationState *s, - QIOChannel *ioc, - const char *hostname, --- -2.27.0 - diff --git a/migration-tls-fix-inverted-semantics-in-multifd_chan.patch b/migration-tls-fix-inverted-semantics-in-multifd_chan.patch deleted file mode 100644 index 3f5a52aa6db6d5ecd034a1fc2f98c994b84ade64..0000000000000000000000000000000000000000 --- a/migration-tls-fix-inverted-semantics-in-multifd_chan.patch +++ /dev/null @@ -1,55 +0,0 @@ -From ee0d1b508a144ab390fb7bc8b7a4fe3161aebecf Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Fri, 5 Mar 2021 16:09:29 +0800 -Subject: [PATCH] migration/tls: fix inverted semantics in - multifd_channel_connect - -Function multifd_channel_connect() return "true" to indicate failure, -which is rather confusing. Fix that. - -Signed-off-by: Hao Wang ---- - migration/ram.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/migration/ram.c b/migration/ram.c -index ba1e729c39..3338363e9d 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1575,9 +1575,9 @@ static bool multifd_channel_connect(MultiFDSendParams *p, - * function after the TLS handshake, - * so we mustn't call multifd_send_thread until then - */ -- return false; -- } else { - return true; -+ } else { -+ return false; - } - } else { - /* update for tls qio channel */ -@@ -1585,10 +1585,10 @@ static bool multifd_channel_connect(MultiFDSendParams *p, - qemu_thread_create(&p->thread, p->name, multifd_send_thread, p, - QEMU_THREAD_JOINABLE); - } -- return false; -+ return true; - } - -- return true; -+ return false; - } - - static void multifd_new_send_channel_cleanup(MultiFDSendParams *p, -@@ -1620,7 +1620,7 @@ static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque) - p->c = QIO_CHANNEL(sioc); - qio_channel_set_delay(p->c, false); - p->running = true; -- if (multifd_channel_connect(p, sioc, local_err)) { -+ if (!multifd_channel_connect(p, sioc, local_err)) { - goto cleanup; - } - return; --- -2.27.0 - diff --git a/migration-tls-save-hostname-into-MigrationState.patch b/migration-tls-save-hostname-into-MigrationState.patch deleted file mode 100644 index 538a8f69179d536f2f5bc307a66d4c900c5fd790..0000000000000000000000000000000000000000 --- a/migration-tls-save-hostname-into-MigrationState.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 08ae1eda02ff08b3431b227ed702ea0fc5f8a4a2 Mon Sep 17 00:00:00 2001 -From: Chuan Zheng -Date: Tue, 15 Sep 2020 11:03:57 +0800 -Subject: [PATCH] migration/tls: save hostname into MigrationState -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -hostname is need in multifd-tls, save hostname into MigrationState. - -Signed-off-by: Chuan Zheng -Signed-off-by: Yan Jin -Message-Id: <1600139042-104593-2-git-send-email-zhengchuan@huawei.com> -Reviewed-by: Daniel P. Berrangé -Signed-off-by: Dr. David Alan Gilbert ---- - migration/channel.c | 1 + - migration/migration.c | 1 + - migration/migration.h | 5 +++++ - migration/tls.c | 2 ++ - 4 files changed, 9 insertions(+) - -diff --git a/migration/channel.c b/migration/channel.c -index 7462181484..46ed40b89c 100644 ---- a/migration/channel.c -+++ b/migration/channel.c -@@ -99,5 +99,6 @@ void migration_channel_connect(MigrationState *s, - } - } - migrate_fd_connect(s, error); -+ g_free(s->hostname); - error_free(error); - } -diff --git a/migration/migration.c b/migration/migration.c -index 7949f2a40b..993d77b7d6 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -1710,6 +1710,7 @@ void migrate_init(MigrationState *s) - s->migration_thread_running = false; - error_free(s->error); - s->error = NULL; -+ s->hostname = NULL; - - migrate_set_state(&s->state, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP); - -diff --git a/migration/migration.h b/migration/migration.h -index feb344306a..e5aaf2ef70 100644 ---- a/migration/migration.h -+++ b/migration/migration.h -@@ -259,6 +259,11 @@ struct MigrationState - * (which is in 4M chunk). - */ - uint8_t clear_bitmap_shift; -+ -+ /* -+ * This save hostname when out-going migration starts -+ */ -+ char *hostname; - }; - - void migrate_set_state(int *state, int old_state, int new_state); -diff --git a/migration/tls.c b/migration/tls.c -index 5171afc6c4..a0eb553e14 100644 ---- a/migration/tls.c -+++ b/migration/tls.c -@@ -155,6 +155,8 @@ void migration_tls_channel_connect(MigrationState *s, - return; - } - -+ /* Save hostname into MigrationState for handshake */ -+ s->hostname = g_strdup(hostname); - trace_migration_tls_outgoing_handshake_start(hostname); - qio_channel_set_name(QIO_CHANNEL(tioc), "migration-tls-outgoing"); - qio_channel_tls_handshake(tioc, --- -2.27.0 - diff --git a/migration-update-ram_counters-for-multifd-sync-packe.patch b/migration-update-ram_counters-for-multifd-sync-packe.patch deleted file mode 100644 index 838380403f1ac31df0f2befd62a14711cee71e58..0000000000000000000000000000000000000000 --- a/migration-update-ram_counters-for-multifd-sync-packe.patch +++ /dev/null @@ -1,35 +0,0 @@ -From e93040851d683f1f7750acfa0e862b4405678f24 Mon Sep 17 00:00:00 2001 -From: Zheng Chuan -Date: Fri, 24 Apr 2020 11:50:41 +0800 -Subject: [PATCH 04/10] migration: update ram_counters for multifd sync packet - -Multifd sync will send MULTIFD_FLAG_SYNC flag info to destination, add -these bytes to ram_counters record. - -Change-Id: I885166f412f58e74de40ea6ffec1c35e82ae4619 -Signed-off-by: Ivan Ren -Suggested-by: Wei Yang -Message-Id: <1564464816-21804-4-git-send-email-ivanren@tencent.com> -Reviewed-by: Juan Quintela -Signed-off-by: Dr. David Alan Gilbert ---- - migration/ram.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/migration/ram.c b/migration/ram.c -index 88ddd2bb..c75716bb 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1085,6 +1085,10 @@ static void multifd_send_sync_main(RAMState *rs) - p->flags |= MULTIFD_FLAG_SYNC; - p->pending_job++; - qemu_file_update_transfer(rs->f, p->packet_len); -+ ram_counters.multifd_bytes += p->packet_len; -+ ram_counters.transferred += p->packet_len; -+ ram_counters.multifd_bytes += p->packet_len; -+ ram_counters.transferred += p->packet_len; - qemu_mutex_unlock(&p->mutex); - qemu_sem_post(&p->sem); - } --- -2.19.1 diff --git a/migration-use-migration_is_active-to-represent-activ.patch b/migration-use-migration_is_active-to-represent-activ.patch deleted file mode 100644 index c9e926ad8e16dcfe9c931fae96cc9b8ad8e0cb93..0000000000000000000000000000000000000000 --- a/migration-use-migration_is_active-to-represent-activ.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 9662d44633dd4582dc47d58f63ee63b2c8f60a4f Mon Sep 17 00:00:00 2001 -From: Wei Yang -Date: Wed, 17 Jul 2019 08:53:41 +0800 -Subject: [PATCH] migration: use migration_is_active to represent active state - -Wrap the check into a function to make it easy to read. - -Signed-off-by: Wei Yang -Message-Id: <20190717005341.14140-1-richardw.yang@linux.intel.com> -Reviewed-by: Dr. David Alan Gilbert -Signed-off-by: Dr. David Alan Gilbert ---- - include/migration/misc.h | 1 + - migration/migration.c | 12 ++++++++---- - 2 files changed, 9 insertions(+), 4 deletions(-) - -diff --git a/include/migration/misc.h b/include/migration/misc.h -index 5cdbabd094..42d6abc920 100644 ---- a/include/migration/misc.h -+++ b/include/migration/misc.h -@@ -61,6 +61,7 @@ void migration_object_init(void); - void migration_shutdown(void); - void qemu_start_incoming_migration(const char *uri, Error **errp); - bool migration_is_idle(void); -+bool migration_is_active(MigrationState *); - void add_migration_state_change_notifier(Notifier *notify); - void remove_migration_state_change_notifier(Notifier *notify); - bool migration_in_setup(MigrationState *); -diff --git a/migration/migration.c b/migration/migration.c -index 9b40380d7c..fd7d81d4b6 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -1578,8 +1578,7 @@ static void migrate_fd_cleanup(MigrationState *s) - qemu_fclose(tmp); - } - -- assert((s->state != MIGRATION_STATUS_ACTIVE) && -- (s->state != MIGRATION_STATUS_POSTCOPY_ACTIVE)); -+ assert(!migration_is_active(s)); - - if (s->state == MIGRATION_STATUS_CANCELLING) { - migrate_set_state(&s->state, MIGRATION_STATUS_CANCELLING, -@@ -1741,6 +1740,12 @@ bool migration_is_idle(void) - return false; - } - -+bool migration_is_active(MigrationState *s) -+{ -+ return (s->state == MIGRATION_STATUS_ACTIVE || -+ s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE); -+} -+ - void migrate_init(MigrationState *s) - { - /* -@@ -3307,8 +3312,7 @@ static void *migration_thread(void *opaque) - - trace_migration_thread_setup_complete(); - -- while (s->state == MIGRATION_STATUS_ACTIVE || -- s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE) { -+ while (migration_is_active(s)) { - int64_t current_time; - - if (urgent || !qemu_file_rate_limit(s->to_dst_file)) { --- -2.27.0 - diff --git a/mirror-Do-not-dereference-invalid-pointers.patch b/mirror-Do-not-dereference-invalid-pointers.patch deleted file mode 100644 index b83e0695e5ff96a429e26f65b2c206eebb9b3f86..0000000000000000000000000000000000000000 --- a/mirror-Do-not-dereference-invalid-pointers.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 609aad11051c6f2053cc32b4881f5581c92435f3 Mon Sep 17 00:00:00 2001 -From: Max Reitz -Date: Mon, 14 Oct 2019 17:39:28 +0200 -Subject: [PATCH] mirror: Do not dereference invalid pointers - -mirror_exit_common() may be called twice (if it is called from -mirror_prepare() and fails, it will be called from mirror_abort() -again). - -In such a case, many of the pointers in the MirrorBlockJob object will -already be freed. This can be seen most reliably for s->target, which -is set to NULL (and then dereferenced by blk_bs()). - -Cc: qemu-stable@nongnu.org -Fixes: 737efc1eda23b904fbe0e66b37715fb0e5c3e58b -Signed-off-by: Max Reitz -Reviewed-by: John Snow -Reviewed-by: Vladimir Sementsov-Ogievskiy -Message-id: 20191014153931.20699-2-mreitz@redhat.com -Signed-off-by: Max Reitz -(cherry picked from commit f93c3add3a773e0e3f6277e5517583c4ad3a43c2) -Signed-off-by: Michael Roth ---- - block/mirror.c | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - -diff --git a/block/mirror.c b/block/mirror.c -index 062dc42..408486c 100644 ---- a/block/mirror.c -+++ b/block/mirror.c -@@ -617,11 +617,11 @@ static int mirror_exit_common(Job *job) - { - MirrorBlockJob *s = container_of(job, MirrorBlockJob, common.job); - BlockJob *bjob = &s->common; -- MirrorBDSOpaque *bs_opaque = s->mirror_top_bs->opaque; -+ MirrorBDSOpaque *bs_opaque; - AioContext *replace_aio_context = NULL; -- BlockDriverState *src = s->mirror_top_bs->backing->bs; -- BlockDriverState *target_bs = blk_bs(s->target); -- BlockDriverState *mirror_top_bs = s->mirror_top_bs; -+ BlockDriverState *src; -+ BlockDriverState *target_bs; -+ BlockDriverState *mirror_top_bs; - Error *local_err = NULL; - bool abort = job->ret < 0; - int ret = 0; -@@ -631,6 +631,11 @@ static int mirror_exit_common(Job *job) - } - s->prepared = true; - -+ mirror_top_bs = s->mirror_top_bs; -+ bs_opaque = mirror_top_bs->opaque; -+ src = mirror_top_bs->backing->bs; -+ target_bs = blk_bs(s->target); -+ - if (bdrv_chain_contains(src, target_bs)) { - bdrv_unfreeze_backing_chain(mirror_top_bs, target_bs); - } --- -1.8.3.1 - diff --git a/mirror-Fix-bdrv_has_zero_init-use.patch b/mirror-Fix-bdrv_has_zero_init-use.patch deleted file mode 100644 index 54fde6927f378bdddbe92495f8b5616dfd3f6953..0000000000000000000000000000000000000000 --- a/mirror-Fix-bdrv_has_zero_init-use.patch +++ /dev/null @@ -1,205 +0,0 @@ -From 7fcb1c1a956a8cad5c2e8585e53878edc4fd9eca Mon Sep 17 00:00:00 2001 -From: Max Reitz -Date: Wed, 24 Jul 2019 19:12:30 +0200 -Subject: [PATCH] mirror: Fix bdrv_has_zero_init() use - -bdrv_has_zero_init() only has meaning for newly created images or image -areas. If the mirror job itself did not create the image, it cannot -rely on bdrv_has_zero_init()'s result to carry any meaning. - -This is the case for drive-mirror with mode=existing and always for -blockdev-mirror. - -Note that we only have to zero-initialize the target with sync=full, -because other modes actually do not promise that the target will contain -the same data as the source after the job -- sync=top only promises to -copy anything allocated in the top layer, and sync=none will only copy -new I/O. (Which is how mirror has always handled it.) - -Signed-off-by: Max Reitz -Message-id: 20190724171239.8764-3-mreitz@redhat.com -Reviewed-by: Maxim Levitsky -Signed-off-by: Max Reitz ---- - block/mirror.c | 11 ++++++++--- - blockdev.c | 16 +++++++++++++--- - include/block/block_int.h | 2 ++ - tests/test-block-iothread.c | 2 +- - 4 files changed, 24 insertions(+), 7 deletions(-) - -diff --git a/block/mirror.c b/block/mirror.c -index ccae49a28e..89a053b265 100644 ---- a/block/mirror.c -+++ b/block/mirror.c -@@ -51,6 +51,8 @@ typedef struct MirrorBlockJob { - Error *replace_blocker; - bool is_none_mode; - BlockMirrorBackingMode backing_mode; -+ /* Whether the target image requires explicit zero-initialization */ -+ bool zero_target; - MirrorCopyMode copy_mode; - BlockdevOnError on_source_error, on_target_error; - bool synced; -@@ -779,7 +781,7 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJob *s) - int ret; - int64_t count; - -- if (base == NULL && !bdrv_has_zero_init(target_bs)) { -+ if (s->zero_target) { - if (!bdrv_can_write_zeroes_with_unmap(target_bs)) { - bdrv_set_dirty_bitmap(s->dirty_bitmap, 0, s->bdev_length); - return 0; -@@ -1531,6 +1533,7 @@ static BlockJob *mirror_start_job( - const char *replaces, int64_t speed, - uint32_t granularity, int64_t buf_size, - BlockMirrorBackingMode backing_mode, -+ bool zero_target, - BlockdevOnError on_source_error, - BlockdevOnError on_target_error, - bool unmap, -@@ -1658,6 +1661,7 @@ static BlockJob *mirror_start_job( - s->on_target_error = on_target_error; - s->is_none_mode = is_none_mode; - s->backing_mode = backing_mode; -+ s->zero_target = zero_target; - s->copy_mode = copy_mode; - s->base = base; - s->granularity = granularity; -@@ -1762,6 +1766,7 @@ void mirror_start(const char *job_id, BlockDriverState *bs, - int creation_flags, int64_t speed, - uint32_t granularity, int64_t buf_size, - MirrorSyncMode mode, BlockMirrorBackingMode backing_mode, -+ bool zero_target, - BlockdevOnError on_source_error, - BlockdevOnError on_target_error, - bool unmap, const char *filter_node_name, -@@ -1779,7 +1784,7 @@ void mirror_start(const char *job_id, BlockDriverState *bs, - is_none_mode = mode == MIRROR_SYNC_MODE_NONE; - base = mode == MIRROR_SYNC_MODE_TOP ? backing_bs(bs) : NULL; - mirror_start_job(job_id, bs, creation_flags, target, replaces, -- speed, granularity, buf_size, backing_mode, -+ speed, granularity, buf_size, backing_mode, zero_target, - on_source_error, on_target_error, unmap, NULL, NULL, - &mirror_job_driver, is_none_mode, base, false, - filter_node_name, true, copy_mode, errp); -@@ -1806,7 +1811,7 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs, - - ret = mirror_start_job( - job_id, bs, creation_flags, base, NULL, speed, 0, 0, -- MIRROR_LEAVE_BACKING_CHAIN, -+ MIRROR_LEAVE_BACKING_CHAIN, false, - on_error, on_error, true, cb, opaque, - &commit_active_job_driver, false, base, auto_complete, - filter_node_name, false, MIRROR_COPY_MODE_BACKGROUND, -diff --git a/blockdev.c b/blockdev.c -index 94e5aee30b..4435795b6d 100644 ---- a/blockdev.c -+++ b/blockdev.c -@@ -3739,6 +3739,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs, - bool has_replaces, const char *replaces, - enum MirrorSyncMode sync, - BlockMirrorBackingMode backing_mode, -+ bool zero_target, - bool has_speed, int64_t speed, - bool has_granularity, uint32_t granularity, - bool has_buf_size, int64_t buf_size, -@@ -3847,7 +3848,7 @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs, - */ - mirror_start(job_id, bs, target, - has_replaces ? replaces : NULL, job_flags, -- speed, granularity, buf_size, sync, backing_mode, -+ speed, granularity, buf_size, sync, backing_mode, zero_target, - on_source_error, on_target_error, unmap, filter_node_name, - copy_mode, errp); - } -@@ -3863,6 +3864,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) - int flags; - int64_t size; - const char *format = arg->format; -+ bool zero_target; - int ret; - - bs = qmp_get_root_bs(arg->device, errp); -@@ -3964,6 +3966,10 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) - goto out; - } - -+ zero_target = (arg->sync == MIRROR_SYNC_MODE_FULL && -+ (arg->mode == NEW_IMAGE_MODE_EXISTING || -+ !bdrv_has_zero_init(target_bs))); -+ - ret = bdrv_try_set_aio_context(target_bs, aio_context, errp); - if (ret < 0) { - bdrv_unref(target_bs); -@@ -3972,7 +3978,8 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) - - blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs, - arg->has_replaces, arg->replaces, arg->sync, -- backing_mode, arg->has_speed, arg->speed, -+ backing_mode, zero_target, -+ arg->has_speed, arg->speed, - arg->has_granularity, arg->granularity, - arg->has_buf_size, arg->buf_size, - arg->has_on_source_error, arg->on_source_error, -@@ -4012,6 +4019,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id, - AioContext *aio_context; - BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN; - Error *local_err = NULL; -+ bool zero_target; - int ret; - - bs = qmp_get_root_bs(device, errp); -@@ -4024,6 +4032,8 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id, - return; - } - -+ zero_target = (sync == MIRROR_SYNC_MODE_FULL); -+ - aio_context = bdrv_get_aio_context(bs); - aio_context_acquire(aio_context); - -@@ -4034,7 +4044,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id, - - blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs, - has_replaces, replaces, sync, backing_mode, -- has_speed, speed, -+ zero_target, has_speed, speed, - has_granularity, granularity, - has_buf_size, buf_size, - has_on_source_error, on_source_error, -diff --git a/include/block/block_int.h b/include/block/block_int.h -index 76117a761a..154b9b5501 100644 ---- a/include/block/block_int.h -+++ b/include/block/block_int.h -@@ -1120,6 +1120,7 @@ BlockJob *commit_active_start(const char *job_id, BlockDriverState *bs, - * @buf_size: The amount of data that can be in flight at one time. - * @mode: Whether to collapse all images in the chain to the target. - * @backing_mode: How to establish the target's backing chain after completion. -+ * @zero_target: Whether the target should be explicitly zero-initialized - * @on_source_error: The action to take upon error reading from the source. - * @on_target_error: The action to take upon error writing to the target. - * @unmap: Whether to unmap target where source sectors only contain zeroes. -@@ -1139,6 +1140,7 @@ void mirror_start(const char *job_id, BlockDriverState *bs, - int creation_flags, int64_t speed, - uint32_t granularity, int64_t buf_size, - MirrorSyncMode mode, BlockMirrorBackingMode backing_mode, -+ bool zero_target, - BlockdevOnError on_source_error, - BlockdevOnError on_target_error, - bool unmap, const char *filter_node_name, -diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c -index 1949d5e61a..debfb69bfb 100644 ---- a/tests/test-block-iothread.c -+++ b/tests/test-block-iothread.c -@@ -611,7 +611,7 @@ static void test_propagate_mirror(void) - - /* Start a mirror job */ - mirror_start("job0", src, target, NULL, JOB_DEFAULT, 0, 0, 0, -- MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN, -+ MIRROR_SYNC_MODE_NONE, MIRROR_OPEN_BACKING_CHAIN, false, - BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT, - false, "filter_node", MIRROR_COPY_MODE_BACKGROUND, - &error_abort); --- -2.27.0 - diff --git a/mirror-Keep-mirror_top_bs-drained-after-dropping-per.patch b/mirror-Keep-mirror_top_bs-drained-after-dropping-per.patch deleted file mode 100644 index 52f07f951aef929e9fe58740955f97af25e5ba85..0000000000000000000000000000000000000000 --- a/mirror-Keep-mirror_top_bs-drained-after-dropping-per.patch +++ /dev/null @@ -1,52 +0,0 @@ -From e092a17d3825a8f2c93cb429aaa5d857b579b64c Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Mon, 22 Jul 2019 17:44:27 +0200 -Subject: [PATCH] mirror: Keep mirror_top_bs drained after dropping permissions - -mirror_top_bs is currently implicitly drained through its connection to -the source or the target node. However, the drain section for target_bs -ends early after moving mirror_top_bs from src to target_bs, so that -requests can already be restarted while mirror_top_bs is still present -in the chain, but has dropped all permissions and therefore runs into an -assertion failure like this: - - qemu-system-x86_64: block/io.c:1634: bdrv_co_write_req_prepare: - Assertion `child->perm & BLK_PERM_WRITE' failed. - -Keep mirror_top_bs drained until all graph changes have completed. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Kevin Wolf -Reviewed-by: Max Reitz -(cherry picked from commit d2da5e288a2e71e82866c8fdefd41b5727300124) -Signed-off-by: Michael Roth ---- - block/mirror.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/block/mirror.c b/block/mirror.c -index 0e3f7923cf..681b305de6 100644 ---- a/block/mirror.c -+++ b/block/mirror.c -@@ -661,7 +661,10 @@ static int mirror_exit_common(Job *job) - s->target = NULL; - - /* We don't access the source any more. Dropping any WRITE/RESIZE is -- * required before it could become a backing file of target_bs. */ -+ * required before it could become a backing file of target_bs. Not having -+ * these permissions any more means that we can't allow any new requests on -+ * mirror_top_bs from now on, so keep it drained. */ -+ bdrv_drained_begin(mirror_top_bs); - bs_opaque->stop = true; - bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing, - &error_abort); -@@ -729,6 +732,7 @@ static int mirror_exit_common(Job *job) - bs_opaque->job = NULL; - - bdrv_drained_end(src); -+ bdrv_drained_end(mirror_top_bs); - s->in_drain = false; - bdrv_unref(mirror_top_bs); - bdrv_unref(src); --- -2.23.0 diff --git a/mirror-Make-sure-that-source-and-target-size-match.patch b/mirror-Make-sure-that-source-and-target-size-match.patch deleted file mode 100644 index 5e4edd26ce42f4507240fe806ed7a2ce57364a41..0000000000000000000000000000000000000000 --- a/mirror-Make-sure-that-source-and-target-size-match.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 9f57569d541acaa4a76513d09ede7d2b19aa69ea Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Wed, 3 Jun 2020 16:03:24 +0100 -Subject: [PATCH] mirror: Make sure that source and target size match - -RH-Author: Kevin Wolf -Message-id: <20200603160325.67506-11-kwolf@redhat.com> -Patchwork-id: 97110 -O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH v2 10/11] mirror: Make sure that source and target size match -Bugzilla: 1778593 -RH-Acked-by: Eric Blake -RH-Acked-by: Max Reitz -RH-Acked-by: Stefano Garzarella - -If the target is shorter than the source, mirror would copy data until -it reaches the end of the target and then fail with an I/O error when -trying to write past the end. - -If the target is longer than the source, the mirror job would complete -successfully, but the target wouldn't actually be an accurate copy of -the source image (it would contain some additional garbage at the end). - -Fix this by checking that both images have the same size when the job -starts. - -Signed-off-by: Kevin Wolf -Reviewed-by: Eric Blake -Message-Id: <20200511135825.219437-4-kwolf@redhat.com> -Reviewed-by: Max Reitz -Reviewed-by: Vladimir Sementsov-Ogievskiy -Signed-off-by: Kevin Wolf -(cherry picked from commit e83dd6808c6e0975970f37b49b27cc37bb54eea8) -Signed-off-by: Kevin Wolf -Signed-off-by: Danilo C. L. de Paula ---- - block/mirror.c | 21 ++++++++++++--------- - 1 file changed, 12 insertions(+), 9 deletions(-) - -diff --git a/block/mirror.c b/block/mirror.c -index ef6c958ff9..8f0d4544d8 100644 ---- a/block/mirror.c -+++ b/block/mirror.c -@@ -853,6 +853,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) - BlockDriverState *target_bs = blk_bs(s->target); - bool need_drain = true; - int64_t length; -+ int64_t target_length; - BlockDriverInfo bdi; - char backing_filename[2]; /* we only need 2 characters because we are only - checking for a NULL string */ -@@ -868,24 +869,26 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) - goto immediate_exit; - } - -+ target_length = blk_getlength(s->target); -+ if (target_length < 0) { -+ ret = target_length; -+ goto immediate_exit; -+ } -+ - /* Active commit must resize the base image if its size differs from the - * active layer. */ - if (s->base == blk_bs(s->target)) { -- int64_t base_length; -- -- base_length = blk_getlength(s->target); -- if (base_length < 0) { -- ret = base_length; -- goto immediate_exit; -- } -- -- if (s->bdev_length > base_length) { -+ if (s->bdev_length > target_length) { - ret = blk_truncate(s->target, s->bdev_length, PREALLOC_MODE_OFF, - NULL); - if (ret < 0) { - goto immediate_exit; - } - } -+ } else if (s->bdev_length != target_length) { -+ error_setg(errp, "Source and target image have different sizes"); -+ ret = -EINVAL; -+ goto immediate_exit; - } - - if (s->bdev_length == 0) { --- -2.27.0 - diff --git a/mirror-Wait-only-for-in-flight-operations.patch b/mirror-Wait-only-for-in-flight-operations.patch deleted file mode 100644 index d1b00c059a7afc7d25a7ec53f18cae8dbcdad85f..0000000000000000000000000000000000000000 --- a/mirror-Wait-only-for-in-flight-operations.patch +++ /dev/null @@ -1,83 +0,0 @@ -From b4e1ea1c59e4dd8cc95b97ccc4eb1d3957fe5489 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Thu, 26 Mar 2020 16:36:28 +0100 -Subject: [PATCH] mirror: Wait only for in-flight operations - -mirror_wait_for_free_in_flight_slot() just picks a random operation to -wait for. However, a MirrorOp is already in s->ops_in_flight when -mirror_co_read() waits for free slots, so if not enough slots are -immediately available, an operation can end up waiting for itself, or -two or more operations can wait for each other to complete, which -results in a hang. - -Fix this by adding a flag to MirrorOp that tells us if the request is -already in flight (and therefore occupies slots that it will later -free), and picking only such operations for waiting. - -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1794692 -Signed-off-by: Kevin Wolf -Message-Id: <20200326153628.4869-3-kwolf@redhat.com> -Reviewed-by: Eric Blake -Signed-off-by: Kevin Wolf ---- - block/mirror.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/block/mirror.c b/block/mirror.c -index 8f0d4544d8..abcf60a961 100644 ---- a/block/mirror.c -+++ b/block/mirror.c -@@ -100,6 +100,7 @@ struct MirrorOp { - - bool is_pseudo_op; - bool is_active_write; -+ bool is_in_flight; - CoQueue waiting_requests; - - QTAILQ_ENTRY(MirrorOp) next; -@@ -290,7 +291,9 @@ mirror_wait_for_any_operation(MirrorBlockJob *s, bool active) - * caller of this function. Since there is only one pseudo op - * at any given time, we will always find some real operation - * to wait on. */ -- if (!op->is_pseudo_op && op->is_active_write == active) { -+ if (!op->is_pseudo_op && op->is_in_flight && -+ op->is_active_write == active) -+ { - qemu_co_queue_wait(&op->waiting_requests, NULL); - return; - } -@@ -364,6 +367,7 @@ static void coroutine_fn mirror_co_read(void *opaque) - /* Copy the dirty cluster. */ - s->in_flight++; - s->bytes_in_flight += op->bytes; -+ op->is_in_flight = true; - trace_mirror_one_iteration(s, op->offset, op->bytes); - - ret = bdrv_co_preadv(s->mirror_top_bs->backing, op->offset, op->bytes, -@@ -379,6 +383,7 @@ static void coroutine_fn mirror_co_zero(void *opaque) - op->s->in_flight++; - op->s->bytes_in_flight += op->bytes; - *op->bytes_handled = op->bytes; -+ op->is_in_flight = true; - - ret = blk_co_pwrite_zeroes(op->s->target, op->offset, op->bytes, - op->s->unmap ? BDRV_REQ_MAY_UNMAP : 0); -@@ -393,6 +398,7 @@ static void coroutine_fn mirror_co_discard(void *opaque) - op->s->in_flight++; - op->s->bytes_in_flight += op->bytes; - *op->bytes_handled = op->bytes; -+ op->is_in_flight = true; - - ret = blk_co_pdiscard(op->s->target, op->offset, op->bytes); - mirror_write_complete(op, ret); -@@ -1305,6 +1311,7 @@ static MirrorOp *coroutine_fn active_write_prepare(MirrorBlockJob *s, - .offset = offset, - .bytes = bytes, - .is_active_write = true, -+ .is_in_flight = true, - }; - qemu_co_queue_init(&op->waiting_requests); - QTAILQ_INSERT_TAIL(&s->ops_in_flight, op, next); --- -2.27.0 - diff --git a/monitor-Discard-BLOCK_IO_ERROR-event-when-VM-reboote.patch b/monitor-Discard-BLOCK_IO_ERROR-event-when-VM-reboote.patch new file mode 100644 index 0000000000000000000000000000000000000000..13d16d03846771b316c9a42c3e616d473c299984 --- /dev/null +++ b/monitor-Discard-BLOCK_IO_ERROR-event-when-VM-reboote.patch @@ -0,0 +1,97 @@ +From f5af9ac3c9af4602812060759f6f95da8725314b Mon Sep 17 00:00:00 2001 +From: Yan Wang +Date: Thu, 10 Feb 2022 11:18:13 +0800 +Subject: [PATCH] monitor: Discard BLOCK_IO_ERROR event when VM rebooted + +Throttled event like QAPI_EVENT_BLOCK_IO_ERROR may be queued +to limit event rate. Event may be delivered when VM is rebooted +if the event was queued in the *monitor_qapi_event_state* hash table. +Which may casue VM pause and other related problems. +Such as seabios blocked during virtio-scsi initialization: + vring_add_buf(vq, sg, out_num, in_num, 0, 0); + vring_kick(vp, vq, 1); + ------------> VM paused here <----------- + /* Wait for reply */ + while (!vring_more_used(vq)) usleep(5); + +Signed-off-by: Yan Wang +--- + include/monitor/monitor.h | 2 ++ + monitor/monitor.c | 30 ++++++++++++++++++++++++++++++ + softmmu/runstate.c | 1 + + 3 files changed, 33 insertions(+) + +diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h +index 12d395d62d..847445f972 100644 +--- a/include/monitor/monitor.h ++++ b/include/monitor/monitor.h +@@ -56,4 +56,6 @@ void monitor_register_hmp(const char *name, bool info, + void monitor_register_hmp_info_hrt(const char *name, + HumanReadableText *(*handler)(Error **errp)); + ++void monitor_qapi_event_discard_io_error(void); ++ + #endif /* MONITOR_H */ +diff --git a/monitor/monitor.c b/monitor/monitor.c +index 013c628695..fb4ae9531c 100644 +--- a/monitor/monitor.c ++++ b/monitor/monitor.c +@@ -34,6 +34,9 @@ + #include "qemu/option.h" + #include "sysemu/qtest.h" + #include "trace.h" ++#include "qemu/log.h" ++#include "qapi/qmp/qjson.h" ++#include "qapi/qmp/qobject.h" + + /* + * To prevent flooding clients, events can be throttled. The +@@ -767,6 +770,33 @@ int monitor_init_opts(QemuOpts *opts, Error **errp) + return ret; + } + ++void monitor_qapi_event_discard_io_error(void) ++{ ++ GHashTableIter event_iter; ++ MonitorQAPIEventState *evstate; ++ gpointer key, value; ++ GString *json; ++ ++ qemu_mutex_lock(&monitor_lock); ++ g_hash_table_iter_init(&event_iter, monitor_qapi_event_state); ++ while (g_hash_table_iter_next(&event_iter, &key, &value)) { ++ evstate = key; ++ /* Only QAPI_EVENT_BLOCK_IO_ERROR is discarded */ ++ if (evstate->event == QAPI_EVENT_BLOCK_IO_ERROR) { ++ g_hash_table_iter_remove(&event_iter); ++ json = qobject_to_json(QOBJECT(evstate->qdict)); ++ qemu_log(" %s event discarded\n", json->str); ++ timer_del(evstate->timer); ++ timer_free(evstate->timer); ++ qobject_unref(evstate->data); ++ qobject_unref(evstate->qdict); ++ g_string_free(json, true); ++ g_free(evstate); ++ } ++ } ++ qemu_mutex_unlock(&monitor_lock); ++} ++ + QemuOptsList qemu_mon_opts = { + .name = "mon", + .implied_opt_name = "chardev", +diff --git a/softmmu/runstate.c b/softmmu/runstate.c +index 10d9b7365a..5736d908db 100644 +--- a/softmmu/runstate.c ++++ b/softmmu/runstate.c +@@ -448,6 +448,7 @@ void qemu_system_reset(ShutdownCause reason) + qapi_event_send_reset(shutdown_caused_by_guest(reason), reason); + } + cpu_synchronize_all_post_reset(); ++ monitor_qapi_event_discard_io_error(); + } + + /* +-- +2.27.0 + diff --git a/monitor-fix-memory-leak-in-monitor_fdset_dup_fd_find.patch b/monitor-fix-memory-leak-in-monitor_fdset_dup_fd_find.patch deleted file mode 100644 index 791449b59540fd0d66cac0c367af8436abb55741..0000000000000000000000000000000000000000 --- a/monitor-fix-memory-leak-in-monitor_fdset_dup_fd_find.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 117082ef493e62e6e2cd972b309e0cd72682ab02 Mon Sep 17 00:00:00 2001 -From: Chen Qun -Date: Tue, 14 Apr 2020 19:50:59 +0800 -Subject: [PATCH] moniter: fix memleak in monitor_fdset_dup_fd_find_remove - -When remove dup_fd in monitor_fdset_dup_fd_find_remove function, -we need to free mon_fdset_fd_dup. ASAN shows memory leak stack: - -Direct leak of 96 byte(s) in 3 object(s) allocated from: - #0 0xfffd37b033b3 in __interceptor_calloc (/lib64/libasan.so.4+0xd33b3) - #1 0xfffd375c71cb in g_malloc0 (/lib64/libglib-2.0.so.0+0x571cb) - #2 0xaaae25bf1c17 in monitor_fdset_dup_fd_add /qemu/monitor.c:2576 - #3 0xaaae265cfd8f in qemu_open /qemu/util/osdep.c:315 - #4 0xaaae264e2b2b in qmp_chardev_open_file_source /qemu/chardev/char-fd.c:122 - #5 0xaaae264e47cf in qmp_chardev_open_file /qemu/chardev/char-file.c:81 - #6 0xaaae264e118b in qemu_char_open /qemu/chardev/char.c:237 - #7 0xaaae264e118b in qemu_chardev_new /qemu/chardev/char.c:964 - #8 0xaaae264e1543 in qemu_chr_new_from_opts /qemu/chardev/char.c:680 - #9 0xaaae25e12e0f in chardev_init_func /qemu/vl.c:2083 - #10 0xaaae26603823 in qemu_opts_foreach /qemu/util/qemu-option.c:1170 - #11 0xaaae258c9787 in main /qemu/vl.c:4089 - #12 0xfffd35b80b9f in __libc_start_main (/lib64/libc.so.6+0x20b9f) - -Reported-by: Euler Robot -Signed-off-by: Chen Qun -(cherry picked from commit a661614de18c89f58cad3fc1bb8aab44e820183a) ---- - monitor/misc.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/monitor/misc.c b/monitor/misc.c -index 00338c00..0d6369ba 100644 ---- a/monitor/misc.c -+++ b/monitor/misc.c -@@ -1746,6 +1746,7 @@ static int64_t monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove) - if (mon_fdset_fd_dup->fd == dup_fd) { - if (remove) { - QLIST_REMOVE(mon_fdset_fd_dup, next); -+ g_free(mon_fdset_fd_dup); - if (QLIST_EMPTY(&mon_fdset->dup_fds)) { - monitor_fdset_cleanup(mon_fdset); - } --- -2.23.0 diff --git a/monitor-limit-io-error-qmp-event-to-at-most-once-per.patch b/monitor-limit-io-error-qmp-event-to-at-most-once-per.patch new file mode 100644 index 0000000000000000000000000000000000000000..2b3b02f82514599c996d2ba05950ac2445afd773 --- /dev/null +++ b/monitor-limit-io-error-qmp-event-to-at-most-once-per.patch @@ -0,0 +1,29 @@ +From 44f45b5c163efed5387dac40e229e0a50bf5921a Mon Sep 17 00:00:00 2001 +From: Yan Wang +Date: Thu, 10 Feb 2022 11:35:58 +0800 +Subject: [PATCH] monitor: limit io error qmp event to at most once per 60s + +The speed of BLOCK IO ERROR event maybe very high (thousands per +second). If we report all BLOCK IO ERRORs, the log file will be flooded +with BLOCK IO ERROR event. So throttle it to at most once per 60s. + +Signed-off-by: Yan Wang +--- + monitor/monitor.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/monitor/monitor.c b/monitor/monitor.c +index fb4ae9531c..621e79eb66 100644 +--- a/monitor/monitor.c ++++ b/monitor/monitor.c +@@ -300,6 +300,7 @@ static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = { + [QAPI_EVENT_QUORUM_FAILURE] = { 1000 * SCALE_MS }, + [QAPI_EVENT_VSERPORT_CHANGE] = { 1000 * SCALE_MS }, + [QAPI_EVENT_MEMORY_DEVICE_SIZE_CHANGE] = { 1000 * SCALE_MS }, ++ [QAPI_EVENT_BLOCK_IO_ERROR] = { 60L * 1000 * SCALE_MS }, + }; + + /* +-- +2.27.0 + diff --git a/monitor-qmp-drop-inflight-rsp-if-qmp-client-broken.patch b/monitor-qmp-drop-inflight-rsp-if-qmp-client-broken.patch new file mode 100644 index 0000000000000000000000000000000000000000..d45cb3189c161de501ac329027b502ec60858546 --- /dev/null +++ b/monitor-qmp-drop-inflight-rsp-if-qmp-client-broken.patch @@ -0,0 +1,111 @@ +From 7eb28408efe75192a0f976a197f8f1906d9073e8 Mon Sep 17 00:00:00 2001 +From: Chuan Zheng +Date: Wed, 9 Feb 2022 14:13:05 +0800 +Subject: [PATCH 14/15] monitor/qmp: drop inflight rsp if qmp client broken + +If libvirt restart while qemu is handle qmp message, libvirt will +reconnect qemu monitor socket, and query status of qemu by qmp. +But qemu may return last qmp respond to new connect socket, and libvirt +recv unexpected respond, So libvirt think qemu is abnormal, and will +kill qemu. + +This patch add qmp connect id, while reconnect id will change. While +respond to libvirt, judge if id is same, if not, drop this respond. +--- + monitor/monitor-internal.h | 1 + + monitor/qmp.c | 19 +++++++++++-------- + 2 files changed, 12 insertions(+), 8 deletions(-) + +diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h +index 3da3f86c6a..5435864add 100644 +--- a/monitor/monitor-internal.h ++++ b/monitor/monitor-internal.h +@@ -144,6 +144,7 @@ typedef struct { + const QmpCommandList *commands; + bool capab_offered[QMP_CAPABILITY__MAX]; /* capabilities offered */ + bool capab[QMP_CAPABILITY__MAX]; /* offered and accepted */ ++ uint64_t qmp_client_id; /*qmp client id, update if peer disconnect */ + /* + * Protects qmp request/response queue. + * Take monitor_lock first when you need both. +diff --git a/monitor/qmp.c b/monitor/qmp.c +index 092c527b6f..4d1ac66785 100644 +--- a/monitor/qmp.c ++++ b/monitor/qmp.c +@@ -125,18 +125,19 @@ void qmp_send_response(MonitorQMP *mon, const QDict *rsp) + * Null @rsp can only happen for commands with QCO_NO_SUCCESS_RESP. + * Nothing is emitted then. + */ +-static void monitor_qmp_respond(MonitorQMP *mon, QDict *rsp) ++static void monitor_qmp_respond(MonitorQMP *mon, QDict *rsp, uint64_t req_client_id) + { +- if (rsp) { +- qmp_send_response(mon, rsp); ++ if (!rsp || (mon->qmp_client_id != req_client_id)) { ++ return; + } ++ qmp_send_response(mon, rsp); + } + + /* + * Runs outside of coroutine context for OOB commands, but in + * coroutine context for everything else. + */ +-static void monitor_qmp_dispatch(MonitorQMP *mon, QObject *req) ++static void monitor_qmp_dispatch(MonitorQMP *mon, QObject *req, uint64_t req_client_id) + { + QDict *rsp; + QDict *error; +@@ -156,7 +157,7 @@ static void monitor_qmp_dispatch(MonitorQMP *mon, QObject *req) + } + } + +- monitor_qmp_respond(mon, rsp); ++ monitor_qmp_respond(mon, rsp, req_client_id); + qobject_unref(rsp); + } + +@@ -315,13 +316,13 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data) + trace_monitor_qmp_cmd_in_band(id_json->str); + g_string_free(id_json, true); + } +- monitor_qmp_dispatch(mon, req_obj->req); ++ monitor_qmp_dispatch(mon, req_obj->req, mon->qmp_client_id); + } else { + assert(req_obj->err); + trace_monitor_qmp_err_in_band(error_get_pretty(req_obj->err)); + rsp = qmp_error_response(req_obj->err); + req_obj->err = NULL; +- monitor_qmp_respond(mon, rsp); ++ monitor_qmp_respond(mon, rsp, mon->qmp_client_id); + qobject_unref(rsp); + } + +@@ -366,7 +367,7 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err) + trace_monitor_qmp_cmd_out_of_band(id_json->str); + g_string_free(id_json, true); + } +- monitor_qmp_dispatch(mon, req); ++ monitor_qmp_dispatch(mon, req, mon->qmp_client_id); + qobject_unref(req); + return; + } +@@ -452,6 +453,7 @@ static void monitor_qmp_event(void *opaque, QEMUChrEvent event) + mon_refcount++; + break; + case CHR_EVENT_CLOSED: ++ mon->qmp_client_id++; + /* + * Note: this is only useful when the output of the chardev + * backend is still open. For example, when the backend is +@@ -505,6 +507,7 @@ void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp) + } + qemu_chr_fe_set_echo(&mon->common.chr, true); + ++ mon->qmp_client_id = 1; + /* Note: we run QMP monitor in I/O thread when @chr supports that */ + monitor_data_init(&mon->common, true, false, + qemu_chr_has_feature(chr, QEMU_CHAR_FEATURE_GCONTEXT)); +-- +2.27.0 + diff --git a/msix-add-valid.accepts-methods-to-check-address.patch b/msix-add-valid.accepts-methods-to-check-address.patch deleted file mode 100644 index 67397549683ec1e44d29c1f858f4154bc3b6a024..0000000000000000000000000000000000000000 --- a/msix-add-valid.accepts-methods-to-check-address.patch +++ /dev/null @@ -1,78 +0,0 @@ -From e9cc24b1737f745b23c408b183dd34fda5abc30c Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Fri, 19 Feb 2021 16:28:00 +0800 -Subject: [PATCH] msix: add valid.accepts methods to check address - -Fix CVE-2020-13754 - -While doing msi-x mmio operations, a guest may send an address -that leads to an OOB access issue. Add valid.accepts methods to -ensure that ensuing mmio r/w operation don't go beyond regions. - -Reported-by: Ren Ding -Reported-by: Hanqing Zhao -Reported-by: Anatoly Trosinenko -Reported-by: Alexander Bulekov -Signed-off-by: Prasad J Pandit - -patch link: https://lists.gnu.org/archive/html/qemu-devel/2020-06/msg00004.html -Signed-off-by: Jiajie Li ---- - hw/pci/msix.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/hw/pci/msix.c b/hw/pci/msix.c -index d39dcf32e8..ec43f16875 100644 ---- a/hw/pci/msix.c -+++ b/hw/pci/msix.c -@@ -192,6 +192,15 @@ static void msix_table_mmio_write(void *opaque, hwaddr addr, - msix_handle_mask_update(dev, vector, was_masked); - } - -+static bool msix_table_accepts(void *opaque, hwaddr addr, unsigned size, -+ bool is_write, MemTxAttrs attrs) -+{ -+ PCIDevice *dev = opaque; -+ uint16_t tbl_size = dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE; -+ -+ return dev->msix_table + addr + 4 <= dev->msix_table + tbl_size; -+} -+ - static const MemoryRegionOps msix_table_mmio_ops = { - .read = msix_table_mmio_read, - .write = msix_table_mmio_write, -@@ -199,6 +208,7 @@ static const MemoryRegionOps msix_table_mmio_ops = { - .valid = { - .min_access_size = 4, - .max_access_size = 4, -+ .accepts = msix_table_accepts - }, - }; - -@@ -220,6 +230,15 @@ static void msix_pba_mmio_write(void *opaque, hwaddr addr, - { - } - -+static bool msix_pba_accepts(void *opaque, hwaddr addr, unsigned size, -+ bool is_write, MemTxAttrs attrs) -+{ -+ PCIDevice *dev = opaque; -+ uint16_t pba_size = QEMU_ALIGN_UP(dev->msix_entries_nr, 64) / 8; -+ -+ return dev->msix_pba + addr + 4 <= dev->msix_pba + pba_size; -+} -+ - static const MemoryRegionOps msix_pba_mmio_ops = { - .read = msix_pba_mmio_read, - .write = msix_pba_mmio_write, -@@ -227,6 +246,7 @@ static const MemoryRegionOps msix_pba_mmio_ops = { - .valid = { - .min_access_size = 4, - .max_access_size = 4, -+ .accepts = msix_pba_accepts - }, - }; - --- -2.27.0 - diff --git a/multifd-Make-sure-that-we-don-t-do-any-IO-after-an-e.patch b/multifd-Make-sure-that-we-don-t-do-any-IO-after-an-e.patch deleted file mode 100644 index ef380e66655d0faf290b1d61072165a64bc0861e..0000000000000000000000000000000000000000 --- a/multifd-Make-sure-that-we-don-t-do-any-IO-after-an-e.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 3db288bbddb730960430fb4907e100f19001ca0a Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 2 Dec 2020 14:31:07 +0800 -Subject: [PATCH] multifd: Make sure that we don't do any IO after an error - -Signed-off-by: Juan Quintela -Reviewed-by: Dr. David Alan Gilbert ---- - migration/ram.c | 22 +++++++++++++--------- - 1 file changed, 13 insertions(+), 9 deletions(-) - -diff --git a/migration/ram.c b/migration/ram.c -index 3ded38c0be..b74929542d 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -3617,7 +3617,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) - { - RAMState **temp = opaque; - RAMState *rs = *temp; -- int ret; -+ int ret = 0; - int i; - int64_t t0; - int done = 0; -@@ -3686,12 +3686,14 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) - ram_control_after_iterate(f, RAM_CONTROL_ROUND); - - out: -- multifd_send_sync_main(rs); -- qemu_put_be64(f, RAM_SAVE_FLAG_EOS); -- qemu_fflush(f); -- ram_counters.transferred += 8; -+ if (ret >= 0) { -+ multifd_send_sync_main(rs); -+ qemu_put_be64(f, RAM_SAVE_FLAG_EOS); -+ qemu_fflush(f); -+ ram_counters.transferred += 8; - -- ret = qemu_file_get_error(f); -+ ret = qemu_file_get_error(f); -+ } - if (ret < 0) { - return ret; - } -@@ -3745,9 +3747,11 @@ static int ram_save_complete(QEMUFile *f, void *opaque) - - rcu_read_unlock(); - -- multifd_send_sync_main(rs); -- qemu_put_be64(f, RAM_SAVE_FLAG_EOS); -- qemu_fflush(f); -+ if (ret >= 0) { -+ multifd_send_sync_main(rs); -+ qemu_put_be64(f, RAM_SAVE_FLAG_EOS); -+ qemu_fflush(f); -+ } - - return ret; - } --- -2.27.0 - diff --git a/multifd-tls-fix-memoryleak-of-the-QIOChannelSocket-o.patch b/multifd-tls-fix-memoryleak-of-the-QIOChannelSocket-o.patch deleted file mode 100644 index a2209ef5776728ced1205b9b1ce3e50daeaa84d3..0000000000000000000000000000000000000000 --- a/multifd-tls-fix-memoryleak-of-the-QIOChannelSocket-o.patch +++ /dev/null @@ -1,37 +0,0 @@ -From a4288f41b3af9f4f73f162b89007c6928509a43c Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 2 Dec 2020 14:51:51 +0800 -Subject: [PATCH] multifd/tls: fix memoryleak of the QIOChannelSocket object - when cancelling migration -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When creating new tls client, the tioc->master will be referenced which results in socket -leaking after multifd_save_cleanup if we cancel migration. -Fix it by do object_unref() after tls client creation. - -Suggested-by: Daniel P. Berrangé -Signed-off-by: Chuan Zheng -Message-Id: <1605104763-118687-1-git-send-email-zhengchuan@huawei.com> -Reviewed-by: Daniel P. Berrangé -Signed-off-by: Dr. David Alan Gilbert ---- - migration/ram.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/migration/ram.c b/migration/ram.c -index a37dbfc049..92ce1a53e7 100644 ---- a/migration/ram.c -+++ b/migration/ram.c -@@ -1246,6 +1246,7 @@ static void multifd_tls_channel_connect(MultiFDSendParams *p, - return; - } - -+ object_unref(OBJECT(ioc)); - trace_multifd_tls_outgoing_handshake_start(ioc, tioc, hostname); - qio_channel_set_name(QIO_CHANNEL(tioc), "multifd-tls-outgoing"); - p->c = QIO_CHANNEL(tioc); --- -2.27.0 - diff --git a/nbd-fix-uninitialized-variable-warning.patch b/nbd-fix-uninitialized-variable-warning.patch deleted file mode 100644 index be69252807d1a7fbd5be7e8e6d187862527c439d..0000000000000000000000000000000000000000 --- a/nbd-fix-uninitialized-variable-warning.patch +++ /dev/null @@ -1,46 +0,0 @@ -From eb5abb631196b97879a868ec75e7f70400695f7f Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Mon, 13 Jan 2020 17:03:08 +0800 -Subject: [PATCH] nbd: fix uninitialized variable warning - -Fixes: -/mnt/sdb/qemu/nbd/server.c: In function 'nbd_handle_request': -/mnt/sdb/qemu/nbd/server.c:2313:9: error: 'ret' may be used uninitialized in this function [-Werror=maybe-uninitialized] - int ret; - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan ---- - nbd/server.c | 10 +--------- - 1 file changed, 1 insertion(+), 9 deletions(-) - -diff --git a/nbd/server.c b/nbd/server.c -index e21bd501..aefb07d9 100644 ---- a/nbd/server.c -+++ b/nbd/server.c -@@ -2304,20 +2304,12 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, - !client->export_meta.bitmap, - NBD_META_ID_BASE_ALLOCATION, - errp); -- if (ret < 0) { -- return ret; -- } -- } -- -- if (client->export_meta.bitmap) { -+ } else { /* client->export_meta.bitmap */ - ret = nbd_co_send_bitmap(client, request->handle, - client->exp->export_bitmap, - request->from, request->len, - dont_fragment, - true, NBD_META_ID_DIRTY_BITMAP, errp); -- if (ret < 0) { -- return ret; -- } - } - - return ret; --- -2.18.1 - - diff --git a/nbd-server-Avoid-long-error-message-assertions-CVE-2.patch b/nbd-server-Avoid-long-error-message-assertions-CVE-2.patch deleted file mode 100644 index 71ce6cabd3a38d5af0701f579babe793b1ea7d07..0000000000000000000000000000000000000000 --- a/nbd-server-Avoid-long-error-message-assertions-CVE-2.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 719292175d391e77487f3c55f5f97a065e44d9f8 Mon Sep 17 00:00:00 2001 -From: Eric Blake -Date: Wed, 10 Jun 2020 18:32:01 -0400 -Subject: [PATCH] nbd/server: Avoid long error message assertions - CVE-2020-10761 - -RH-Author: Eric Blake -Message-id: <20200610183202.3780750-2-eblake@redhat.com> -Patchwork-id: 97494 -O-Subject: [RHEL-AV-8.2.1 qemu-kvm PATCH 1/2] nbd/server: Avoid long error message assertions CVE-2020-10761 -Bugzilla: 1845384 -RH-Acked-by: Sergio Lopez Pascual -RH-Acked-by: Max Reitz -RH-Acked-by: Stefan Hajnoczi - -Ever since commit 36683283 (v2.8), the server code asserts that error -strings sent to the client are well-formed per the protocol by not -exceeding the maximum string length of 4096. At the time the server -first started sending error messages, the assertion could not be -triggered, because messages were completely under our control. -However, over the years, we have added latent scenarios where a client -could trigger the server to attempt an error message that would -include the client's information if it passed other checks first: - -- requesting NBD_OPT_INFO/GO on an export name that is not present - (commit 0cfae925 in v2.12 echoes the name) - -- requesting NBD_OPT_LIST/SET_META_CONTEXT on an export name that is - not present (commit e7b1948d in v2.12 echoes the name) - -At the time, those were still safe because we flagged names larger -than 256 bytes with a different message; but that changed in commit -93676c88 (v4.2) when we raised the name limit to 4096 to match the NBD -string limit. (That commit also failed to change the magic number -4096 in nbd_negotiate_send_rep_err to the just-introduced named -constant.) So with that commit, long client names appended to server -text can now trigger the assertion, and thus be used as a denial of -service attack against a server. As a mitigating factor, if the -server requires TLS, the client cannot trigger the problematic paths -unless it first supplies TLS credentials, and such trusted clients are -less likely to try to intentionally crash the server. - -We may later want to further sanitize the user-supplied strings we -place into our error messages, such as scrubbing out control -characters, but that is less important to the CVE fix, so it can be a -later patch to the new nbd_sanitize_name. - -Consideration was given to changing the assertion in -nbd_negotiate_send_rep_verr to instead merely log a server error and -truncate the message, to avoid leaving a latent path that could -trigger a future CVE DoS on any new error message. However, this -merely complicates the code for something that is already (correctly) -flagging coding errors, and now that we are aware of the long message -pitfall, we are less likely to introduce such errors in the future, -which would make such error handling dead code. - -Reported-by: Xueqiang Wei -CC: qemu-stable@nongnu.org -Fixes: https://bugzilla.redhat.com/1843684 CVE-2020-10761 -Fixes: 93676c88d7 -Signed-off-by: Eric Blake -Message-Id: <20200610163741.3745251-2-eblake@redhat.com> -Reviewed-by: Vladimir Sementsov-Ogievskiy -(cherry picked from commit 5c4fe018c025740fef4a0a4421e8162db0c3eefd) -Signed-off-by: Eric Blake -Signed-off-by: Eduardo Lima (Etrunko) ---- - nbd/server.c | 21 +++++++++++++++++++-- - tests/qemu-iotests/143 | 4 ++++ - tests/qemu-iotests/143.out | 2 ++ - 3 files changed, 25 insertions(+), 2 deletions(-) - -diff --git a/nbd/server.c b/nbd/server.c -index 2d81248967..115e8f06ed 100644 ---- a/nbd/server.c -+++ b/nbd/server.c -@@ -229,6 +229,19 @@ out: - return ret; - } - -+/* -+ * Return a malloc'd copy of @name suitable for use in an error reply. -+ */ -+static char * -+nbd_sanitize_name(const char *name) -+{ -+ if (strnlen(name, 80) < 80) { -+ return g_strdup(name); -+ } -+ /* XXX Should we also try to sanitize any control characters? */ -+ return g_strdup_printf("%.80s...", name); -+} -+ - /* Send an error reply. - * Return -errno on error, 0 on success. */ - static int GCC_FMT_ATTR(4, 5) -@@ -584,9 +597,11 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags, - - exp = nbd_export_find(name); - if (!exp) { -+ g_autofree char *sane_name = nbd_sanitize_name(name); -+ - return nbd_negotiate_send_rep_err(client, NBD_REP_ERR_UNKNOWN, - errp, "export '%s' not present", -- name); -+ sane_name); - } - - /* Don't bother sending NBD_INFO_NAME unless client requested it */ -@@ -975,8 +990,10 @@ static int nbd_negotiate_meta_queries(NBDClient *client, - - meta->exp = nbd_export_find(export_name); - if (meta->exp == NULL) { -+ g_autofree char *sane_name = nbd_sanitize_name(export_name); -+ - return nbd_opt_drop(client, NBD_REP_ERR_UNKNOWN, errp, -- "export '%s' not present", export_name); -+ "export '%s' not present", sane_name); - } - - ret = nbd_opt_read(client, &nb_queries, sizeof(nb_queries), errp); -diff --git a/tests/qemu-iotests/143 b/tests/qemu-iotests/143 -index f649b36195..d2349903b1 100755 ---- a/tests/qemu-iotests/143 -+++ b/tests/qemu-iotests/143 -@@ -58,6 +58,10 @@ _send_qemu_cmd $QEMU_HANDLE \ - $QEMU_IO_PROG -f raw -c quit \ - "nbd+unix:///no_such_export?socket=$SOCK_DIR/nbd" 2>&1 \ - | _filter_qemu_io | _filter_nbd -+# Likewise, with longest possible name permitted in NBD protocol -+$QEMU_IO_PROG -f raw -c quit \ -+ "nbd+unix:///$(printf %4096d 1 | tr ' ' a)?socket=$SOCK_DIR/nbd" 2>&1 \ -+ | _filter_qemu_io | _filter_nbd | sed 's/aaaa*aa/aa--aa/' - - _send_qemu_cmd $QEMU_HANDLE \ - "{ 'execute': 'quit' }" \ -diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out -index 037d34a409..fc7bab3129 100644 ---- a/tests/qemu-iotests/143.out -+++ b/tests/qemu-iotests/143.out -@@ -3,6 +3,8 @@ QA output created by 143 - {"return": {}} - qemu-io: can't open device nbd+unix:///no_such_export?socket=SOCK_DIR/nbd: Requested export not available - server reported: export 'no_such_export' not present -+qemu-io: can't open device nbd+unix:///aa--aa1?socket=SOCK_DIR/nbd: Requested export not available -+server reported: export 'aa--aa...' not present - {"return": {}} - {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} - *** done --- -2.27.0 - diff --git a/nbd-server.c-fix-invalid-read-after-client-was-alrea.patch b/nbd-server.c-fix-invalid-read-after-client-was-alrea.patch new file mode 100644 index 0000000000000000000000000000000000000000..b6ba4e43042cefc06fe36e3a932a1c5a764a5a1d --- /dev/null +++ b/nbd-server.c-fix-invalid-read-after-client-was-alrea.patch @@ -0,0 +1,45 @@ +From 4b156248776f734d63fe37629d56c40234fda9c0 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 10:42:33 +0800 +Subject: [PATCH] nbd/server.c: fix invalid read after client was already free + +In the process of NBD equipment pressurization, executing QEMU NBD will +lead to the failure of IO distribution and go to NBD_ Out process of trip(). +If two or more IO go to the out process, client NBD will release in nbd_request_put(). +The user after free problem that is read again in close(). +Through the NBD_ Save the value of client > closing before the out process in trip +to solve the use after free problem. + +Signed-off-by: wangjian161 +--- + nbd/server.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/nbd/server.c b/nbd/server.c +index 4630dd7322..37515ed520 100644 +--- a/nbd/server.c ++++ b/nbd/server.c +@@ -2606,6 +2606,7 @@ static coroutine_fn void nbd_trip(void *opaque) + NBDRequestData *req; + NBDRequest request = { 0 }; /* GCC thinks it can be used uninitialized */ + int ret; ++ bool client_closing; + Error *local_err = NULL; + + trace_nbd_trip(); +@@ -2681,8 +2682,11 @@ disconnect: + if (local_err) { + error_reportf_err(local_err, "Disconnect client, due to: "); + } ++ client_closing = client->closing; + nbd_request_put(req); +- client_close(client, true); ++ if (!client_closing) { ++ client_close(client, true); ++ } + nbd_client_put(client); + } + +-- +2.27.0 + diff --git a/net-dump.c-Suppress-spurious-compiler-warning.patch b/net-dump.c-Suppress-spurious-compiler-warning.patch new file mode 100644 index 0000000000000000000000000000000000000000..5db07d345719ea6895740fc529358d52c6eb4b0d --- /dev/null +++ b/net-dump.c-Suppress-spurious-compiler-warning.patch @@ -0,0 +1,51 @@ +From 08801d190afd21f7d3db9a2cdce2b1528903ac2c Mon Sep 17 00:00:00 2001 +From: liuxiangdong +Date: Tue, 8 Feb 2022 15:10:25 +0800 +Subject: [PATCH] net/dump.c: Suppress spurious compiler warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Compiling with gcc version 11.2.0 (Ubuntu 11.2.0-13ubuntu1) results in +a (spurious) warning: + + In function ‘dump_receive_iov’, + inlined from ‘filter_dump_receive_iov’ at ../net/dump.c:157:5: + ../net/dump.c:89:9: error: ‘writev’ specified size 18446744073709551600 +exceeds maximum object size 9223372036854775807 [-Werror=stringop-overflow=] + 89 | if (writev(s->fd, dumpiov, cnt + 1) != sizeof(hdr) + caplen) { + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + In file included from /home/ptomsich/qemu/include/qemu/osdep.h:108, + from ../net/dump.c:25: + ../net/dump.c: In function ‘filter_dump_receive_iov’: + /usr/include/x86_64-linux-gnu/sys/uio.h:52:16: note: in a call to function +‘writev’ declared with attribute ‘read_only (2, 3)’ + 52 | extern ssize_t writev (int __fd, const struct iovec *__iovec, int +__count) + | ^~~~~~ + cc1: all warnings being treated as errors + +This change helps that version of GCC to understand what is going on +and suppresses this warning. + +Signed-off-by: Philipp Tomsich +--- + net/dump.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/dump.c b/net/dump.c +index a07ba62401..c32d3bf4e6 100644 +--- a/net/dump.c ++++ b/net/dump.c +@@ -86,7 +86,7 @@ static ssize_t dump_receive_iov(DumpState *s, const struct iovec *iov, int cnt) + dumpiov[0].iov_len = sizeof(hdr); + cnt = iov_copy(&dumpiov[1], cnt, iov, cnt, 0, caplen); + +- if (writev(s->fd, dumpiov, cnt + 1) != sizeof(hdr) + caplen) { ++ if (writev(s->fd, &dumpiov[0], cnt + 1) != sizeof(hdr) + caplen) { + error_report("network dump write error - stopping dump"); + close(s->fd); + s->fd = -1; +-- +2.27.0 + diff --git a/net-eepro100-validate-various-address-valuesi-CVE-20.patch b/net-eepro100-validate-various-address-valuesi-CVE-20.patch new file mode 100644 index 0000000000000000000000000000000000000000..47095713aabaf1232ac04d75dc97f189c67df4aa --- /dev/null +++ b/net-eepro100-validate-various-address-valuesi-CVE-20.patch @@ -0,0 +1,58 @@ +From 5db012b1116d21c64da88ad206b3589ddf5f219b Mon Sep 17 00:00:00 2001 +From: zhouli57 +Date: Sat, 18 Dec 2021 09:39:57 +0800 +Subject: [PATCH] net: eepro100: validate various address + valuesi(CVE-2021-20255) + +fix CVE-2021-20255 + +patch link: https://lists.gnu.org/archive/html/qemu-devel/2021-02/msg06098.html + +fix CVE-2021-20255, sync patch from ostms platform. + +Signed-off-by: zhouli57 +Signed-off-by: Yan Wang +--- + hw/net/eepro100.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c +index 16e95ef9cc..2474cf3dc2 100644 +--- a/hw/net/eepro100.c ++++ b/hw/net/eepro100.c +@@ -279,6 +279,9 @@ typedef struct { + /* Quasi static device properties (no need to save them). */ + uint16_t stats_size; + bool has_extended_tcb_support; ++ ++ /* Flag to avoid recursions. */ ++ bool busy; + } EEPRO100State; + + /* Word indices in EEPROM. */ +@@ -837,6 +840,14 @@ static void action_command(EEPRO100State *s) + Therefore we limit the number of iterations. */ + unsigned max_loop_count = 16; + ++ if (s->busy) { ++ /* Prevent recursions. */ ++ logout("recursion in %s:%u\n", __FILE__, __LINE__); ++ return; ++ } ++ ++ s->busy = true; ++ + for (;;) { + bool bit_el; + bool bit_s; +@@ -933,6 +944,7 @@ static void action_command(EEPRO100State *s) + } + TRACE(OTHER, logout("CU list empty\n")); + /* List is empty. Now CU is idle or suspended. */ ++ s->busy = false; + } + + static void eepro100_cu_command(EEPRO100State * s, uint8_t val) +-- +2.27.0 + diff --git a/net-l2tpv3-Remove-redundant-check-in-net_init_l2tpv3.patch b/net-l2tpv3-Remove-redundant-check-in-net_init_l2tpv3.patch deleted file mode 100644 index a96c178294ea7c2afe5a860f4021efe361a6a18f..0000000000000000000000000000000000000000 --- a/net-l2tpv3-Remove-redundant-check-in-net_init_l2tpv3.patch +++ /dev/null @@ -1,46 +0,0 @@ -From cb6048ace290e770b0ec1a6011209192541d3e8a Mon Sep 17 00:00:00 2001 -From: AlexChen -Date: Fri, 30 Oct 2020 10:46:55 +0800 -Subject: [PATCH] net/l2tpv3: Remove redundant check in net_init_l2tpv3() - -The result has been checked to be NULL before, it cannot be NULL here, -so the check is redundant. Remove it. - -Reported-by: Euler Robot -Signed-off-by: AlexChen -Signed-off-by: Jason Wang -(cherry-picked from commit d949fe64b0) ---- - net/l2tpv3.c | 9 +++------ - 1 file changed, 3 insertions(+), 6 deletions(-) - -diff --git a/net/l2tpv3.c b/net/l2tpv3.c -index 55fea17c0f..e4d4218db6 100644 ---- a/net/l2tpv3.c -+++ b/net/l2tpv3.c -@@ -655,9 +655,8 @@ int net_init_l2tpv3(const Netdev *netdev, - error_setg(errp, "could not bind socket err=%i", errno); - goto outerr; - } -- if (result) { -- freeaddrinfo(result); -- } -+ -+ freeaddrinfo(result); - - memset(&hints, 0, sizeof(hints)); - -@@ -686,9 +685,7 @@ int net_init_l2tpv3(const Netdev *netdev, - memcpy(s->dgram_dst, result->ai_addr, result->ai_addrlen); - s->dst_size = result->ai_addrlen; - -- if (result) { -- freeaddrinfo(result); -- } -+ freeaddrinfo(result); - - if (l2tpv3->has_counter && l2tpv3->counter) { - s->has_counter = true; --- -2.27.0 - diff --git a/net-remove-an-assert-call-in-eth_get_gso_type.patch b/net-remove-an-assert-call-in-eth_get_gso_type.patch deleted file mode 100644 index 79d740922a2c2fd766b19c89d68df49a6d0a96f1..0000000000000000000000000000000000000000 --- a/net-remove-an-assert-call-in-eth_get_gso_type.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 9b210ed120ac82e647ed99be3679bab2bc55932b Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Wed, 21 Oct 2020 11:35:50 +0530 -Subject: [PATCH] net: remove an assert call in eth_get_gso_type - -fix CVE-2020-27617 - -eth_get_gso_type() routine returns segmentation offload type based on -L3 protocol type. It calls g_assert_not_reached if L3 protocol is -unknown, making the following return statement unreachable. Remove the -g_assert call, it maybe triggered by a guest user. - -Reported-by: Gaoning Pan -Signed-off-by: Prasad J Pandit -Signed-off-by: Jason Wang - -cherry-pick from commit 7564bf7701f00214cdc8a678a9f7df765244def1 -Signed-off-by: Jiajie Li ---- - net/eth.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/net/eth.c b/net/eth.c -index 0c1d413ee2..1e0821c5f8 100644 ---- a/net/eth.c -+++ b/net/eth.c -@@ -16,6 +16,7 @@ - */ - - #include "qemu/osdep.h" -+#include "qemu/log.h" - #include "net/eth.h" - #include "net/checksum.h" - #include "net/tap.h" -@@ -71,9 +72,8 @@ eth_get_gso_type(uint16_t l3_proto, uint8_t *l3_hdr, uint8_t l4proto) - return VIRTIO_NET_HDR_GSO_TCPV6 | ecn_state; - } - } -- -- /* Unsupported offload */ -- g_assert_not_reached(); -+ qemu_log_mask(LOG_UNIMP, "%s: probably not GSO frame, " -+ "unknown L3 protocol: 0x%04"PRIx16"\n", __func__, l3_proto); - - return VIRTIO_NET_HDR_GSO_NONE | ecn_state; - } --- -2.27.0 - diff --git a/net-vmxnet3-validate-configuration-values-during-act.patch b/net-vmxnet3-validate-configuration-values-during-act.patch deleted file mode 100644 index a4ed4bccc5534b5b6f04d61ea7c4bccfc72e3fa8..0000000000000000000000000000000000000000 --- a/net-vmxnet3-validate-configuration-values-during-act.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 18d22b1f2b2f89bbdd77bd4d62e0fe42f19b3962 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Tue, 9 Mar 2021 17:37:20 +0800 -Subject: [PATCH] net: vmxnet3: validate configuration values during activate - (CVE-2021-20203) - -fix CVE-2021-20203 #I3A34O - -While activating device in vmxnet3_acticate_device(), it does not -validate guest supplied configuration values against predefined -minimum - maximum limits. This may lead to integer overflow or -OOB access issues. Add checks to avoid it. - -Fixes: CVE-2021-20203 -Buglink: https://bugs.launchpad.net/qemu/+bug/1913873 -Reported-by: Gaoning Pan -Signed-off-by: Prasad J Pandit - -Signed-off-by: Jiajie Li ---- - hw/net/vmxnet3.c | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - -diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c -index 10d01d0058..ecc4f5bcf0 100644 ---- a/hw/net/vmxnet3.c -+++ b/hw/net/vmxnet3.c -@@ -1418,6 +1418,7 @@ static void vmxnet3_activate_device(VMXNET3State *s) - vmxnet3_setup_rx_filtering(s); - /* Cache fields from shared memory */ - s->mtu = VMXNET3_READ_DRV_SHARED32(d, s->drv_shmem, devRead.misc.mtu); -+ assert(VMXNET3_MIN_MTU <= s->mtu && s->mtu < VMXNET3_MAX_MTU); - VMW_CFPRN("MTU is %u", s->mtu); - - s->max_rx_frags = -@@ -1471,7 +1472,9 @@ static void vmxnet3_activate_device(VMXNET3State *s) - /* Read rings memory locations for TX queues */ - pa = VMXNET3_READ_TX_QUEUE_DESCR64(d, qdescr_pa, conf.txRingBasePA); - size = VMXNET3_READ_TX_QUEUE_DESCR32(d, qdescr_pa, conf.txRingSize); -- -+ if (size > VMXNET3_TX_RING_MAX_SIZE) { -+ size = VMXNET3_TX_RING_MAX_SIZE; -+ } - vmxnet3_ring_init(d, &s->txq_descr[i].tx_ring, pa, size, - sizeof(struct Vmxnet3_TxDesc), false); - VMXNET3_RING_DUMP(VMW_CFPRN, "TX", i, &s->txq_descr[i].tx_ring); -@@ -1481,6 +1484,9 @@ static void vmxnet3_activate_device(VMXNET3State *s) - /* TXC ring */ - pa = VMXNET3_READ_TX_QUEUE_DESCR64(d, qdescr_pa, conf.compRingBasePA); - size = VMXNET3_READ_TX_QUEUE_DESCR32(d, qdescr_pa, conf.compRingSize); -+ if (size > VMXNET3_TC_RING_MAX_SIZE) { -+ size = VMXNET3_TC_RING_MAX_SIZE; -+ } - vmxnet3_ring_init(d, &s->txq_descr[i].comp_ring, pa, size, - sizeof(struct Vmxnet3_TxCompDesc), true); - VMXNET3_RING_DUMP(VMW_CFPRN, "TXC", i, &s->txq_descr[i].comp_ring); -@@ -1522,6 +1528,9 @@ static void vmxnet3_activate_device(VMXNET3State *s) - /* RX rings */ - pa = VMXNET3_READ_RX_QUEUE_DESCR64(d, qd_pa, conf.rxRingBasePA[j]); - size = VMXNET3_READ_RX_QUEUE_DESCR32(d, qd_pa, conf.rxRingSize[j]); -+ if (size > VMXNET3_RX_RING_MAX_SIZE) { -+ size = VMXNET3_RX_RING_MAX_SIZE; -+ } - vmxnet3_ring_init(d, &s->rxq_descr[i].rx_ring[j], pa, size, - sizeof(struct Vmxnet3_RxDesc), false); - VMW_CFPRN("RX queue %d:%d: Base: %" PRIx64 ", Size: %d", -@@ -1531,6 +1540,9 @@ static void vmxnet3_activate_device(VMXNET3State *s) - /* RXC ring */ - pa = VMXNET3_READ_RX_QUEUE_DESCR64(d, qd_pa, conf.compRingBasePA); - size = VMXNET3_READ_RX_QUEUE_DESCR32(d, qd_pa, conf.compRingSize); -+ if (size > VMXNET3_RC_RING_MAX_SIZE) { -+ size = VMXNET3_RC_RING_MAX_SIZE; -+ } - vmxnet3_ring_init(d, &s->rxq_descr[i].comp_ring, pa, size, - sizeof(struct Vmxnet3_RxCompDesc), true); - VMW_CFPRN("RXC queue %d: Base: %" PRIx64 ", Size: %d", i, pa, size); --- -2.27.0 - diff --git a/nvram-add-nrf51_soc-flash-read-method.patch b/nvram-add-nrf51_soc-flash-read-method.patch deleted file mode 100644 index 915bbf8a1e6eecaa0974f14db93847cedded7d85..0000000000000000000000000000000000000000 --- a/nvram-add-nrf51_soc-flash-read-method.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 6f88633406e546eb6a01786b910a2ab12373abf8 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Thu, 25 Mar 2021 17:19:15 +0800 -Subject: [PATCH] nvram: add nrf51_soc flash read method - -fix CVE-2020-15469 - -Add nrf51_soc mmio read method to avoid NULL pointer dereference -issue. - -Reported-by: Lei Sun -Signed-off-by: Prasad J Pandit - -Signed-off-by: Jiajie Li ---- - hw/nvram/nrf51_nvm.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/hw/nvram/nrf51_nvm.c b/hw/nvram/nrf51_nvm.c -index eca0cb35b5..7b2b1351f4 100644 ---- a/hw/nvram/nrf51_nvm.c -+++ b/hw/nvram/nrf51_nvm.c -@@ -271,6 +271,10 @@ static const MemoryRegionOps io_ops = { - .endianness = DEVICE_LITTLE_ENDIAN, - }; - -+static uint64_t flash_read(void *opaque, hwaddr offset, unsigned size) -+{ -+ g_assert_not_reached(); -+} - - static void flash_write(void *opaque, hwaddr offset, uint64_t value, - unsigned int size) -@@ -298,6 +302,7 @@ static void flash_write(void *opaque, hwaddr offset, uint64_t value, - - - static const MemoryRegionOps flash_ops = { -+ .read = flash_read, - .write = flash_write, - .valid.min_access_size = 4, - .valid.max_access_size = 4, --- -2.27.0 - diff --git a/object-return-self-in-object_ref.patch b/object-return-self-in-object_ref.patch deleted file mode 100644 index e851fb30d20a4c56b65bb7ce1c6ddb9109c643aa..0000000000000000000000000000000000000000 --- a/object-return-self-in-object_ref.patch +++ /dev/null @@ -1,58 +0,0 @@ -From b77ade9bb37b2e9813a42008cb21d0c743aa50a1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Fri, 10 Jan 2020 19:30:31 +0400 -Subject: [PATCH] object: return self in object_ref() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This allow for simpler assignment with ref: foo = object_ref(bar) - -Signed-off-by: Marc-André Lureau -Reviewed-by: Philippe Mathieu-Daudé -Message-Id: <20200110153039.1379601-19-marcandre.lureau@redhat.com> -Signed-off-by: Paolo Bonzini -Signed-off-by: Zhenyu Ye ---- - include/qom/object.h | 3 ++- - qom/object.c | 5 +++-- - 2 files changed, 5 insertions(+), 3 deletions(-) - -diff --git a/include/qom/object.h b/include/qom/object.h -index 5e2f60d4b0..18660fde1c 100644 ---- a/include/qom/object.h -+++ b/include/qom/object.h -@@ -1005,8 +1005,9 @@ GSList *object_class_get_list_sorted(const char *implements_type, - * - * Increase the reference count of a object. A object cannot be freed as long - * as its reference count is greater than zero. -+ * Returns: @obj - */ --void object_ref(Object *obj); -+Object *object_ref(Object *obj); - - /** - * object_unref: -diff --git a/qom/object.c b/qom/object.c -index 66c4a5f1cb..555c8b9d07 100644 ---- a/qom/object.c -+++ b/qom/object.c -@@ -1107,12 +1107,13 @@ GSList *object_class_get_list_sorted(const char *implements_type, - object_class_cmp); - } - --void object_ref(Object *obj) -+Object *object_ref(Object *obj) - { - if (!obj) { -- return; -+ return NULL; - } - atomic_inc(&obj->ref); -+ return obj; - } - - void object_unref(Object *obj) --- -2.22.0.windows.1 - diff --git a/oslib-posix-optimise-vm-startup-time-for-1G-hugepage.patch b/oslib-posix-optimise-vm-startup-time-for-1G-hugepage.patch new file mode 100644 index 0000000000000000000000000000000000000000..6e87543dfe4485d6799039e6783c165d87452a39 --- /dev/null +++ b/oslib-posix-optimise-vm-startup-time-for-1G-hugepage.patch @@ -0,0 +1,56 @@ +From e5fc3a755c9ba9f18bc0416c60f745912cb5b104 Mon Sep 17 00:00:00 2001 +From: Chuan Zheng +Date: Wed, 9 Feb 2022 14:21:39 +0800 +Subject: [PATCH 15/15] oslib-posix: optimise vm startup time for 1G hugepage + +It takes quit a long time to clear 1G-hugepage, which makes glibc +pthread_create quit slow. +Create touch_pages threads in advance, and then handle the touch_pages +callback. Only read lock is held here. +--- + util/oslib-posix.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/util/oslib-posix.c b/util/oslib-posix.c +index e8bdb02e1d..18a38b9464 100644 +--- a/util/oslib-posix.c ++++ b/util/oslib-posix.c +@@ -84,6 +84,7 @@ typedef struct MemsetThread MemsetThread; + + static MemsetThread *memset_thread; + static int memset_num_threads; ++static int started_num_threads; + static bool memset_thread_failed; + + static QemuMutex page_mutex; +@@ -464,6 +465,10 @@ static void *do_touch_pages(void *arg) + } + qemu_mutex_unlock(&page_mutex); + ++ while (started_num_threads != memset_num_threads) { ++ smp_mb(); ++ } ++ + /* unblock SIGBUS */ + sigemptyset(&set); + sigaddset(&set, SIGBUS); +@@ -529,7 +534,7 @@ static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages, + memset_thread = g_new0(MemsetThread, memset_num_threads); + numpages_per_thread = numpages / memset_num_threads; + leftover = numpages % memset_num_threads; +- for (i = 0; i < memset_num_threads; i++) { ++ for (i = 0, started_num_threads = 0; i < memset_num_threads; i++) { + memset_thread[i].addr = addr; + memset_thread[i].numpages = numpages_per_thread + (i < leftover); + memset_thread[i].hpagesize = hpagesize; +@@ -537,6 +542,7 @@ static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages, + do_touch_pages, &memset_thread[i], + QEMU_THREAD_JOINABLE); + addr += memset_thread[i].numpages * hpagesize; ++ started_num_threads++; + } + + qemu_mutex_lock(&page_mutex); +-- +2.27.0 + diff --git a/pc-Don-t-make-die-id-mandatory-unless-necessary.patch b/pc-Don-t-make-die-id-mandatory-unless-necessary.patch deleted file mode 100644 index c51b40f33020e36547f44b895b040acc07bf741c..0000000000000000000000000000000000000000 --- a/pc-Don-t-make-die-id-mandatory-unless-necessary.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 7ebcd375ade505358c1c45542de22f188c599bdd Mon Sep 17 00:00:00 2001 -From: Eduardo Habkost -Date: Fri, 16 Aug 2019 14:07:50 -0300 -Subject: [PATCH] pc: Don't make die-id mandatory unless necessary - -We have this issue reported when using libvirt to hotplug CPUs: -https://bugzilla.redhat.com/show_bug.cgi?id=1741451 - -Basically, libvirt is not copying die-id from -query-hotpluggable-cpus, but die-id is now mandatory. - -We could blame libvirt and say it is not following the documented -interface, because we have this buried in the QAPI schema -documentation: - -> Note: currently there are 5 properties that could be present -> but management should be prepared to pass through other -> properties with device_add command to allow for future -> interface extension. This also requires the filed names to be kept in -> sync with the properties passed to -device/device_add. - -But I don't think this would be reasonable from us. We can just -make QEMU more flexible and let die-id to be omitted when there's -no ambiguity. This will allow us to keep compatibility with -existing libvirt versions. - -Test case included to ensure we don't break this again. - -Fixes: commit 176d2cda0dee ("i386/cpu: Consolidate die-id validity in smp context") -Signed-off-by: Eduardo Habkost -Message-Id: <20190816170750.23910-1-ehabkost@redhat.com> -Signed-off-by: Eduardo Habkost -(cherry picked from commit fea374e7c8079563bca7c8fac895c6a880f76adc) -Signed-off-by: Michael Roth ---- - hw/i386/pc.c | 8 ++++++ - tests/acceptance/pc_cpu_hotplug_props.py | 35 ++++++++++++++++++++++++ - 2 files changed, 43 insertions(+) - create mode 100644 tests/acceptance/pc_cpu_hotplug_props.py - -diff --git a/hw/i386/pc.c b/hw/i386/pc.c -index 549c437050..947f81070f 100644 ---- a/hw/i386/pc.c -+++ b/hw/i386/pc.c -@@ -2403,6 +2403,14 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev, - int max_socket = (ms->smp.max_cpus - 1) / - smp_threads / smp_cores / pcms->smp_dies; - -+ /* -+ * die-id was optional in QEMU 4.0 and older, so keep it optional -+ * if there's only one die per socket. -+ */ -+ if (cpu->die_id < 0 && pcms->smp_dies == 1) { -+ cpu->die_id = 0; -+ } -+ - if (cpu->socket_id < 0) { - error_setg(errp, "CPU socket-id is not set"); - return; -diff --git a/tests/acceptance/pc_cpu_hotplug_props.py b/tests/acceptance/pc_cpu_hotplug_props.py -new file mode 100644 -index 0000000000..08b7e632c6 ---- /dev/null -+++ b/tests/acceptance/pc_cpu_hotplug_props.py -@@ -0,0 +1,35 @@ -+# -+# Ensure CPU die-id can be omitted on -device -+# -+# Copyright (c) 2019 Red Hat Inc -+# -+# Author: -+# Eduardo Habkost -+# -+# This library is free software; you can redistribute it and/or -+# modify it under the terms of the GNU Lesser General Public -+# License as published by the Free Software Foundation; either -+# version 2 of the License, or (at your option) any later version. -+# -+# This library 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 -+# Lesser General Public License for more details. -+# -+# You should have received a copy of the GNU Lesser General Public -+# License along with this library; if not, see . -+# -+ -+from avocado_qemu import Test -+ -+class OmittedCPUProps(Test): -+ """ -+ :avocado: tags=arch:x86_64 -+ """ -+ def test_no_die_id(self): -+ self.vm.add_args('-nodefaults', '-S') -+ self.vm.add_args('-smp', '1,sockets=2,cores=2,threads=2,maxcpus=8') -+ self.vm.add_args('-cpu', 'qemu64') -+ self.vm.add_args('-device', 'qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id=0') -+ self.vm.launch() -+ self.assertEquals(len(self.vm.command('query-cpus')), 2) --- -2.23.0 diff --git a/pc-bios-s390-ccw-net-fix-a-possible-memory-leak-in-g.patch b/pc-bios-s390-ccw-net-fix-a-possible-memory-leak-in-g.patch deleted file mode 100644 index 6e29f08d69c56a2907892008c9c4ce177778c097..0000000000000000000000000000000000000000 --- a/pc-bios-s390-ccw-net-fix-a-possible-memory-leak-in-g.patch +++ /dev/null @@ -1,34 +0,0 @@ -From d2bb5b4c4ed3b1dbc0096deb195b6df33f813f23 Mon Sep 17 00:00:00 2001 -From: Yifan Luo -Date: Wed, 14 Aug 2019 14:14:26 +0800 -Subject: [PATCH 5/5] pc-bios/s390-ccw/net: fix a possible memory leak in - get_uuid() - -There is a possible memory leak in get_uuid(). Should free allocated mem -before -return NULL. - -Signed-off-by: Yifan Luo -Message-Id: <02cf01d55267$86cf2850$946d78f0$@cmss.chinamobile.com> -Reviewed-by: Thomas Huth -Reviewed-by: Cornelia Huck -Signed-off-by: Thomas Huth ---- - pc-bios/s390-ccw/netmain.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c -index f3542cb2..f2dcc01e 100644 ---- a/pc-bios/s390-ccw/netmain.c -+++ b/pc-bios/s390-ccw/netmain.c -@@ -269,6 +269,7 @@ static const char *get_uuid(void) - : "d" (r0), "d" (r1), [addr] "a" (buf) - : "cc", "memory"); - if (cc) { -+ free(mem); - return NULL; - } - --- -2.23.0 - diff --git a/pci-Add-return_page_response-pci-ops.patch b/pci-Add-return_page_response-pci-ops.patch index 133762085ba7a4a01fd5e909a3c17cd45a975978..25e665f8bb14c8004760a11f67e8d7b572fc1b17 100644 --- a/pci-Add-return_page_response-pci-ops.patch +++ b/pci-Add-return_page_response-pci-ops.patch @@ -1,4 +1,4 @@ -From e3b498a1afec138693251bf1bd1fa9b322a880fb Mon Sep 17 00:00:00 2001 +From 228345cfa59c764e725e2d3680a4bc3ecb237609 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Fri, 6 Nov 2020 14:34:35 +0100 Subject: [PATCH] pci: Add return_page_response pci ops @@ -15,10 +15,10 @@ Signed-off-by: Kunkun Jiang 3 files changed, 28 insertions(+) diff --git a/hw/pci/pci.c b/hw/pci/pci.c -index f11ca7964e..a8b3d1c071 100644 +index 4a9374c025..64db325d6b 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c -@@ -2660,6 +2660,22 @@ int pci_device_set_pasid_table(PCIBus *bus, int32_t devfn, +@@ -2793,6 +2793,22 @@ int pci_device_set_pasid_table(PCIBus *bus, int32_t devfn, return -ENOENT; } @@ -60,10 +60,10 @@ index 12092bda7b..5890f095b1 100644 #endif /* QEMU_HW_IOMMU_IOMMU_H */ diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h -index bb14ed61b0..5e7e0e4e6f 100644 +index abffa12a99..809eb32f4a 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h -@@ -266,6 +266,8 @@ typedef struct PCIReqIDCache PCIReqIDCache; +@@ -268,6 +268,8 @@ typedef struct PCIReqIDCache PCIReqIDCache; struct PCIPASIDOps { int (*set_pasid_table)(PCIBus *bus, int32_t devfn, IOMMUConfig *config); @@ -72,7 +72,7 @@ index bb14ed61b0..5e7e0e4e6f 100644 }; typedef struct PCIPASIDOps PCIPASIDOps; -@@ -495,6 +497,8 @@ void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque); +@@ -508,6 +510,8 @@ void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque); void pci_setup_pasid_ops(PCIDevice *dev, PCIPASIDOps *ops); bool pci_device_is_pasid_ops_set(PCIBus *bus, int32_t devfn); int pci_device_set_pasid_table(PCIBus *bus, int32_t devfn, IOMMUConfig *config); diff --git a/pci-check-bus-pointer-before-dereference.patch b/pci-check-bus-pointer-before-dereference.patch index 540caaf945f28b4e13e53a299495528cb0703b5d..fbd30a32937a53dede688323163c8d229e93a054 100644 --- a/pci-check-bus-pointer-before-dereference.patch +++ b/pci-check-bus-pointer-before-dereference.patch @@ -1,4 +1,4 @@ -From e393095e6d1456e2fb22f3cde3a9f0a307152562 Mon Sep 17 00:00:00 2001 +From 92da19fb18c234bb8872b9d8f7dedcc73e5fcafb Mon Sep 17 00:00:00 2001 From: Prasad J Pandit Date: Wed, 14 Oct 2020 15:00:20 +0800 Subject: [PATCH] pci: check bus pointer before dereference @@ -27,15 +27,16 @@ avoid it. Reported-by: Ruhr-University Signed-off-by: Prasad J Pandit +Signed-off-by: Yan Wang --- hw/pci/pci.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/pci/pci.c b/hw/pci/pci.c -index de0fae10ab..df5a2c3294 100644 +index e5993c1ef5..6d1c39a9de 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c -@@ -253,6 +253,9 @@ static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change) +@@ -270,6 +270,9 @@ static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change) PCIBus *bus; for (;;) { bus = pci_get_bus(pci_dev); @@ -46,5 +47,5 @@ index de0fae10ab..df5a2c3294 100644 if (bus->set_irq) break; -- -2.23.0 +2.27.0 diff --git a/pci-host-add-pcie-msi-read-method.patch b/pci-host-add-pcie-msi-read-method.patch deleted file mode 100644 index 7433fb0c3ce55f68593f3d612663c4db3a9960cd..0000000000000000000000000000000000000000 --- a/pci-host-add-pcie-msi-read-method.patch +++ /dev/null @@ -1,56 +0,0 @@ -From dd86dc83fcccc0d1773bd93c509e3a03e7ef9b38 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Thu, 25 Mar 2021 17:08:24 +0800 -Subject: [PATCH] pci-host: add pcie-msi read method - -fix CVE-2020-15469 - -Add pcie-msi mmio read method to avoid NULL pointer dereference -issue. - -Reported-by: Lei Sun -Reviewed-by: Li Qiang -Signed-off-by: Prasad J Pandit - -Signed-off-by: Jiajie Li ---- - hw/pci-host/designware.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c -index 9ae8c0deb7..23e3de3cad 100644 ---- a/hw/pci-host/designware.c -+++ b/hw/pci-host/designware.c -@@ -21,6 +21,7 @@ - #include "qemu/osdep.h" - #include "qapi/error.h" - #include "qemu/module.h" -+#include "qemu/log.h" - #include "hw/pci/msi.h" - #include "hw/pci/pci_bridge.h" - #include "hw/pci/pci_host.h" -@@ -60,6 +61,13 @@ designware_pcie_root_to_host(DesignwarePCIERoot *root) - return DESIGNWARE_PCIE_HOST(bus->parent); - } - -+static uint64_t designware_pcie_root_msi_read(void *opaque, hwaddr addr, -+ unsigned size) -+{ -+ qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__); -+ return 0; -+} -+ - static void designware_pcie_root_msi_write(void *opaque, hwaddr addr, - uint64_t val, unsigned len) - { -@@ -74,6 +82,7 @@ static void designware_pcie_root_msi_write(void *opaque, hwaddr addr, - } - - static const MemoryRegionOps designware_pci_host_msi_ops = { -+ .read = designware_pcie_root_msi_read, - .write = designware_pcie_root_msi_write, - .endianness = DEVICE_LITTLE_ENDIAN, - .valid = { --- -2.27.0 - diff --git a/pci-introduce-PCIPASIDOps-to-PCIDevice.patch b/pci-introduce-PCIPASIDOps-to-PCIDevice.patch index e89cdc8df7130e348c916988d8b85f39ec4b6d19..f4cb611607899f89956b788e615d2d964b3a71ec 100644 --- a/pci-introduce-PCIPASIDOps-to-PCIDevice.patch +++ b/pci-introduce-PCIPASIDOps-to-PCIDevice.patch @@ -1,4 +1,4 @@ -From 26adddfe4645b69c16ed8d6601f373d40bddd0e3 Mon Sep 17 00:00:00 2001 +From c71485494970e7aa986be2b05bf7e2847017e264 Mon Sep 17 00:00:00 2001 From: Liu Yi L Date: Fri, 5 Jul 2019 19:01:36 +0800 Subject: [PATCH] pci: introduce PCIPASIDOps to PCIDevice @@ -35,10 +35,10 @@ Signed-off-by: Kunkun Jiang 2 files changed, 45 insertions(+) diff --git a/hw/pci/pci.c b/hw/pci/pci.c -index e74143ccc3..f11ca7964e 100644 +index e5993c1ef5..4a9374c025 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c -@@ -2626,6 +2626,40 @@ void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque) +@@ -2759,6 +2759,40 @@ void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque) bus->iommu_opaque = opaque; } @@ -80,18 +80,18 @@ index e74143ccc3..f11ca7964e 100644 { Range *range = opaque; diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h -index aaf1b9f70d..bb14ed61b0 100644 +index e7cdf2d5ec..abffa12a99 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -9,6 +9,7 @@ - #include "hw/isa/isa.h" #include "hw/pci/pcie.h" + #include "qom/object.h" +#include "hw/iommu/iommu.h" extern bool pci_available; -@@ -263,6 +264,11 @@ struct PCIReqIDCache { +@@ -265,6 +266,11 @@ struct PCIReqIDCache { }; typedef struct PCIReqIDCache PCIReqIDCache; @@ -102,16 +102,16 @@ index aaf1b9f70d..bb14ed61b0 100644 + struct PCIDevice { DeviceState qdev; - -@@ -352,6 +358,7 @@ struct PCIDevice { - MSIVectorUseNotifier msix_vector_use_notifier; - MSIVectorReleaseNotifier msix_vector_release_notifier; - MSIVectorPollNotifier msix_vector_poll_notifier; + bool partially_hotplugged; +@@ -361,6 +367,7 @@ struct PCIDevice { + /* ID of standby device in net_failover pair */ + char *failover_pair_id; + uint32_t acpi_index; + PCIPASIDOps *pasid_ops; }; void pci_register_bar(PCIDevice *pci_dev, int region_num, -@@ -485,6 +492,10 @@ typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int); +@@ -498,6 +505,10 @@ typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int); AddressSpace *pci_device_iommu_address_space(PCIDevice *dev); void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque); diff --git a/pcie-Add-pcie-root-port-fast-plug-unplug-feature.patch b/pcie-Add-pcie-root-port-fast-plug-unplug-feature.patch index bf5b144d12407aacbd859ebd813b8f303126f789..7822fb936d6cedc0169e8abe2370ac030db7188a 100644 --- a/pcie-Add-pcie-root-port-fast-plug-unplug-feature.patch +++ b/pcie-Add-pcie-root-port-fast-plug-unplug-feature.patch @@ -1,7 +1,7 @@ -From 55c4f093b3a527c52cc8ed7138c330512973c9e6 Mon Sep 17 00:00:00 2001 -From: fangying -Date: Wed, 18 Mar 2020 12:49:33 +0800 -Subject: [PATCH 1/2] pcie: Add pcie-root-port fast plug/unplug feature +From 2412c1968777a0fe77cb24dda935e3414e00ebb1 Mon Sep 17 00:00:00 2001 +From: Yan Wang +Date: Tue, 8 Feb 2022 16:10:31 +0800 +Subject: [PATCH 5/6] pcie: Add pcie-root-port fast plug/unplug feature If a device is plugged in the pcie-root-port when VM kernel is booting, the kernel may wrongly disable the device. @@ -15,108 +15,85 @@ so we must fix it up. We hack into the pcie native hotplug patch so that hotplug/unplug will work under this circumstance. Signed-off-by: Ying Fang +Signed-off-by: Yan Wang --- - hw/core/machine.c | 1 + - hw/pci-bridge/gen_pcie_root_port.c | 3 ++- - hw/pci/pcie.c | 23 +++++++++++++++++++---- - include/hw/pci/pcie_port.h | 3 ++- - 4 files changed, 24 insertions(+), 6 deletions(-) + hw/core/machine.c | 2 ++ + hw/pci-bridge/gen_pcie_root_port.c | 2 ++ + hw/pci/pcie.c | 13 ++++++++++++- + include/hw/pci/pcie_port.h | 3 +++ + 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/hw/core/machine.c b/hw/core/machine.c -index 2baf9ec3..3138f97b 100644 +index 53a99ab..126e3e2 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c -@@ -33,6 +33,7 @@ GlobalProperty hw_compat_3_1[] = { +@@ -121,6 +121,8 @@ 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" }, - { "pcie-root-port", "fast-plug", "0" }, ++ { "pcie-root-port", "fast-plug", "0" }, + { "pcie-root-port", "fast-unplug", "0" }, { "memory-backend-file", "x-use-canonical-path-for-ramblock-id", "true" }, { "memory-backend-memfd", "x-use-canonical-path-for-ramblock-id", "true" }, { "tpm-crb", "ppi", "false" }, diff --git a/hw/pci-bridge/gen_pcie_root_port.c b/hw/pci-bridge/gen_pcie_root_port.c -index 3179c4ea..2fbb11d0 100644 +index 20099a8..0bf9df9 100644 --- a/hw/pci-bridge/gen_pcie_root_port.c +++ b/hw/pci-bridge/gen_pcie_root_port.c -@@ -131,7 +131,8 @@ static Property gen_rp_props[] = { +@@ -140,6 +140,8 @@ static Property gen_rp_props[] = { speed, PCIE_LINK_SPEED_16), DEFINE_PROP_PCIE_LINK_WIDTH("x-width", PCIESlot, width, PCIE_LINK_WIDTH_32), -- DEFINE_PROP_UINT8("fast-plug", PCIESlot, disable_lnksta_dllla, 0), + DEFINE_PROP_UINT8("fast-plug", PCIESlot, fast_plug, 0), + DEFINE_PROP_UINT8("fast-unplug", PCIESlot, fast_unplug, 0), DEFINE_PROP_END_OF_LIST() }; diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c -index c0d6ff13..2a8ff86d 100644 +index d7d73a3..d7d1504 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c -@@ -85,7 +85,7 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version) - * To fix this up, let's enable the PCI_EXP_LNKSTA_DLLLA - * only if it is a PCIESlot device. - */ -- if (s == NULL || s->disable_lnksta_dllla == 0) { -+ if (s == NULL || s->fast_plug == 0) { - if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) { - pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, - PCI_EXP_LNKSTA_DLLLA); -@@ -136,8 +136,11 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev) - */ - pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKCAP, - PCI_EXP_LNKCAP_DLLLARC); -- pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, -- PCI_EXP_LNKSTA_DLLLA); -+ -+ if(s->fast_plug == 0) { -+ pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, -+ PCI_EXP_LNKSTA_DLLLA); -+ } - - /* - * Target Link Speed defaults to the highest link speed supported by -@@ -477,6 +480,8 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, - Error *local_err = NULL; - PCIDevice *pci_dev = PCI_DEVICE(dev); - PCIBus *bus = pci_get_bus(pci_dev); -+ PCIESlot *s = PCIE_SLOT(PCI_DEVICE(hotplug_dev)); -+ uint8_t *exp_cap = pci_dev->config + pci_dev->exp.exp_cap; +@@ -526,6 +526,7 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, + uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap; + uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP); + uint16_t sltctl = pci_get_word(exp_cap + PCI_EXP_SLTCTL); ++ PCIESlot *s = PCIE_SLOT(hotplug_pdev); - pcie_cap_slot_plug_common(PCI_DEVICE(hotplug_dev), dev, &local_err); - if (local_err) { -@@ -495,7 +500,17 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, + /* Check if hot-unplug is disabled on the slot */ + if ((sltcap & PCI_EXP_SLTCAP_HPC) == 0) { +@@ -572,7 +573,17 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev, return; } -- pcie_cap_slot_push_attention_button(PCI_DEVICE(hotplug_dev)); +- pcie_cap_slot_push_attention_button(hotplug_pdev); + if ((pci_dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) && s->fast_plug) { -+ pci_word_test_and_clear_mask(exp_cap+ PCI_EXP_LNKSTA, ++ pci_word_test_and_clear_mask(pci_dev->config + pci_dev->exp.exp_cap + PCI_EXP_LNKSTA, + PCI_EXP_LNKSTA_DLLLA); + } + + if (s->fast_unplug) { -+ pcie_cap_slot_event(PCI_DEVICE(hotplug_dev), ++ pcie_cap_slot_event(hotplug_pdev, + PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP); + } else { -+ pcie_cap_slot_push_attention_button(PCI_DEVICE(hotplug_dev)); ++ pcie_cap_slot_push_attention_button(hotplug_pdev); + } } /* pci express slot for pci express root/downstream port diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h -index c3969921..b57af4ee 100644 +index e25b289..5b80a13 100644 --- a/include/hw/pci/pcie_port.h +++ b/include/hw/pci/pcie_port.h -@@ -50,7 +50,8 @@ struct PCIESlot { +@@ -51,6 +51,9 @@ struct PCIESlot { uint8_t chassis; uint16_t slot; -- uint8_t disable_lnksta_dllla; + uint8_t fast_plug; + uint8_t fast_unplug; - ++ PCIExpLinkSpeed speed; PCIExpLinkWidth width; + -- -2.19.1 +1.9.1 diff --git a/pcie-Compat-with-devices-which-do-not-support-Link-W.patch b/pcie-Compat-with-devices-which-do-not-support-Link-W.patch index f5c261916fb66e0a54844ddea65ab70fe2bfdee8..aeb31bbf66402b4db3fb510e53f9cc2f7e29abf3 100644 --- a/pcie-Compat-with-devices-which-do-not-support-Link-W.patch +++ b/pcie-Compat-with-devices-which-do-not-support-Link-W.patch @@ -1,7 +1,7 @@ -From 5e1ad9f0f3c344b9fe20fc01ea2f1dfb8ac7fd67 Mon Sep 17 00:00:00 2001 +From 14d1ad1309a1bd035250512368221088c2f83f32 Mon Sep 17 00:00:00 2001 From: fangying Date: Wed, 18 Mar 2020 12:51:33 +0800 -Subject: [PATCH 2/2] pcie: Compat with devices which do not support Link +Subject: [PATCH 6/6] pcie: Compat with devices which do not support Link Width, such as ioh3420 We hack into PCI_EXP_LNKCAP to support device fast plug/unplug @@ -9,15 +9,16 @@ for pcie-root-port. However some devices like ioh3420 does not suport it, so PCI_EXP_LNKCAP is not set for such devices. Signed-off-by: Ying Fang +Signed-off-by: Yan Wang --- hw/pci/pcie.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c -index 2a8ff86d..5044bff4 100644 +index d7d1504..30c09ed 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c -@@ -108,13 +108,6 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev) +@@ -92,13 +92,6 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev) return; } @@ -31,7 +32,7 @@ index 2a8ff86d..5044bff4 100644 /* * Link bandwidth notification is required for all root ports and * downstream ports supporting links wider than x1 or multiple link -@@ -122,6 +115,12 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev) +@@ -106,6 +99,12 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev) */ if (s->width > QEMU_PCI_EXP_LNK_X1 || s->speed > QEMU_PCI_EXP_LNK_2_5GT) { @@ -45,5 +46,5 @@ index 2a8ff86d..5044bff4 100644 PCI_EXP_LNKCAP_LBNC); } -- -2.19.1 +1.9.1 diff --git a/pcie-disable-the-PCI_EXP_LINKSTA_DLLA-cap.patch b/pcie-disable-the-PCI_EXP_LINKSTA_DLLA-cap.patch deleted file mode 100644 index dc31a503345e1599abe5cf879b8edfeff4ee22e9..0000000000000000000000000000000000000000 --- a/pcie-disable-the-PCI_EXP_LINKSTA_DLLA-cap.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 7381599d4222f9b5cff6935a66e8b311af77f620 Mon Sep 17 00:00:00 2001 -From: Li Mingwang -Date: Thu, 17 Oct 2019 16:57:52 +0800 -Subject: [PATCH] Subject: [PATCH] pcie: disable the PCI_EXP_LINKSTA_DLLA cap - for pcie-root-port by default - -If the PCI_EXP_LNKSTA_DLLLA capability is set by default, linux -kernel will send PDC event to detect whether there is a device in -pcie slot. If a device is pluged in the pcie-root-port at the same -time, hot-plug device will send ABP + PDC events to the kernel. The -VM kernel will wrongly unplug the device if two PDC events get too -close. Thus we'd better set the PCI_EXP_LNKSTA_DLLLA capability only -in hotplug scenario - -Signed-off-by: Li Mingwang ---- - hw/core/machine.c | 1 + - hw/pci-bridge/gen_pcie_root_port.c | 1 + - hw/pci/pcie.c | 18 ++++++++++++++---- - include/hw/pci/pcie_port.h | 2 ++ - 4 files changed, 18 insertions(+), 4 deletions(-) - -diff --git a/hw/core/machine.c b/hw/core/machine.c -index 5d046a43..29a708da 100644 ---- a/hw/core/machine.c -+++ b/hw/core/machine.c -@@ -30,6 +30,7 @@ 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" }, -+ { "pcie-root-port", "fast-plug", "0" }, - { "memory-backend-file", "x-use-canonical-path-for-ramblock-id", "true" }, - { "memory-backend-memfd", "x-use-canonical-path-for-ramblock-id", "true" }, - { "tpm-crb", "ppi", "false" }, -diff --git a/hw/pci-bridge/gen_pcie_root_port.c b/hw/pci-bridge/gen_pcie_root_port.c -index 26bda73e..3179c4ea 100644 ---- a/hw/pci-bridge/gen_pcie_root_port.c -+++ b/hw/pci-bridge/gen_pcie_root_port.c -@@ -131,6 +131,7 @@ static Property gen_rp_props[] = { - speed, PCIE_LINK_SPEED_16), - DEFINE_PROP_PCIE_LINK_WIDTH("x-width", PCIESlot, - width, PCIE_LINK_WIDTH_32), -+ DEFINE_PROP_UINT8("fast-plug", PCIESlot, disable_lnksta_dllla, 0), - DEFINE_PROP_END_OF_LIST() - }; - -diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c -index cf1ca30f..c0d6ff13 100644 ---- a/hw/pci/pcie.c -+++ b/hw/pci/pcie.c -@@ -50,6 +50,7 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version) - { - uint8_t *exp_cap = dev->config + dev->exp.exp_cap; - uint8_t *cmask = dev->cmask + dev->exp.exp_cap; -+ PCIESlot *s = (PCIESlot *)object_dynamic_cast(OBJECT(dev), TYPE_PCIE_SLOT); - - /* capability register - interrupt message number defaults to 0 */ -@@ -76,11 +77,20 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version) - QEMU_PCI_EXP_LNKSTA_NLW(QEMU_PCI_EXP_LNK_X1) | - QEMU_PCI_EXP_LNKSTA_CLS(QEMU_PCI_EXP_LNK_2_5GT)); - -- if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) { -- pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, -- PCI_EXP_LNKSTA_DLLLA); -+ /* If a device is plugged in the pcie-root-port when VM kernel -+ * is just booting, the kernel will wrongly disable the device. -+ * This bug was brought in two patches of the linux kernel, i.e. -+ * https://patchwork.kernel.org/patch/10575355/ and -+ * https://patchwork.kernel.org/patch/10766219/. -+ * To fix this up, let's enable the PCI_EXP_LNKSTA_DLLLA -+ * only if it is a PCIESlot device. -+ */ -+ if (s == NULL || s->disable_lnksta_dllla == 0) { -+ if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA) { -+ pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA, -+ PCI_EXP_LNKSTA_DLLLA); -+ } - } -- - /* We changed link status bits over time, and changing them across - * migrations is generally fine as hardware changes them too. - * Let's not bother checking. -diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h -index 09586f46..c3969921 100644 ---- a/include/hw/pci/pcie_port.h -+++ b/include/hw/pci/pcie_port.h -@@ -50,6 +50,8 @@ struct PCIESlot { - uint8_t chassis; - uint16_t slot; - -+ uint8_t disable_lnksta_dllla; -+ - PCIExpLinkSpeed speed; - PCIExpLinkWidth width; - --- -2.19.1 - diff --git a/pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch b/pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch index b375c20f10426f4328d288d1be037609c06842de..a917143fd0d18befb2c11f0bf6bb0a11b758d218 100644 --- a/pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch +++ b/pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch @@ -1,7 +1,7 @@ -From f995e8b5e5c14f83a16433f192440ec5c82c87fa Mon Sep 17 00:00:00 2001 +From 696abba190a0daad488d709d733f0d1f10df6f89 Mon Sep 17 00:00:00 2001 From: Ying Fang Date: Mon, 29 Jul 2019 16:16:35 +0800 -Subject: [PATCH] pl011: reset read FIFO when UARTTIMSC=0 & UARTICR=0xffff +Subject: [PATCH 1/6] 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 @@ -17,15 +17,16 @@ https://www.spinics.net/lists/linux-serial/msg23163.html Signed-off-by: Haibin Wang Reviewed-by: Shannon Zhao Reviewed-by: Ying Fang +Signed-off-by: Yan Wang --- 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 +index 6e2d7f7..8ca2a4e 100644 --- a/hw/char/pl011.c +++ b/hw/char/pl011.c -@@ -223,6 +223,10 @@ static void pl011_write(void *opaque, hwaddr offset, +@@ -255,6 +255,10 @@ static void pl011_write(void *opaque, hwaddr offset, case 17: /* UARTICR */ s->int_level &= ~value; pl011_update(s); @@ -37,5 +38,5 @@ index e5dd448f..899745ef 100644 case 18: /* UARTDMACR */ s->dmacr = value; -- -2.19.1 +1.9.1 diff --git a/pl031-support-rtc-timer-property-for-pl031.patch b/pl031-support-rtc-timer-property-for-pl031.patch index 7bd977af364da6871f7b0b7f8cb62af2f23ab26c..b57f0e75965a62e7f929b740babe184546efa0c5 100644 --- a/pl031-support-rtc-timer-property-for-pl031.patch +++ b/pl031-support-rtc-timer-property-for-pl031.patch @@ -1,23 +1,25 @@ -From 68d4653b5ffde629e9b05d5de13b6adcde9d153b Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Mon, 29 Jul 2019 16:20:51 +0800 +From f8e5f099c5b6665e3ed9f397ddca9283148938a4 Mon Sep 17 00:00:00 2001 +From: Jinhao Gao +Date: Tue, 15 Feb 2022 17:02:08 +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 -Reviewed-by: Shannon Zhao +Reviewed-by: Shannon Zhao Reviewed-by: Ying Fang +Signed-off-by: Keqian Zhu +Signed-off-by: Jinhao Gao --- - hw/timer/pl031.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) + hw/rtc/pl031.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 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) +diff --git a/hw/rtc/pl031.c b/hw/rtc/pl031.c +index da8b061e91..61a2948f77 100644 +--- a/hw/rtc/pl031.c ++++ b/hw/rtc/pl031.c +@@ -63,6 +63,15 @@ static uint32_t pl031_get_count(PL031State *s) return s->tick_offset + now / NANOSECONDS_PER_SECOND; } @@ -33,17 +35,36 @@ index 274ad47a..04331472 100644 static void pl031_set_alarm(PL031State *s) { uint32_t ticks; -@@ -191,6 +200,10 @@ static void pl031_init(Object *obj) +@@ -201,6 +210,20 @@ 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); ++} + -+ object_property_add_tm(OBJECT(s), "date", pl031_get_date, NULL); ++static void pl031_realize(DeviceState *d, Error **errp) ++{ + object_property_add_alias(qdev_get_machine(), "rtc-time", -+ OBJECT(s), "date", NULL); ++ OBJECT(d), "date"); ++} ++ ++static void pl031_unrealize(DeviceState *d) ++{ ++ if (object_property_find(qdev_get_machine(), "rtc-time")) { ++ object_property_del(qdev_get_machine(), "rtc-time"); ++ } + } + + static void pl031_finalize(Object *obj) +@@ -337,6 +360,8 @@ static void pl031_class_init(ObjectClass *klass, void *data) + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->vmsd = &vmstate_pl031; ++ dc->realize = pl031_realize; ++ dc->unrealize = pl031_unrealize; + device_class_set_props(dc, pl031_properties); } - static int pl031_pre_save(void *opaque) -- -2.19.1 +2.27.0 diff --git a/pr-manager-Fix-invalid-g_free-crash-bug.patch b/pr-manager-Fix-invalid-g_free-crash-bug.patch deleted file mode 100644 index b171cdb5ae34dab7135926c2250541814d543a02..0000000000000000000000000000000000000000 --- a/pr-manager-Fix-invalid-g_free-crash-bug.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 57fdf4a13ff16d9d48a43f02a5e7b42e3d264f83 Mon Sep 17 00:00:00 2001 -From: Markus Armbruster -Date: Thu, 22 Aug 2019 15:38:46 +0200 -Subject: [PATCH] pr-manager: Fix invalid g_free() crash bug -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -pr_manager_worker() passes its @opaque argument to g_free(). Wrong; -it points to pr_manager_worker()'s automatic @data. Broken when -commit 2f3a7ab39be converted @data from heap- to stack-allocated. Fix -by deleting the g_free(). - -Fixes: 2f3a7ab39bec4ba8022dc4d42ea641165b004e3e -Cc: qemu-stable@nongnu.org -Signed-off-by: Markus Armbruster -Reviewed-by: Philippe Mathieu-Daudé -Acked-by: Paolo Bonzini -Signed-off-by: Kevin Wolf -(cherry picked from commit 6b9d62c2a9e83bbad73fb61406f0ff69b46ff6f3) -Signed-off-by: Michael Roth ---- - scsi/pr-manager.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/scsi/pr-manager.c b/scsi/pr-manager.c -index ee43663576..0c866e8698 100644 ---- a/scsi/pr-manager.c -+++ b/scsi/pr-manager.c -@@ -39,7 +39,6 @@ static int pr_manager_worker(void *opaque) - int fd = data->fd; - int r; - -- g_free(data); - trace_pr_manager_run(fd, hdr->cmdp[0], hdr->cmdp[1]); - - /* The reference was taken in pr_manager_execute. */ --- -2.23.0 diff --git a/prep-add-ppc-parity-write-method.patch b/prep-add-ppc-parity-write-method.patch deleted file mode 100644 index fbc3dcc8cf024a5f26ce66f73ff653b5c74837dd..0000000000000000000000000000000000000000 --- a/prep-add-ppc-parity-write-method.patch +++ /dev/null @@ -1,50 +0,0 @@ -From f4eed258b1b8b434927fbc9a18bbcb52d3f55ce6 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Thu, 25 Mar 2021 17:16:14 +0800 -Subject: [PATCH] prep: add ppc-parity write method - -fix CVE-2020-15469 - -Add ppc-parity mmio write method to avoid NULL pointer dereference -issue. - -Reported-by: Lei Sun -Acked-by: David Gibson -Signed-off-by: Prasad J Pandit - -Signed-off-by: Jiajie Li ---- - hw/ppc/prep_systemio.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/hw/ppc/prep_systemio.c b/hw/ppc/prep_systemio.c -index df7603b986..67244ed48c 100644 ---- a/hw/ppc/prep_systemio.c -+++ b/hw/ppc/prep_systemio.c -@@ -23,6 +23,7 @@ - */ - - #include "qemu/osdep.h" -+#include "qemu/log.h" - #include "hw/isa/isa.h" - #include "exec/address-spaces.h" - #include "qemu/error-report.h" /* for error_report() */ -@@ -232,8 +233,15 @@ static uint64_t ppc_parity_error_readl(void *opaque, hwaddr addr, - return val; - } - -+static void ppc_parity_error_writel(void *opaque, hwaddr addr, -+ uint64_t data, unsigned size) -+{ -+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid write access\n", __func__); -+} -+ - static const MemoryRegionOps ppc_parity_error_ops = { - .read = ppc_parity_error_readl, -+ .write = ppc_parity_error_writel, - .valid = { - .min_access_size = 4, - .max_access_size = 4, --- -2.27.0 - diff --git a/ps2-fix-oob-in-ps2-kbd.patch b/ps2-fix-oob-in-ps2-kbd.patch new file mode 100644 index 0000000000000000000000000000000000000000..a385968fd30566264e234cc57ef60a7ad03097a3 --- /dev/null +++ b/ps2-fix-oob-in-ps2-kbd.patch @@ -0,0 +1,35 @@ +From 19523565181bb6efb1b9f819d45a7ca8ea6eca19 Mon Sep 17 00:00:00 2001 +From: Chuan Zheng +Date: Wed, 9 Feb 2022 11:21:28 +0800 +Subject: [PATCH 11/15] ps2: fix oob in ps2 kbd + +fix oob in ps2 kbd +--- + hw/input/ps2.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/input/ps2.c b/hw/input/ps2.c +index 9376a8f4ce..5d82ee3cdf 100644 +--- a/hw/input/ps2.c ++++ b/hw/input/ps2.c +@@ -205,7 +205,7 @@ void ps2_queue_noirq(PS2State *s, int b) + } + + q->data[q->wptr] = b; +- if (++q->wptr == PS2_BUFFER_SIZE) { ++ if (++q->wptr >= PS2_BUFFER_SIZE) { + q->wptr = 0; + } + q->count++; +@@ -578,7 +578,7 @@ uint32_t ps2_read_data(PS2State *s) + val = q->data[index]; + } else { + val = q->data[q->rptr]; +- if (++q->rptr == PS2_BUFFER_SIZE) { ++ if (++q->rptr >= PS2_BUFFER_SIZE) { + q->rptr = 0; + } + q->count--; +-- +2.27.0 + diff --git a/qapi-Add-VFIO-devices-migration-stats-in-Migration-s.patch b/qapi-Add-VFIO-devices-migration-stats-in-Migration-s.patch deleted file mode 100644 index 3ee078c19f392be5b53214f0f03dcea3ecc216fa..0000000000000000000000000000000000000000 --- a/qapi-Add-VFIO-devices-migration-stats-in-Migration-s.patch +++ /dev/null @@ -1,214 +0,0 @@ -From f97eaa27e2fb6b985f090af9acaa780bb6a2ee5b Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:27 +0530 -Subject: [PATCH] qapi: Add VFIO devices migration stats in Migration stats - -Added amount of bytes transferred to the VM at destination by all VFIO -devices - -Signed-off-by: Kirti Wankhede -Reviewed-by: Dr. David Alan Gilbert -Signed-off-by: Alex Williamson ---- - hw/vfio/common.c | 19 +++++++++++++++++++ - hw/vfio/migration.c | 9 +++++++++ - include/hw/vfio/vfio-common.h | 3 +++ - migration/migration.c | 17 +++++++++++++++++ - monitor/hmp-cmds.c | 6 ++++++ - qapi/migration.json | 17 +++++++++++++++++ - 6 files changed, 71 insertions(+) - -diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index 4ce1c10734..a86a4c4506 100644 ---- a/hw/vfio/common.c -+++ b/hw/vfio/common.c -@@ -291,6 +291,25 @@ const MemoryRegionOps vfio_region_ops = { - * Device state interfaces - */ - -+bool vfio_mig_active(void) -+{ -+ VFIOGroup *group; -+ VFIODevice *vbasedev; -+ -+ if (QLIST_EMPTY(&vfio_group_list)) { -+ return false; -+ } -+ -+ QLIST_FOREACH(group, &vfio_group_list, next) { -+ QLIST_FOREACH(vbasedev, &group->device_list, next) { -+ if (vbasedev->migration_blocker) { -+ return false; -+ } -+ } -+ } -+ return true; -+} -+ - static bool vfio_devices_all_stopped_and_saving(VFIOContainer *container) - { - VFIOGroup *group; -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -index 0bdf6a1820..b77c66557e 100644 ---- a/hw/vfio/migration.c -+++ b/hw/vfio/migration.c -@@ -45,6 +45,8 @@ - #define VFIO_MIG_FLAG_DEV_SETUP_STATE (0xffffffffef100003ULL) - #define VFIO_MIG_FLAG_DEV_DATA_STATE (0xffffffffef100004ULL) - -+static int64_t bytes_transferred; -+ - static inline int vfio_mig_access(VFIODevice *vbasedev, void *val, int count, - off_t off, bool iswrite) - { -@@ -255,6 +257,7 @@ static int vfio_save_buffer(QEMUFile *f, VFIODevice *vbasedev, uint64_t *size) - *size = data_size; - } - -+ bytes_transferred += data_size; - return ret; - } - -@@ -785,6 +788,7 @@ static void vfio_migration_state_notifier(Notifier *notifier, void *data) - case MIGRATION_STATUS_CANCELLING: - case MIGRATION_STATUS_CANCELLED: - case MIGRATION_STATUS_FAILED: -+ bytes_transferred = 0; - ret = vfio_migration_set_state(vbasedev, - ~(VFIO_DEVICE_STATE_SAVING | VFIO_DEVICE_STATE_RESUMING), - VFIO_DEVICE_STATE_RUNNING); -@@ -866,6 +870,11 @@ err: - - /* ---------------------------------------------------------------------- */ - -+int64_t vfio_mig_bytes_transferred(void) -+{ -+ return bytes_transferred; -+} -+ - int vfio_migration_probe(VFIODevice *vbasedev, Error **errp) - { - VFIOContainer *container = vbasedev->group->container; -diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index 8fd0212264..048731e81f 100644 ---- a/include/hw/vfio/vfio-common.h -+++ b/include/hw/vfio/vfio-common.h -@@ -203,6 +203,9 @@ extern const MemoryRegionOps vfio_region_ops; - typedef QLIST_HEAD(VFIOGroupList, VFIOGroup) VFIOGroupList; - extern VFIOGroupList vfio_group_list; - -+bool vfio_mig_active(void); -+int64_t vfio_mig_bytes_transferred(void); -+ - #ifdef CONFIG_LINUX - int vfio_get_region_info(VFIODevice *vbasedev, int index, - struct vfio_region_info **info); -diff --git a/migration/migration.c b/migration/migration.c -index b0b9430822..9faf5f63a6 100644 ---- a/migration/migration.c -+++ b/migration/migration.c -@@ -49,6 +49,10 @@ - #include "monitor/monitor.h" - #include "net/announce.h" - -+#ifdef CONFIG_VFIO -+#include "hw/vfio/vfio-common.h" -+#endif -+ - #define MAX_THROTTLE (32 << 20) /* Migration transfer speed throttling */ - - /* Amount of time to allocate to each "chunk" of bandwidth-throttled -@@ -908,6 +912,17 @@ static void populate_disk_info(MigrationInfo *info) - } - } - -+static void populate_vfio_info(MigrationInfo *info) -+{ -+#ifdef CONFIG_VFIO -+ if (vfio_mig_active()) { -+ info->has_vfio = true; -+ info->vfio = g_malloc0(sizeof(*info->vfio)); -+ info->vfio->transferred = vfio_mig_bytes_transferred(); -+ } -+#endif -+} -+ - static void fill_source_migration_info(MigrationInfo *info) - { - MigrationState *s = migrate_get_current(); -@@ -941,6 +956,7 @@ static void fill_source_migration_info(MigrationInfo *info) - - populate_ram_info(info, s); - populate_disk_info(info); -+ populate_vfio_info(info); - break; - case MIGRATION_STATUS_COLO: - info->has_status = true; -@@ -956,6 +972,7 @@ static void fill_source_migration_info(MigrationInfo *info) - info->setup_time = s->setup_time; - - populate_ram_info(info, s); -+ populate_vfio_info(info); - break; - case MIGRATION_STATUS_FAILED: - info->has_status = true; -diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c -index e5a7a88ba2..cecaae0a47 100644 ---- a/monitor/hmp-cmds.c -+++ b/monitor/hmp-cmds.c -@@ -370,6 +370,12 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) - } - monitor_printf(mon, "]\n"); - } -+ -+ if (info->has_vfio) { -+ monitor_printf(mon, "vfio device transferred: %" PRIu64 " kbytes\n", -+ info->vfio->transferred >> 10); -+ } -+ - qapi_free_MigrationInfo(info); - qapi_free_MigrationCapabilityStatusList(caps); - } -diff --git a/qapi/migration.json b/qapi/migration.json -index 587ef65872..1f0eb19ac6 100644 ---- a/qapi/migration.json -+++ b/qapi/migration.json -@@ -141,6 +141,18 @@ - 'active', 'postcopy-active', 'postcopy-paused', - 'postcopy-recover', 'completed', 'failed', 'colo', - 'pre-switchover', 'device' ] } -+## -+# @VfioStats: -+# -+# Detailed VFIO devices migration statistics -+# -+# @transferred: amount of bytes transferred to the target VM by VFIO devices -+# -+# Since: 5.2 -+# -+## -+{ 'struct': 'VfioStats', -+ 'data': {'transferred': 'int' } } - - ## - # @MigrationInfo: -@@ -202,11 +214,16 @@ - # - # @socket-address: Only used for tcp, to know what the real port is (Since 4.0) - # -+# @vfio: @VfioStats containing detailed VFIO devices migration statistics, -+# only returned if VFIO device is present, migration is supported by all -+# VFIO devices and status is 'active' or 'completed' (since 5.2) -+# - # Since: 0.14.0 - ## - { 'struct': 'MigrationInfo', - 'data': {'*status': 'MigrationStatus', '*ram': 'MigrationStats', - '*disk': 'MigrationStats', -+ '*vfio': 'VfioStats', - '*xbzrle-cache': 'XBZRLECacheStats', - '*total-time': 'int', - '*expected-downtime': 'int', --- -2.27.0 - diff --git a/qapi-add-BitmapSyncMode-enum.patch b/qapi-add-BitmapSyncMode-enum.patch deleted file mode 100644 index 778faeee0dc98c233e2415190a8941ed6bd137db..0000000000000000000000000000000000000000 --- a/qapi-add-BitmapSyncMode-enum.patch +++ /dev/null @@ -1,54 +0,0 @@ -From bd1d5d79f4629520d0753676cea8129c60fc6bbc Mon Sep 17 00:00:00 2001 -From: John Snow -Date: Mon, 29 Jul 2019 16:35:52 -0400 -Subject: [PATCH] qapi: add BitmapSyncMode enum - -Depending on what a user is trying to accomplish, there might be a few -bitmap cleanup actions that occur when an operation is finished that -could be useful. - -I am proposing three: -- NEVER: The bitmap is never synchronized against what was copied. -- ALWAYS: The bitmap is always synchronized, even on failures. -- ON-SUCCESS: The bitmap is synchronized only on success. - -The existing incremental backup modes use 'on-success' semantics, -so add just that one for right now. - -Signed-off-by: John Snow -Reviewed-by: Max Reitz -Reviewed-by: Markus Armbruster -Message-id: 20190709232550.10724-5-jsnow@redhat.com -Signed-off-by: John Snow ---- - qapi/block-core.json | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/qapi/block-core.json b/qapi/block-core.json -index 37aa1b7b9a..b8d12a4951 100644 ---- a/qapi/block-core.json -+++ b/qapi/block-core.json -@@ -1134,6 +1134,20 @@ - { 'enum': 'MirrorSyncMode', - 'data': ['top', 'full', 'none', 'incremental'] } - -+## -+# @BitmapSyncMode: -+# -+# An enumeration of possible behaviors for the synchronization of a bitmap -+# when used for data copy operations. -+# -+# @on-success: The bitmap is only synced when the operation is successful. -+# This is the behavior always used for 'INCREMENTAL' backups. -+# -+# Since: 4.2 -+## -+{ 'enum': 'BitmapSyncMode', -+ 'data': ['on-success'] } -+ - ## - # @MirrorCopyMode: - # --- -2.27.0 - diff --git a/qapi-block-core-Add-retry-option-for-error-action.patch b/qapi-block-core-Add-retry-option-for-error-action.patch index 817ff7051db6ab8b9a36d8d53427495c628a2a89..f1536884698c15c4470c3c049093d24ffcc8b4c9 100644 --- a/qapi-block-core-Add-retry-option-for-error-action.patch +++ b/qapi-block-core-Add-retry-option-for-error-action.patch @@ -1,22 +1,23 @@ -From 9a95d75bdd469c9c7d44c7c72bc16d57ef2f65cc Mon Sep 17 00:00:00 2001 +From 4c3d47e04886e072acc0e4fefdc49e9d1f6b4ad1 Mon Sep 17 00:00:00 2001 From: Jiahui Cen Date: Thu, 21 Jan 2021 15:46:45 +0800 -Subject: [PATCH] qapi/block-core: Add retry option for error action +Subject: [PATCH 1/7] qapi/block-core: Add retry option for error action Add a new error action 'retry' to support retry on errors. Signed-off-by: Jiahui Cen Signed-off-by: Ying Fang +Signed-off-by: Alex Chen --- blockdev.c | 2 ++ qapi/block-core.json | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/blockdev.c b/blockdev.c -index 4d141e9a1f..0f49fd290e 100644 +index b35072644e..6f1981635b 100644 --- a/blockdev.c +++ b/blockdev.c -@@ -319,6 +319,8 @@ static int parse_block_error_action(const char *buf, bool is_read, Error **errp) +@@ -333,6 +333,8 @@ static int parse_block_error_action(const char *buf, bool is_read, Error **errp) return BLOCKDEV_ON_ERROR_STOP; } else if (!strcmp(buf, "report")) { return BLOCKDEV_ON_ERROR_REPORT; @@ -26,10 +27,10 @@ index 4d141e9a1f..0f49fd290e 100644 error_setg(errp, "'%s' invalid %s error action", buf, is_read ? "read" : "write"); diff --git a/qapi/block-core.json b/qapi/block-core.json -index 0d43d4f37c..db24f0dfe5 100644 +index 1d3dd9cb48..804beabfb0 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json -@@ -1113,7 +1113,7 @@ +@@ -1146,7 +1146,7 @@ # Since: 1.3 ## { 'enum': 'BlockdevOnError', @@ -38,7 +39,7 @@ index 0d43d4f37c..db24f0dfe5 100644 ## # @MirrorSyncMode: -@@ -4894,7 +4894,7 @@ +@@ -4952,7 +4952,7 @@ # Since: 2.1 ## { 'enum': 'BlockErrorAction', diff --git a/qapi-block-core-Introduce-BackupCommon.patch b/qapi-block-core-Introduce-BackupCommon.patch deleted file mode 100644 index 2d160748c79371b993fd4f0c82a48b535d7b29cd..0000000000000000000000000000000000000000 --- a/qapi-block-core-Introduce-BackupCommon.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 2204b4839fb90658e13ddc608df7b35ed1ea9fd0 Mon Sep 17 00:00:00 2001 -From: John Snow -Date: Mon, 29 Jul 2019 16:35:52 -0400 -Subject: [PATCH] qapi/block-core: Introduce BackupCommon - -drive-backup and blockdev-backup have an awful lot of things in common -that are the same. Let's fix that. - -I don't deduplicate 'target', because the semantics actually did change -between each structure. Leave that one alone so it can be documented -separately. - -Where documentation was not identical, use the most up-to-date version. -For "speed", use Blockdev-Backup's version. For "sync", use -Drive-Backup's version. - -Signed-off-by: John Snow -Reviewed-by: Max Reitz -[Maintainer edit: modified commit message. --js] -Reviewed-by: Markus Armbruster -Message-id: 20190709232550.10724-2-jsnow@redhat.com -Signed-off-by: John Snow ---- - qapi/block-core.json | 95 ++++++++++++++------------------------------ - 1 file changed, 29 insertions(+), 66 deletions(-) - -diff --git a/qapi/block-core.json b/qapi/block-core.json -index db24f0dfe5..37aa1b7b9a 100644 ---- a/qapi/block-core.json -+++ b/qapi/block-core.json -@@ -1315,32 +1315,23 @@ - 'data': { 'node': 'str', 'overlay': 'str' } } - - ## --# @DriveBackup: -+# @BackupCommon: - # - # @job-id: identifier for the newly-created block job. If - # omitted, the device name will be used. (Since 2.7) - # - # @device: the device name or node-name of a root node which should be copied. - # --# @target: the target of the new image. If the file exists, or if it --# is a device, the existing file/device will be used as the new --# destination. If it does not exist, a new file will be created. --# --# @format: the format of the new destination, default is to --# probe if @mode is 'existing', else the format of the source --# - # @sync: what parts of the disk image should be copied to the destination - # (all the disk, only the sectors allocated in the topmost image, from a - # dirty bitmap, or only new I/O). - # --# @mode: whether and how QEMU should create a new image, default is --# 'absolute-paths'. --# --# @speed: the maximum speed, in bytes per second -+# @speed: the maximum speed, in bytes per second. The default is 0, -+# for unlimited. - # - # @bitmap: the name of dirty bitmap if sync is "incremental". - # Must be present if sync is "incremental", must NOT be present --# otherwise. (Since 2.4) -+# otherwise. (Since 2.4 (drive-backup), 3.1 (blockdev-backup)) - # - # @compress: true to compress data, if the target format supports it. - # (default: false) (since 2.8) -@@ -1370,75 +1361,47 @@ - # I/O. If an error occurs during a guest write request, the device's - # rerror/werror actions will be used. - # --# Since: 1.6 -+# Since: 4.2 - ## --{ 'struct': 'DriveBackup', -- 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str', -- '*format': 'str', 'sync': 'MirrorSyncMode', -- '*mode': 'NewImageMode', '*speed': 'int', -+{ 'struct': 'BackupCommon', -+ 'data': { '*job-id': 'str', 'device': 'str', -+ 'sync': 'MirrorSyncMode', '*speed': 'int', - '*bitmap': 'str', '*compress': 'bool', - '*on-source-error': 'BlockdevOnError', - '*on-target-error': 'BlockdevOnError', - '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } } - - ## --# @BlockdevBackup: --# --# @job-id: identifier for the newly-created block job. If --# omitted, the device name will be used. (Since 2.7) --# --# @device: the device name or node-name of a root node which should be copied. --# --# @target: the device name or node-name of the backup target node. --# --# @sync: what parts of the disk image should be copied to the destination --# (all the disk, only the sectors allocated in the topmost image, or --# only new I/O). --# --# @speed: the maximum speed, in bytes per second. The default is 0, --# for unlimited. --# --# @bitmap: the name of dirty bitmap if sync is "incremental". --# Must be present if sync is "incremental", must NOT be present --# otherwise. (Since 3.1) --# --# @compress: true to compress data, if the target format supports it. --# (default: false) (since 2.8) -+# @DriveBackup: - # --# @on-source-error: the action to take on an error on the source, --# default 'report'. 'stop' and 'enospc' can only be used --# if the block device supports io-status (see BlockInfo). -+# @target: the target of the new image. If the file exists, or if it -+# is a device, the existing file/device will be used as the new -+# destination. If it does not exist, a new file will be created. - # --# @on-target-error: the action to take on an error on the target, --# default 'report' (no limitations, since this applies to --# a different block device than @device). -+# @format: the format of the new destination, default is to -+# probe if @mode is 'existing', else the format of the source - # --# @auto-finalize: When false, this job will wait in a PENDING state after it has --# finished its work, waiting for @block-job-finalize before --# making any block graph changes. --# When true, this job will automatically --# perform its abort or commit actions. --# Defaults to true. (Since 2.12) -+# @mode: whether and how QEMU should create a new image, default is -+# 'absolute-paths'. - # --# @auto-dismiss: When false, this job will wait in a CONCLUDED state after it --# has completely ceased all work, and awaits @block-job-dismiss. --# When true, this job will automatically disappear from the query --# list without user intervention. --# Defaults to true. (Since 2.12) -+# Since: 1.6 -+## -+{ 'struct': 'DriveBackup', -+ 'base': 'BackupCommon', -+ 'data': { 'target': 'str', -+ '*format': 'str', -+ '*mode': 'NewImageMode' } } -+ -+## -+# @BlockdevBackup: - # --# Note: @on-source-error and @on-target-error only affect background --# I/O. If an error occurs during a guest write request, the device's --# rerror/werror actions will be used. -+# @target: the device name or node-name of the backup target node. - # - # Since: 2.3 - ## - { 'struct': 'BlockdevBackup', -- 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str', -- 'sync': 'MirrorSyncMode', '*speed': 'int', -- '*bitmap': 'str', '*compress': 'bool', -- '*on-source-error': 'BlockdevOnError', -- '*on-target-error': 'BlockdevOnError', -- '*auto-finalize': 'bool', '*auto-dismiss': 'bool' } } -+ 'base': 'BackupCommon', -+ 'data': { 'target': 'str' } } - - ## - # @blockdev-snapshot-sync: --- -2.27.0 - diff --git a/qapi-machine.json-Fix-incorrect-description-for-die-.patch b/qapi-machine.json-Fix-incorrect-description-for-die-.patch new file mode 100644 index 0000000000000000000000000000000000000000..a5e605aca092a558d266b46771b4020a81c4a33c --- /dev/null +++ b/qapi-machine.json-Fix-incorrect-description-for-die-.patch @@ -0,0 +1,35 @@ +From b04e92ed13e49f666f62c8f3daa5746109caf17b Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Mon, 22 Nov 2021 11:26:51 +0800 +Subject: [PATCH 01/24] qapi/machine.json: Fix incorrect description for die-id + +In terms of scope, die-id should mean "the die number within +socket the CPU belongs to" instead of "the die number within +node/board the CPU belongs to". Fix it to avoid confusing +the Doc reader. + +Fixes: 176d2cda0d ("i386/cpu: Consolidate die-id validity in smp context") +Signed-off-by: Yanan Wang +Reviewed-by: Eric Blake +Message-Id: <20211122032651.16064-1-wangyanan55@huawei.com> +Signed-off-by: Paolo Bonzini +--- + qapi/machine.json | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/qapi/machine.json b/qapi/machine.json +index 067e3f5378..f1839acf20 100644 +--- a/qapi/machine.json ++++ b/qapi/machine.json +@@ -867,7 +867,7 @@ + # + # @node-id: NUMA node ID the CPU belongs to + # @socket-id: socket number within node/board the CPU belongs to +-# @die-id: die number within node/board the CPU belongs to (Since 4.1) ++# @die-id: die number within socket the CPU belongs to (since 4.1) + # @core-id: core number within die the CPU belongs to + # @thread-id: thread number within core the CPU belongs to + # +-- +2.27.0 + diff --git a/qcow2-Fix-QCOW2_COMPRESSED_SECTOR_MASK.patch b/qcow2-Fix-QCOW2_COMPRESSED_SECTOR_MASK.patch deleted file mode 100644 index f2a4e5c26f50c820eb9122e8a8449b76713a8db7..0000000000000000000000000000000000000000 --- a/qcow2-Fix-QCOW2_COMPRESSED_SECTOR_MASK.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 405deba14f6b61b9c557484b46e863308c8cf373 Mon Sep 17 00:00:00 2001 -From: Max Reitz -Date: Mon, 28 Oct 2019 17:18:40 +0100 -Subject: [PATCH] qcow2: Fix QCOW2_COMPRESSED_SECTOR_MASK - -Masks for L2 table entries should have 64 bit. - -Fixes: b6c246942b14d3e0dec46a6c5868ed84e7dbea19 -Buglink: https://bugs.launchpad.net/qemu/+bug/1850000 -Cc: qemu-stable@nongnu.org -Signed-off-by: Max Reitz -Message-id: 20191028161841.1198-2-mreitz@redhat.com -Reviewed-by: Alberto Garcia -Signed-off-by: Max Reitz -(cherry picked from commit 24552feb6ae2f615b76c2b95394af43901f75046) -Signed-off-by: Michael Roth ---- - block/qcow2.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/block/qcow2.h b/block/qcow2.h -index fc1b0d3c1e..359197f89f 100644 ---- a/block/qcow2.h -+++ b/block/qcow2.h -@@ -77,7 +77,7 @@ - - /* Defined in the qcow2 spec (compressed cluster descriptor) */ - #define QCOW2_COMPRESSED_SECTOR_SIZE 512U --#define QCOW2_COMPRESSED_SECTOR_MASK (~(QCOW2_COMPRESSED_SECTOR_SIZE - 1)) -+#define QCOW2_COMPRESSED_SECTOR_MASK (~(QCOW2_COMPRESSED_SECTOR_SIZE - 1ULL)) - - /* Must be at least 2 to cover COW */ - #define MIN_L2_CACHE_SIZE 2 /* cache entries */ --- -2.23.0 diff --git a/qcow2-Fix-corruption-bug-in-qcow2_detect_metadata_pr.patch b/qcow2-Fix-corruption-bug-in-qcow2_detect_metadata_pr.patch deleted file mode 100644 index b4c25806d7f7b99408a0419987c22c2175f4fee3..0000000000000000000000000000000000000000 --- a/qcow2-Fix-corruption-bug-in-qcow2_detect_metadata_pr.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 416a692e51b8b582407e30046ddcffbbe52ecf77 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Thu, 24 Oct 2019 16:26:58 +0200 -Subject: [PATCH] qcow2: Fix corruption bug in - qcow2_detect_metadata_preallocation() - -qcow2_detect_metadata_preallocation() calls qcow2_get_refcount() which -requires s->lock to be taken to protect its accesses to the refcount -table and refcount blocks. However, nothing in this code path actually -took the lock. This could cause the same cache entry to be used by two -requests at the same time, for different tables at different offsets, -resulting in image corruption. - -As it would be preferable to base the detection on consistent data (even -though it's just heuristics), let's take the lock not only around the -qcow2_get_refcount() calls, but around the whole function. - -This patch takes the lock in qcow2_co_block_status() earlier and asserts -in qcow2_detect_metadata_preallocation() that we hold the lock. - -Fixes: 69f47505ee66afaa513305de0c1895a224e52c45 -Cc: qemu-stable@nongnu.org -Reported-by: Michael Weiser -Signed-off-by: Kevin Wolf -Tested-by: Michael Weiser -Reviewed-by: Michael Weiser -Reviewed-by: Vladimir Sementsov-Ogievskiy -Reviewed-by: Max Reitz -(cherry picked from commit 5e9785505210e2477e590e61b1ab100d0ec22b01) -Signed-off-by: Michael Roth ---- - block/qcow2-refcount.c | 2 ++ - block/qcow2.c | 3 ++- - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c -index ef965d7895..0d64bf5a5e 100644 ---- a/block/qcow2-refcount.c -+++ b/block/qcow2-refcount.c -@@ -3455,6 +3455,8 @@ int qcow2_detect_metadata_preallocation(BlockDriverState *bs) - int64_t i, end_cluster, cluster_count = 0, threshold; - int64_t file_length, real_allocation, real_clusters; - -+ qemu_co_mutex_assert_locked(&s->lock); -+ - file_length = bdrv_getlength(bs->file->bs); - if (file_length < 0) { - return file_length; -diff --git a/block/qcow2.c b/block/qcow2.c -index 865839682c..c0f5439dc8 100644 ---- a/block/qcow2.c -+++ b/block/qcow2.c -@@ -1899,6 +1899,8 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, - unsigned int bytes; - int status = 0; - -+ qemu_co_mutex_lock(&s->lock); -+ - if (!s->metadata_preallocation_checked) { - ret = qcow2_detect_metadata_preallocation(bs); - s->metadata_preallocation = (ret == 1); -@@ -1906,7 +1908,6 @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs, - } - - bytes = MIN(INT_MAX, count); -- qemu_co_mutex_lock(&s->lock); - ret = qcow2_get_cluster_offset(bs, offset, &bytes, &cluster_offset); - qemu_co_mutex_unlock(&s->lock); - if (ret < 0) { --- -2.23.0 diff --git a/qcow2-Fix-qcow2_alloc_cluster_abort-for-external-dat.patch b/qcow2-Fix-qcow2_alloc_cluster_abort-for-external-dat.patch deleted file mode 100644 index 8d9b71c70ea503d0bc2480439d5826357e5ab931..0000000000000000000000000000000000000000 --- a/qcow2-Fix-qcow2_alloc_cluster_abort-for-external-dat.patch +++ /dev/null @@ -1,39 +0,0 @@ -From fad649b88c93d0567be4e426f23063b439037095 Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Tue, 11 Feb 2020 10:48:59 +0100 -Subject: [PATCH] qcow2: Fix qcow2_alloc_cluster_abort() for external data file - -For external data file, cluster allocations return an offset in the data -file and are not refcounted. In this case, there is nothing to do for -qcow2_alloc_cluster_abort(). Freeing the same offset in the qcow2 file -is wrong and causes crashes in the better case or image corruption in -the worse case. - -Signed-off-by: Kevin Wolf -Message-Id: <20200211094900.17315-3-kwolf@redhat.com> -Signed-off-by: Kevin Wolf ---- - block/qcow2-cluster.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c -index f8576031b6..7e7e051437 100644 ---- a/block/qcow2-cluster.c -+++ b/block/qcow2-cluster.c -@@ -1026,8 +1026,11 @@ err: - void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m) - { - BDRVQcow2State *s = bs->opaque; -- qcow2_free_clusters(bs, m->alloc_offset, m->nb_clusters << s->cluster_bits, -- QCOW2_DISCARD_NEVER); -+ if (!has_data_file(bs)) { -+ qcow2_free_clusters(bs, m->alloc_offset, -+ m->nb_clusters << s->cluster_bits, -+ QCOW2_DISCARD_NEVER); -+ } - } - - /* --- -2.27.0 - diff --git a/qcow2-Fix-the-calculation-of-the-maximum-L2-cache-si.patch b/qcow2-Fix-the-calculation-of-the-maximum-L2-cache-si.patch deleted file mode 100644 index be2c3c72ced8b33f569fabef0c1f01dd382993ef..0000000000000000000000000000000000000000 --- a/qcow2-Fix-the-calculation-of-the-maximum-L2-cache-si.patch +++ /dev/null @@ -1,58 +0,0 @@ -From c9ffb12754b1575babfef45168b6e1b1af80a95f Mon Sep 17 00:00:00 2001 -From: Alberto Garcia -Date: Fri, 16 Aug 2019 15:17:42 +0300 -Subject: [PATCH] qcow2: Fix the calculation of the maximum L2 cache size - -The size of the qcow2 L2 cache defaults to 32 MB, which can be easily -larger than the maximum amount of L2 metadata that the image can have. -For example: with 64 KB clusters the user would need a qcow2 image -with a virtual size of 256 GB in order to have 32 MB of L2 metadata. - -Because of that, since commit b749562d9822d14ef69c9eaa5f85903010b86c30 -we forbid the L2 cache to become larger than the maximum amount of L2 -metadata for the image, calculated using this formula: - - uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8); - -The problem with this formula is that the result should be rounded up -to the cluster size because an L2 table on disk always takes one full -cluster. - -For example, a 1280 MB qcow2 image with 64 KB clusters needs exactly -160 KB of L2 metadata, but we need 192 KB on disk (3 clusters) even if -the last 32 KB of those are not going to be used. - -However QEMU rounds the numbers down and only creates 2 cache tables -(128 KB), which is not enough for the image. - -A quick test doing 4KB random writes on a 1280 MB image gives me -around 500 IOPS, while with the correct cache size I get 16K IOPS. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Alberto Garcia -Signed-off-by: Kevin Wolf -(cherry picked from commit b70d08205b2e4044c529eefc21df2c8ab61b473b) -Signed-off-by: Michael Roth ---- - block/qcow2.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/block/qcow2.c b/block/qcow2.c -index 039bdc2f7e..865839682c 100644 ---- a/block/qcow2.c -+++ b/block/qcow2.c -@@ -826,7 +826,11 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts, - bool l2_cache_entry_size_set; - int min_refcount_cache = MIN_REFCOUNT_CACHE_SIZE * s->cluster_size; - uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE; -- uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8); -+ uint64_t max_l2_entries = DIV_ROUND_UP(virtual_disk_size, s->cluster_size); -+ /* An L2 table is always one cluster in size so the max cache size -+ * should be a multiple of the cluster size. */ -+ uint64_t max_l2_cache = ROUND_UP(max_l2_entries * sizeof(uint64_t), -+ s->cluster_size); - - combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE); - l2_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_L2_CACHE_SIZE); --- -2.23.0 diff --git a/qcow2-Limit-total-allocation-range-to-INT_MAX.patch b/qcow2-Limit-total-allocation-range-to-INT_MAX.patch deleted file mode 100644 index 3f915adcf6c57f828466e8ea0feff735a2a27937..0000000000000000000000000000000000000000 --- a/qcow2-Limit-total-allocation-range-to-INT_MAX.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 3d83643fb8d69f1c38df3e90634f9b82d4a62a1c Mon Sep 17 00:00:00 2001 -From: Max Reitz -Date: Thu, 10 Oct 2019 12:08:57 +0200 -Subject: [PATCH] qcow2: Limit total allocation range to INT_MAX -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When the COW areas are included, the size of an allocation can exceed -INT_MAX. This is kind of limited by handle_alloc() in that it already -caps avail_bytes at INT_MAX, but the number of clusters still reflects -the original length. - -This can have all sorts of effects, ranging from the storage layer write -call failing to image corruption. (If there were no image corruption, -then I suppose there would be data loss because the .cow_end area is -forced to be empty, even though there might be something we need to -COW.) - -Fix all of it by limiting nb_clusters so the equivalent number of bytes -will not exceed INT_MAX. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Max Reitz -Reviewed-by: Eric Blake -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Kevin Wolf -(cherry picked from commit d1b9d19f99586b33795e20a79f645186ccbc070f) -Signed-off-by: Michael Roth ---- - block/qcow2-cluster.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c -index 974a4e8..c4a99c1 100644 ---- a/block/qcow2-cluster.c -+++ b/block/qcow2-cluster.c -@@ -1342,6 +1342,9 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset, - nb_clusters = MIN(nb_clusters, s->l2_slice_size - l2_index); - assert(nb_clusters <= INT_MAX); - -+ /* Limit total allocation byte count to INT_MAX */ -+ nb_clusters = MIN(nb_clusters, INT_MAX >> s->cluster_bits); -+ - /* Find L2 entry for the first involved cluster */ - ret = get_cluster_table(bs, guest_offset, &l2_slice, &l2_index); - if (ret < 0) { -@@ -1430,7 +1433,7 @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset, - * request actually writes to (excluding COW at the end) - */ - uint64_t requested_bytes = *bytes + offset_into_cluster(s, guest_offset); -- int avail_bytes = MIN(INT_MAX, nb_clusters << s->cluster_bits); -+ int avail_bytes = nb_clusters << s->cluster_bits; - int nb_bytes = MIN(requested_bytes, avail_bytes); - QCowL2Meta *old_m = *m; - --- -1.8.3.1 - diff --git a/qcow2-bitmap-Fix-uint64_t-left-shift-overflow.patch b/qcow2-bitmap-Fix-uint64_t-left-shift-overflow.patch deleted file mode 100644 index 358fc61764ab3a8170a4d625af0ee4136531b7c0..0000000000000000000000000000000000000000 --- a/qcow2-bitmap-Fix-uint64_t-left-shift-overflow.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 66ad3c6ecce098d8f01545859c5ebf7a9e505e2c Mon Sep 17 00:00:00 2001 -From: Tuguoyi -Date: Fri, 1 Nov 2019 07:37:35 +0000 -Subject: [PATCH] qcow2-bitmap: Fix uint64_t left-shift overflow - -There are two issues in In check_constraints_on_bitmap(), -1) The sanity check on the granularity will cause uint64_t -integer left-shift overflow when cluster_size is 2M and the -granularity is BIGGER than 32K. -2) The way to calculate image size that the maximum bitmap -supported can map to is a bit incorrect. -This patch fix it by add a helper function to calculate the -number of bytes needed by a normal bitmap in image and compare -it to the maximum bitmap bytes supported by qemu. - -Fixes: 5f72826e7fc62167cf3a -Signed-off-by: Guoyi Tu -Message-id: 4ba40cd1e7ee4a708b40899952e49f22@h3c.com -Reviewed-by: Vladimir Sementsov-Ogievskiy -Cc: qemu-stable@nongnu.org -Signed-off-by: Max Reitz -(cherry picked from commit 570542ecb11e04b61ef4b3f4d0965a6915232a88) -Signed-off-by: Michael Roth ---- - block/qcow2-bitmap.c | 14 +++++++++++--- - 1 file changed, 11 insertions(+), 3 deletions(-) - -diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c -index e53a160..997923f 100644 ---- a/block/qcow2-bitmap.c -+++ b/block/qcow2-bitmap.c -@@ -143,6 +143,13 @@ static int check_table_entry(uint64_t entry, int cluster_size) - return 0; - } - -+static int64_t get_bitmap_bytes_needed(int64_t len, uint32_t granularity) -+{ -+ int64_t num_bits = DIV_ROUND_UP(len, granularity); -+ -+ return DIV_ROUND_UP(num_bits, 8); -+} -+ - static int check_constraints_on_bitmap(BlockDriverState *bs, - const char *name, - uint32_t granularity, -@@ -151,6 +158,7 @@ static int check_constraints_on_bitmap(BlockDriverState *bs, - BDRVQcow2State *s = bs->opaque; - int granularity_bits = ctz32(granularity); - int64_t len = bdrv_getlength(bs); -+ int64_t bitmap_bytes; - - assert(granularity > 0); - assert((granularity & (granularity - 1)) == 0); -@@ -172,9 +180,9 @@ static int check_constraints_on_bitmap(BlockDriverState *bs, - return -EINVAL; - } - -- if ((len > (uint64_t)BME_MAX_PHYS_SIZE << granularity_bits) || -- (len > (uint64_t)BME_MAX_TABLE_SIZE * s->cluster_size << -- granularity_bits)) -+ bitmap_bytes = get_bitmap_bytes_needed(len, granularity); -+ if ((bitmap_bytes > (uint64_t)BME_MAX_PHYS_SIZE) || -+ (bitmap_bytes > (uint64_t)BME_MAX_TABLE_SIZE * s->cluster_size)) - { - error_setg(errp, "Too much space will be occupied by the bitmap. " - "Use larger granularity"); --- -1.8.3.1 - diff --git a/qcow2-fix-memory-leak-in-qcow2_read_extensions.patch b/qcow2-fix-memory-leak-in-qcow2_read_extensions.patch index 2837a02342a4d6fde0e7f0370d64557089450870..ae629423b0389acc4594c930a3360c82898a843b 100644 --- a/qcow2-fix-memory-leak-in-qcow2_read_extensions.patch +++ b/qcow2-fix-memory-leak-in-qcow2_read_extensions.patch @@ -1,21 +1,22 @@ -From 76ab77108279f9d328e4a7fe1684141084698d97 Mon Sep 17 00:00:00 2001 +From a999e010c6af90f0fc1ad9b998e2a9b760c40f1a Mon Sep 17 00:00:00 2001 From: zhanghailiang Date: Thu, 25 Jul 2019 16:05:11 +0800 -Subject: [PATCH] qcow2: fix memory leak in qcow2_read_extensions +Subject: [PATCH 2/6] qcow2: fix memory leak in qcow2_read_extensions Free feature_table if it is failed in bdrv_pread. Signed-off-by: fangyi +Signed-off-by: Yan Wang --- block/qcow2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/qcow2.c b/block/qcow2.c -index 3ace3b22..5e85cf4b 100644 +index d509016..be90a89 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)); +@@ -272,6 +272,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); @@ -23,5 +24,5 @@ index 3ace3b22..5e85cf4b 100644 "Could not read table"); return ret; -- -2.19.1 +1.9.1 diff --git a/qdev-monitors-Fix-reundant-error_setg-of-qdev_add_de.patch b/qdev-monitors-Fix-reundant-error_setg-of-qdev_add_de.patch index 85467e8412ec264d6034f59ae3704a3042d1e5e0..e02dbf6f365184c098159a72f29b7e256d235dac 100644 --- a/qdev-monitors-Fix-reundant-error_setg-of-qdev_add_de.patch +++ b/qdev-monitors-Fix-reundant-error_setg-of-qdev_add_de.patch @@ -1,4 +1,4 @@ -From 4f1396f9e173a24f78204b8849c209100499d639 Mon Sep 17 00:00:00 2001 +From ada323e932c83271184a6ddba1cfd74a29378963 Mon Sep 17 00:00:00 2001 From: Kunkun Jiang Date: Thu, 29 Jul 2021 15:24:48 +0800 Subject: [PATCH] qdev/monitors: Fix reundant error_setg of qdev_add_device @@ -9,15 +9,16 @@ will trigger an asseration "assert(*errp == NULL)". Fixes: 515a7970490 (log: Add some logs on VM runtime path) Signed-off-by: Kunkun Jiang +Signed-off-by: Yan Wang --- - qdev-monitor.c | 1 - + softmmu/qdev-monitor.c | 1 - 1 file changed, 1 deletion(-) -diff --git a/qdev-monitor.c b/qdev-monitor.c -index c6c1d3f06a..ab2bdef105 100644 ---- a/qdev-monitor.c -+++ b/qdev-monitor.c -@@ -587,7 +587,6 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) +diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c +index dfd6429bf3..4a20f5dbd7 100644 +--- a/softmmu/qdev-monitor.c ++++ b/softmmu/qdev-monitor.c +@@ -636,7 +636,6 @@ DeviceState *qdev_device_add_from_qdict(const QDict *opts, if (path != NULL) { bus = qbus_find(path, errp); if (!bus) { diff --git a/qemu-4.1.0.tar.xz b/qemu-6.2.0.tar.xz similarity index 46% rename from qemu-4.1.0.tar.xz rename to qemu-6.2.0.tar.xz index 79ad0661eda38092de13a677ef70eeaece3ad848..da2f1cd0f62dc3048369fa1b4c459d005b104a79 100644 Binary files a/qemu-4.1.0.tar.xz and b/qemu-6.2.0.tar.xz differ diff --git a/qemu-file-Don-t-do-IO-after-shutdown.patch b/qemu-file-Don-t-do-IO-after-shutdown.patch deleted file mode 100644 index 72cfc4d7c97cc130be5ffb5556852790c17b2afa..0000000000000000000000000000000000000000 --- a/qemu-file-Don-t-do-IO-after-shutdown.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 1f8bc46e8af4ffe6d062f378bd11e0ad70d30ac8 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 2 Dec 2020 14:25:13 +0800 -Subject: [PATCH] qemu-file: Don't do IO after shutdown - -Be sure that we are not doing neither read/write after shutdown of the -QEMUFile. - -Signed-off-by: Juan Quintela -Reviewed-by: Dr. David Alan Gilbert ---- - migration/qemu-file.c | 22 +++++++++++++++++++++- - 1 file changed, 21 insertions(+), 1 deletion(-) - -diff --git a/migration/qemu-file.c b/migration/qemu-file.c -index 18f480529a..cd96d04e9a 100644 ---- a/migration/qemu-file.c -+++ b/migration/qemu-file.c -@@ -51,6 +51,8 @@ struct QEMUFile { - unsigned int iovcnt; - - int last_error; -+ /* has the file has been shutdown */ -+ bool shutdown; - }; - - /* -@@ -59,10 +61,18 @@ struct QEMUFile { - */ - int qemu_file_shutdown(QEMUFile *f) - { -+ int ret; -+ -+ f->shutdown = true; - if (!f->ops->shut_down) { - return -ENOSYS; - } -- return f->ops->shut_down(f->opaque, true, true); -+ -+ ret = f->ops->shut_down(f->opaque, true, true); -+ if (!f->last_error) { -+ qemu_file_set_error(f, -EIO); -+ } -+ return ret; - } - - /* -@@ -181,6 +191,10 @@ void qemu_fflush(QEMUFile *f) - return; - } - -+ if (f->shutdown) { -+ return; -+ } -+ - if (f->iovcnt > 0) { - expect = iov_size(f->iov, f->iovcnt); - ret = f->ops->writev_buffer(f->opaque, f->iov, f->iovcnt, f->pos); -@@ -293,6 +307,9 @@ static ssize_t qemu_fill_buffer(QEMUFile *f) - f->buf_index = 0; - f->buf_size = pending; - -+ if (f->shutdown) { -+ return 0; -+ } - len = f->ops->get_buffer(f->opaque, f->buf + pending, f->pos, - IO_BUF_SIZE - pending); - if (len > 0) { -@@ -591,6 +608,9 @@ int64_t qemu_ftell(QEMUFile *f) - - int qemu_file_rate_limit(QEMUFile *f) - { -+ if (f->shutdown) { -+ return 1; -+ } - if (qemu_file_get_error(f)) { - return 1; - } --- -2.27.0 - diff --git a/qemu-img-add-qemu-img-direct-create.patch b/qemu-img-add-qemu-img-direct-create.patch new file mode 100644 index 0000000000000000000000000000000000000000..082c110f1e2f83c06724a17b51e2b9c5f2d0b1a2 --- /dev/null +++ b/qemu-img-add-qemu-img-direct-create.patch @@ -0,0 +1,534 @@ +From 8832a7dcad4e09229537781ff8db98496aa6f533 Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Thu, 10 Feb 2022 21:27:53 +0800 +Subject: [PATCH] qemu-img: add qemu-img direct create + +Introdue buffer_size while creating raw file, then we +can controll the speed of direct write by: + qemu-img create -t 'cache' -o buffer_size='num' + +Signed-off-by: Jinhua Cao +--- + block/file-posix.c | 65 +++++++++++++++++++++-- + include/block/block_int.h | 2 + + qapi/block-core.json | 6 ++- + qemu-img-cmds.hx | 4 +- + qemu-img.c | 14 ++++- + tests/qemu-iotests/049.out | 102 ++++++++++++++++++------------------- + tests/qemu-iotests/099.out | 2 +- + 7 files changed, 134 insertions(+), 61 deletions(-) + +diff --git a/block/file-posix.c b/block/file-posix.c +index aed7529f44..5180fd1d0b 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -128,6 +128,10 @@ + #define FTYPE_CD 1 + + #define MAX_BLOCKSIZE 4096 ++#define DEFAULT_BUFFER_SIZE 65536 ++#define BUFFER_ALIGN_SIZE 65536 ++#define MIN_BUFFER_SIZE 65536 ++#define MAX_BUFFER_SIZE 16777216 + + /* Posix file locking bytes. Libvirt takes byte 0, we start from higher bytes, + * leaving a few more bytes for its future use. */ +@@ -206,6 +210,8 @@ typedef struct RawPosixAIOData { + off_t aio_offset; + uint64_t aio_nbytes; + ++ size_t buffer_size; ++ + union { + struct { + struct iovec *iov; +@@ -2218,7 +2224,8 @@ static void raw_close(BlockDriverState *bs) + */ + static int coroutine_fn + raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset, +- PreallocMode prealloc, Error **errp) ++ PreallocMode prealloc, size_t buffer_size, ++ Error **errp) + { + RawPosixAIOData acb; + +@@ -2227,6 +2234,7 @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset, + .aio_fildes = fd, + .aio_type = QEMU_AIO_TRUNCATE, + .aio_offset = offset, ++ .buffer_size = buffer_size, + .truncate = { + .prealloc = prealloc, + .errp = errp, +@@ -2252,7 +2260,8 @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset, + + if (S_ISREG(st.st_mode)) { + /* Always resizes to the exact @offset */ +- return raw_regular_truncate(bs, s->fd, offset, prealloc, errp); ++ return raw_regular_truncate(bs, s->fd, offset, prealloc, ++ DEFAULT_BUFFER_SIZE, errp); + } + + if (prealloc != PREALLOC_MODE_OFF) { +@@ -2465,6 +2474,8 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp) + int fd; + uint64_t perm, shared; + int result = 0; ++ int flags = O_RDWR | O_BINARY; ++ size_t buffer_size = DEFAULT_BUFFER_SIZE; + + /* Validate options and set default values */ + assert(options->driver == BLOCKDEV_DRIVER_FILE); +@@ -2484,9 +2495,19 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp) + error_setg(errp, "Extent size hint is too large"); + goto out; + } ++ if (!file_opts->has_cache) { ++ file_opts->cache = g_strdup("writeback"); ++ } ++ if (file_opts->preallocation == PREALLOC_MODE_FULL && ++ !strcmp(file_opts->cache, "none")) { ++ flags |= O_DIRECT; ++ } ++ if (file_opts->has_buffersize) { ++ buffer_size = file_opts->buffersize; ++ } + + /* Create file */ +- fd = qemu_create(file_opts->filename, O_RDWR | O_BINARY, 0644, errp); ++ fd = qemu_create(file_opts->filename, flags, 0644, errp); + if (fd < 0) { + result = -errno; + goto out; +@@ -2521,7 +2542,8 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp) + } + + /* Clear the file by truncating it to 0 */ +- result = raw_regular_truncate(NULL, fd, 0, PREALLOC_MODE_OFF, errp); ++ result = raw_regular_truncate(NULL, fd, 0, PREALLOC_MODE_OFF, ++ buffer_size, errp); + if (result < 0) { + goto out_unlock; + } +@@ -2565,7 +2587,8 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp) + /* Resize and potentially preallocate the file to the desired + * final size */ + result = raw_regular_truncate(NULL, fd, file_opts->size, +- file_opts->preallocation, errp); ++ file_opts->preallocation, ++ buffer_size, errp); + if (result < 0) { + goto out_unlock; + } +@@ -2586,6 +2609,7 @@ out_close: + error_setg_errno(errp, -result, "Could not close the new file"); + } + out: ++ g_free(file_opts->cache); + return result; + } + +@@ -2602,6 +2626,8 @@ static int coroutine_fn raw_co_create_opts(BlockDriver *drv, + PreallocMode prealloc; + char *buf = NULL; + Error *local_err = NULL; ++ size_t buffersize = DEFAULT_BUFFER_SIZE; ++ char *cache = NULL; + + /* Skip file: protocol prefix */ + strstart(filename, "file:", &filename); +@@ -2624,6 +2650,21 @@ static int coroutine_fn raw_co_create_opts(BlockDriver *drv, + return -EINVAL; + } + ++ buffersize = qemu_opt_get_size_del(opts, BLOCK_OPT_BUFFER_SIZE, ++ DEFAULT_BUFFER_SIZE); ++ if (buffersize < MIN_BUFFER_SIZE || buffersize > MAX_BUFFER_SIZE) { ++ error_setg_errno(errp, EINVAL, "Buffer size must be between %d " ++ "and %d", MIN_BUFFER_SIZE, MAX_BUFFER_SIZE); ++ return -EINVAL; ++ } ++ ++ cache = qemu_opt_get_del(opts, BLOCK_OPT_CACHE); ++ if (!cache) { ++ cache = g_strdup("writeback"); ++ } ++ ++ buffersize = ROUND_UP(buffersize, BUFFER_ALIGN_SIZE); ++ + options = (BlockdevCreateOptions) { + .driver = BLOCKDEV_DRIVER_FILE, + .u.file = { +@@ -2635,6 +2676,10 @@ static int coroutine_fn raw_co_create_opts(BlockDriver *drv, + .nocow = nocow, + .has_extent_size_hint = has_extent_size_hint, + .extent_size_hint = extent_size_hint, ++ .has_buffersize = true, ++ .buffersize = buffersize, ++ .has_cache = true, ++ .cache = cache, + }, + }; + return raw_co_create(&options, errp); +@@ -3133,6 +3178,16 @@ static QemuOptsList raw_create_opts = { + .type = QEMU_OPT_SIZE, + .help = "Extent size hint for the image file, 0 to disable" + }, ++ { ++ .name = BLOCK_OPT_CACHE, ++ .type = QEMU_OPT_STRING, ++ .help = "Cache mode (allowed values: writeback, none)" ++ }, ++ { ++ .name = BLOCK_OPT_BUFFER_SIZE, ++ .type = QEMU_OPT_SIZE, ++ .help = "write buffer size" ++ }, + { /* end of list */ } + } + }; +diff --git a/include/block/block_int.h b/include/block/block_int.h +index f4c75e8ba9..701f031102 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -61,6 +61,8 @@ + #define BLOCK_OPT_DATA_FILE_RAW "data_file_raw" + #define BLOCK_OPT_COMPRESSION_TYPE "compression_type" + #define BLOCK_OPT_EXTL2 "extended_l2" ++#define BLOCK_OPT_CACHE "cache" ++#define BLOCK_OPT_BUFFER_SIZE "buffer_size" + + #define BLOCK_PROBE_BUF_SIZE 512 + +diff --git a/qapi/block-core.json b/qapi/block-core.json +index 804beabfb0..e65fabe36d 100644 +--- a/qapi/block-core.json ++++ b/qapi/block-core.json +@@ -4437,6 +4437,8 @@ + # @nocow: Turn off copy-on-write (valid only on btrfs; default: off) + # @extent-size-hint: Extent size hint to add to the image file; 0 for not + # adding an extent size hint (default: 1 MB, since 5.1) ++# @cache: Cache mode used to write the output disk image ++# @buffersize: Buffer size for creating image + # + # Since: 2.12 + ## +@@ -4445,7 +4447,9 @@ + 'size': 'size', + '*preallocation': 'PreallocMode', + '*nocow': 'bool', +- '*extent-size-hint': 'size'} } ++ '*extent-size-hint': 'size', ++ '*cache': 'str', ++ '*buffersize': 'size'} } + + ## + # @BlockdevCreateOptionsGluster: +diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx +index 72bcdcfbfa..ec6aa2886a 100644 +--- a/qemu-img-cmds.hx ++++ b/qemu-img-cmds.hx +@@ -52,9 +52,9 @@ SRST + ERST + + DEF("create", img_create, +- "create [--object objectdef] [-q] [-f fmt] [-b backing_file] [-F backing_fmt] [-u] [-o options] filename [size]") ++ "create [--object objectdef] [-q] [-f fmt] [-b backing_file] [-F backing_fmt] [-u] [-t cache] [-o options] filename [size]") + SRST +-.. option:: create [--object OBJECTDEF] [-q] [-f FMT] [-b BACKING_FILE] [-F BACKING_FMT] [-u] [-o OPTIONS] FILENAME [SIZE] ++.. option:: create [--object OBJECTDEF] [-q] [-f FMT] [-b BACKING_FILE] [-F BACKING_FMT] [-u] [-t CACHE] [-o OPTIONS] FILENAME [SIZE] + ERST + + DEF("dd", img_dd, +diff --git a/qemu-img.c b/qemu-img.c +index f036a1d428..9409558772 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -504,6 +504,7 @@ static int img_create(int argc, char **argv) + const char *base_fmt = NULL; + const char *filename; + const char *base_filename = NULL; ++ const char *cache = BDRV_DEFAULT_CACHE; + char *options = NULL; + Error *local_err = NULL; + bool quiet = false; +@@ -515,7 +516,7 @@ static int img_create(int argc, char **argv) + {"object", required_argument, 0, OPTION_OBJECT}, + {0, 0, 0, 0} + }; +- c = getopt_long(argc, argv, ":F:b:f:ho:qu", ++ c = getopt_long(argc, argv, ":F:b:f:t:ho:qu", + long_options, NULL); + if (c == -1) { + break; +@@ -539,6 +540,9 @@ static int img_create(int argc, char **argv) + case 'f': + fmt = optarg; + break; ++ case 't': ++ cache = optarg; ++ break; + case 'o': + if (accumulate_options(&options, optarg) < 0) { + goto fail; +@@ -582,6 +586,14 @@ static int img_create(int argc, char **argv) + error_exit("Unexpected argument: %s", argv[optind]); + } + ++ if (!options) { ++ options = g_strdup_printf(BLOCK_OPT_CACHE"=%s", cache); ++ } else { ++ char *old_options = options; ++ options = g_strdup_printf("%s,"BLOCK_OPT_CACHE"=%s", options, cache); ++ g_free(old_options); ++ } ++ + bdrv_img_create(filename, fmt, base_filename, base_fmt, + options, img_size, flags, quiet, &local_err); + if (local_err) { +diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out +index 8719c91b48..6aca1a7797 100644 +--- a/tests/qemu-iotests/049.out ++++ b/tests/qemu-iotests/049.out +@@ -4,90 +4,90 @@ QA output created by 049 + == 1. Traditional size parameter == + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024b +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1k +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1K +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1G +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1T +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0b +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5k +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5K +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5G +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5T +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16 cache=writeback + + == 2. Specifying size via -o == + + qemu-img create -f qcow2 -o size=1024 TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o size=1024b TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o size=1k TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o size=1K TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o size=1M TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o size=1G TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o size=1T TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o size=1024.0 TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o size=1024.0b TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o size=1.5k TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o size=1.5K TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o size=1.5M TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o size=1.5G TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o size=1.5T TEST_DIR/t.qcow2 +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16 cache=writeback + + == 3. Invalid sizes == + +@@ -135,84 +135,84 @@ qemu-img: TEST_DIR/t.qcow2: The image size must be specified only once + == Check correct interpretation of suffixes for cluster size == + + qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o cluster_size=1024b TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o cluster_size=1k TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o cluster_size=1K TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o cluster_size=1M TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1048576 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1048576 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o cluster_size=1024.0 TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o cluster_size=1024.0b TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o cluster_size=0.5k TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o cluster_size=0.5K TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o cluster_size=0.5M TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=524288 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=524288 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + + == Check compat level option == + + qemu-img create -f qcow2 -o compat=0.10 TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o compat=1.1 TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.42 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.42 lazy_refcounts=off refcount_bits=16 cache=writeback + qemu-img: TEST_DIR/t.qcow2: Parameter 'version' does not accept value '0.42' + + qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=foobar lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=foobar lazy_refcounts=off refcount_bits=16 cache=writeback + qemu-img: TEST_DIR/t.qcow2: Parameter 'version' does not accept value 'foobar' + + == Check preallocation option == + + qemu-img create -f qcow2 -o preallocation=off TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=metadata compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=metadata compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=1234 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=1234 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + qemu-img: TEST_DIR/t.qcow2: Parameter 'preallocation' does not accept value '1234' + + == Check encryption option == + + qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=off cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=off cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=on encrypt.key-secret=sec0 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=on encrypt.key-secret=sec0 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16 cache=writeback + + == Check lazy_refcounts option (only with v3) == + + qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=off TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=on TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=on refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=on refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=off TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16 cache=writeback + + qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M +-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=on refcount_bits=16 ++Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=on refcount_bits=16 cache=writeback + qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater) + + == Expect error when backing file name is empty string == +diff --git a/tests/qemu-iotests/099.out b/tests/qemu-iotests/099.out +index 8cce627529..f6f8f25957 100644 +--- a/tests/qemu-iotests/099.out ++++ b/tests/qemu-iotests/099.out +@@ -1,6 +1,6 @@ + QA output created by 099 + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 +-Formatting 'TEST_DIR/t.IMGFMT.compare', fmt=raw size=131072 ++Formatting 'TEST_DIR/t.IMGFMT.compare', fmt=raw size=131072 cache=writeback + + === Testing simple filename for blkverify === + +-- +2.27.0 + diff --git a/qemu-img-block-dont-blk_make_zero-if-discard_zeroes-.patch b/qemu-img-block-dont-blk_make_zero-if-discard_zeroes-.patch new file mode 100644 index 0000000000000000000000000000000000000000..c96e5b429f72f4830bd7361891dbda78ac217cf6 --- /dev/null +++ b/qemu-img-block-dont-blk_make_zero-if-discard_zeroes-.patch @@ -0,0 +1,26 @@ +From 724134432ef21f1fb2b18bbe55b891d31181ccca Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Fri, 11 Feb 2022 14:25:39 +0800 +Subject: [PATCH] qemu-img: block: dont blk_make_zero if discard_zeroes false + +Signed-off-by: Jinhua Cao +--- + block/file-posix.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/file-posix.c b/block/file-posix.c +index b283093e5b..aed7529f44 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -804,7 +804,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, + } + #endif + +- bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK; ++ bs->supported_zero_flags = s->discard_zeroes ? (BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) : 0; + if (S_ISREG(st.st_mode)) { + /* When extending regular files, we get zeros from the OS */ + bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE; +-- +2.27.0 + diff --git a/qemu-img-convert-Don-t-pre-zero-images.patch b/qemu-img-convert-Don-t-pre-zero-images.patch deleted file mode 100644 index 925590c34903cd73307b3f806a0b407c6c744fb5..0000000000000000000000000000000000000000 --- a/qemu-img-convert-Don-t-pre-zero-images.patch +++ /dev/null @@ -1,73 +0,0 @@ -From a2fcbe2b82c42f890a857ad8d4edcfdb273106ea Mon Sep 17 00:00:00 2001 -From: Kevin Wolf -Date: Fri, 31 Jul 2020 08:18:31 -0400 -Subject: [PATCH] qemu-img convert: Don't pre-zero images - -RH-Author: Kevin Wolf -Message-id: <20200731081831.13781-2-kwolf@redhat.com> -Patchwork-id: 98117 -O-Subject: [RHEL-AV-8.2.1.z qemu-kvm PATCH 1/1] qemu-img convert: Don't pre-zero images -Bugzilla: 1861682 -RH-Acked-by: Stefano Garzarella -RH-Acked-by: Max Reitz -RH-Acked-by: Eric Blake - -Since commit 5a37b60a61c, qemu-img create will pre-zero the target image -if it isn't already zero-initialised (most importantly, for host block -devices, but also iscsi etc.), so that writing explicit zeros wouldn't -be necessary later. - -This could speed up the operation significantly, in particular when the -source image file was only sparsely populated. However, it also means -that some block are written twice: Once when pre-zeroing them, and then -when they are overwritten with actual data. On a full image, the -pre-zeroing is wasted work because everything will be overwritten. - -In practice, write_zeroes typically turns out faster than writing -explicit zero buffers, but slow enough that first zeroing everything and -then overwriting parts can be a significant net loss. - -Meanwhile, qemu-img convert was rewritten in 690c7301600 and zero blocks -are now written to the target using bdrv_co_pwrite_zeroes() if the -target could be pre-zeroed. This way we already make use of the faster -write_zeroes operation, but avoid writing any blocks twice. - -Remove the pre-zeroing because these days this former optimisation has -actually turned into a pessimisation in the common case. - -Reported-by: Nir Soffer -Signed-off-by: Kevin Wolf -Message-Id: <20200622151203.35624-1-kwolf@redhat.com> -Tested-by: Nir Soffer -Reviewed-by: Eric Blake -Signed-off-by: Kevin Wolf -(cherry picked from commit edafc70c0c8510862f2f213a3acf7067113bcd08) -Signed-off-by: Kevin Wolf -Signed-off-by: Danilo C. L. de Paula ---- - qemu-img.c | 9 --------- - 1 file changed, 9 deletions(-) - -diff --git a/qemu-img.c b/qemu-img.c -index 2e9cc5db7c..e4abd4978a 100644 ---- a/qemu-img.c -+++ b/qemu-img.c -@@ -1981,15 +1981,6 @@ static int convert_do_copy(ImgConvertState *s) - ? bdrv_has_zero_init(blk_bs(s->target)) - : false; - -- if (!s->has_zero_init && !s->target_has_backing && -- bdrv_can_write_zeroes_with_unmap(blk_bs(s->target))) -- { -- ret = blk_make_zero(s->target, BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK); -- if (ret == 0) { -- s->has_zero_init = true; -- } -- } -- - /* Allocate buffer for copied data. For compressed images, only one cluster - * can be copied at a time. */ - if (s->compressed) { --- -2.27.0 - diff --git a/qemu-img-free-memory-before-re-assign.patch b/qemu-img-free-memory-before-re-assign.patch deleted file mode 100644 index 2d46d64b1b9664b66efc76ea6490a1bc22663137..0000000000000000000000000000000000000000 --- a/qemu-img-free-memory-before-re-assign.patch +++ /dev/null @@ -1,33 +0,0 @@ -From d22af5cb41c16829dbf3ed3c611ef56ceeb840ff Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Thu, 27 Feb 2020 09:29:50 +0800 -Subject: [PATCH 02/14] qemu-img: free memory before re-assign - -collect_image_check() is called twice in img_check(), the filename/format will be alloced without free the original memory. -It is not a big deal since the process will exit anyway, but seems like a clean code and it will remove the warning spotted by asan. - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan -Message-Id: <20200227012950.12256-3-pannengyuan@huawei.com> -Signed-off-by: Max Reitz -Signed-off-by: Peng Liang ---- - qemu-img.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/qemu-img.c b/qemu-img.c -index 79983772de39..2e9cc5db7c4c 100644 ---- a/qemu-img.c -+++ b/qemu-img.c -@@ -808,6 +808,8 @@ static int img_check(int argc, char **argv) - check->corruptions_fixed); - } - -+ qapi_free_ImageCheck(check); -+ check = g_new0(ImageCheck, 1); - ret = collect_image_check(bs, check, filename, fmt, 0); - - check->leaks_fixed = leaks_fixed; --- -2.26.2 - diff --git a/qemu-nbd-make-native-as-the-default-aio-mode.patch b/qemu-nbd-make-native-as-the-default-aio-mode.patch new file mode 100644 index 0000000000000000000000000000000000000000..c53f50a27d3d96cb9a970e73b381124c207b43ed --- /dev/null +++ b/qemu-nbd-make-native-as-the-default-aio-mode.patch @@ -0,0 +1,35 @@ +From de6f3fb0cf92e04c0989a9065910158eecbe4304 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 10:48:58 +0800 +Subject: [PATCH] qemu-nbd: make native as the default aio mode + +When the file system is dealing with multithreading concurrent writing to a file, +the performance will be degraded because of the lock. +At present, the default AIO mode of QEMU NBD is threads. In the case of large blocks, +because IO is divided into small pieces and multiple queues, it will become multithreading +concurrent writing the same file. Due to the file system, the performance will be greatly reduced. +If you change to native mode, this problem will not exist. + +Signed-off-by: wangjian161 +--- + qemu-nbd.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/qemu-nbd.c b/qemu-nbd.c +index c6c20df68a..15a4bc4018 100644 +--- a/qemu-nbd.c ++++ b/qemu-nbd.c +@@ -800,6 +800,10 @@ int main(int argc, char **argv) + trace_init_file(); + qemu_set_log(LOG_TRACE); + ++ if (!seen_aio && (flags & BDRV_O_NOCACHE)) { ++ flags |= BDRV_O_NATIVE_AIO; ++ } ++ + socket_activation = check_socket_activation(); + if (socket_activation == 0) { + setup_address_and_port(&bindto, &port); +-- +2.27.0 + diff --git a/qemu-nbd-set-timeout-to-qemu-nbd-socket.patch b/qemu-nbd-set-timeout-to-qemu-nbd-socket.patch new file mode 100644 index 0000000000000000000000000000000000000000..3ef9b6ae61755fa3f9289a91b14a0e4fa559304e --- /dev/null +++ b/qemu-nbd-set-timeout-to-qemu-nbd-socket.patch @@ -0,0 +1,42 @@ +From f665f7836a019cc8bb8d46d076508afc761923f0 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 10:55:08 +0800 +Subject: [PATCH] qemu-nbd: set timeout to qemu-nbd socket + +In case of insufficient memory and kill-9, +the NBD socket cannot be processed and stuck all the time. + +Signed-off-by: wangjian161 +--- + nbd/client.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/nbd/client.c b/nbd/client.c +index 30d5383cb1..8ed50140f2 100644 +--- a/nbd/client.c ++++ b/nbd/client.c +@@ -24,6 +24,8 @@ + #include "nbd-internal.h" + #include "qemu/cutils.h" + ++#define NBD_TIMEOUT_SECONDS 30 ++ + /* Definitions for opaque data types */ + + static QTAILQ_HEAD(, NBDExport) exports = QTAILQ_HEAD_INITIALIZER(exports); +@@ -1301,6 +1303,12 @@ int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info, + } + } + ++ if (ioctl(fd, NBD_SET_TIMEOUT, NBD_TIMEOUT_SECONDS) < 0) { ++ int serrno = errno; ++ error_setg(errp, "Failed setting timeout"); ++ return -serrno; ++ } ++ + trace_nbd_init_finish(); + + return 0; +-- +2.27.0 + diff --git a/qemu-options-Improve-readability-of-SMP-related-Docs.patch b/qemu-options-Improve-readability-of-SMP-related-Docs.patch new file mode 100644 index 0000000000000000000000000000000000000000..63dc895ac31d7be9be0de1a0390a039a7f66b6f3 --- /dev/null +++ b/qemu-options-Improve-readability-of-SMP-related-Docs.patch @@ -0,0 +1,146 @@ +From 07991b049fc9ebdb62c311eda1535ad4831625e5 Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Tue, 28 Dec 2021 17:22:08 +0800 +Subject: [PATCH 10/24] qemu-options: Improve readability of SMP related Docs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We have a description in qemu-options.hx for each CPU topology +parameter to explain what it exactly means, and also an extra +declaration for the target-specific one, e.g. "for PC only" +when describing "dies", and "for PC, it's on one die" when +describing "cores". + +Now we are going to introduce one more non-generic parameter +"clusters", it will make the Doc less readable and if we still +continue to use the legacy way to describe it. + +So let's at first make two tweaks of the Docs to improve the +readability and also scalability: +1) In the -help text: Delete the extra specific declaration and + describe each topology parameter level by level. Then add a + note to declare that different machines may support different + subsets and the actual meaning of the supported parameters + will vary accordingly. +2) In the rST text: List all the sub-hierarchies currently + supported in QEMU, and correspondingly give an example of + -smp configuration for each of them. + +Signed-off-by: Yanan Wang +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20211228092221.21068-2-wangyanan55@huawei.com> +Signed-off-by: Philippe Mathieu-Daudé +--- + qemu-options.hx | 76 ++++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 59 insertions(+), 17 deletions(-) + +diff --git a/qemu-options.hx b/qemu-options.hx +index ae2c6dbbfc..7a59db7764 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -207,14 +207,26 @@ ERST + + DEF("smp", HAS_ARG, QEMU_OPTION_smp, + "-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]\n" +- " set the number of CPUs to 'n' [default=1]\n" ++ " set the number of initial CPUs to 'n' [default=1]\n" + " maxcpus= maximum number of total CPUs, including\n" + " offline CPUs for hotplug, etc\n" +- " sockets= number of discrete sockets in the system\n" +- " dies= number of CPU dies on one socket (for PC only)\n" +- " cores= number of CPU cores on one socket (for PC, it's on one die)\n" +- " threads= number of threads on one CPU core\n", +- QEMU_ARCH_ALL) ++ " sockets= number of sockets on the machine board\n" ++ " dies= number of dies in one socket\n" ++ " cores= number of cores in one die\n" ++ " threads= number of threads in one core\n" ++ "Note: Different machines may have different subsets of the CPU topology\n" ++ " parameters supported, so the actual meaning of the supported parameters\n" ++ " will vary accordingly. For example, for a machine type that supports a\n" ++ " three-level CPU hierarchy of sockets/cores/threads, the parameters will\n" ++ " sequentially mean as below:\n" ++ " sockets means the number of sockets on the machine board\n" ++ " cores means the number of cores in one socket\n" ++ " threads means the number of threads in one core\n" ++ " For a particular machine type board, an expected CPU topology hierarchy\n" ++ " can be defined through the supported sub-option. Unsupported parameters\n" ++ " can also be provided in addition to the sub-option, but their values\n" ++ " must be set as 1 in the purpose of correct parsing.\n", ++ QEMU_ARCH_ALL) + SRST + ``-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]`` + Simulate a SMP system with '\ ``n``\ ' CPUs initially present on +@@ -225,27 +237,57 @@ SRST + initial CPU count will match the maximum number. When only one of them + is given then the omitted one will be set to its counterpart's value. + Both parameters may be specified, but the maximum number of CPUs must +- be equal to or greater than the initial CPU count. Both parameters are +- subject to an upper limit that is determined by the specific machine +- type chosen. +- +- To control reporting of CPU topology information, the number of sockets, +- dies per socket, cores per die, and threads per core can be specified. +- The sum `` sockets * cores * dies * threads `` must be equal to the +- maximum CPU count. CPU targets may only support a subset of the topology +- parameters. Where a CPU target does not support use of a particular +- topology parameter, its value should be assumed to be 1 for the purpose +- of computing the CPU maximum count. ++ be equal to or greater than the initial CPU count. Product of the ++ CPU topology hierarchy must be equal to the maximum number of CPUs. ++ Both parameters are subject to an upper limit that is determined by ++ the specific machine type chosen. ++ ++ To control reporting of CPU topology information, values of the topology ++ parameters can be specified. Machines may only support a subset of the ++ parameters and different machines may have different subsets supported ++ which vary depending on capacity of the corresponding CPU targets. So ++ for a particular machine type board, an expected topology hierarchy can ++ be defined through the supported sub-option. Unsupported parameters can ++ also be provided in addition to the sub-option, but their values must be ++ set as 1 in the purpose of correct parsing. + + Either the initial CPU count, or at least one of the topology parameters + must be specified. The specified parameters must be greater than zero, + explicit configuration like "cpus=0" is not allowed. Values for any + omitted parameters will be computed from those which are given. ++ ++ For example, the following sub-option defines a CPU topology hierarchy ++ (2 sockets totally on the machine, 2 cores per socket, 2 threads per ++ core) for a machine that only supports sockets/cores/threads. ++ Some members of the option can be omitted but their values will be ++ automatically computed: ++ ++ :: ++ ++ -smp 8,sockets=2,cores=2,threads=2,maxcpus=8 ++ ++ The following sub-option defines a CPU topology hierarchy (2 sockets ++ totally on the machine, 2 dies per socket, 2 cores per die, 2 threads ++ per core) for PC machines which support sockets/dies/cores/threads. ++ Some members of the option can be omitted but their values will be ++ automatically computed: ++ ++ :: ++ ++ -smp 16,sockets=2,dies=2,cores=2,threads=2,maxcpus=16 ++ + Historically preference was given to the coarsest topology parameters + when computing missing values (ie sockets preferred over cores, which + were preferred over threads), however, this behaviour is considered + liable to change. Prior to 6.2 the preference was sockets over cores + over threads. Since 6.2 the preference is cores over sockets over threads. ++ ++ For example, the following option defines a machine board with 2 sockets ++ of 1 core before 6.2 and 1 socket of 2 cores after 6.2: ++ ++ :: ++ ++ -smp 2 + ERST + + DEF("numa", HAS_ARG, QEMU_OPTION_numa, +-- +2.27.0 + diff --git a/qemu-pr-fixed-ioctl-failed-for-multipath-disk.patch b/qemu-pr-fixed-ioctl-failed-for-multipath-disk.patch new file mode 100644 index 0000000000000000000000000000000000000000..7985a92790e80f44d2aaef55a0603bb8eb86b998 --- /dev/null +++ b/qemu-pr-fixed-ioctl-failed-for-multipath-disk.patch @@ -0,0 +1,36 @@ +From 56f59125707c0222bbb5d7f820792aba17c3db08 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 11:10:42 +0800 +Subject: [PATCH] qemu-pr: fixed ioctl failed for multipath disk + +We use ioctl to detect multipath devices. However, we only set flags in +struct dm_ioctl (the argument to ioctl) and left other fields in random, +which may cause the failure of calling ioctl. Hence, we set other +fields to 0 to avoid the failure. + +Signed-off-by: wangjian161 +--- + scsi/qemu-pr-helper.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c +index f281daeced..bbb9b57741 100644 +--- a/scsi/qemu-pr-helper.c ++++ b/scsi/qemu-pr-helper.c +@@ -288,9 +288,12 @@ static void multipath_pr_init(void) + + static int is_mpath(int fd) + { +- struct dm_ioctl dm = { .flags = DM_NOFLUSH_FLAG }; ++ struct dm_ioctl dm; + struct dm_target_spec *tgt; + ++ memset(&dm, 0, sizeof(struct dm_ioctl)); ++ dm.flags = DM_NOFLUSH_FLAG; ++ + tgt = dm_dev_ioctl(fd, DM_TABLE_STATUS, &dm); + if (!tgt) { + if (errno == ENXIO) { +-- +2.27.0 + diff --git a/qemu.spec b/qemu.spec index e195e6abbfb8a6675e6ad6fd89cf85d1e4e99b74..2326488ce45b3e567ddc03808e395501ed8f0de5 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,6 +1,6 @@ Name: qemu -Version: 4.1.0 -Release: 85 +Version: 6.2.0 +Release: 27 Epoch: 2 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -9,567 +9,233 @@ Source0: https://www.qemu.org/download/%{name}-%{version}%{?rcstr}.tar.xz Source1: 80-kvm.rules Source2: 99-qemu-guest-agent.rules Source3: bridge.conf - -Patch0001: pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch -Patch0002: pl031-support-rtc-timer-property-for-pl031.patch -Patch0003: vhost-cancel-migration-when-vhost-user-restarted.patch -Patch0004: qcow2-fix-memory-leak-in-qcow2_read_extensions.patch -Patch0005: bios-tables-test-prepare-to-change-ARM-virt-ACPI-DSDT.patch -Patch0006: hw-arm-expose-host-CPU-frequency-info-to-guest.patch -Patch0007: smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch -Patch0008: tests-bios-tables-test-disable-this-testcase.patch -Patch0009: hw-arm-virt-Introduce-cpu-topology-support.patch -Patch0010: hw-arm64-add-vcpu-cache-info-support.patch -Patch0011: xhci-Fix-memory-leak-in-xhci_address_slot.patch -Patch0012: xhci-Fix-memory-leak-in-xhci_kick_epctx.patch -Patch0013: ehci-fix-queue-dev-null-ptr-dereference.patch -Patch0014: util-async-hold-AioContext-ref-to-prevent-use-after-free.patch -Patch0015: vhost-user-scsi-prevent-using-uninitialized-vqs.patch -Patch0016: cpu-add-Kunpeng-920-cpu-support.patch -Patch0017: cpu-parse-feature-to-avoid-failure.patch -Patch0018: cpu-add-Cortex-A72-processor-kvm-target-support.patch -Patch0019: pcie-disable-the-PCI_EXP_LINKSTA_DLLA-cap.patch -Patch0020: vnc-fix-memory-leak-when-vnc-disconnect.patch -Patch0021: linux-headers-update-against-KVM-ARM-Fix-256-vcpus.patch -Patch0022: intc-arm_gic-Support-IRQ-injection-for-more-than-256.patch -Patch0023: ARM-KVM-Check-KVM_CAP_ARM_IRQ_LINE_LAYOUT_2-for-smp.patch -Patch0024: 9pfs-local-Fix-possible-memory-leak-in-local_link.patch -Patch0025: scsi-disk-define-props-in-scsi_block_disk-to-avoid-memleaks.patch -Patch0026: arm-translate-a64-fix-uninitialized-variable-warning.patch -Patch0027: nbd-fix-uninitialized-variable-warning.patch -Patch0028: xhci-Fix-memory-leak-in-xhci_kick_epctx-when-poweroff.patch -Patch0029: block-fix-memleaks-in-bdrv_refresh_filename.patch -Patch0030: iscsi-Cap-block-count-from-GET-LBA-STATUS-CVE-2020-1.patch -Patch0031: tcp_emu-Fix-oob-access.patch -Patch0032: slirp-use-correct-size-while-emulating-IRC-commands.patch -Patch0033: slirp-use-correct-size-while-emulating-commands.patch -Patch0034: util-add-slirp_fmt-helpers.patch -Patch0035: tcp_emu-fix-unsafe-snprintf-usages.patch -Patch0036: block-iscsi-use-MIN-between-mx_sb_len-and-sb_len_wr.patch -Patch0037: monitor-fix-memory-leak-in-monitor_fdset_dup_fd_find.patch -Patch0038: memory-Align-MemoryRegionSections-fields.patch -Patch0039: memory-Provide-an-equality-function-for-MemoryRegion.patch -Patch0040: vhost-Fix-memory-region-section-comparison.patch -Patch0041: file-posix-Handle-undetectable-alignment.patch -Patch0042: block-backup-fix-max_transfer-handling-for-copy_rang.patch -Patch0043: block-backup-fix-backup_cow_with_offload-for-last-cl.patch -Patch0044: qcow2-Limit-total-allocation-range-to-INT_MAX.patch -Patch0045: mirror-Do-not-dereference-invalid-pointers.patch -Patch0046: COLO-compare-Fix-incorrect-if-logic.patch -Patch0047: qcow2-bitmap-Fix-uint64_t-left-shift-overflow.patch -Patch0048: pcie-Add-pcie-root-port-fast-plug-unplug-feature.patch -Patch0049: pcie-Compat-with-devices-which-do-not-support-Link-W.patch -Patch0050: aio-wait-delegate-polling-of-main-AioContext-if-BQL-not-held.patch -Patch0051: async-use-explicit-memory-barriers.patch -Patch0052: dma-helpers-ensure-AIO-callback-is-invoked-after-can.patch -Patch0053: Revert-ide-ahci-Check-for-ECANCELED-in-aio-callbacks.patch -Patch0054: pc-Don-t-make-die-id-mandatory-unless-necessary.patch -Patch0055: block-file-posix-Reduce-xfsctl-use.patch -Patch0056: pr-manager-Fix-invalid-g_free-crash-bug.patch -Patch0057: x86-do-not-advertise-die-id-in-query-hotpluggbale-cp.patch -Patch0058: vpc-Return-0-from-vpc_co_create-on-success.patch -Patch0059: target-arm-Free-TCG-temps-in-trans_VMOV_64_sp.patch -Patch0060: target-arm-Don-t-abort-on-M-profile-exception-return.patch -Patch0061: libvhost-user-fix-SLAVE_SEND_FD-handling.patch -Patch0062: qcow2-Fix-the-calculation-of-the-maximum-L2-cache-si.patch -Patch0063: block-nfs-tear-down-aio-before-nfs_close.patch -Patch0064: blockjob-update-nodes-head-while-removing-all-bdrv.patch -Patch0065: block-qcow2-Fix-corruption-introduced-by-commit-8ac0.patch -Patch0066: coroutine-Add-qemu_co_mutex_assert_locked.patch -Patch0067: qcow2-Fix-corruption-bug-in-qcow2_detect_metadata_pr.patch -Patch0068: hw-arm-boot.c-Set-NSACR.-CP11-CP10-for-NS-kernel-boo.patch -Patch0069: make-release-pull-in-edk2-submodules-so-we-can-build.patch -Patch0070: roms-Makefile.edk2-don-t-pull-in-submodules-when-bui.patch -Patch0071: block-snapshot-Restrict-set-of-snapshot-nodes.patch -Patch0072: vhost-user-save-features-if-the-char-dev-is-closed.patch -Patch0073: hw-core-loader-Fix-possible-crash-in-rom_copy.patch -Patch0074: ui-Fix-hanging-up-Cocoa-display-on-macOS-10.15-Catal.patch -Patch0075: virtio-new-post_load-hook.patch -Patch0076: virtio-net-prevent-offloads-reset-on-migration.patch -Patch0077: util-hbitmap-strict-hbitmap_reset.patch -Patch0078: hbitmap-handle-set-reset-with-zero-length.patch -Patch0079: target-arm-Allow-reading-flags-from-FPSCR-for-M-prof.patch -Patch0080: scsi-lsi-exit-infinite-loop-while-executing-script-C.patch -Patch0081: virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch -Patch0082: qcow2-Fix-QCOW2_COMPRESSED_SECTOR_MASK.patch -Patch0083: util-iov-introduce-qemu_iovec_init_extended.patch -Patch0084: util-iov-improve-qemu_iovec_is_zero.patch -Patch0085: block-io-refactor-padding.patch -Patch0086: block-Make-wait-mark-serialising-requests-public.patch -Patch0087: block-Add-bdrv_co_get_self_request.patch -Patch0088: block-file-posix-Let-post-EOF-fallocate-serialize.patch -Patch0089: block-posix-Always-allocate-the-first-block.patch -Patch0090: block-create-Do-not-abort-if-a-block-driver-is-not-a.patch -Patch0091: mirror-Keep-mirror_top_bs-drained-after-dropping-per.patch -Patch0092: target-arm-kvm-trivial-Clean-up-header-documentation.patch -Patch0093: target-arm-kvm64-kvm64-cpus-have-timer-registers.patch -Patch0094: target-arm-kvm-Implement-virtual-time-adjustment.patch -Patch0095: target-arm-cpu-Add-the-kvm-no-adjvtime-CPU-property.patch -Patch0096: hw-acpi-Make-ACPI-IO-address-space-configurable.patch -Patch0097: hw-acpi-Do-not-create-memory-hotplug-method-when-han.patch -Patch0098: hw-acpi-Add-ACPI-Generic-Event-Device-Support.patch -Patch0099: hw-arm-virt-Add-memory-hotplug-framework.patch -Patch0100: hw-arm-virt-Enable-device-memory-cold-hot-plug-with-.patch -Patch0101: hw-arm-virt-acpi-build-Add-PC-DIMM-in-SRAT.patch -Patch0102: hw-arm-Factor-out-powerdown-notifier-from-GPIO.patch -Patch0103: hw-arm-Use-GED-for-system_powerdown-event.patch -Patch0104: docs-specs-Add-ACPI-GED-documentation.patch -Patch0105: tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch -Patch0106: tests-acpi-add-empty-files.patch -Patch0107: tests-allow-empty-expected-files.patch -Patch0108: tests-Add-bios-tests-to-arm-virt.patch -Patch0109: tests-document-how-to-update-acpi-tables.patch -Patch0110: hw-arm-virt-Simplify-by-moving-the-gic-in-the-machin.patch -Patch0111: bugfix-Use-gicr_typer-in-arm_gicv3_icc_reset.patch -Patch0112: Typo-Correct-the-name-of-CPU-hotplug-memory-region.patch -Patch0113: acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch -Patch0114: acpi-ged-Add-virt_madt_cpu_entry-to-madt_cpu-hook.patch -Patch0115: arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch -Patch0116: acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch -Patch0117: acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch -Patch0118: arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch -Patch0119: arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch -Patch0120: arm-virt-Add-CPU-hotplug-framework.patch -Patch0121: arm-virt-Add-CPU-topology-support.patch -Patch0122: test-numa-Adjust-aarch64-numa-test.patch -Patch0123: hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch -Patch0124: hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch -Patch0125: arm-virt-gic-Construct-irqs-connection-from-create_g.patch -Patch0126: intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch -Patch0127: intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch -Patch0128: intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch -Patch0129: hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch -Patch0130: accel-kvm-Add-pre-park-vCPU-support.patch -Patch0131: intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch -Patch0132: acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch -Patch0133: arm-virt-Add-cpu_hotplug_enabled-field.patch -Patch0134: arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch -Patch0135: arm-virt-Pre-sizing-MADT-GICC-PPTT-GICv3-and-Pre-par.patch -Patch0136: arm-virt-Add-some-sanity-checks-in-cpu_pre_plug-hook.patch -Patch0137: arm-virt-Start-up-CPU-hot-plug.patch -Patch0138: migration-always-initialise-ram_counters-for-a-new-m.patch -Patch0139: migration-add-qemu_file_update_transfer-interface.patch -Patch0140: migration-add-speed-limit-for-multifd-migration.patch -Patch0141: migration-update-ram_counters-for-multifd-sync-packe.patch -Patch0142: migration-Make-global-sem_sync-semaphore-by-channel.patch -Patch0143: migration-multifd-fix-nullptr-access-in-terminating-m.patch -Patch0144: migration-Maybe-VM-is-paused-when-migration-is-cance.patch -Patch0145: migration-multifd-fix-potential-wrong-acception-orde.patch -Patch0146: migration-multifd-fix-destroyed-mutex-access-in-term.patch -Patch0147: migration-multifd-fix-nullptr-access-in-multifd_send.patch -Patch0148: vtimer-compat-cross-version-migration-from-v4.0.1.patch -Patch0149: migration-ram-Do-error_free-after-migrate_set_error-.patch -Patch0150: migration-ram-fix-memleaks-in-multifd_new_send_chann.patch -Patch0151: migration-rdma-fix-a-memleak-on-error-path-in-rdma_s.patch -Patch0152: arm-virt-Support-CPU-cold-plug.patch -Patch0153: ide-Fix-incorrect-handling-of-some-PRDTs-in-ide_dma_.patch -Patch0154: ati-vga-Fix-checks-in-ati_2d_blt-to-avoid-crash.patch -Patch0155: slirp-tftp-restrict-relative-path-access.patch -Patch0156: ip_reass-Fix-use-after-free.patch -Patch0157: bt-use-size_t-type-for-length-parameters-instead-of-.patch -Patch0158: log-Add-some-logs-on-VM-runtime-path.patch -Patch0159: Revert-vtimer-compat-cross-version-migration-from-v4.patch -Patch0160: ARM64-record-vtimer-tick-when-cpu-is-stopped.patch -Patch0161: hw-arm-virt-add-missing-compat-for-kvm-no-adjvtime.patch -Patch0162: migration-Compat-virtual-timer-adjust-for-v4.0.1-and.patch -Patch0163: vtimer-Drop-vtimer-virtual-timer-adjust.patch -Patch0164: target-arm-Add-the-kvm_adjvtime-vcpu-property-for-Co.patch -Patch0165: target-arm-Fix-PAuth-sbox-functions.patch -Patch0166: tests-Disalbe-filemonitor-testcase.patch -Patch0167: es1370-check-total-frame-count-against-current-frame.patch -Patch0168: exec-set-map-length-to-zero-when-returning-NULL.patch -Patch0169: ati-vga-check-mm_index-before-recursive-call-CVE-202.patch -Patch0170: megasas-use-unsigned-type-for-reply_queue_head-and-c.patch -Patch0171: megasas-avoid-NULL-pointer-dereference.patch -Patch0172: megasas-use-unsigned-type-for-positive-numeric-field.patch -Patch0173: hw-scsi-megasas-Fix-possible-out-of-bounds-array-acc.patch -Patch0174: hw-arm-acpi-enable-SHPC-native-hot-plug.patch -Patch0175: hw-tpm-rename-Error-parameter-to-more-common-errp.patch -Patch0176: tpm-ppi-page-align-PPI-RAM.patch -Patch0177: tpm-Move-tpm_tis_show_buffer-to-tpm_util.c.patch -Patch0178: spapr-Implement-get_dt_compatible-callback.patch -Patch0179: delete-the-in-tpm.txt.patch -Patch0180: tpm_spapr-Support-TPM-for-ppc64-using-CRQ-based-inte.patch -Patch0181: tpm_spapr-Support-suspend-and-resume.patch -Patch0182: hw-ppc-Kconfig-Enable-TPM_SPAPR-as-part-of-PSERIES-c.patch -Patch0183: docs-specs-tpm-reST-ify-TPM-documentation.patch -Patch0184: tpm-rename-TPM_TIS-into-TPM_TIS_ISA.patch -Patch0185: tpm-Use-TPMState-as-a-common-struct.patch -Patch0186: tpm-Separate-tpm_tis-common-functions-from-isa-code.patch -Patch0187: tpm-Separate-TPM_TIS-and-TPM_TIS_ISA-configs.patch -Patch0188: tpm-Add-the-SysBus-TPM-TIS-device.patch -Patch0189: hw-arm-virt-vTPM-support.patch -Patch0190: docs-specs-tpm-Document-TPM_TIS-sysbus-device-for-AR.patch -Patch0191: test-tpm-pass-optional-machine-options-to-swtpm-test.patch -Patch0192: test-tpm-tis-Get-prepared-to-share-tests-between-ISA.patch -Patch0193: test-tpm-tis-Add-Sysbus-TPM-TIS-device-test.patch -Patch0194: build-smt-processor-structure-to-support-smt-topolog.patch -Patch0195: target-arm-Add-isar_feature-tests-for-PAN-ATS1E1.patch -Patch0196: target-arm-Add-ID_AA64MMFR2_EL1.patch -Patch0197: target-arm-Add-and-use-FIELD-definitions-for-ID_AA64.patch -Patch0198: target-arm-Use-FIELD-macros-for-clearing-ID_DFR0-PER.patch -Patch0199: target-arm-Define-an-aa32_pmu_8_1-isar-feature-test-.patch -Patch0200: target-arm-Add-_aa64_-and-_any_-versions-of-pmu_8_1-.patch -Patch0201: target-arm-Stop-assuming-DBGDIDR-always-exists.patch -Patch0202: target-arm-Move-DBGDIDR-into-ARMISARegisters.patch -Patch0203: target-arm-Enable-ARMv8.2-ATS1E1-in-cpu-max.patch -Patch0204: target-arm-Test-correct-register-in-aa32_pan-and-aa3.patch -Patch0205: target-arm-Read-debug-related-ID-registers-from-KVM.patch -Patch0206: target-arm-monitor-Introduce-qmp_query_cpu_model_exp.patch -Patch0207: target-arm-monitor-query-cpu-model-expansion-crashed.patch -Patch0208: target-arm-convert-isar-regs-to-array.patch -Patch0209: target-arm-parse-cpu-feature-related-options.patch -Patch0210: target-arm-register-CPU-features-for-property.patch -Patch0211: target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch -Patch0212: target-arm-introduce-CPU-feature-dependency-mechanis.patch -Patch0213: target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch -Patch0214: target-arm-Add-CPU-features-to-query-cpu-model-expan.patch -Patch0215: target-arm-Update-ID-fields.patch -Patch0216: target-arm-Add-more-CPU-features.patch -Patch0217: hw-usb-core-fix-buffer-overflow.patch -Patch0218: target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch -Patch0219: Drop-bogus-IPv6-messages.patch -Patch0220: hw-sd-sdhci-Fix-DMA-Transfer-Block-Size-field.patch -Patch0221: hw-xhci-check-return-value-of-usb_packet_map.patch -Patch0222: hw-net-xgmac-Fix-buffer-overflow-in-xgmac_enet_send.patch -Patch0223: hw-net-net_tx_pkt-fix-assertion-failure-in-net_tx_pk.patch -Patch0224: sm501-Convert-printf-abort-to-qemu_log_mask.patch -Patch0225: sm501-Shorten-long-variable-names-in-sm501_2d_operat.patch -Patch0226: sm501-Use-BIT-x-macro-to-shorten-constant.patch -Patch0227: sm501-Clean-up-local-variables-in-sm501_2d_operation.patch -Patch0228: sm501-Replace-hand-written-implementation-with-pixma.patch -Patch0229: pci-check-bus-pointer-before-dereference.patch -Patch0230: hw-ide-check-null-block-before-_cancel_dma_sync.patch -Patch0231: elf2dmp-Fix-memory-leak-on-main-error-paths.patch -Patch0232: io-Don-t-use-flag-of-printf-format.patch -Patch0233: hw-display-omap_lcdc-Fix-potential-NULL-pointer-dere.patch -Patch0234: hw-display-exynos4210_fimd-Fix-potential-NULL-pointe.patch -Patch0235: block-vvfat-Fix-bad-printf-format-specifiers.patch -Patch0236: block-Remove-unused-include.patch -Patch0237: ssi-Fix-bad-printf-format-specifiers.patch -Patch0238: net-l2tpv3-Remove-redundant-check-in-net_init_l2tpv3.patch -Patch0239: ati-check-x-y-display-parameter-values.patch -Patch0240: migration-dirtyrate-setup-up-query-dirtyrate-framwor.patch -Patch0241: migration-dirtyrate-add-DirtyRateStatus-to-denote-ca.patch -Patch0242: migration-dirtyrate-Add-RamblockDirtyInfo-to-store-s.patch -Patch0243: migration-dirtyrate-Add-dirtyrate-statistics-series-.patch -Patch0244: migration-dirtyrate-move-RAMBLOCK_FOREACH_MIGRATABLE.patch -Patch0245: migration-dirtyrate-Record-hash-results-for-each-sam.patch -Patch0246: migration-dirtyrate-Compare-page-hash-results-for-re.patch -Patch0247: migration-dirtyrate-skip-sampling-ramblock-with-size.patch -Patch0248: migration-dirtyrate-Implement-set_sample_page_period.patch -Patch0249: migration-dirtyrate-Implement-calculate_dirtyrate-fu.patch -Patch0250: migration-dirtyrate-Implement-qmp_cal_dirty_rate-qmp.patch -Patch0251: migration-dirtyrate-Add-trace_calls-to-make-it-easie.patch -Patch0252: migration-dirtyrate-record-start_time-and-calc_time-.patch -Patch0253: migration-dirtyrate-present-dirty-rate-only-when-que.patch -Patch0254: migration-dirtyrate-simplify-includes-in-dirtyrate.c.patch -Patch0255: migration-tls-save-hostname-into-MigrationState.patch -Patch0256: migration-tls-extract-migration_tls_client_create-fo.patch -Patch0257: migration-tls-add-tls_hostname-into-MultiFDSendParam.patch -Patch0258: migration-tls-extract-cleanup-function-for-common-us.patch -Patch0259: migration-tls-add-support-for-multifd-tls-handshake.patch -Patch0260: migration-tls-add-trace-points-for-multifd-tls.patch -Patch0261: qemu-file-Don-t-do-IO-after-shutdown.patch -Patch0262: multifd-Make-sure-that-we-don-t-do-any-IO-after-an-e.patch -Patch0263: migration-Don-t-send-data-if-we-have-stopped.patch -Patch0264: migration-Create-migration_is_running.patch -Patch0265: migration-fix-COLO-broken-caused-by-a-previous-commi.patch -Patch0266: migration-multifd-fix-hangup-with-TLS-Multifd-due-to.patch -Patch0267: multifd-tls-fix-memoryleak-of-the-QIOChannelSocket-o.patch -Patch0268: net-remove-an-assert-call-in-eth_get_gso_type.patch -Patch0269: json-Fix-a-memleak-in-parse_pair.patch -Patch0270: Bugfix-hw-acpi-Use-max_cpus-instead-of-cpus-when-bui.patch -Patch0271: slirp-check-pkt_len-before-reading-protocol-header.patch -Patch0272: hw-usb-hcd-ohci-check-for-processed-TD-before-retire.patch -Patch0273: hw-ehci-check-return-value-of-usb_packet_map.patch -Patch0274: hw-usb-hcd-ohci-check-len-and-frame_number-variables.patch -Patch0275: hw-net-e1000e-advance-desc_offset-in-case-of-null-de.patch -Patch0276: hostmem-Fix-up-free-host_nodes-list-right-after-visi.patch -Patch0277: target-arm-Fix-write-redundant-values-to-kvm.patch -Patch0278: memory-clamp-cached-translation-in-case-it-points-to.patch -Patch0279: scsi-bus-Refactor-the-code-that-retries-requests.patch -Patch0280: scsi-disk-Add-support-for-retry-on-errors.patch -Patch0281: qapi-block-core-Add-retry-option-for-error-action.patch -Patch0282: block-backend-Introduce-retry-timer.patch -Patch0283: block-backend-Add-device-specific-retry-callback.patch -Patch0284: block-backend-Enable-retry-action-on-errors.patch -Patch0285: block-backend-Add-timeout-support-for-retry.patch -Patch0286: block-Add-error-retry-param-setting.patch -Patch0287: virtio-blk-Refactor-the-code-that-processes-queued-r.patch -Patch0288: virtio-blk-On-restart-process-queued-requests-in-the.patch -Patch0289: virtio_blk-Add-support-for-retry-on-errors.patch -Patch0290: migration-Add-multi-thread-compress-method.patch -Patch0291: migration-Refactoring-multi-thread-compress-migratio.patch -Patch0292: migration-Add-multi-thread-compress-ops.patch -Patch0293: migration-Add-zstd-support-in-multi-thread-compressi.patch -Patch0294: migration-Add-compress_level-sanity-check.patch -Patch0295: doc-Update-multi-thread-compression-doc.patch -Patch0296: configure-Enable-test-and-libs-for-zstd.patch -Patch0297: ati-use-vga_read_byte-in-ati_cursor_define.patch -Patch0298: sd-sdhci-assert-data_count-is-within-fifo_buffer.patch -Patch0299: msix-add-valid.accepts-methods-to-check-address.patch -Patch0300: ide-atapi-check-io_buffer_index-in-ide_atapi_cmd_rep.patch -Patch0301: block-backend-Stop-retrying-when-draining.patch -Patch0302: migration-fix-memory-leak-in-qmp_migrate_set_paramet.patch -Patch0303: migration-tls-fix-inverted-semantics-in-multifd_chan.patch -Patch0304: migration-tls-add-error-handling-in-multifd_tls_hand.patch -Patch0305: net-vmxnet3-validate-configuration-values-during-act.patch -Patch0306: block-Add-sanity-check-when-setting-retry-parameters.patch -Patch0307: hw-pci-host-add-pci-intack-write-method.patch -Patch0308: pci-host-add-pcie-msi-read-method.patch -Patch0309: vfio-add-quirk-device-write-method.patch -Patch0310: prep-add-ppc-parity-write-method.patch -Patch0311: nvram-add-nrf51_soc-flash-read-method.patch -Patch0312: spapr_pci-add-spapr-msi-read-method.patch -Patch0313: tz-ppc-add-dummy-read-write-methods.patch -Patch0314: imx7-ccm-add-digprog-mmio-write-method.patch -Patch0315: util-cacheinfo-fix-crash-when-compiling-with-uClibc.patch -Patch0316: arm-cpu-Fixed-function-undefined-error-at-compile-ti.patch -Patch0317: blockjob-Fix-crash-with-IOthread-when-block-commit-a.patch -Patch0318: vhost-user-gpu-fix-resource-leak-in-vg_resource_crea.patch -Patch0319: vhost-user-gpu-fix-memory-leak-in-vg_resource_attach.patch -Patch0320: vhost-user-gpu-fix-memory-leak-while-calling-vg_reso.patch -Patch0321: vhost-user-gpu-fix-memory-leak-in-virgl_cmd_resource.patch -Patch0322: vhost-user-gpu-fix-memory-leak-in-virgl_resource_att.patch -Patch0323: vhost-user-gpu-fix-memory-disclosure-in-virgl_cmd_ge.patch -Patch0324: vhost-user-gpu-fix-OOB-write-in-virgl_cmd_get_capset.patch -Patch0325: ide-ahci-add-check-to-avoid-null-dereference-CVE-201.patch -Patch0326: hw-intc-arm_gic-Fix-interrupt-ID-in-GICD_SGIR-regist.patch -Patch0327: usb-limit-combined-packets-to-1-MiB-CVE-2021-3527.patch -Patch0328: hw-net-rocker_of_dpa-fix-double-free-bug-of-rocker-d.patch -Patch0329: x86-Intel-AVX512_BF16-feature-enabling.patch -Patch0330: i386-Add-MSR-feature-bit-for-MDS-NO.patch -Patch0331: i386-Add-macro-for-stibp.patch -Patch0332: i386-Add-new-CPU-model-Cooperlake.patch -Patch0333: target-i386-Add-new-bit-definitions-of-MSR_IA32_ARCH.patch -Patch0334: target-i386-Add-missed-security-features-to-Cooperla.patch -Patch0335: target-i386-add-PSCHANGE_NO-bit-for-the-ARCH_CAPABIL.patch -Patch0336: target-i386-Export-TAA_NO-bit-to-guests.patch -Patch0337: target-i386-Introduce-Denverton-CPU-model.patch -Patch0338: target-i386-Add-Snowridge-v2-no-MPX-CPU-model.patch -Patch0339: i386-Add-CPUID-bit-for-CLZERO-and-XSAVEERPTR.patch -Patch0340: crypto-add-support-for-nettle-s-native-XTS-impl.patch -Patch0341: crypto-add-support-for-gcrypt-s-native-XTS-impl.patch -Patch0342: tests-benchmark-crypto-with-fixed-data-size-not-time.patch -Patch0343: tests-allow-filtering-crypto-cipher-benchmark-tests.patch -Patch0344: target-i386-handle-filtered_features-in-a-new-functi.patch -Patch0345: target-i386-introduce-generic-feature-dependency-mec.patch -Patch0346: target-i386-expand-feature-words-to-64-bits.patch -Patch0347: target-i386-add-VMX-definitions.patch -Patch0348: vmxcap-correct-the-name-of-the-variables.patch -Patch0349: target-i386-add-VMX-features.patch -Patch0350: target-i386-work-around-KVM_GET_MSRS-bug-for-seconda.patch -Patch0351: target-i386-add-VMX-features-to-named-CPU-models.patch -Patch0352: target-i386-add-two-missing-VMX-features-for-Skylake.patch -Patch0353: target-i386-disable-VMX-features-if-nested-0.patch -Patch0354: i386-cpu-Don-t-add-unavailable_features-to-env-user_.patch -Patch0355: target-i386-do-not-set-unsupported-VMX-secondary-exe.patch -Patch0356: migration-fix-multifd_send_pages-next-channel.patch -Patch0357: migration-Make-sure-that-we-don-t-call-write-in-case.patch -Patch0358: virtio-don-t-enable-notifications-during-polling.patch -Patch0359: usbredir-Prevent-recursion-in-usbredir_write.patch -Patch0360: xhci-recheck-slot-status.patch -Patch0361: vhost-Add-names-to-section-rounded-warning.patch -Patch0362: vhost-user-Print-unexpected-slave-message-types.patch -Patch0363: contrib-libvhost-user-Protect-slave-fd-with-mutex.patch -Patch0364: libvhost-user-Fix-some-memtable-remap-cases.patch -Patch0365: xics-Don-t-deassert-outputs.patch -Patch0366: i386-Resolve-CPU-models-to-v1-by-default.patch -Patch0367: block-curl-HTTP-header-fields-allow-whitespace-aroun.patch -Patch0368: block-curl-HTTP-header-field-names-are-case-insensit.patch -Patch0369: backup-Improve-error-for-bdrv_getlength-failure.patch -Patch0370: mirror-Make-sure-that-source-and-target-size-match.patch -Patch0371: iotests-143-Create-socket-in-SOCK_DIR.patch -Patch0372: nbd-server-Avoid-long-error-message-assertions-CVE-2.patch -Patch0373: block-Call-attention-to-truncation-of-long-NBD-expor.patch -Patch0374: qemu-img-convert-Don-t-pre-zero-images.patch -Patch0375: qcow2-Fix-qcow2_alloc_cluster_abort-for-external-dat.patch -Patch0376: mirror-Wait-only-for-in-flight-operations.patch -Patch0377: virtio-net-delete-also-control-queue-when-TX-RX-dele.patch -Patch0378: target-i386-enable-monitor-and-ucode-revision-with-c.patch -Patch0379: target-i386-set-the-CPUID-level-to-0x14-on-old-machi.patch -Patch0380: target-i386-kvm-initialize-feature-MSRs-very-early.patch -Patch0381: target-i386-add-a-ucode-rev-property.patch -Patch0382: migration-use-migration_is_active-to-represent-activ.patch -Patch0383: migration-Rate-limit-inside-host-pages.patch -Patch0384: hw-pci-pcie-Move-hot-plug-capability-check-to-pre_pl.patch -Patch0385: qapi-block-core-Introduce-BackupCommon.patch -Patch0386: drive-backup-create-do_backup_common.patch -Patch0387: blockdev-backup-utilize-do_backup_common.patch -Patch0388: qapi-add-BitmapSyncMode-enum.patch -Patch0389: block-backup-Add-mirror-sync-mode-bitmap.patch -Patch0390: block-backup-add-never-policy-to-bitmap-sync-mode.patch -Patch0391: block-backup-loosen-restriction-on-readonly-bitmaps.patch -Patch0392: block-backup-hoist-bitmap-check-into-QMP-interface.patch -Patch0393: block-backup-deal-with-zero-detection.patch -Patch0394: mirror-Fix-bdrv_has_zero_init-use.patch -Patch0395: blockdev-fix-coding-style-issues-in-drive_backup_pre.patch -Patch0396: blockdev-unify-qmp_drive_backup-and-drive-backup-tra.patch -Patch0397: blockdev-unify-qmp_blockdev_backup-and-blockdev-back.patch -Patch0398: blockdev-honor-bdrv_try_set_aio_context-context-requ.patch -Patch0399: blockdev-Return-bs-to-the-proper-context-on-snapshot.patch -Patch0400: block-Fix-cross-AioContext-blockdev-snapshot.patch -Patch0401: vl-Don-t-mismatch-g_strsplit-g_free.patch -Patch0402: seqlock-fix-seqlock_write_unlock_impl-function.patch -Patch0403: target-i386-kvm-initialize-microcode-revision-from-K.patch -Patch0404: target-i386-check-for-availability-of-MSR_IA32_UCODE.patch -Patch0405: hw-arm-virt-Init-PMU-for-hotplugged-vCPU.patch -Patch0406: Fixed-integer-overflow-in-e1000e.patch -Patch0407: migration-fix-cleanup_bh-leak-on-resume.patch -Patch0408: qmp-fix-leak-on-callbacks-that-return-both-value-and.patch -Patch0409: qga-commands-posix-fix-use-after-free-of-local_err.patch -Patch0410: file-posix-Fix-leaked-fd-in-raw_open_common-error-pa.patch -Patch0411: object-return-self-in-object_ref.patch -Patch0412: lm32-do-not-leak-memory-on-object_new-object_unref.patch -Patch0413: cris-do-not-leak-struct-cris_disasm_data.patch -Patch0414: hppa-fix-leak-from-g_strdup_printf.patch -Patch0415: mcf5208-fix-leak-from-qemu_allocate_irqs.patch -Patch0416: microblaze-fix-leak-of-fdevice-tree-blob.patch -Patch0417: ide-fix-leak-from-qemu_allocate_irqs.patch -Patch0418: make-check-unit-use-after-free-in-test-opts-visitor.patch -Patch0419: xhci-fix-valid.max_access_size-to-access-address-reg.patch -Patch0420: qga-fix-assert-regression-on-guest-shutdown.patch -Patch0421: char-fix-use-after-free-with-dup-chardev-reconnect.patch -Patch0422: migration-Count-new_dirty-instead-of-real_dirty.patch -Patch0423: qga-Plug-unlikely-memory-leak-in-guest-set-memory-bl.patch -Patch0424: chardev-tcp-Fix-error-message-double-free-error.patch -Patch0425: colo-compare-Fix-memory-leak-in-packet_enqueue.patch -Patch0426: hw-block-nvme-fix-pin-based-interrupt-behavior.patch -Patch0427: hw-block-nvme-fix-pci-doorbell-size-calculation.patch -Patch0428: virtio-pci-fix-queue_enable-write.patch -Patch0429: hw-pci-pci_bridge-Correct-pci_bridge_io-memory-regio.patch -Patch0430: linux-user-mmap.c-fix-integer-underflow-in-target_mr.patch -Patch0431: migration-rdma-cleanup-rdma-context-before-g_free-to.patch -Patch0432: pc-bios-s390-ccw-net-fix-a-possible-memory-leak-in-g.patch -Patch0433: block-qcow2-do-free-crypto_opts-in-qcow2_close.patch -Patch0434: qemu-img-free-memory-before-re-assign.patch -Patch0435: block-qcow2-threads-fix-qcow2_decompress.patch -Patch0436: block-Avoid-memleak-on-qcow2-image-info-failure.patch -Patch0437: block-bdrv_set_backing_bs-fix-use-after-free.patch -Patch0438: hmp-vnc-Fix-info-vnc-list-leak.patch -Patch0439: migration-colo-fix-use-after-free-of-local_err.patch -Patch0440: migration-ram-fix-use-after-free-of-local_err.patch -Patch0441: block-mirror-fix-use-after-free-of-local_err.patch -Patch0442: block-fix-bdrv_root_attach_child-forget-to-unref-chi.patch -Patch0443: virtio-serial-bus-Plug-memory-leak-on-realize-error-.patch -Patch0444: virtio-blk-delete-vqs-on-the-error-path-in-realize.patch -Patch0445: fix-vhost_user_blk_watch-crash.patch -Patch0446: vhost-user-blk-delay-vhost_user_blk_disconnect.patch -Patch0447: usbredir-fix-buffer-overflow-on-vmload.patch -Patch0448: display-bochs-display-fix-memory-leak.patch -Patch0449: audio-fix-integer-overflow.patch -Patch0450: migration-multifd-clean-pages-after-filling-packet.patch -Patch0451: migration-multifd-not-use-multifd-during-postcopy.patch -Patch0452: migration-Define-VMSTATE_INSTANCE_ID_ANY.patch -Patch0453: migration-Change-SaveStateEntry.instance_id-into-uin.patch -Patch0454: apic-Use-32bit-APIC-ID-for-migration-instance-ID.patch -Patch0455: virtio-add-ability-to-delete-vq-through-a-pointer.patch -Patch0456: virtio-pmem-do-delete-rq_vq-in-virtio_pmem_unrealize.patch -Patch0457: virtio-crypto-do-delete-ctrl_vq-in-virtio_crypto_dev.patch -Patch0458: vhost-user-blk-delete-virtioqueues-in-unrealize-to-f.patch -Patch0459: vhost-user-blk-convert-to-new-virtio_delete_queue.patch -Patch0460: block-nbd-extract-the-common-cleanup-code.patch -Patch0461: virtio-gracefully-handle-invalid-region-caches.patch -Patch0462: migration-savevm-release-gslist-after-dump_vmstate_j.patch -Patch0463: virtio-input-fix-memory-leak-on-unrealize.patch -Patch0464: target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch -Patch0465: target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch -Patch0466: target-arm-Update-the-ID-registers-of-Kunpeng-920.patch -Patch0467: hw-net-fix-vmxnet3-live-migration.patch -Patch0468: include-Make-headers-more-self-contained.patch -Patch0469: migration-register_savevm_live-doesn-t-need-dev.patch -Patch0470: vmstate-add-qom-interface-to-get-id.patch -Patch0471: linux-headers-Update-against-Add-migration-support-f.patch -Patch0472: vfio-Add-function-to-unmap-VFIO-region.patch -Patch0473: vfio-Add-vfio_get_object-callback-to-VFIODeviceOps.patch -Patch0474: vfio-Add-save-and-load-functions-for-VFIO-PCI-device.patch -Patch0475: vfio-Add-migration-region-initialization-and-finaliz.patch -Patch0476: vfio-Add-VM-state-change-handler-to-know-state-of-VM.patch -Patch0477: vfio-Add-migration-state-change-notifier.patch -Patch0478: vfio-Register-SaveVMHandlers-for-VFIO-device.patch -Patch0479: vfio-Add-save-state-functions-to-SaveVMHandlers.patch -Patch0480: vfio-Add-load-state-functions-to-SaveVMHandlers.patch -Patch0481: memory-Set-DIRTY_MEMORY_MIGRATION-when-IOMMU-is-enab.patch -Patch0482: vfio-Get-migration-capability-flags-for-container.patch -Patch0483: vfio-Add-function-to-start-and-stop-dirty-pages-trac.patch -Patch0484: vfio-Add-vfio_listener_log_sync-to-mark-dirty-pages.patch -Patch0485: vfio-Dirty-page-tracking-when-vIOMMU-is-enabled.patch -Patch0486: vfio-Add-ioctl-to-get-dirty-pages-bitmap-during-dma-.patch -Patch0487: vfio-Make-vfio-pci-device-migration-capable.patch -Patch0488: qapi-Add-VFIO-devices-migration-stats-in-Migration-s.patch -Patch0489: vfio-Move-the-saving-of-the-config-space-to-the-righ.patch -Patch0490: vfio-Set-the-priority-of-the-VFIO-VM-state-change-ha.patch -Patch0491: vfio-Avoid-disabling-and-enabling-vectors-repeatedly.patch -Patch0492: kvm-split-too-big-memory-section-on-several-memslots.patch -Patch0493: kvm-Reallocate-dirty_bmap-when-we-change-a-slot.patch -Patch0494: accel-kvm-Fix-memory-waste-under-mismatch-page-size.patch -Patch0495: memory-Skip-dirty-tracking-for-un-migratable-memory-.patch -Patch0496: Fix-use-after-free-in-vfio_migration_probe.patch -Patch0497: vfio-Make-migration-support-experimental.patch -Patch0498: vfio-Change-default-dirty-pages-tracking-behavior-du.patch -Patch0499: vfio-Fix-vfio_listener_log_sync-function-name-typo.patch -Patch0500: vfio-Support-host-translation-granule-size.patch -Patch0501: vfio-migrate-Move-switch-of-dirty-tracking-into-vfio.patch -Patch0502: vfio-Fix-unregister-SaveVMHandler-in-vfio_migration_.patch -Patch0503: migration-ram-Reduce-unnecessary-rate-limiting.patch -Patch0504: migration-ram-Optimize-ram_save_host_page.patch -Patch0505: qdev-monitors-Fix-reundant-error_setg-of-qdev_add_de.patch -Patch0506: linux-headers-update-against-5.10-and-manual-clear-v.patch -Patch0507: vfio-Maintain-DMA-mapping-range-for-the-container.patch -Patch0508: vfio-migration-Add-support-for-manual-clear-vfio-dir.patch -Patch0509: hw-arm-smmuv3-Support-16K-translation-granule.patch -Patch0510: hw-arm-smmuv3-Set-the-restoration-priority-of-the-vS.patch -Patch0511: hw-vfio-common-trace-vfio_connect_container-operatio.patch -Patch0512: update-linux-headers-Import-iommu.h.patch -Patch0513: vfio.h-and-iommu.h-header-update-against-5.10.patch -Patch0514: memory-Add-new-fields-in-IOTLBEntry.patch -Patch0515: hw-arm-smmuv3-Improve-stage1-ASID-invalidation.patch -Patch0516: hw-arm-smmu-common-Allow-domain-invalidation-for-NH_.patch -Patch0517: memory-Add-IOMMU_ATTR_VFIO_NESTED-IOMMU-memory-regio.patch -Patch0518: memory-Add-IOMMU_ATTR_MSI_TRANSLATE-IOMMU-memory-reg.patch -Patch0519: memory-Introduce-IOMMU-Memory-Region-inject_faults-A.patch -Patch0520: iommu-Introduce-generic-header.patch -Patch0521: pci-introduce-PCIPASIDOps-to-PCIDevice.patch -Patch0522: vfio-Force-nested-if-iommu-requires-it.patch -Patch0523: vfio-Introduce-hostwin_from_range-helper.patch -Patch0524: vfio-Introduce-helpers-to-DMA-map-unmap-a-RAM-sectio.patch -Patch0525: vfio-Set-up-nested-stage-mappings.patch -Patch0526: vfio-Pass-stage-1-MSI-bindings-to-the-host.patch -Patch0527: vfio-Helper-to-get-IRQ-info-including-capabilities.patch -Patch0528: vfio-pci-Register-handler-for-iommu-fault.patch -Patch0529: vfio-pci-Set-up-the-DMA-FAULT-region.patch -Patch0530: vfio-pci-Implement-the-DMA-fault-handler.patch -Patch0531: hw-arm-smmuv3-Advertise-MSI_TRANSLATE-attribute.patch -Patch0532: hw-arm-smmuv3-Store-the-PASID-table-GPA-in-the-trans.patch -Patch0533: hw-arm-smmuv3-Fill-the-IOTLBEntry-arch_id-on-NH_VA-i.patch -Patch0534: hw-arm-smmuv3-Fill-the-IOTLBEntry-leaf-field-on-NH_V.patch -Patch0535: hw-arm-smmuv3-Pass-stage-1-configurations-to-the-hos.patch -Patch0536: hw-arm-smmuv3-Implement-fault-injection.patch -Patch0537: hw-arm-smmuv3-Allow-MAP-notifiers.patch -Patch0538: pci-Add-return_page_response-pci-ops.patch -Patch0539: vfio-pci-Implement-return_page_response-page-respons.patch -Patch0540: vfio-common-Avoid-unmap-ram-section-at-vfio_listener.patch -Patch0541: vfio-Introduce-helpers-to-mark-dirty-pages-of-a-RAM-.patch -Patch0542: vfio-Add-vfio_prereg_listener_log_sync-in-nested-sta.patch -Patch0543: vfio-Add-vfio_prereg_listener_log_clear-to-re-enable.patch -Patch0544: vfio-Add-vfio_prereg_listener_global_log_start-stop-.patch -Patch0545: hw-arm-smmuv3-Post-load-stage-1-configurations-to-th.patch -Patch0546: usbredir-fix-free-call.patch -Patch0547: vfio-common-Fix-incorrect-address-alignment-in-vfio_.patch -Patch0548: vfio-common-Add-address-alignment-check-in-vfio_list.patch -Patch0549: uas-add-stream-number-sanity-checks.patch -Patch0550: virtio-net-fix-use-after-unmap-free-for-sg.patch -Patch0551: Add-mtod_check.patch -Patch0552: bootp-limit-vendor-specific-area-to-input-packet-mem.patch -Patch0553: bootp-check-bootp_input-buffer-size.patch -Patch0554: upd6-check-udp6_input-buffer-size.patch -Patch0555: tftp-check-tftp_input-buffer-size.patch -Patch0556: tftp-introduce-a-header-structure.patch -Patch0557: fix-cve-2020-35504.patch -Patch0558: fix-cve-2020-35505.patch -Patch0559: virtio-balloon-apply-upstream-patch.patch -Patch0560: add-Phytium-s-CPU-models-FT-2000-and-Tengyun-S2500.patch +Source4: BinDir.tar.gz + +Patch0001: net-dump.c-Suppress-spurious-compiler-warning.patch +Patch0002: cpu-parse-feature-to-avoid-failure.patch +Patch0003: cpu-add-Kunpeng-920-cpu-support.patch +Patch0004: cpu-add-Cortex-A72-processor-kvm-target-support.patch +Patch0005: add-Phytium-s-CPU-models-FT-2000-and-Tengyun-S2500.patch +Patch0006: qapi-block-core-Add-retry-option-for-error-action.patch +Patch0007: block-backend-Introduce-retry-timer.patch +Patch0008: block-backend-Add-device-specific-retry-callback.patch +Patch0009: block-backend-Enable-retry-action-on-errors.patch +Patch0010: block-backend-Add-timeout-support-for-retry.patch +Patch0011: block-Add-error-retry-param-setting.patch +Patch0012: virtio_blk-Add-support-for-retry-on-errors.patch +Patch0013: vhost-cancel-migration-when-vhost-user-restarted-dur.patch +Patch0014: migration-Add-multi-thread-compress-method.patch +Patch0015: migration-Refactoring-multi-thread-compress-migratio.patch +Patch0016: migration-Add-multi-thread-compress-ops.patch +Patch0017: migration-Add-zstd-support-in-multi-thread-compressi.patch +Patch0018: migration-Add-compress_level-sanity-check.patch +Patch0019: doc-Update-multi-thread-compression-doc.patch +Patch0020: Revert-cpu-parse-feature-to-avoid-failure.patch +Patch0021: Revert-cpu-add-Cortex-A72-processor-kvm-target-suppo.patch +Patch0022: 0003-cpu-add-Cortex-A72-processor-kvm-target-support.patch +Patch0023: hugepages-hugepages-files-maybe-leftover.patch +Patch0024: target-i386-Modify-the-VM-s-physical-bits-value-set-.patch +Patch0025: vfio-pci-Ascend310-need-4Bytes-quirk-in-bar4.patch +Patch0026: vfio-pci-Ascend710-need-4Bytes-quirk-in-bar0.patch +Patch0027: vfio-pci-Ascend910-need-4Bytes-quirk-in-bar0.patch +Patch0028: scsi-bus-Refactor-the-code-that-retries-requests.patch +Patch0029: scsi-disk-Add-support-for-retry-on-errors.patch +Patch0030: block-backend-Stop-retrying-when-draining.patch +Patch0031: block-Add-sanity-check-when-setting-retry-parameters.patch +Patch0032: migration-skip-cache_drop-for-bios-bootloader-and-nv.patch +Patch0033: ps2-fix-oob-in-ps2-kbd.patch +Patch0034: Currently-while-kvm-and-qemu-can-not-handle-some-kvm.patch +Patch0035: cpu-features-fix-bug-for-memory-leakage.patch +Patch0036: monitor-qmp-drop-inflight-rsp-if-qmp-client-broken.patch +Patch0037: oslib-posix-optimise-vm-startup-time-for-1G-hugepage.patch +Patch0038: nbd-server.c-fix-invalid-read-after-client-was-alrea.patch +Patch0039: qemu-nbd-make-native-as-the-default-aio-mode.patch +Patch0040: qemu-nbd-set-timeout-to-qemu-nbd-socket.patch +Patch0041: qemu-pr-fixed-ioctl-failed-for-multipath-disk.patch +Patch0042: block-enable-cache-mode-of-empty-cdrom.patch +Patch0043: block-disallow-block-jobs-when-there-is-a-BDRV_O_INA.patch +Patch0044: scsi-cdrom-Fix-crash-after-remote-cdrom-detached.patch +Patch0045: block-bugfix-disable-process-AIO-when-attach-scsi-di.patch +Patch0046: block-bugfix-Don-t-pause-vm-when-NOSPACE-EIO-happene.patch +Patch0047: scsi-bugfix-fix-division-by-zero.patch +Patch0048: i386-cache-passthrough-Update-Intel-CPUID4.EAX-25-14.patch +Patch0049: i386-cache-passthrough-Update-AMD-8000_001D.EAX-25-1.patch +Patch0050: target-arm-convert-isar-regs-to-array.patch +Patch0051: target-arm-parse-cpu-feature-related-options.patch +Patch0052: target-arm-register-CPU-features-for-property.patch +Patch0053: target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch +Patch0054: target-arm-introduce-CPU-feature-dependency-mechanis.patch +Patch0055: target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch +Patch0056: target-arm-Add-CPU-features-to-query-cpu-model-expan.patch +Patch0057: target-arm-Add-more-CPU-features.patch +Patch0058: target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch +Patch0059: target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch +Patch0060: target-arm-Fix-write-redundant-values-to-kvm.patch +Patch0061: target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch +Patch0062: target-arm-Update-the-ID-registers-of-Kunpeng-920.patch +Patch0063: freeclock-add-qmp-command-to-get-time-offset-of-vm-i.patch +Patch0064: freeclock-set-rtc_date_diff-for-arm.patch +Patch0065: freeclock-set-rtc_date_diff-for-X86.patch +Patch0066: hw-usb-reduce-the-vpcu-cost-of-UHCI-when-VNC-disconn.patch +Patch0067: hw-net-rocker-fix-security-vulnerability.patch +Patch0068: tests-Disable-filemonitor-testcase.patch +Patch0069: seabios-convert-value-of-be16_to_cpu-to-u64-before-s.patch +Patch0070: seabios-do-not-give-back-high-ram.patch +Patch0071: seabios-drop-yield-in-smp_setup.patch +Patch0072: seabios-fix-memory-leak-when-pci-check.patch +Patch0073: seabios-increase-the-seabios-high-mem-zone-size.patch +Patch0074: seabios-increase-the-seabios-minibiostable.patch +Patch0075: IPv6-add-support-for-IPv6-protocol.patch +Patch0076: Use-post-increment-only-in-inffast.c.patch +Patch0077: util-log-add-CONFIG_DISABLE_QEMU_LOG-macro.patch +Patch0078: log-Add-some-logs-on-VM-runtime-path.patch +Patch0079: qdev-monitors-Fix-reundant-error_setg-of-qdev_add_de.patch +Patch0080: bios-tables-test-Allow-changes-to-q35-SSDT.dimmpxm-f.patch +Patch0081: smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch +Patch0082: net-eepro100-validate-various-address-valuesi-CVE-20.patch +Patch0083: pci-check-bus-pointer-before-dereference.patch +Patch0084: ide-ahci-add-check-to-avoid-null-dereference-CVE-201.patch +Patch0085: tap-return-err-when-tap-TUNGETIFF-fail.patch +Patch0086: xhci-check-reg-to-avoid-OOB-read.patch +Patch0087: monitor-Discard-BLOCK_IO_ERROR-event-when-VM-reboote.patch +Patch0088: monitor-limit-io-error-qmp-event-to-at-most-once-per.patch +Patch0089: linux-headers-update-against-5.10-and-manual-clear-v.patch +Patch0090: vfio-Maintain-DMA-mapping-range-for-the-container.patch +Patch0091: vfio-migration-Add-support-for-manual-clear-vfio-dir.patch +Patch0092: update-linux-headers-Import-iommu.h.patch +Patch0093: vfio.h-and-iommu.h-header-update-against-5.10.patch +Patch0094: memory-Add-new-fields-in-IOTLBEntry.patch +Patch0095: hw-arm-smmuv3-Improve-stage1-ASID-invalidation.patch +Patch0096: hw-arm-smmu-common-Allow-domain-invalidation-for-NH_.patch +Patch0097: memory-Add-IOMMU_ATTR_VFIO_NESTED-IOMMU-memory-regio.patch +Patch0098: memory-Add-IOMMU_ATTR_MSI_TRANSLATE-IOMMU-memory-reg.patch +Patch0099: memory-Introduce-IOMMU-Memory-Region-inject_faults-A.patch +Patch0100: iommu-Introduce-generic-header.patch +Patch0101: pci-introduce-PCIPASIDOps-to-PCIDevice.patch +Patch0102: vfio-Force-nested-if-iommu-requires-it.patch +Patch0103: vfio-Introduce-hostwin_from_range-helper.patch +Patch0104: vfio-Introduce-helpers-to-DMA-map-unmap-a-RAM-sectio.patch +Patch0105: vfio-Set-up-nested-stage-mappings.patch +Patch0106: vfio-Pass-stage-1-MSI-bindings-to-the-host.patch +Patch0107: vfio-Helper-to-get-IRQ-info-including-capabilities.patch +Patch0108: vfio-pci-Register-handler-for-iommu-fault.patch +Patch0109: vfio-pci-Set-up-the-DMA-FAULT-region.patch +Patch0110: vfio-pci-Implement-the-DMA-fault-handler.patch +Patch0111: hw-arm-smmuv3-Advertise-MSI_TRANSLATE-attribute.patch +Patch0112: hw-arm-smmuv3-Store-the-PASID-table-GPA-in-the-trans.patch +Patch0113: hw-arm-smmuv3-Fill-the-IOTLBEntry-arch_id-on-NH_VA-i.patch +Patch0114: hw-arm-smmuv3-Fill-the-IOTLBEntry-leaf-field-on-NH_V.patch +Patch0115: hw-arm-smmuv3-Pass-stage-1-configurations-to-the-hos.patch +Patch0116: hw-arm-smmuv3-Implement-fault-injection.patch +Patch0117: hw-arm-smmuv3-Allow-MAP-notifiers.patch +Patch0118: pci-Add-return_page_response-pci-ops.patch +Patch0119: vfio-pci-Implement-return_page_response-page-respons.patch +Patch0120: vfio-common-Avoid-unmap-ram-section-at-vfio_listener.patch +Patch0121: vfio-Introduce-helpers-to-mark-dirty-pages-of-a-RAM-.patch +Patch0122: vfio-Add-vfio_prereg_listener_log_sync-in-nested-sta.patch +Patch0123: vfio-Add-vfio_prereg_listener_log_clear-to-re-enable.patch +Patch0124: vfio-Add-vfio_prereg_listener_global_log_start-stop-.patch +Patch0125: hw-arm-smmuv3-Post-load-stage-1-configurations-to-th.patch +Patch0126: vfio-common-Fix-incorrect-address-alignment-in-vfio_.patch +Patch0127: vfio-common-Add-address-alignment-check-in-vfio_list.patch +Patch0128: log-Add-log-at-boot-cpu-init-for-aarch64.patch +Patch0129: feature-Add-log-for-each-modules.patch +Patch0130: feature-Add-logs-for-vm-start-and-destroy.patch +Patch0131: bugfix-fix-some-illegal-memory-access-and-memory-lea.patch +Patch0132: bugfix-fix-possible-memory-leak.patch +Patch0133: bugfix-fix-eventfds-may-double-free-when-vm_id-reuse.patch +Patch0134: block-mirror-fix-file-system-went-to-read-only-after.patch +Patch0135: bugfix-fix-mmio-information-leak-and-ehci-vm-escape-.patch +Patch0136: target-i386-Fix-the-RES-memory-inc-which-caused-by-t.patch +Patch0137: virtio-scsi-bugfix-fix-qemu-crash-for-hotplug-scsi-d.patch +Patch0138: virtio-net-tap-bugfix-del-net-client-if-net_init_tap.patch +Patch0139: virtio-bugfix-clean-up-callback-when-del-virtqueue.patch +Patch0140: virtio-net-bugfix-do-not-delete-netdev-before-virtio.patch +Patch0141: virtio-net-fix-max-vring-buf-size-when-set-ring-num.patch +Patch0142: virtio-check-descriptor-numbers.patch +Patch0143: virtio-bugfix-add-rcu_read_lock-when-vring_avail_idx.patch +Patch0144: virtio-print-the-guest-virtio_net-features-that-host.patch +Patch0145: virtio-bugfix-check-the-value-of-caches-before-acces.patch +Patch0146: virtio-net-set-the-max-of-queue-size-to-4096.patch +Patch0147: virtio-net-update-the-default-and-max-of-rx-tx_queue.patch +Patch0148: vhost-user-add-unregister_savevm-when-vhost-user-cle.patch +Patch0149: qemu-img-block-dont-blk_make_zero-if-discard_zeroes-.patch +Patch0150: vhost-user-Add-support-reconnect-vhost-user-socket.patch +Patch0151: vhost-user-Set-the-acked_features-to-vm-s-featrue.patch +Patch0152: vhost-user-add-vhost_set_mem_table-when-vm-load_setu.patch +Patch0153: vhost-user-add-separate-memslot-counter-for-vhost-us.patch +Patch0154: vhost-user-quit-infinite-loop-while-used-memslots-is.patch +Patch0155: qmp-add-command-to-query-used-memslots-of-vhost-net-.patch +Patch0156: vhost-user-scsi-add-support-for-SPDK-hot-upgrade.patch +Patch0157: i6300esb-watchdog-bugfix-Add-a-runstate-transition.patch +Patch0158: bugfix-irq-Avoid-covering-object-refcount-of-qemu_ir.patch +Patch0159: seabios-add-check-to-avoid-dereference-NULL-pointer.patch +Patch0160: qemu-img-add-qemu-img-direct-create.patch +Patch0161: log-Delete-redudant-qemu_log.patch +Patch0162: bios-tables-test-Update-expected-q35-SSDT.dimmpxm-fi.patch +Patch0163: qapi-machine.json-Fix-incorrect-description-for-die-.patch +Patch0164: tests-unit-test-smp-parse-Pass-machine-type-as-argum.patch +Patch0165: tests-unit-test-smp-parse-Split-the-generic-test-in-.patch +Patch0166: tests-unit-test-smp-parse-Add-smp-with-dies-machine-.patch +Patch0167: tests-unit-test-smp-parse-Add-smp-generic-invalid-ma.patch +Patch0168: tests-unit-test-smp-parse-Add-smp-generic-valid-mach.patch +Patch0169: tests-unit-test-smp-parse-Simplify-pointer-to-compou.patch +Patch0170: tests-unit-test-smp-parse-Constify-some-pointer-stru.patch +Patch0171: hw-core-Rename-smp_parse-machine_parse_smp_config.patch +Patch0172: qemu-options-Improve-readability-of-SMP-related-Docs.patch +Patch0173: hw-core-machine-Introduce-CPU-cluster-topology-suppo.patch +Patch0174: tests-unit-test-smp-parse-Add-testcases-for-CPU-clus.patch +Patch0175: tests-unit-test-smp-parse-No-need-to-explicitly-zero.patch +Patch0176: tests-unit-test-smp-parse-Keep-default-MIN-MAX-CPUs-.patch +Patch0177: hw-arm-virt-Support-CPU-cluster-on-ARM-virt-machine.patch +Patch0178: hw-arm-virt-Support-cluster-level-in-DT-cpu-map.patch +Patch0179: hw-acpi-aml-build-Improve-scalability-of-PPTT-genera.patch +Patch0180: tests-acpi-bios-tables-test-Allow-changes-to-virt-PP.patch +Patch0181: hw-acpi-aml-build-Support-cluster-level-in-PPTT-gene.patch +Patch0182: tests-acpi-bios-table-test-Update-expected-virt-PPTT.patch +Patch0183: softmmu-device_tree-Silence-compiler-warning-with-en.patch +Patch0184: softmmu-device_tree-Remove-redundant-pointer-assignm.patch +Patch0185: hw-arm64-add-vcpu-cache-info-support.patch +Patch0186: arm64-Add-the-cpufreq-device-to-show-cpufreq-info-to.patch +Patch0187: Revert-qmp-add-command-to-query-used-memslots-of-vho.patch +Patch0188: target-arm-Fix-some-compile-errors.patch +Patch0189: pl031-support-rtc-timer-property-for-pl031.patch +Patch0190: i386-cpu-fix-compile-error-in-all-target-configure.patch +Patch0191: acpi-madt-Factor-out-the-building-of-MADT-GICC-struc.patch +Patch0192: hw-arm-virt-Assign-virt_madt_cpu_entry-to-acpi_ged-m.patch +Patch0193: arm-virt-acpi-Factor-out-CPPC-building-from-DSDT-CPU.patch +Patch0194: acpi-cpu-Prepare-build_cpus_aml-for-arm-virt.patch +Patch0195: acpi-ged-Extend-ACPI-GED-to-support-CPU-hotplug.patch +Patch0196: arm-cpu-assign-arm_get_arch_id-handler-to-get_arch_i.patch +Patch0197: tests-acpi-bios-tables-test-Allow-changes-to-virt-DS.patch +Patch0198: arm-virt-Attach-ACPI-CPU-hotplug-support-to-virt.patch +Patch0199: tests-acpi-bios-table-test-Update-expected-virt-DSDT.patch +Patch0200: arm-virt-Add-CPU-hotplug-framework.patch +Patch0201: arm-virt-Add-CPU-topology-support.patch +Patch0202: test-numa-Adjust-aarch64-numa-test.patch +Patch0203: hw-arm-virt-Factor-out-some-CPU-init-codes-to-pre_pl.patch +Patch0204: hw-arm-boot-Add-manually-register-and-trigger-of-CPU.patch +Patch0205: arm-virt-gic-Construct-irqs-connection-from-create_g.patch +Patch0206: intc-gicv3_common-Factor-out-arm_gicv3_common_cpu_re.patch +Patch0207: intc-gicv3_cpuif-Factor-out-gicv3_init_one_cpuif.patch +Patch0208: intc-kvm_gicv3-Factor-out-kvm_arm_gicv3_cpu_realize.patch +Patch0209: hw-intc-gicv3-Add-CPU-hotplug-realize-hook.patch +Patch0210: accel-kvm-Add-pre-park-vCPU-support.patch +Patch0211: intc-gicv3-Add-pre-sizing-capability-to-GICv3.patch +Patch0212: acpi-madt-Add-pre-sizing-capability-to-MADT-GICC-str.patch +Patch0213: arm-virt-Add-cpu_hotplug_enabled-field.patch +Patch0214: arm-virt-acpi-Extend-cpufreq-to-support-max_cpus.patch +Patch0215: arm-virt-Pre-sizing-MADT-GICC-GICv3-and-Pre-park-KVM.patch +Patch0216: arm-virt-Start-up-CPU-hot-plug-and-cold-plug.patch +Patch0217: pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch +Patch0218: qcow2-fix-memory-leak-in-qcow2_read_extensions.patch +Patch0219: scsi-disk-define-props-in-scsi_block_disk-to-avoid-m.patch +Patch0220: pcie-Add-pcie-root-port-fast-plug-unplug-feature.patch +Patch0221: pcie-Compat-with-devices-which-do-not-support-Link-W.patch +Patch0222: scsi-bus-fix-unmatched-object_unref.patch +Patch0223: tools-virtiofsd-Add-rseq-syscall-to-the-seccomp-allo.patch +Patch0224: sw_64-Add-sw64-architecture-support.patch +Patch0225: coro-support-live-patch-for-libcare.patch BuildRequires: flex BuildRequires: gcc @@ -580,9 +246,10 @@ BuildRequires: kernel BuildRequires: chrpath BuildRequires: gettext BuildRequires: python-sphinx +BuildRequires: ninja-build BuildRequires: zlib-devel -BuildRequires: zstd-devel >= 1.4.5 +BuildRequires: zstd-devel BuildRequires: gtk3-devel BuildRequires: gnutls-devel BuildRequires: numactl-devel @@ -603,7 +270,6 @@ BuildRequires: libattr-devel BuildRequires: libcurl-devel BuildRequires: libjpeg-devel BuildRequires: libpng-devel -BuildRequires: brlapi-devel BuildRequires: pixman-devel BuildRequires: libusbx-devel BuildRequires: bzip2-devel @@ -618,14 +284,11 @@ BuildRequires: librbd-devel BuildRequires: krb5-devel BuildRequires: libssh-devel BuildRequires: glib2 -BuildRequires: spice-server-devel >= 0.12.5 -BuildRequires: spice-protocol >= 0.12.3 %ifarch aarch64 BuildRequires: libfdt-devel BuildRequires: virglrenderer-devel %endif -Requires: zstd >= 1.4.5 Requires(post): /usr/bin/getent Requires(post): /usr/sbin/groupadd Requires(post): /usr/sbin/useradd @@ -711,14 +374,21 @@ buildarch="aarch64-softmmu" %endif buildldflags="VL_LDFLAGS=-Wl,--build-id" +qemubuilddir="build" + +tar xf %{SOURCE4} +cd BinDir/ +\cp -r -a * ../ +cd ../ + ./configure \ --prefix=%{_prefix} \ --target-list=${buildarch} \ - --extra-cflags="%{optflags} -fPIE -DPIE -fPIC" \ - --extra-ldflags="-Wl,--build-id -pie -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack" \ + --extra-cflags="%{optflags} -fPIE -DPIE -fPIC -ftls-model=initial-exec" \ + --extra-ldflags="-Wl,--build-id -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack" \ --datadir=%{_datadir} \ - --docdir=%{_docdir}/%{name} \ + --docdir=%{_docdir}/ \ --libdir=%{_libdir} \ --libexecdir=%{_libexecdir} \ --localstatedir=%{_localstatedir} \ @@ -745,28 +415,28 @@ buildldflags="VL_LDFLAGS=-Wl,--build-id" --enable-tpm \ --enable-modules \ --enable-libssh \ - --enable-spice \ %ifarch aarch64 --enable-fdt \ --enable-virglrenderer \ %endif --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 \ - --enable-zstd + --enable-zstd \ + --disable-brlapi \ + --disable-plugins \ + --enable-debug make %{?_smp_mflags} $buildldflags V=1 -cp -a ${buildarch}/qemu-system-* qemu-kvm +cp ${qemubuilddir}/${buildarch}/qemu-system-* qemu-kvm %install @@ -794,7 +464,11 @@ touch %{buildroot}%{_localstatedir}/log/qga-fsfreeze-hook.log # For qemu docs package %global qemudocdir %{_docdir}/%{name} rm -rf %{buildroot}%{qemudocdir}/specs -install -D -p -m 0644 -t %{buildroot}%{qemudocdir} Changelog README COPYING COPYING.LIB LICENSE +rm -rf %{buildroot}%{qemudocdir}/.buildinfo +rm -rf %{buildroot}%{qemudocdir}/objects.inv +rm -rf %{buildroot}%{qemudocdir}/genindex.html +rm -rf %{buildroot}%{qemudocdir}/index.html +install -D -p -m 0644 -t %{buildroot}%{qemudocdir} README.rst COPYING COPYING.LIB LICENSE chmod -x %{buildroot}%{_mandir}/man1/* @@ -811,6 +485,9 @@ rm -rf %{buildroot}%{_datadir}/%{name}/pvh.bin %ifarch x86_64 rm -rf %{buildroot}%{_datadir}/%{name}/vgabios-ati.bin %endif +rm -rf %{buildroot}%{_datadir}/%{name}/bios-microvm.bin +rm -rf %{buildroot}%{_datadir}/%{name}/multiboot_dma.bin +rm -rf %{buildroot}%{_datadir}/%{name}/npcm7xx_bootrom.bin rm -rf %{buildroot}%{_datadir}/%{name}/openbios-* rm -rf %{buildroot}%{_datadir}/%{name}/slof.bin rm -rf %{buildroot}%{_datadir}/%{name}/QEMU,*.bin @@ -836,8 +513,20 @@ rm -rf %{buildroot}%{_libdir}/%{name}/block-gluster.so rm -rf %{buildroot}%{_libdir}/%{name}/ui-curses.so rm -rf %{buildroot}%{_libdir}/%{name}/ui-gtk.so rm -rf %{buildroot}%{_libdir}/%{name}/ui-sdl.so +rm -rf %{buildroot}%{_libdir}/%{name}/audio-spice.so +rm -rf %{buildroot}%{_libdir}/%{name}/chardev-baum.so +rm -rf %{buildroot}%{_libdir}/%{name}/chardev-spice.so +rm -rf %{buildroot}%{_libdir}/%{name}/hw-display-qxl.so +rm -rf %{buildroot}%{_libdir}/%{name}/hw-s390x-virtio-gpu-ccw.so +rm -rf %{buildroot}%{_libdir}/%{name}/hw-usb-host.so +rm -rf %{buildroot}%{_libdir}/%{name}/hw-usb-redirect.so +rm -rf %{buildroot}%{_libdir}/%{name}/ui-opengl.so +rm -rf %{buildroot}%{_libdir}/%{name}/ui-spice-app.so +rm -rf %{buildroot}%{_libdir}/%{name}/ui-spice-core.so + rm -rf %{buildroot}%{_libexecdir}/vhost-user-gpu rm -rf %{buildroot}%{_datadir}/%{name}/vhost-user/50-qemu-gpu.json +rm -rf %{buildroot}%{_datadir}/%{name}/vhost-user/50-qemu-virtiofsd.json strip %{buildroot}%{_libdir}/%{name}/block-rbd.so strip %{buildroot}%{_libdir}/%{name}/block-iscsi.so @@ -850,6 +539,8 @@ for f in %{buildroot}%{_bindir}/* %{buildroot}%{_libdir}/* \ done %check +echo "#define CONFIG_DISABLE_QEMU_LOG" >> build/config-host.h +make %{?_smp_mflags} $buildldflags V=1 make check V=1 %pre @@ -870,6 +561,16 @@ getent passwd qemu >/dev/null || \ %dir %{_datadir}/%{name}/ %{_libexecdir}/qemu-kvm %{_bindir}/qemu-kvm +%{_libdir}/%{name}/accel-qtest-*.so +%ifarch x86_64 +%{_libdir}/%{name}/accel-tcg-*.so +%{_libdir}/%{name}/hw-display-virtio-vga-gl.so +%{_libdir}/%{name}/hw-display-virtio-vga.so +%endif +%{_libdir}/%{name}/hw-display-virtio-gpu-gl.so +%{_libdir}/%{name}/hw-display-virtio-gpu-pci-gl.so +%{_libdir}/%{name}/hw-display-virtio-gpu-pci.so +%{_libdir}/%{name}/hw-display-virtio-gpu.so %{_datadir}/%{name}/efi-virtio.rom %{_datadir}/%{name}/efi-e1000.rom %{_datadir}/%{name}/efi-e1000e.rom @@ -884,6 +585,7 @@ getent passwd qemu >/dev/null || \ %{_datadir}/%{name}/pxe-pcnet.rom %{_datadir}/%{name}/pxe-rtl8139.rom %{_datadir}/%{name}/pxe-eepro100.rom +%{_datadir}/%{name}/qboot.rom %{_datadir}/%{name}/trace-events-all %{_datadir}/applications/qemu.desktop %{_datadir}/icons/hicolor/*/apps/* @@ -892,7 +594,8 @@ getent passwd qemu >/dev/null || \ %{_bindir}/qemu-edid %{_bindir}/qemu-keymap %{_bindir}/qemu-pr-helper -%{_bindir}/virtfs-proxy-helper +%{_libexecdir}/virtfs-proxy-helper +%{_libexecdir}/virtiofsd %{_unitdir}/qemu-pr-helper.service %{_unitdir}/qemu-pr-helper.socket %attr(4755, root, root) %{_libexecdir}/qemu-bridge-helper @@ -921,26 +624,35 @@ getent passwd qemu >/dev/null || \ %{_datadir}/%{name}/kvmvapic.bin %{_datadir}/%{name}/sgabios.bin %endif +%exclude %{_datadir}/%{name}/core3-hmcode +%exclude %{_datadir}/%{name}/core3-reset +%exclude %{_datadir}/%{name}/uefi-bios-sw %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}/about +%doc %{qemudocdir}/devel %doc %{qemudocdir}/interop -%doc %{qemudocdir}/README -%doc %{qemudocdir}/Changelog +%doc %{qemudocdir}/search* +%doc %{qemudocdir}/_static +%doc %{qemudocdir}/system +%doc %{qemudocdir}/tools +%doc %{qemudocdir}/user +%doc %{qemudocdir}/README.rst %{_mandir}/man1/qemu.1* +%{_mandir}/man1/qemu-img.1* +%{_mandir}/man1/qemu-storage-daemon.1* %{_mandir}/man1/virtfs-proxy-helper.1* +%{_mandir}/man1/virtiofsd.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}/man7/qemu-storage-daemon-qmp-ref.7* +%{_mandir}/man8/qemu-ga.8* %{_mandir}/man8/qemu-nbd.8* +%{_mandir}/man8/qemu-pr-helper.8* + %files guest-agent %defattr(-,root,root,-) @@ -954,6 +666,7 @@ getent passwd qemu >/dev/null || \ %{_bindir}/qemu-img %{_bindir}/qemu-io %{_bindir}/qemu-nbd +%{_bindir}/qemu-storage-daemon %files block-rbd %{_libdir}/%{name}/block-rbd.so @@ -974,54 +687,161 @@ getent passwd qemu >/dev/null || \ %endif %changelog -* Tue Dec 21 2021 Chen Qun -- add Phytium's CPU models: FT-2000+ and Tengyun-S2500. - -* Tue Dec 21 2021 Chen Qun -- virtio-balloon: apply upstream patch. - -* Tue Dec 21 2021 Chen Qun -- fix cve-2020-35504 -- fix cve-2020-35505 - -* Tue Oct 26 2021 imxcc -- fix cve-2021-3592 cve-2021-3593 cve-2021-3595 - -* Sun Sep 26 2021 Chen Qun -- virtio-net: fix use after unmap/free for sg - -* Thu Sep 16 2021 Chen Qun -- uas: add stream number sanity checks. - -* Tue Sep 14 2021 Chen Qun -- vfio/common: Add address alignment check in vfio_listener_region_del - -* Wed Sep 08 2021 Chen Qun -- vfio/common: Fix incorrect address alignment in vfio_dma_map_ram_section - -* Mon Aug 30 2021 Zhongrui Tang -- qemu.spec: Specify the package version of zstd and zstd-devel that qemu depends on. - -* Thu Aug 19 2021 Jiajie Li -- add qemu-block-curl package -- add qemu-block-curl requirement for qemu. - -* Mon Aug 16 2021 Chen Qun -- usbredir: fix free call +* Fri Mar 18 2022 yezengruan +- coro: support live patch for libcare +- add patch for sw64 support + +* Tue Mar 15 2022 jiangdawei +- cflags: add ftls-mode=initial-exec + +* Tue Mar 15 2022 yezengruan +- sw_64: Add sw64 architecture support +- update BinDir + +* Mon Mar 14 2022 jiangdawei +- qemu.spec: Add --enable-debug parameter to configure + +* Thu Mar 03 2022 Chen Qun +- tools/virtiofsd: Add rseq syscall to the seccomp allowlist + +* Thu Mar 03 2022 Chen Qun +- scsi-bus: fix unmatched object_unref() + +* Sat Feb 26 2022 Yan Wang +- pl011-reset-read-FIFO-when-UARTTIMSC-0-UARTICR-0xfff.patch +- qcow2-fix-memory-leak-in-qcow2_read_extensions.patch +- scsi-disk-define-props-in-scsi_block_disk-to-avoid-m.patch +- pcie-Add-pcie-root-port-fast-plug-unplug-feature.patch +- pcie-Compat-with-devices-which-do-not-support-Link-W.patch + +* Wed Feb 23 2022 Chen Qun +- acpi/madt: Factor out the building of MADT GICC struct +- hw/arm/virt: Assign virt_madt_cpu_entry to acpi_ged madt_cpu hook +- arm/virt/acpi: Factor out CPPC building from DSDT CPU aml +- acpi/cpu: Prepare build_cpus_aml for arm virt +- acpi/ged: Extend ACPI GED to support CPU hotplug +- arm/cpu: assign arm_get_arch_id handler to get_arch_id hook +- tests/acpi/bios-tables-test: Allow changes to virt/DSDT file +- arm/virt: Attach ACPI CPU hotplug support to virt +- tests/acpi/bios-table-test: Update expected virt/DSDT file +- arm/virt: Add CPU hotplug framework +- arm/virt: Add CPU topology support +- test/numa: Adjust aarch64 numa test +- hw/arm/virt: Factor out some CPU init codes to pre_plug hook +- hw/arm/boot: Add manually register and trigger of CPU reset +- arm/virt/gic: Construct irqs connection from create_gic +- intc/gicv3_common: Factor out arm_gicv3_common_cpu_realize +- intc/gicv3_cpuif: Factor out gicv3_init_one_cpuif +- intc/kvm_gicv3: Factor out kvm_arm_gicv3_cpu_realize +- hw/intc/gicv3: Add CPU hotplug realize hook +- accel/kvm: Add pre-park vCPU support +- intc/gicv3: Add pre-sizing capability to GICv3 +- acpi/madt: Add pre-sizing capability to MADT GICC struct +- arm/virt: Add cpu_hotplug_enabled field +- arm/virt/acpi: Extend cpufreq to support max_cpus +- arm/virt: Pre-sizing MADT-GICC GICv3 and Pre-park KVM vCPU +- arm/virt: Start up CPU hot-plug and cold-plug + +* Mon Feb 21 2022 Chen Qun +- i386/cpu: fix compile error in all target configure + +* Mon Feb 21 2022 Chen Qun +- pl031: support rtc-timer property for pl031 -* Wed Aug 04 2021 Chen Qun -- vfio: Support host translation granule size -- vfio/migrate: Move switch of dirty tracking into vfio_memory_listener -- vfio: Fix unregister SaveVMHandler in vfio_migration_finalize -- migration/ram: Reduce unnecessary rate limiting -- migration/ram: Optimize ram_save_host_page() -- qdev/monitors: Fix reundant error_setg of qdev_add_device +* Mon Feb 21 2022 Chen Qun +- target/arm: Fix some compile errors + +* Mon Feb 21 2022 Chen Qun +- Revert "qmp: add command to query used memslots of vhost-net and vhost-user" + +* Thu Feb 17 2022 imxcc +- qapi/machine.json: Fix incorrect description for die-id +- tests/unit/test-smp-parse: Pass machine type as +- tests/unit/test-smp-parse: Split the 'generic' test in +- tests/unit/test-smp-parse: Add 'smp-with-dies' machine +- tests/unit/test-smp-parse: Add 'smp-generic-invalid' +- tests/unit/test-smp-parse: Add 'smp-generic-valid' +- tests/unit/test-smp-parse: Simplify pointer to compound +- tests/unit/test-smp-parse: Constify some pointer/struct +- hw/core: Rename smp_parse() -> +- qemu-options: Improve readability of SMP related Docs +- hw/core/machine: Introduce CPU cluster topology support +- tests/unit/test-smp-parse: Add testcases for CPU +- tests/unit/test-smp-parse: No need to explicitly zero +- tests/unit/test-smp-parse: Keep default MIN/MAX CPUs in +- hw/arm/virt: Support CPU cluster on ARM virt machine +- hw/arm/virt: Support cluster level in DT cpu-map +- hw/acpi/aml-build: Improve scalability of PPTT +- tests/acpi/bios-tables-test: Allow changes to virt/PPTT +- hw/acpi/aml-build: Support cluster level in PPTT +- tests/acpi/bios-table-test: Update expected virt/PPTT +- update BinDir +- softmmu/device_tree: Silence compiler warning with +- softmmu/device_tree: Remove redundant pointer +- hw/arm64: add vcpu cache info support +- update BinDir +- arm64: Add the cpufreq device to show cpufreq info to +- update BinDir + +* Thu Feb 17 2022 imxcc +- bios-tables-test: Update expected q35/SSDT.dimmpxm file +- spec: add BinDir + +* Tue Feb 15 2022 Liuxiangdong +- feature: disable spice protocol + +* Mon Feb 14 2022 Chen Qun +- log: Delete redudant qemu_log + +* Mon Feb 14 2022 Chen Qun +- qemu-img: add qemu-img direct create + +* Mon Feb 14 2022 eillon +- seabios: add check to avoid dereference NULL pointer + +* Sat Feb 12 2022 Chen Qun +- bugfix: irq: Avoid covering object refcount of qemu_irq + +* Sat Feb 12 2022 Chen Qun +- virtio-scsi: bugfix: fix qemu crash for hotplug scsi disk with dataplane +- virtio: net-tap: bugfix: del net client if net_init_tap_one failed +- virtio: bugfix: clean up callback when del virtqueue +- virtio-net: bugfix: do not delete netdev before virtio net +- virtio-net: fix max vring buf size when set ring num +- virtio: check descriptor numbers +- virtio: bugfix: add rcu_read_lock when vring_avail_idx is called +- virtio: print the guest virtio_net features that host does not support +- virtio: bugfix: check the value of caches before accessing it +- virtio-net: set the max of queue size to 4096 +- virtio-net: update the default and max of rx/tx_queue_size +- vhost-user: add unregister_savevm when vhost-user cleanup +- qemu-img: block: dont blk_make_zero if discard_zeroes false +- vhost-user: Add support reconnect vhost-user socket +- vhost-user: Set the acked_features to vm's featrue +- vhost-user: add vhost_set_mem_table when vm load_setup at destination +- vhost-user: add separate memslot counter for vhost-user +- vhost-user: quit infinite loop while used memslots is more than the backend limit +- qmp: add command to query used memslots of vhost-net and vhost-user +- vhost-user-scsi: add support for SPDK hot upgrade +- i6300esb watchdog: bugfix: Add a runstate transition + +* Sat Feb 12 2022 Chen Qun +- bugfix: fix some illegal memory access and memory leak +- bugfix: fix possible memory leak +- bugfix: fix eventfds may double free when vm_id reused in ivshmem +- block/mirror: fix file-system went to read-only after block-mirror +- bugfix: fix mmio information leak and ehci vm escape 0-day vulnerability +- target-i386: Fix the RES memory inc which caused by the coroutine created + +* Sat Feb 12 2022 Chen Qun +- log: Add log at boot & cpu init for aarch64 +- feature: Add log for each modules +- feature: Add logs for vm start and destroy + +* Sat Feb 12 2022 Chen Qun - linux-headers: update against 5.10 and manual clear vfio dirty log series - vfio: Maintain DMA mapping range for the container - vfio/migration: Add support for manual clear vfio dirty log -- hw/arm/smmuv3: Support 16K translation granule -- hw/arm/smmuv3: Set the restoration priority of the vSMMUv3 explicitly -- hw/vfio/common: trace vfio_connect_container operations - update-linux-headers: Import iommu.h - vfio.h and iommu.h header update against 5.10 - memory: Add new fields in IOTLBEntry @@ -1056,609 +876,139 @@ getent passwd qemu >/dev/null || \ - vfio: Add vfio_prereg_listener_log_clear to re-enable mark dirty pages - vfio: Add vfio_prereg_listener_global_log_start/stop in nested stage - hw/arm/smmuv3: Post-load stage 1 configurations to the host +- vfio/common: Fix incorrect address alignment in vfio_dma_map_ram_section +- vfio/common: Add address alignment check in vfio_listener_region_del -* Tue Aug 03 2021 Chen Qun -- kvm: split too big memory section on several memslots -- kvm: Reallocate dirty_bmap when we change a slot -- accel: kvm: Fix memory waste under mismatch page size -- memory: Skip dirty tracking for un-migratable memory regions -- Fix use after free in vfio_migration_probe -- vfio: Make migration support experimental -- vfio: Change default dirty pages tracking behavior during migration -- vfio: Fix vfio_listener_log_sync function name typo - -* Thu Jul 29 2021 Chen Qun -- vfio: Move the saving of the config space to the right place in VFIO migration -- vfio: Set the priority of the VFIO VM state change handler explicitly -- vfio: Avoid disabling and enabling vectors repeatedly in VFIO migration - -* Thu Jul 29 2021 imxcc -- hw/net: fix vmxnet3 live migration -- include: Make headers more self-contained -- migration: register_savevm_live doesn't need dev -- vmstate: add qom interface to get id -- linux headers: Update against "Add migration support for VFIO devices" -- vfio: Add function to unmap VFIO region -- vfio: Add vfio_get_object callback to VFIODeviceOps -- vfio: Add save and load functions for VFIO PCI devices -- vfio: Add migration region initialization and finalize function -- vfio: Add VM state change handler to know state of VM -- vfio: Add migration state change notifier -- vfio: Register SaveVMHandlers for VFIO device -- vfio: Add save state functions to SaveVMHandlers -- vfio: Add load state functions to SaveVMHandlers -- memory: Set DIRTY_MEMORY_MIGRATION when IOMMU is enabled -- vfio: Get migration capability flags for container -- vfio: Add function to start and stop dirty pages tracking -- vfio: Add vfio_listener_log_sync to mark dirty pages -- vfio: Dirty page tracking when vIOMMU is enabled -- vfio: Add ioctl to get dirty pages bitmap during dma unmap -- vfio: Make vfio-pci device migration capable -- qapi: Add VFIO devices migration stats in Migration stats - -* Wed Jul 28 2021 imxcc -- object: return self in object_ref() -- file-posix: Fix leaked fd in raw_open_common() error path -- qga/commands-posix: fix use after free of local_err -- qmp: fix leak on callbacks that return both value and error -- migration: fix cleanup_bh leak on resume -- Fixed integer overflow in e1000e -- lm32-do-not-leak-memory-on-object_new-object_unref.patch -- cris-do-not-leak-struct-cris_disasm_data.patch -- hppa-fix-leak-from-g_strdup_printf.patch -- mcf5208-fix-leak-from-qemu_allocate_irqs.patch -- microblaze-fix-leak-of-fdevice-tree-blob.patch -- ide-fix-leak-from-qemu_allocate_irqs.patch -- make-check-unit-use-after-free-in-test-opts-visitor.patch -- virtio-pci: fix queue_enable write -- hw/block/nvme: fix pci doorbell size calculation -- hw/block/nvme: fix pin-based interrupt behavior -- colo-compare: Fix memory leak in packet_enqueue() -- chardev/tcp: Fix error message double free error -- qga: Plug unlikely memory leak in guest-set-memory-blocks -- migration: Count new_dirty instead of real_dirty -- char: fix use-after-free with dup chardev & reconnect -- qga: fix assert regression on guest-shutdown -- xhci: fix valid.max_access_size to access address registers -- block/qcow2: do free crypto_opts in qcow2_close() -- qemu-img: free memory before re-assign -- block/qcow2-threads: fix qcow2_decompress -- block: Avoid memleak on qcow2 image info failure -- block: bdrv_set_backing_bs: fix use-after-free -- hmp/vnc: Fix info vnc list leak -- migration/colo: fix use after free of local_err -- migration/ram: fix use after free of local_err -- block/mirror: fix use after free of local_err -- block: fix bdrv_root_attach_child forget to unref child_bs -- virtio-serial-bus: Plug memory leak on realize() error paths -- virtio-blk: delete vqs on the error path in realize() -- fix vhost_user_blk_watch crash -- vhost-user-blk: delay vhost_user_blk_disconnect -- hw-pci-pci_bridge-Correct-pci_bridge_io-memory-regio.patch -- linux-user-mmap.c-fix-integer-underflow-in-target_mr.patch -- migration-rdma-cleanup-rdma-context-before-g_free-to.patch -- pc-bios-s390-ccw-net-fix-a-possible-memory-leak-in-g.patch -- usbredir-fix-buffer-overflow-on-vmload.patch -- apic: Use 32bit APIC ID for migration instance-ID -- audio: fix integer overflow -- display/bochs-display: fix memory leak -- migration: Change SaveStateEntry.instance_id into uint32_t -- migration: Define VMSTATE_INSTANCE_ID_ANY -- migration/multifd: clean pages after filling packet -- migration/multifd: not use multifd during postcopy -- virtio: add ability to delete vq through a pointer -- virtio-pmem: do delete rq_vq in virtio_pmem_unrealize -- virtio-crypto: do delete ctrl_vq in virtio_crypto_device_unrealize -- vhost-user-blk: delete virtioqueues in unrealize to fix memleaks -- vhost-user-blk: convert to new virtio_delete_queue -- block/nbd: extract the common cleanup code -- virtio: gracefully handle invalid region caches -- migration/savevm: release gslist after dump_vmstate_json -- virtio-input: fix memory leak on unrealize +* Sat Feb 12 2022 Chen Qun +- log: Add some logs on VM runtime path +- qdev/monitors: Fix reundant error_setg of qdev_add_device +- bios-tables-test: Allow changes to q35/SSDT.dimmpxm file +- smbios: Add missing member of type 4 for smbios 3.0 +- net: eepro100: validate various address valuesi(CVE-2021-20255) +- pci: check bus pointer before dereference +- ide: ahci: add check to avoid null dereference (CVE-2019-12067) +- tap: return err when tap TUNGETIFF fail +- xhci: check reg to avoid OOB read +- monitor: Discard BLOCK_IO_ERROR event when VM rebooted +- monitor: limit io error qmp event to at most once per 60s + +* Sat Feb 12 2022 Chen Qun +- util/log: add CONFIG_DISABLE_QEMU_LOG macro + +* Sat Feb 12 2022 Yan Wang +- ipxe: IPv6 add support for IPv6 protocol +- u-boot: Use post increment only in inffast.c + +* Sat Feb 12 2022 jiangdongxu +- seabios: convert value of be16_to_cpu to u64 before shifting +- seabios: do not give back high ram +- seabios: fix memory leak when pci check +- seabios: drop yield() in smp_setup() +- seabios: increase the seabios minibiostable +- seabios: increase the seabios high mem zone size + +* Fri Feb 11 2022 Chen Qun +- hw/net/rocker: fix security vulnerability +- tests: Disable filemonitor testcase + +* Fri Feb 11 2022 Chen Qun +- hw/usb: reduce the vpcu cost of UHCI when VNC disconnect + +* Fri Feb 11 2022 Chen Qun +- freeclock: add qmp command to get time offset of vm in seconds +- freeclock: set rtc_date_diff for arm +- freeclock: set rtc_date_diff for X86 + +* Fri Feb 11 2022 Chen Qun +- target/arm: convert isar regs to array +- target/arm: parse cpu feature related options +- target/arm: register CPU features for property +- target/arm: Allow ID registers to synchronize to KVM +- target/arm: introduce CPU feature dependency mechanism +- target/arm: introduce KVM_CAP_ARM_CPU_FEATURE +- target/arm: Add CPU features to query-cpu-model-expansion +- target/arm: Add more CPU features +- target/arm: ignore evtstrm and cpuid CPU features - target/arm: only set ID_PFR1_EL1.GIC for AArch32 guest +- target/arm: Fix write redundant values to kvm - target/arm: clear EL2 and EL3 only when kvm is not enabled - target/arm: Update the ID registers of Kunpeng-920 -* Fri Jul 23 2021 imxcc -- hw/arm/virt: Init PMU for hotplugged vCPU - -* Fri Jul 23 2021 Chen Qun -- vl: Don't mismatch g_strsplit()/g_free() -- seqlock: fix seqlock_write_unlock_impl function -- target/i386: kvm: initialize microcode revision from KVM -- target/i386: check for availability of MSR_IA32_UCODE_REV as an emulated MSR - -* Thu Jul 22 2021 Chen Qun -- qapi/block-core: Introduce BackupCommon -- drive-backup: create do_backup_common -- blockdev-backup: utilize do_backup_common -- qapi: add BitmapSyncMode enum -- block/backup: Add mirror sync mode 'bitmap' -- block/backup: add 'never' policy to bitmap sync mode -- block/backup: loosen restriction on readonly bitmaps -- block/backup: hoist bitmap check into QMP interface -- block/backup: deal with zero detection -- mirror: Fix bdrv_has_zero_init() use -- blockdev: fix coding style issues in drive_backup_prepare -- blockdev: unify qmp_drive_backup and drive-backup transaction paths -- blockdev: unify qmp_blockdev_backup and blockdev-backup transaction paths -- blockdev: honor bdrv_try_set_aio_context() context requirements -- blockdev: Return bs to the proper context on snapshot abort -- block: Fix cross-AioContext blockdev-snapshot - -* Thu Jul 22 2021 Chen Qun -- hw/pci/pcie: Move hot plug capability check to pre_plug callback - -* Thu Jul 22 2021 Chen Qun -- migration: use migration_is_active to represent active state -- migration: Rate limit inside host pages - -* Thu Jul 22 2021 Chen Qun -- virtio-net: delete also control queue when TX/RX deleted -- target/i386: enable monitor and ucode revision with -cpu max -- target/i386: set the CPUID level to 0x14 on old machine-type -- target/i386: kvm: initialize feature MSRs very early -- target/i386: add a ucode-rev property - -* Thu Jul 22 2021 Chen Qun -- qcow2: Fix qcow2_alloc_cluster_abort() for external data file -- mirror: Wait only for in-flight operations - -* Wed Jul 21 2021 Chen Qun -- block/curl: HTTP header fields allow whitespace around values -- block/curl: HTTP header field names are case insensitive -- backup: Improve error for bdrv_getlength() failure -- mirror: Make sure that source and target size match -- iotests/143: Create socket in $SOCK_DIR -- nbd/server: Avoid long error message assertions CVE-2020-10761 -- block: Call attention to truncation of long NBD exports -- qemu-img convert: Don't pre-zero images - -* Wed Jul 21 2021 Chen Qun -- virtio: don't enable notifications during polling -- usbredir: Prevent recursion in usbredir_write -- xhci: recheck slot status -- vhost: Add names to section rounded warning -- vhost-user: Print unexpected slave message types -- contrib/libvhost-user: Protect slave fd with mutex -- libvhost-user: Fix some memtable remap cases -- xics: Don't deassert outputs -- i386: Resolve CPU models to v1 by default - -* Wed Jul 21 2021 imxcc -- target/i386: handle filtered_features in a new function mark_unavailable_features -- target/i386: introduce generic feature dependency mechanism -- target/i386: expand feature words to 64 bits -- target/i386: add VMX definitions -- vmxcap: correct the name of the variables -- target/i386: add VMX features -- target/i386: work around KVM_GET_MSRS bug for secondary execution controls -- target/i386: add VMX features to named CPU models -- target/i386: add two missing VMX features for Skylake and CascadeLake Server -- target/i386: disable VMX features if nested=0 -- i386/cpu: Don't add unavailable_features to env->user_features -- target/i386: do not set unsupported VMX secondary execution controls -- migration: fix multifd_send_pages() next channel -- migration: Make sure that we don't call write() in case of error - -* Tue Jul 20 2021 Chen Qun -- crypto: add support for nettle's native XTS impl -- crypto: add support for gcrypt's native XTS impl -- tests: benchmark crypto with fixed data size, not time period -- tests: allow filtering crypto cipher benchmark tests - -* Tue Jul 20 2021 Chen Qun -- target/i386: Introduce Denverton CPU model -- target/i386: Add Snowridge-v2 (no MPX) CPU model -- i386: Add CPUID bit for CLZERO and XSAVEERPTR - -* Mon Jul 19 2021 Chen Qun -- x86: Intel AVX512_BF16 feature enabling -- i386: Add MSR feature bit for MDS-NO -- i386: Add macro for stibp -- i386: Add new CPU model Cooperlake -- target/i386: Add new bit definitions of MSR_IA32_ARCH_CAPABILITIES -- target/i386: Add missed security features to Cooperlake CPU model -- target/i386: add PSCHANGE_NO bit for the ARCH_CAPABILITIES MSR -- target/i386: Export TAA_NO bit to guests - -* Mon Jul 19 2021 Chen Qun -- hw/net/rocker_of_dpa: fix double free bug of rocker device - -* Mon Jun 28 2021 imxcc -- spec: add gcc buildrequire - -* Mon Jun 21 2021 Chen Qun -- ide: ahci: add check to avoid null dereference (CVE-2019-12067) -- hw/intc/arm_gic: Fix interrupt ID in GICD_SGIR register -- usb: limit combined packets to 1 MiB (CVE-2021-3527) - -* Tue Jun 15 2021 Chen Qun -- vhost-user-gpu: fix resource leak in 'vg_resource_create_2d' (CVE-2021-3544) -- vhost-user-gpu: fix memory leak in vg_resource_attach_backing (CVE-2021-3544) -- vhost-user-gpu: fix memory leak while calling 'vg_resource_unref' (CVE-2021-3544) -- vhost-user-gpu: fix memory leak in 'virgl_cmd_resource_unref' (CVE-2021-3544) -- vhost-user-gpu: fix memory leak in 'virgl_resource_attach_backing' (CVE-2021-3544) -- vhost-user-gpu: fix memory disclosure in virgl_cmd_get_capset_info (CVE-2021-3545) -- vhost-user-gpu: fix OOB write in 'virgl_cmd_get_capset' (CVE-2021-3546) - -* Fri May 28 2021 Chen Qun -- blockjob: Fix crash with IOthread when block commit after snapshot - -* Thu May 20 2021 zhouli57 -- arm/cpu: Fixed function undefined error at compile time under arm - -* Wed May 19 2021 Ming Yang -- add strip for block-iscsi.so, block-rbd.so and block-ssh.so. - -* Wed May 19 2021 zhouli57 -- util/cacheinfo: fix crash when compiling with uClibc - -* Fri Mar 26 2021 Chen Qun -- hw/pci-host: add pci-intack write method -- pci-host: add pcie-msi read method -- vfio: add quirk device write method -- prep: add ppc-parity write method -- nvram: add nrf51_soc flash read method -- spapr_pci: add spapr msi read method -- tz-ppc: add dummy read/write methods -- imx7-ccm: add digprog mmio write method - -* Thu Mar 18 2021 Chen Qun +* Fri Feb 11 2022 Chen Qun +- i386: cache passthrough: Update Intel CPUID4.EAX[25:14] based on vCPU topo +- i386: cache passthrough: Update AMD 8000_001D.EAX[25:14] based on vCPU topo + +* Fri Feb 11 2022 Chen Qun +- nbd/server.c: fix invalid read after client was already free +- qemu-nbd: make native as the default aio mode +- qemu-nbd: set timeout to qemu-nbd socket +- qemu-pr: fixed ioctl failed for multipath disk +- block: enable cache mode of empty cdrom +- block: disallow block jobs when there is a BDRV_O_INACTIVE flag +- scsi: cdrom: Fix crash after remote cdrom detached +- block: bugfix: disable process AIO when attach scsi disk +- block: bugfix: Don't pause vm when NOSPACE EIO happened +- scsi: bugfix: fix division by zero + +* Fri Feb 11 2022 imxcc +- migration: skip cache_drop for bios bootloader and +- ps2: fix oob in ps2 kbd +- Currently, while kvm and qemu can not handle some kvm +- cpu/features: fix bug for memory leakage +- monitor/qmp: drop inflight rsp if qmp client broken +- oslib-posix: optimise vm startup time for 1G hugepage + +* Fri Feb 11 2022 imxcc +- scsi-bus: Refactor the code that retries requests +- scsi-disk: Add support for retry on errors +- block-backend: Stop retrying when draining - block: Add sanity check when setting retry parameters -* Wed Mar 17 2021 Huawei Technologies Co., Ltd -- qemu.spec: enable strip for qemu-block-rbd.so and qemu-block-ssh.so - -* Fri Mar 12 2021 Chen Qun -- net: vmxnet3: validate configuration values during activate (CVE-2021-20203) +* Fri Feb 11 2022 imxcc +- vfio/pci: Ascend310 need 4Bytes quirk in bar4 +- vfio/pci: Ascend710 need 4Bytes quirk in bar0 +- vfio/pci: Ascend910 need 4Bytes quirk in bar0 -* Fri Mar 12 2021 Chen Qun -- migration: fix memory leak in qmp_migrate_set_parameters -- migration/tls: fix inverted semantics in multifd_channel_connect -- migration/tls: add error handling in multifd_tls_handshake_thread +* Fri Feb 11 2022 imxcc +- hugepages: hugepages files maybe leftover +- Patch0024: target-i386: Modify the VM's physical bits value set -* Thu Mar 11 2021 Huawei Technologies Co., Ltd -- qemu.spec: add iscsi rpm package requirement +* Fri Feb 11 2022 Yan Wang +- log: disable qemu_log function for "make check V=1" -* Wed Mar 10 2021 Huawei Technologies Co., Ltd -- qemu.spec: make iscsi rpm package - -* Tue Mar 02 2021 Huawei Technologies Co., Ltd -- qemu.spec: Add --enable-zstd compile parameter - -* Fri Feb 26 2021 Huawei Technologies Co., Ltd -- block-backend: Stop retrying when draining +* Fri Feb 11 2022 Yan Wang +- chardev/baum: disable unused brlapi -* Fri Feb 26 2021 Huawei Technologies Co., Ltd -- ide:atapi: check io_buffer_index in ide_atapi_cmd_reply_end - -* Fri Feb 19 2021 Huawei Technologies Co., Ltd -- ati: use vga_read_byte in ati_cursor_define -- sd: sdhci: assert data_count is within fifo_buffer -- msix: add valid.accepts methods to check address - -* Thu Feb 04 2021 Huawei Technologies Co., Ltd -- migration: Add multi-thread compress method -- migration: Refactoring multi-thread compress migration -- migration: Add multi-thread compress ops -- migration: Add zstd support in multi-thread compression -- migration: Add compress_level sanity check -- doc: Update multi-thread compression doc -- configure: Enable test and libs for zstd +* Fri Feb 11 2022 imxcc +- Revert "cpu: parse +/- feature to avoid failure" +- Revert "cpu: add Cortex-A72 processor kvm target support" +- cpu: add Cortex-A72 processor kvm target support -* Sat Jan 30 2021 Huawei Technologies Co., Ltd -- scsi-bus: Refactor the code that retries requests -- scsi-disk: Add support for retry on errors +* Thu Feb 10 2022 imxcc +- qapi/block-core: Add retry option for error action - qapi/block-core: Add retry option for error action - block-backend: Introduce retry timer - block-backend: Add device specific retry callback - block-backend: Enable retry action on errors - block-backend: Add timeout support for retry - block: Add error retry param setting -- virtio-blk: Refactor the code that processes queued requests -- virtio-blk: On restart, process queued requests in the proper context - virtio_blk: Add support for retry on errors +- vhost: cancel migration when vhost-user restarted +- migration: Add multi-thread compress method +- migration: Refactoring multi-thread compress migration +- migration: Add multi-thread compress ops +- migration: Add zstd support in multi-thread compression +- migration: Add compress_level sanity check +- doc: Update multi-thread compression doc -* Mon Jan 18 2021 Huawei Technologies Co., Ltd -- feature: enable spice protocol - -* Mon Jan 18 2021 Huawei Technologies Co., Ltd -- reorder changelog in desceding order - -* Fri Jan 15 2021 Huawei Technologies Co., Ltd -- memory: clamp cached translation in case it points to an MMIO region - -* Fri Dec 25 2020 Huawei Technologies Co., Ltd -- add qemu-block-rbd package -- add qemu-block-ssh package - -* Fri Dec 11 2020 Huawei Technologies Co., Ltd -- hostmem: Fix up free host_nodes list right after visited - -* Fri Dec 11 2020 Huawei Technologies Co., Ltd -- slirp: check pkt_len before reading protocol header for fixing CVE-2020-29129 and CVE-2020-29130 - -* Wed Dec 9 2020 Huawei Technologies Co., Ltd -- target/arm: Fix write redundant values to kvm - -* Wed Dec 2 2020 Huawei Technologies Co., Ltd -- migration/tls: save hostname into MigrationState -- migration/tls: extract migration_tls_client_create for common-use -- migration/tls: add tls_hostname into MultiFDSendParams -- migration/tls: extract cleanup function for common-use -- migration/tls: add support for multifd tls-handshake -- migration/tls: add trace points for multifd-tls -- qemu-file: Don't do IO after shutdown -- multifd: Make sure that we don't do any IO after an error -- migration: Don't send data if we have stopped -- migration: Create migration_is_running() -- migration: fix COLO broken caused by a previous commit -- migration/multifd: fix hangup with TLS-Multifd due to blocking handshake -- multifd/tls: fix memoryleak of the QIOChannelSocket object when cancelling migration - -* Wed Nov 18 2020 Huawei Technologies Co., Ltd -- ati: check x y display parameter values - -* Fri Nov 13 2020 Huawei Technologies Co., Ltd -- json: Fix a memleak in parse_pair() - -* Wed Nov 11 2020 Huawei Technologies Co., Ltd -- hw: usb: hcd-ohci: check for processed TD before retire -- hw: ehci: check return value of 'usb_packet_map' -- hw: usb: hcd-ohci: check len and frame_number variables -- hw/net/e1000e: advance desc_offset in case of null descriptor - -* Fri Oct 30 2020 Huawei Technologies Co., Ltd -- migration/dirtyrate: setup up query-dirtyrate framwork -- migration/dirtyrate: add DirtyRateStatus to denote calculation status -- migration/dirtyrate: Add RamblockDirtyInfo to store sampled page info -- migration/dirtyrate: Add dirtyrate statistics series functions -- migration/dirtyrate: move RAMBLOCK_FOREACH_MIGRATABLE into ram.h -- migration/dirtyrate: Record hash results for each sampled page -- migration/dirtyrate: Compare page hash results for recorded sampled page -- migration/dirtyrate: skip sampling ramblock with size below MIN_RAMBLOCK_SIZE -- migration/dirtyrate: Implement set_sample_page_period() and is_sample_period_valid() -- migration/dirtyrate: Implement calculate_dirtyrate() function -- migration/dirtyrate: Implement qmp_cal_dirty_rate()/qmp_get_dirty_rate() function -- migration/dirtyrate: Add trace_calls to make it easier to debug -- migration/dirtyrate: record start_time and calc_time while at the measuring state -- migration/dirtyrate: present dirty rate only when querying the rate has completed -- migration/dirtyrate: simplify includes in dirtyrate.c - -* Fri Oct 30 2020 Huawei Technologies Co., Ltd -- elf2dmp: Fix memory leak on main() error paths -- io: Don't use '#' flag of printf format -- hw/display/omap_lcdc: Fix potential NULL pointer dereference -- hw/display/exynos4210_fimd: Fix potential NULL pointer dereference -- block/vvfat: Fix bad printf format specifiers -- block: Remove unused include -- ssi: Fix bad printf format specifiers -- net/l2tpv3: Remove redundant check in net_init_l2tpv3() - -* Thu Oct 29 2020 Huawei Technologies Co., Ltd -- Bugfix: hw/acpi: Use max_cpus instead of cpus when build PPTT table - -* Wed Oct 21 2020 Huawei Technologies Co., Ltd -- net: remove an assert call in eth_get_gso_type - -* Wed Oct 14 2020 Prasad J Pandit -- pci: check bus pointer before dereference -- hw/ide: check null block before _cancel_dma_sync - -* Mon Sep 28 2020 Huawei Technologies Co., Ltd -- sm501: Replace hand written implementation with pixman where possible -- sm501: Clean up local variables in sm501_2d_operation -- sm501: Use BIT(x) macro to shorten constant -- sm501: Shorten long variable names in sm501_2d_operation -- sm501: Convert printf + abort to qemu_log_mask -- hw/net/net_tx_pkt: fix assertion failure in net_tx_pkt_add_raw_fragment -- hw/net/xgmac: Fix buffer overflow in xgmac_enet_send() - -* Fri Sep 18 2020 Huawei Technologies Co., Ltd -- hw-sd-sdhci-Fix-DMA-Transfer-Block-Size-field.patch -- hw-xhci-check-return-value-of-usb_packet_map.patch - -* Fri Sep 11 2020 Huawei Technologies Co., Ltd -- slirp/src/ip6_input.c: fix out-of-bounds read information vulnerability - -* Tue Sep 08 2020 Huawei Technologies Co., Ltd -- target/arm: ignore evtstrm and cpuid CPU features - -* Fri Aug 21 2020 Huawei Technologies Co., Ltd -- hw/usb/core.c: fix buffer overflow in do_token_setup function - -* Wed Aug 19 2020 Huawei Technologies Co., Ltd -- target-arm-convert-isar-regs-to-array.patch -- target-arm-parse-cpu-feature-related-options.patch -- target-arm-register-CPU-features-for-property.patch -- target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch -- target-arm-introduce-CPU-feature-dependency-mechanis.patch -- target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch -- target-arm-Add-CPU-features-to-query-cpu-model-expan.patch -- target-arm-Update-ID-fields.patch -- target-arm-Add-more-CPU-features.patch - -* Wed Aug 19 2020 Huawei Technologies Co., Ltd -- target-arm-Add-isar_feature-tests-for-PAN-ATS1E1.patch -- target-arm-Add-ID_AA64MMFR2_EL1.patch -- target-arm-Add-and-use-FIELD-definitions-for-ID_AA64.patch -- target-arm-Use-FIELD-macros-for-clearing-ID_DFR0-PER.patch -- target-arm-Define-an-aa32_pmu_8_1-isar-feature-test-.patch -- target-arm-Add-_aa64_-and-_any_-versions-of-pmu_8_1-.patch -- target-arm-Stop-assuming-DBGDIDR-always-exists.patch -- target-arm-Move-DBGDIDR-into-ARMISARegisters.patch -- target-arm-Enable-ARMv8.2-ATS1E1-in-cpu-max.patch -- target-arm-Test-correct-register-in-aa32_pan-and-aa3.patch -- target-arm-Read-debug-related-ID-registers-from-KVM.patch -- target-arm-monitor-Introduce-qmp_query_cpu_model_exp.patch -- target-arm-monitor-query-cpu-model-expansion-crashed.patch - -* Tue Aug 18 2020 Huawei Technologies Co., Ltd -- hw/acpi/aml-build.c: build smt processor structure to support smt topology - -* Thu Aug 13 2020 Huawei Technologies Co., Ltd --target/arm: Aarch64 support vtpm - -* Wed Aug 12 2020 Huawei Technologies Co., Ltd -- backport upstream patch to support SHPCHotplug in arm - -* Thu Aug 6 2020 Huawei Technologies Co., Ltd -- es1370: check total frame count against current frame -- exec: set map length to zero when returning NULL -- ati-vga: check mm_index before recursive call (CVE-2020-13800) -- megasas: use unsigned type for reply_queue_head and check index -- megasas: avoid NULL pointer dereference -- megasas: use unsigned type for positive numeric fields -- hw/scsi/megasas: Fix possible out-of-bounds array access in tracepoints - -* Thu Aug 6 2020 Huawei Technologies Co., Ltd -- tests: Disalbe filemonitor testcase - -* Sat Jun 20 2020 Huawei Technologies Co., Ltd -- target/arm: Fix PAuth sbox functions -- fix two patches' format which can cause git am failed - -* Fri May 29 2020 Huawei Technologies Co., Ltd -- target/arm: Add the kvm_adjvtime vcpu property for Cortex-A72 - -* Wed May 27 2020 Huawei Technologies Co., Ltd. -- Revert: "vtimer: compat cross version migration from v4.0.1" -- ARM64: record vtimer tick when cpu is stopped -- hw/arm/virt: add missing compat for kvm-no-adjvtime -- migration: Compat virtual timer adjust for v4.0.1 and v4.1.0 -- vtimer: Drop vtimer virtual timer adjust - -* Fri May 22 2020 Huawei Technologies Co., Ltd. -- ip_reass: Fix use after free -- bt: use size_t type for length parameters instead of int -- log: Add some logs on VM runtime path - -* Fri May 15 2020 Huawei Technologies Co., Ltd. -- ide: Fix incorrect handling of some PRDTs in ide_dma_cb() -- ati-vga: Fix checks in ati_2d_blt() to avoid crash -- slirp: tftp: restrict relative path access - -* Tue May 12 2020 Huawei Technologies Co., Ltd. -- arm/virt: Support CPU cold plug - -* Sat May 9 2020 Huawei Technologies Co., Ltd. -- migration/ram: do error_free after migrate_set_error to avoid memleaks. -- migration/ram: fix memleaks in multifd_new_send_channel_async. -- migration/rdma: fix a memleak on error path in rdma_start_incoming_migration. - -* Fri May 8 2020 Huawei Technologies Co., Ltd. -- vtimer: compat cross version migration from v4.0.1 - -* Fri Apr 24 2020 Huawei Technologies Co., Ltd. -- migration: backport migration patches from upstream - -* Fri Apr 24 2020 Huawei Technologies Co., Ltd. -- arm/virt: Add CPU hotplug support - -* Wed Apr 22 2020 Huawei Technologies Co., Ltd. -- backport patch to enable arm/virt memory hotplug - -* Wed Apr 22 2020 Huawei Technologies Co., Ltd. -- backport patch to enable target/arm/kvm Adjust virtual time - -* Fri Apr 17 2020 Huawei Technologies Co., Ltd. -- backport patch bundles from qemu stable v4.1.1 - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- aio-wait: delegate polling of main AioContext if BQL not held -- async: use explicit memory barriers - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- pcie: Add pcie-root-port fast plug/unplug feature -- pcie: Compat with devices which do not support Link Width, such as ioh3420 - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- qcow2-bitmap: Fix uint64_t left-shift overflow - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- COLO-compare: Fix incorrect `if` logic - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- block/backup: fix max_transfer handling for copy_range -- block/backup: fix backup_cow_with_offload for last cluster -- qcow2: Limit total allocation range to INT_MAX -- mirror: Do not dereference invalid pointers - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- file-posix: Handle undetectable alignment - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- vhost: Fix memory region section comparison -- memory: Provide an equality function for MemoryRegionSections -- memory: Align MemoryRegionSections fields - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- block/iscsi: use MIN() between mx_sb_len and sb_len_wr -- moniter: fix memleak in monitor_fdset_dup_fd_find_remove - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- tcp_emu: fix unsafe snprintf() usages -- util: add slirp_fmt() helpers -- slirp: use correct size while emulating commands -- slirp: use correct size while emulating IRC commands -- tcp_emu: Fix oob access -- iscsi: Cap block count from GET LBA STATUS (CVE-2020-1711) - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- 9pfs: local: Fix possible memory leak in local_link() -- scsi-disk: define props in scsi_block_disk to avoid memleaks -- arm/translate-a64: fix uninitialized variable warning -- block: fix memleaks in bdrv_refresh_filename -- vnc: fix memory leak when vnc disconnect -- block: fix memleaks in bdrv_refresh_filename - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- linux headers: update against "KVM/ARM: Fix >256 vcpus" -- intc/arm_gic: Support IRQ injection for more than 256 vcpus -- ARM: KVM: Check KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 for smp_cpus > - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- vnc: fix memory leak when vnc disconnect - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- pcie: disable the PCI_EXP_LINKSTA_DLLA cap for pcie-root-port by default - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- cpu: add Kunpeng-920 cpu support +* Wed Feb 09 2022 Chen Qun - cpu: parse +/- feature to avoid failure +- cpu: add Kunpeng-920 cpu support - cpu: add Cortex-A72 processor kvm target support +- add Phytium's CPU models: FT-2000+ and Tengyun-S2500. -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- vhost-user-scsi: prevent using uninitialized vqs - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- util/async: hold AioContext ref to prevent use-after-free - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- xhci: Fix memory leak in xhci_address_slot -- xhci: Fix memory leak in xhci_kick_epctx -- ehci: fix queue->dev null ptr dereference - -* Thu Apr 16 2020 Huawei Technologies Co., Ltd. -- tests/bios-tables-test: disable this testcase -- hw/arm/virt: Introduce cpu topology support -- hw/arm64: add vcpu cache info support - -* Wed Apr 15 2020 Huawei Technologies Co., Ltd. -- smbios: Add missing member of type 4 for smbios 3.0 - -* Wed Apr 15 2020 Huawei Technologies Co., Ltd. -- bios-tables-test: prepare to change ARM virt ACPI DSDT -- arm64: Add the cpufreq device to show cpufreq info to guest - -* Wed Apr 15 2020 Huawei Technologies Co., Ltd. -- qcow2: fix memory leak in qcow2_read_extensions - -* Wed Apr 15 2020 Huawei Technologies Co., Ltd. -- pl011: reset read FIFIO when UARTTIMSC=0 & UARTICR=0xff -- pl031: support rtc-timer property for pl031 -- vhost: cancel migration when vhost-user restarted +* Tue Feb 8 2022 Xiangdong Liu +- net/dump.c: Suppress spurious compiler warning -* Mon Apr 13 2020 openEuler Buildteam - version-release +* Thu Jan 27 2022 Xiangdong Liu - Package init diff --git a/qga-Plug-unlikely-memory-leak-in-guest-set-memory-bl.patch b/qga-Plug-unlikely-memory-leak-in-guest-set-memory-bl.patch deleted file mode 100644 index a901a500181bb9a36f9bd307d8bdee5929b6144f..0000000000000000000000000000000000000000 --- a/qga-Plug-unlikely-memory-leak-in-guest-set-memory-bl.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 1580682eafb489eaf417456778267662629cf696 Mon Sep 17 00:00:00 2001 -From: Markus Armbruster -Date: Tue, 30 Jun 2020 11:03:33 +0200 -Subject: [PATCH 05/11] qga: Plug unlikely memory leak in - guest-set-memory-blocks - -transfer_memory_block() leaks an Error object when reading file -/sys/devices/system/memory/memory/state fails with errno other -than ENOENT, and @sys2memblk is false, i.e. when the state file exists -but cannot be read (seems quite unlikely), and this is -guest-set-memory-blocks, not guest-get-memory-blocks. - -Plug the leak. - -Fixes: bd240fca42d5f072fb758a71720d9de9990ac553 -Cc: Michael Roth -Cc: Hailiang Zhang -Signed-off-by: Markus Armbruster -Reviewed-by: zhanghailiang -Message-Id: <20200630090351.1247703-9-armbru@redhat.com> -Signed-off-by: BiaoXiang Ye ---- - qga/commands-posix.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/qga/commands-posix.c b/qga/commands-posix.c -index dfc05f5b..c318cee7 100644 ---- a/qga/commands-posix.c -+++ b/qga/commands-posix.c -@@ -2420,6 +2420,7 @@ static void transfer_memory_block(GuestMemoryBlock *mem_blk, bool sys2memblk, - if (sys2memblk) { - error_propagate(errp, local_err); - } else { -+ error_free(local_err); - result->response = - GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED; - } --- -2.27.0.dirty - diff --git a/qga-commands-posix-fix-use-after-free-of-local_err.patch b/qga-commands-posix-fix-use-after-free-of-local_err.patch deleted file mode 100644 index 9628d0c59445c9d29ddaa39e6fb271fe73a5c274..0000000000000000000000000000000000000000 --- a/qga-commands-posix-fix-use-after-free-of-local_err.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 15847279f29b0bd67b95daefff395cab8fad80d3 Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Tue, 24 Mar 2020 18:36:30 +0300 -Subject: [PATCH 4/5] qga/commands-posix: fix use after free of local_err - -local_err is used several times in guest_suspend(). Setting non-NULL -local_err will crash, so let's zero it after freeing. Also fix possible -leak of local_err in final if(). - -Signed-off-by: Vladimir Sementsov-Ogievskiy -Message-Id: <20200324153630.11882-7-vsementsov@virtuozzo.com> -Reviewed-by: Richard Henderson -Signed-off-by: Markus Armbruster -Signed-off-by: Zhenyu Ye ---- - qga/commands-posix.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/qga/commands-posix.c b/qga/commands-posix.c -index dfc05f5b..66164e6c 100644 ---- a/qga/commands-posix.c -+++ b/qga/commands-posix.c -@@ -1760,6 +1760,7 @@ static void guest_suspend(SuspendMode mode, Error **errp) - } - - error_free(local_err); -+ local_err = NULL; - - if (pmutils_supports_mode(mode, &local_err)) { - mode_supported = true; -@@ -1771,6 +1772,7 @@ static void guest_suspend(SuspendMode mode, Error **errp) - } - - error_free(local_err); -+ local_err = NULL; - - if (linux_sys_state_supports_mode(mode, &local_err)) { - mode_supported = true; -@@ -1778,6 +1780,7 @@ static void guest_suspend(SuspendMode mode, Error **errp) - } - - if (!mode_supported) { -+ error_free(local_err); - error_setg(errp, - "the requested suspend mode is not supported by the guest"); - } else { --- -2.22.0.windows.1 - diff --git a/qga-fix-assert-regression-on-guest-shutdown.patch b/qga-fix-assert-regression-on-guest-shutdown.patch deleted file mode 100644 index c5f1e1069b5097ff1adf2328bea6a25e9483cda1..0000000000000000000000000000000000000000 --- a/qga-fix-assert-regression-on-guest-shutdown.patch +++ /dev/null @@ -1,47 +0,0 @@ -From aeccff89333c565c7a894f99c17c0044d7d43be2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Thu, 4 Jun 2020 11:44:25 +0200 -Subject: [PATCH 02/11] qga: fix assert regression on guest-shutdown -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Since commit 781f2b3d1e ("qga: process_event() simplification"), -send_response() is called unconditionally, but will assert when "rsp" is -NULL. This may happen with QCO_NO_SUCCESS_RESP commands, such as -"guest-shutdown". - -Fixes: 781f2b3d1e5ef389b44016a897fd55e7a780bf35 -Cc: Michael Roth -Reported-by: Christian Ehrhardt -Signed-off-by: Marc-André Lureau -Reviewed-by: Philippe Mathieu-Daudé -Reviewed-by: Christian Ehrhardt -Tested-by: Christian Ehrhardt -Cc: qemu-stable@nongnu.org -Signed-off-by: Michael Roth -Signed-off-by: BiaoXiang Ye ---- - qga/main.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/qga/main.c b/qga/main.c -index c35c2a21..12fa463f 100644 ---- a/qga/main.c -+++ b/qga/main.c -@@ -529,7 +529,11 @@ static int send_response(GAState *s, const QDict *rsp) - QString *payload_qstr, *response_qstr; - GIOStatus status; - -- g_assert(rsp && s->channel); -+ g_assert(s->channel); -+ -+ if (!rsp) { -+ return 0; -+ } - - payload_qstr = qobject_to_json(QOBJECT(rsp)); - if (!payload_qstr) { --- -2.27.0.dirty - diff --git a/qmp-add-command-to-query-used-memslots-of-vhost-net-.patch b/qmp-add-command-to-query-used-memslots-of-vhost-net-.patch new file mode 100644 index 0000000000000000000000000000000000000000..10d69dd73c18a4748c4afcc7f89acac49b4d3ae4 --- /dev/null +++ b/qmp-add-command-to-query-used-memslots-of-vhost-net-.patch @@ -0,0 +1,131 @@ +From 1545a60a8b78490c7dc8909b7012bca63dba63cd Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Sat, 12 Feb 2022 15:41:08 +0800 +Subject: [PATCH] qmp: add command to query used memslots of vhost-net and + vhost-user + +Signed-off-by: Jinhua Cao +--- + hw/virtio/vhost-backend.c | 2 +- + hw/virtio/vhost-user.c | 2 +- + include/hw/virtio/vhost-backend.h | 2 ++ + monitor/qmp-cmds.c | 12 ++++++++++++ + qapi/net.json | 18 ++++++++++++++++++ + qapi/pragma.json | 4 +++- + 6 files changed, 37 insertions(+), 3 deletions(-) + +diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c +index 2acfb750fd..d8e1710758 100644 +--- a/hw/virtio/vhost-backend.c ++++ b/hw/virtio/vhost-backend.c +@@ -300,7 +300,7 @@ static void vhost_kernel_set_used_memslots(struct vhost_dev *dev) + vhost_kernel_used_memslots = dev->mem->nregions; + } + +-static unsigned int vhost_kernel_get_used_memslots(void) ++unsigned int vhost_kernel_get_used_memslots(void) + { + return vhost_kernel_used_memslots; + } +diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c +index 176cae9244..8f69a3b850 100644 +--- a/hw/virtio/vhost-user.c ++++ b/hw/virtio/vhost-user.c +@@ -2544,7 +2544,7 @@ static void vhost_user_set_used_memslots(struct vhost_dev *dev) + vhost_user_used_memslots = counter; + } + +-static unsigned int vhost_user_get_used_memslots(void) ++unsigned int vhost_user_get_used_memslots(void) + { + return vhost_user_used_memslots; + } +diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h +index a64708f456..7bbc658161 100644 +--- a/include/hw/virtio/vhost-backend.h ++++ b/include/hw/virtio/vhost-backend.h +@@ -190,4 +190,6 @@ int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev, + + int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd); + ++unsigned int vhost_kernel_get_used_memslots(void); ++unsigned int vhost_user_get_used_memslots(void); + #endif /* VHOST_BACKEND_H */ +diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c +index 98868cee03..f3e80ec8a7 100644 +--- a/monitor/qmp-cmds.c ++++ b/monitor/qmp-cmds.c +@@ -36,6 +36,7 @@ + #include "qapi/qapi-commands-machine.h" + #include "qapi/qapi-commands-misc.h" + #include "qapi/qapi-commands-ui.h" ++#include "qapi/qapi-commands-net.h" + #include "qapi/type-helpers.h" + #include "qapi/qmp/qerror.h" + #include "exec/ramlist.h" +@@ -43,6 +44,7 @@ + #include "hw/acpi/acpi_dev_interface.h" + #include "hw/intc/intc.h" + #include "hw/rdma/rdma.h" ++#include "hw/virtio/vhost-backend.h" + + NameInfo *qmp_query_name(Error **errp) + { +@@ -471,3 +473,13 @@ int64_t qmp_query_rtc_date_diff(Error **errp) + { + return get_rtc_date_diff(); + } ++ ++uint32_t qmp_query_vhost_kernel_used_memslots(Error **errp) ++{ ++ return vhost_kernel_get_used_memslots(); ++} ++ ++uint32_t qmp_query_vhost_user_used_memslots(Error **errp) ++{ ++ return vhost_user_get_used_memslots(); ++} +diff --git a/qapi/net.json b/qapi/net.json +index 7fab2e7cd8..c9ff849eed 100644 +--- a/qapi/net.json ++++ b/qapi/net.json +@@ -696,3 +696,21 @@ + ## + { 'event': 'FAILOVER_NEGOTIATED', + 'data': {'device-id': 'str'} } ++ ++## ++# @query-vhost-kernel-used-memslots: ++# ++# Get vhost-kernel nic used memslots ++# ++# Since: 4.1 ++## ++{ 'command': 'query-vhost-kernel-used-memslots', 'returns': 'uint32' } ++ ++## ++# @query-vhost-user-used-memslots: ++# ++# Get vhost-user nic used memslots ++# ++# Since: 4.1 ++## ++{ 'command': 'query-vhost-user-used-memslots', 'returns': 'uint32' } +diff --git a/qapi/pragma.json b/qapi/pragma.json +index b37f6de445..d35c897acb 100644 +--- a/qapi/pragma.json ++++ b/qapi/pragma.json +@@ -27,7 +27,9 @@ + 'query-tpm-models', + 'query-tpm-types', + 'ringbuf-read', +- 'query-rtc-date-diff' ], ++ 'query-rtc-date-diff', ++ 'query-vhost-user-used-memslots', ++ 'query-vhost-kernel-used-memslots' ], + # Externally visible types whose member names may use uppercase + 'member-name-exceptions': [ # visible in: + 'ACPISlotType', # query-acpi-ospm-status +-- +2.27.0 + diff --git a/qmp-fix-leak-on-callbacks-that-return-both-value-and.patch b/qmp-fix-leak-on-callbacks-that-return-both-value-and.patch deleted file mode 100644 index 1ceb1e70b84f1e1a9a3f785ff2d4d55b697a7cb4..0000000000000000000000000000000000000000 --- a/qmp-fix-leak-on-callbacks-that-return-both-value-and.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 1f1949368d4ac7a18973aa83a074daf01daf97ad Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Wed, 25 Mar 2020 19:47:22 +0100 -Subject: [PATCH 3/5] qmp: fix leak on callbacks that return both value and - error -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Direct leak of 4120 byte(s) in 1 object(s) allocated from: - #0 0x7fa114931887 in __interceptor_calloc (/lib64/libasan.so.6+0xb0887) - #1 0x7fa1144ad8f0 in g_malloc0 (/lib64/libglib-2.0.so.0+0x588f0) - #2 0x561e3c9c8897 in qmp_object_add /home/elmarco/src/qemu/qom/qom-qmp-cmds.c:291 - #3 0x561e3cf48736 in qmp_dispatch /home/elmarco/src/qemu/qapi/qmp-dispatch.c:155 - #4 0x561e3c8efb36 in monitor_qmp_dispatch /home/elmarco/src/qemu/monitor/qmp.c:145 - #5 0x561e3c8f09ed in monitor_qmp_bh_dispatcher /home/elmarco/src/qemu/monitor/qmp.c:234 - #6 0x561e3d08c993 in aio_bh_call /home/elmarco/src/qemu/util/async.c:136 - #7 0x561e3d08d0a5 in aio_bh_poll /home/elmarco/src/qemu/util/async.c:164 - #8 0x561e3d0a535a in aio_dispatch /home/elmarco/src/qemu/util/aio-posix.c:380 - #9 0x561e3d08e3ca in aio_ctx_dispatch /home/elmarco/src/qemu/util/async.c:298 - #10 0x7fa1144a776e in g_main_context_dispatch (/lib64/libglib-2.0.so.0+0x5276e) - -Signed-off-by: Marc-André Lureau -Message-Id: <20200325184723.2029630-3-marcandre.lureau@redhat.com> -Reviewed-by: Markus Armbruster -Signed-off-by: Paolo Bonzini -Signed-off-by: Zhenyu Ye ---- - qapi/qmp-dispatch.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c -index 6dfdad57..a635abb9 100644 ---- a/qapi/qmp-dispatch.c -+++ b/qapi/qmp-dispatch.c -@@ -189,6 +189,8 @@ QDict *qmp_dispatch(QmpCommandList *cmds, QObject *request, - - ret = do_qmp_dispatch(cmds, request, allow_oob, &err); - if (err) { -+ /* or assert(!ret) after reviewing all handlers: */ -+ qobject_unref(ret); - rsp = qmp_error_response(err); - } else if (ret) { - rsp = qdict_new(); --- -2.22.0.windows.1 - diff --git a/roms-Makefile.edk2-don-t-pull-in-submodules-when-bui.patch b/roms-Makefile.edk2-don-t-pull-in-submodules-when-bui.patch deleted file mode 100644 index 00e672662ddd5d848fc031967a0efdcf9dc4432b..0000000000000000000000000000000000000000 --- a/roms-Makefile.edk2-don-t-pull-in-submodules-when-bui.patch +++ /dev/null @@ -1,54 +0,0 @@ -From fc5afb1a9230fe21d76bcef527b0d3cee90a2cd3 Mon Sep 17 00:00:00 2001 -From: Michael Roth -Date: Thu, 12 Sep 2019 18:12:02 -0500 -Subject: [PATCH] roms/Makefile.edk2: don't pull in submodules when building - from tarball -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Currently the `make efi` target pulls submodules nested under the -roms/edk2 submodule as dependencies. However, when we attempt to build -from a tarball this fails since we are no longer in a git tree. - -A preceding patch will pre-populate these submodules in the tarball, -so assume this build dependency is only needed when building from a -git tree. - -Cc: Laszlo Ersek -Cc: Bruce Rogers -Cc: qemu-stable@nongnu.org # v4.1.0 -Reported-by: Bruce Rogers -Reviewed-by: Laszlo Ersek -Reviewed-by: Philippe Mathieu-Daudé -Tested-by: Philippe Mathieu-Daudé -Signed-off-by: Michael Roth -Message-Id: <20190912231202.12327-3-mdroth@linux.vnet.ibm.com> -Signed-off-by: Philippe Mathieu-Daudé -(cherry picked from commit f3e330e3c319160ac04954399b5a10afc965098c) -Signed-off-by: Michael Roth ---- - roms/Makefile.edk2 | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/roms/Makefile.edk2 b/roms/Makefile.edk2 -index c2f2ff59d5..33a074d3a4 100644 ---- a/roms/Makefile.edk2 -+++ b/roms/Makefile.edk2 -@@ -46,8 +46,13 @@ all: $(foreach flashdev,$(flashdevs),../pc-bios/edk2-$(flashdev).fd.bz2) \ - # files. - .INTERMEDIATE: $(foreach flashdev,$(flashdevs),../pc-bios/edk2-$(flashdev).fd) - -+# Fetch edk2 submodule's submodules. If it is not in a git tree, assume -+# we're building from a tarball and that they've already been fetched by -+# make-release/tarball scripts. - submodules: -- cd edk2 && git submodule update --init --force -+ if test -d edk2/.git; then \ -+ cd edk2 && git submodule update --init --force; \ -+ fi - - # See notes on the ".NOTPARALLEL" target and the "+" indicator in - # "tests/uefi-test-tools/Makefile". --- -2.23.0 diff --git a/scsi-bugfix-fix-division-by-zero.patch b/scsi-bugfix-fix-division-by-zero.patch new file mode 100644 index 0000000000000000000000000000000000000000..685c8d54e320562b912323497637ad1b2fd7c9c6 --- /dev/null +++ b/scsi-bugfix-fix-division-by-zero.patch @@ -0,0 +1,57 @@ +From ba8fd8a3d11655da0b51148e69c01b78794a3f69 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 16:34:05 +0800 +Subject: [PATCH] scsi: bugfix: fix division by zero + +Error of PRDM disk may cause divide by zero in +scsi_read_complete(), so add LOG and assert(). + +Signed-off-by: wangjian161 +--- + hw/scsi/scsi-generic.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c +index 0306ccc7b1..1f51586048 100644 +--- a/hw/scsi/scsi-generic.c ++++ b/hw/scsi/scsi-generic.c +@@ -179,6 +179,10 @@ static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len) + (r->req.cmd.buf[1] & 0x01)) { + page = r->req.cmd.buf[2]; + if (page == 0xb0) { ++ if (s->blocksize == 0) { ++ qemu_log("device blocksize is 0!\n"); ++ abort(); ++ } + uint64_t max_transfer = blk_get_max_hw_transfer(s->conf.blk); + uint32_t max_iov = blk_get_max_hw_iov(s->conf.blk); + +@@ -314,11 +318,23 @@ static void scsi_read_complete(void * opaque, int ret) + /* Snoop READ CAPACITY output to set the blocksize. */ + if (r->req.cmd.buf[0] == READ_CAPACITY_10 && + (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) { +- s->blocksize = ldl_be_p(&r->buf[4]); ++ int new_blocksize = ldl_be_p(&r->buf[4]); ++ if (s->blocksize != new_blocksize) { ++ qemu_log("device id=%s type=%d: blocksize %d change to %d\n", ++ s->qdev.id ? s->qdev.id : "null", s->type, ++ s->blocksize, new_blocksize); ++ } ++ s->blocksize = new_blocksize; + s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL; + } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 && + (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) { +- s->blocksize = ldl_be_p(&r->buf[8]); ++ int new_blocksize = ldl_be_p(&r->buf[8]); ++ if (s->blocksize != new_blocksize) { ++ qemu_log("device id=%s type=%d: blocksize %d change to %d\n", ++ s->qdev.id ? s->qdev.id : "null", s->type, ++ s->blocksize, new_blocksize); ++ } ++ s->blocksize = new_blocksize; + s->max_lba = ldq_be_p(&r->buf[0]); + } + blk_set_guest_block_size(s->conf.blk, s->blocksize); +-- +2.27.0 + diff --git a/scsi-bus-Refactor-the-code-that-retries-requests.patch b/scsi-bus-Refactor-the-code-that-retries-requests.patch index eae42b854e2ba7818ff3c5e9812c7e3ed7f94ac9..84802c483fb08d03c8e101106f33bdc0ce31461c 100644 --- a/scsi-bus-Refactor-the-code-that-retries-requests.patch +++ b/scsi-bus-Refactor-the-code-that-retries-requests.patch @@ -1,7 +1,7 @@ -From eb55d7c4f6e0adae2aab8bd750dccf9cd7a8c784 Mon Sep 17 00:00:00 2001 +From 391dd8f1458c8db0b848450718af5c69285e5705 Mon Sep 17 00:00:00 2001 From: Jiahui Cen Date: Thu, 21 Jan 2021 15:46:54 +0800 -Subject: [PATCH] scsi-bus: Refactor the code that retries requests +Subject: [PATCH 6/9] scsi-bus: Refactor the code that retries requests Move the code that retries requests from scsi_dma_restart_bh() to its own, non-static, function. This will allow us to call it from the @@ -9,17 +9,18 @@ retry_request_cb() of scsi-disk in a future patch. Signed-off-by: Jiahui Cen Signed-off-by: Ying Fang +Signed-off-by: Alex Chen --- hw/scsi/scsi-bus.c | 16 +++++++++++----- include/hw/scsi/scsi.h | 1 + 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c -index fdc3a0e4e0..9dc09b5f3e 100644 +index 77325d8cc7..5e6f891b9d 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c -@@ -99,14 +99,10 @@ void scsi_bus_new(SCSIBus *bus, size_t bus_size, DeviceState *host, - qbus_set_bus_hotplug_handler(BUS(bus), &error_abort); +@@ -143,14 +143,10 @@ void scsi_bus_init_named(SCSIBus *bus, size_t bus_size, DeviceState *host, + qbus_set_bus_hotplug_handler(BUS(bus)); } -static void scsi_dma_restart_bh(void *opaque) @@ -34,8 +35,8 @@ index fdc3a0e4e0..9dc09b5f3e 100644 aio_context_acquire(blk_get_aio_context(s->conf.blk)); QTAILQ_FOREACH_SAFE(req, &s->requests, next, next) { scsi_req_ref(req); -@@ -128,6 +124,16 @@ static void scsi_dma_restart_bh(void *opaque) - aio_context_release(blk_get_aio_context(s->conf.blk)); +@@ -174,6 +170,16 @@ static void scsi_dma_restart_bh(void *opaque) + object_unref(OBJECT(s)); } +static void scsi_dma_restart_bh(void *opaque) @@ -52,10 +53,10 @@ index fdc3a0e4e0..9dc09b5f3e 100644 { /* No need to save a reference, because scsi_dma_restart_bh just diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h -index 426566a5c6..1231d30b35 100644 +index a567a5ed86..e5d90cd9dc 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h -@@ -184,6 +184,7 @@ void scsi_req_cancel_complete(SCSIRequest *req); +@@ -212,6 +212,7 @@ void scsi_req_cancel_complete(SCSIRequest *req); void scsi_req_cancel(SCSIRequest *req); void scsi_req_cancel_async(SCSIRequest *req, Notifier *notifier); void scsi_req_retry(SCSIRequest *req); diff --git a/scsi-bus-fix-unmatched-object_unref.patch b/scsi-bus-fix-unmatched-object_unref.patch new file mode 100644 index 0000000000000000000000000000000000000000..0cb39a07610c8da0396119e87e942b400dbdddf5 --- /dev/null +++ b/scsi-bus-fix-unmatched-object_unref.patch @@ -0,0 +1,42 @@ +From 239ffdcf42e0795b5f025f87fa19ce01642811f2 Mon Sep 17 00:00:00 2001 +From: Yan Wang +Date: Tue, 1 Mar 2022 20:12:12 +0800 +Subject: [PATCH] scsi-bus: fix unmatched object_unref() + +Fix commit 391dd8f1("scsi-bus: Refactor the code that retries requests"), +which split scsi_dma_restart_bh(), but the object_unref() belongs to +scsi_dma_restart_bh(). +So, we should mv object_unref() from scsi_retry_requests() to +scsi_dma_restart_bh(). + +Signed-off-by: Yan Wang +--- + hw/scsi/scsi-bus.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c +index 5e6f891b9d..9d37f490ce 100644 +--- a/hw/scsi/scsi-bus.c ++++ b/hw/scsi/scsi-bus.c +@@ -166,8 +166,6 @@ void scsi_retry_requests(SCSIDevice *s) + scsi_req_unref(req); + } + aio_context_release(blk_get_aio_context(s->conf.blk)); +- /* Drop the reference that was acquired in scsi_dma_restart_cb */ +- object_unref(OBJECT(s)); + } + + static void scsi_dma_restart_bh(void *opaque) +@@ -178,6 +176,9 @@ static void scsi_dma_restart_bh(void *opaque) + s->bh = NULL; + + scsi_retry_requests(s); ++ ++ /* Drop the reference that was acquired in scsi_dma_restart_cb */ ++ object_unref(OBJECT(s)); + } + + void scsi_req_retry(SCSIRequest *req) +-- +2.27.0 + diff --git a/scsi-cdrom-Fix-crash-after-remote-cdrom-detached.patch b/scsi-cdrom-Fix-crash-after-remote-cdrom-detached.patch new file mode 100644 index 0000000000000000000000000000000000000000..d1147fce44d9bd2cc06e8bbd2b2da1f1ac8083af --- /dev/null +++ b/scsi-cdrom-Fix-crash-after-remote-cdrom-detached.patch @@ -0,0 +1,35 @@ +From 77496578b22e127eb50a5a8c463e92fb3245a7e0 Mon Sep 17 00:00:00 2001 +From: WangJian +Date: Wed, 9 Feb 2022 11:42:47 +0800 +Subject: [PATCH] scsi: cdrom: Fix crash after remote cdrom detached + +There is a small window between the twice blk_is_available in +scsi_disk_emulate_command which would cause crash due to the later +assertion if the remote cdrom is detached in this window. + +So this patch replaces assertions with return to avoid qemu crash. + +Signed-off-by: wangjian161 +--- + hw/scsi/scsi-disk.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c +index d4914178ea..a1053f4036 100644 +--- a/hw/scsi/scsi-disk.c ++++ b/hw/scsi/scsi-disk.c +@@ -1930,7 +1930,10 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) + memset(outbuf, 0, r->buflen); + switch (req->cmd.buf[0]) { + case TEST_UNIT_READY: +- assert(blk_is_available(s->qdev.conf.blk)); ++ if (!blk_is_available(s->qdev.conf.blk)) { ++ scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); ++ return 0; ++ } + break; + case INQUIRY: + buflen = scsi_disk_emulate_inquiry(req, outbuf); +-- +2.27.0 + diff --git a/scsi-disk-Add-support-for-retry-on-errors.patch b/scsi-disk-Add-support-for-retry-on-errors.patch index e0bd91ec86fd13c70499567df0c18f9761e06c35..69f76143bc27c0ea1f121d7419b88ae2764e07dc 100644 --- a/scsi-disk-Add-support-for-retry-on-errors.patch +++ b/scsi-disk-Add-support-for-retry-on-errors.patch @@ -1,22 +1,34 @@ -From 34f1552a6d7e05f2f2146ebc6d50deb2de7e5fd4 Mon Sep 17 00:00:00 2001 +From 52115ca0ad925b1d719eb46e22c455aa5839534a Mon Sep 17 00:00:00 2001 From: Jiahui Cen Date: Thu, 21 Jan 2021 15:46:55 +0800 -Subject: [PATCH] scsi-disk: Add support for retry on errors +Subject: [PATCH 7/9] scsi-disk: Add support for retry on errors Mark failed requests as to be retried and implement retry_request_cb to handle these requests. Signed-off-by: Jiahui Cen Signed-off-by: Ying Fang +Signed-off-by: Alex Chen --- hw/scsi/scsi-disk.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c -index cd90cd780e..93fdd913fe 100644 +index d4914178ea..d278efc701 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c -@@ -184,6 +184,8 @@ static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req) +@@ -246,6 +246,10 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed) + scsi_req_retry(&r->req); + return true; + ++ case BLOCK_ERROR_ACTION_RETRY: ++ scsi_req_retry(&r->req); ++ return true; ++ + default: + g_assert_not_reached(); + } +@@ -253,6 +257,8 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed) static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed) { @@ -25,26 +37,15 @@ index cd90cd780e..93fdd913fe 100644 if (r->req.io_canceled) { scsi_req_cancel_complete(&r->req); return true; -@@ -193,6 +195,7 @@ static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed) - return scsi_handle_rw_error(r, -ret, acct_failed); +@@ -262,6 +268,7 @@ static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed) + return scsi_handle_rw_error(r, ret, acct_failed); } + blk_error_retry_reset_timeout(s->qdev.conf.blk); return false; } -@@ -480,6 +483,10 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed) - } - } - -+ if (action == BLOCK_ERROR_ACTION_RETRY) { -+ scsi_req_retry(&r->req); -+ } -+ - blk_error_action(s->qdev.conf.blk, action, is_read, error); - if (action == BLOCK_ERROR_ACTION_IGNORE) { - scsi_req_complete(&r->req, 0); -@@ -2252,6 +2259,13 @@ static void scsi_disk_resize_cb(void *opaque) +@@ -2278,6 +2285,13 @@ static void scsi_disk_resize_cb(void *opaque) } } @@ -58,7 +59,7 @@ index cd90cd780e..93fdd913fe 100644 static void scsi_cd_change_media_cb(void *opaque, bool load, Error **errp) { SCSIDiskState *s = opaque; -@@ -2300,10 +2314,12 @@ static const BlockDevOps scsi_disk_removable_block_ops = { +@@ -2326,10 +2340,12 @@ static const BlockDevOps scsi_disk_removable_block_ops = { .is_medium_locked = scsi_cd_is_medium_locked, .resize_cb = scsi_disk_resize_cb, diff --git a/scsi-disk-define-props-in-scsi_block_disk-to-avoid-memleaks.patch b/scsi-disk-define-props-in-scsi_block_disk-to-avoid-m.patch similarity index 74% rename from scsi-disk-define-props-in-scsi_block_disk-to-avoid-memleaks.patch rename to scsi-disk-define-props-in-scsi_block_disk-to-avoid-m.patch index a180aa1a08062f11cd313f5019d35933cd55747c..f3befe79a7e6f6b9b4513cecd5614b3aea91054e 100644 --- a/scsi-disk-define-props-in-scsi_block_disk-to-avoid-memleaks.patch +++ b/scsi-disk-define-props-in-scsi_block_disk-to-avoid-m.patch @@ -1,7 +1,7 @@ -From 79da8e2e18610ae22a3bd640c117ba56b911038d Mon Sep 17 00:00:00 2001 +From e026850b32231abb97d7790a04d7c94515bd1081 Mon Sep 17 00:00:00 2001 From: Pan Nengyuan Date: Mon, 13 Jan 2020 15:53:32 +0800 -Subject: [PATCH] scsi-disk: define props in scsi_block_disk to avoid +Subject: [PATCH 3/6] scsi-disk: define props in scsi_block_disk to avoid memleaks scsi_block_realize() use scsi_realize() to init some props, but @@ -11,19 +11,20 @@ not be freed. This patch defines these prop in scsi_block_disk_properties to avoid memleaks. Signed-off-by: Pan Nengyuan +Signed-off-by: Yan Wang --- hw/scsi/scsi-disk.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c -index e7e865ab..233afb4a 100644 +index d491417..1d7799d 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c -@@ -3026,9 +3026,7 @@ static const TypeInfo scsi_cd_info = { +@@ -3107,9 +3107,7 @@ static const TypeInfo scsi_cd_info = { #ifdef __linux__ static Property scsi_block_properties[] = { -- DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), \ +- DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), - DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.blk), - DEFINE_PROP_BOOL("share-rw", SCSIDiskState, qdev.conf.share_rw, false), + DEFINE_SCSI_DISK_PROPERTIES(), @@ -31,6 +32,5 @@ index e7e865ab..233afb4a 100644 DEFINE_PROP_UINT64("max_unmap_size", SCSIDiskState, max_unmap_size, DEFAULT_MAX_UNMAP_SIZE), -- -2.18.1 - +1.9.1 diff --git a/scsi-lsi-exit-infinite-loop-while-executing-script-C.patch b/scsi-lsi-exit-infinite-loop-while-executing-script-C.patch deleted file mode 100644 index 5d20a9f009c9bd52f9eef578344c5b0012ee8942..0000000000000000000000000000000000000000 --- a/scsi-lsi-exit-infinite-loop-while-executing-script-C.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 051c9b3cbcb4beb42a6ed017c2146ec3e7a754fb Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Wed, 14 Aug 2019 17:35:21 +0530 -Subject: [PATCH] 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 -Signed-off-by: Paolo Bonzini -Signed-off-by: Prasad J Pandit -Signed-off-by: Paolo Bonzini -(cherry picked from commit de594e47659029316bbf9391efb79da0a1a08e08) -Signed-off-by: Michael Roth ---- - 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 10468c1ec1..72f7b59ab5 100644 ---- a/hw/scsi/lsi53c895a.c -+++ b/hw/scsi/lsi53c895a.c -@@ -185,6 +185,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; -@@ -1132,7 +1135,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 -@@ -1569,19 +1586,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 { -@@ -1969,6 +1974,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); -@@ -1987,6 +1996,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; --- -2.23.0 diff --git a/sd-sdhci-assert-data_count-is-within-fifo_buffer.patch b/sd-sdhci-assert-data_count-is-within-fifo_buffer.patch deleted file mode 100644 index e38bfaa471d280a7de334e81906747938ab57b7c..0000000000000000000000000000000000000000 --- a/sd-sdhci-assert-data_count-is-within-fifo_buffer.patch +++ /dev/null @@ -1,65 +0,0 @@ -From e8d2655821caa2b8efce429c0036a93342b8383d Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Mon, 8 Feb 2021 17:14:21 +0800 -Subject: [PATCH] sd: sdhci: assert data_count is within fifo_buffer -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fix CVE-2020-17380 - -While doing multi block SDMA, transfer block size may exceed -the 's->fifo_buffer[s->buf_maxsz]' size. It may leave the -current element pointer 's->data_count' pointing out of bounds. -Leading the subsequent DMA r/w operation to OOB access issue. -Assert that 's->data_count' is within fifo_buffer. - - -> https://ruhr-uni-bochum.sciebo.de/s/NNWP2GfwzYKeKwE?path=%2Fsdhci_oob_write1 - ==1459837==ERROR: AddressSanitizer: heap-buffer-overflow - WRITE of size 54722048 at 0x61500001e280 thread T3 - #0 __interceptor_memcpy (/lib64/libasan.so.6+0x3a71d) - #1 flatview_read_continue ../exec.c:3245 - #2 flatview_read ../exec.c:3278 - #3 address_space_read_full ../exec.c:3291 - #4 address_space_rw ../exec.c:3319 - #5 dma_memory_rw_relaxed ../include/sysemu/dma.h:87 - #6 dma_memory_rw ../include/sysemu/dma.h:110 - #7 dma_memory_read ../include/sysemu/dma.h:116 - #8 sdhci_sdma_transfer_multi_blocks ../hw/sd/sdhci.c:629 - #9 sdhci_write ../hw/sd/sdhci.c:1097 - #10 memory_region_write_accessor ../softmmu/memory.c:483 - ... - -Reported-by: Ruhr-University -Suggested-by: Philippe Mathieu-Daudé -Signed-off-by: Prasad J Pandit - -patch link: https://lists.nongnu.org/archive/html/qemu-devel/2020-09/msg01175.html -Signed-off-by: Jiajie Li ---- - hw/sd/sdhci.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c -index 7b80b1d93f..e51573fe3c 100644 ---- a/hw/sd/sdhci.c -+++ b/hw/sd/sdhci.c -@@ -613,6 +613,7 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s) - s->blkcnt--; - } - } -+ assert(s->data_count <= s->buf_maxsz && s->data_count > begin); - dma_memory_write(s->dma_as, s->sdmasysad, - &s->fifo_buffer[begin], s->data_count - begin); - s->sdmasysad += s->data_count - begin; -@@ -635,6 +636,7 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s) - s->data_count = block_size; - boundary_count -= block_size - begin; - } -+ assert(s->data_count <= s->buf_maxsz && s->data_count > begin); - dma_memory_read(s->dma_as, s->sdmasysad, - &s->fifo_buffer[begin], s->data_count - begin); - s->sdmasysad += s->data_count - begin; --- -2.27.0 - diff --git a/seabios-add-check-to-avoid-dereference-NULL-pointer.patch b/seabios-add-check-to-avoid-dereference-NULL-pointer.patch new file mode 100644 index 0000000000000000000000000000000000000000..6c94c4681c2a74df31ea77ed2a83c5d775b1d429 --- /dev/null +++ b/seabios-add-check-to-avoid-dereference-NULL-pointer.patch @@ -0,0 +1,36 @@ +From e6b133311a7a5a618b48c6f38e3c3bb9e9a395c9 Mon Sep 17 00:00:00 2001 +From: eillon +Date: Mon, 14 Feb 2022 15:35:28 +0800 +Subject: [PATCH] seabios: add check to avoid dereference NULL pointer + +alloc_find_lowest() may return NULL, check it. + +Signed-off-by: eillon +--- + roms/seabios/src/malloc.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/roms/seabios/src/malloc.c b/roms/seabios/src/malloc.c +index 5827a6523..99fa3b7e0 100644 +--- a/roms/seabios/src/malloc.c ++++ b/roms/seabios/src/malloc.c +@@ -544,10 +544,12 @@ malloc_prepboot(void) + + // Clear unused f-seg ram. + struct allocinfo_s *info = alloc_find_lowest(&ZoneFSeg); +- u32 size = info->range_end - info->range_start; +- memset(memremap(info->range_start, size), 0, size); +- dprintf(1, "Space available for UMB: %x-%x, %x-%x\n" +- , RomEnd, base, info->range_start, info->range_end); ++ if (info) { ++ u32 size = info->range_end - info->range_start; ++ memset(memremap(info->range_start, size), 0, size); ++ dprintf(1, "Space available for UMB: %x-%x, %x-%x\n" ++ , RomEnd, base, info->range_start, info->range_end); ++ } + + // We should not give back unused high ram, to support some special + // guest OS, like oracle linux series. +-- +2.27.0 + diff --git a/seabios-convert-value-of-be16_to_cpu-to-u64-before-s.patch b/seabios-convert-value-of-be16_to_cpu-to-u64-before-s.patch new file mode 100644 index 0000000000000000000000000000000000000000..be0218f935178a0cd5ad9bfdbef24199acdbba2f --- /dev/null +++ b/seabios-convert-value-of-be16_to_cpu-to-u64-before-s.patch @@ -0,0 +1,31 @@ +From c2ec0efb903e27f83cb9a54041764f76e2e1d390 Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Fri, 11 Feb 2022 16:12:21 +0800 +Subject: [PATCH 1/6] seabios: convert value of be16_to_cpu to u64 before + shifting + +be16_to_cpu(scsi_lun->lun[i]) is 16 bits and left shifting by more than 16 will have undefined behaviour. +convert it to u64 before shifting. + +Signed-off-by: liuxiangdong +Signed-off-by: jiangdongxu +--- + roms/seabios/src/hw/blockcmd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/roms/seabios/src/hw/blockcmd.c b/roms/seabios/src/hw/blockcmd.c +index 6b6fea9707..af6d33544f 100644 +--- a/roms/seabios/src/hw/blockcmd.c ++++ b/roms/seabios/src/hw/blockcmd.c +@@ -210,7 +210,7 @@ static u64 scsilun2u64(struct scsi_lun *scsi_lun) + int i; + u64 ret = 0; + for (i = 0; i < ARRAY_SIZE(scsi_lun->lun); i++) +- ret |= be16_to_cpu(scsi_lun->lun[i]) << (16 * i); ++ ret |= (u64)be16_to_cpu(scsi_lun->lun[i]) << (16 * i); + return ret; + } + +-- +2.27.0 + diff --git a/seabios-do-not-give-back-high-ram.patch b/seabios-do-not-give-back-high-ram.patch new file mode 100644 index 0000000000000000000000000000000000000000..df40892f44b00f51ba244ae5d8af14e69c99e7e5 --- /dev/null +++ b/seabios-do-not-give-back-high-ram.patch @@ -0,0 +1,43 @@ +From 74f052de33cb14d7a1656079a53102a7cbbb6e75 Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Fri, 11 Feb 2022 16:16:05 +0800 +Subject: [PATCH 2/6] seabios: do not give back high ram + +Oracle 6 and 7 series virtual machines will use the high ram returned by +sebios. Since these high ram will not be initialized before kernel used, +this will cause a system exception. This patch removes the logic for +returning high ram, making the virtual machine will not use this part +of the memory, thus avoiding this kernel bug. + +Signed-off-by: wangxin +Signed-off-by: Fangyi +Signed-off-by: jiangdongxu +--- + roms/seabios/src/malloc.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/roms/seabios/src/malloc.c b/roms/seabios/src/malloc.c +index 3733855caf..5827a6523a 100644 +--- a/roms/seabios/src/malloc.c ++++ b/roms/seabios/src/malloc.c +@@ -549,6 +549,9 @@ malloc_prepboot(void) + dprintf(1, "Space available for UMB: %x-%x, %x-%x\n" + , RomEnd, base, info->range_start, info->range_end); + ++ // We should not give back unused high ram, to support some special ++ // guest OS, like oracle linux series. ++#ifdef HIGH_MEM_BACK + // Give back unused high ram. + info = alloc_find_lowest(&ZoneHigh); + if (info) { +@@ -556,6 +559,7 @@ malloc_prepboot(void) + e820_add(info->range_start, giveback, E820_RAM); + dprintf(1, "Returned %d bytes of ZoneHigh\n", giveback); + } ++#endif + + calcRamSize(); + } +-- +2.27.0 + diff --git a/seabios-drop-yield-in-smp_setup.patch b/seabios-drop-yield-in-smp_setup.patch new file mode 100644 index 0000000000000000000000000000000000000000..1c55aa0da4c4eecf6eeeb5b0d9dc5451d99672e6 --- /dev/null +++ b/seabios-drop-yield-in-smp_setup.patch @@ -0,0 +1,39 @@ +From 1a8defda890d6fe3efe2238cff1ef2ae6ca8928c Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Fri, 11 Feb 2022 16:31:25 +0800 +Subject: [PATCH 4/6] seabios: drop yield() in smp_setup() + +Fix SeaBIOS stuck problem becuase SeaBIOS open hardware interrupt +by invoking yield(). That's dangerous and unnecessary. Let's drop +it, and make the processing of setup smp more security in SeaBIOS. + +Signed-off-by: liuxiangdong +Signed-off-by: jiangdongxu +--- + roms/seabios/src/fw/smp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/roms/seabios/src/fw/smp.c b/roms/seabios/src/fw/smp.c +index 46d1da1784..e5e407be0c 100644 +--- a/roms/seabios/src/fw/smp.c ++++ b/roms/seabios/src/fw/smp.c +@@ -149,6 +149,7 @@ smp_scan(void) + + // Wait for other CPUs to process the SIPI. + u16 expected_cpus_count = qemu_get_present_cpus_count(); ++ dprintf(1,"expected_cpus_count=%d\n", expected_cpus_count); + while (expected_cpus_count != CountCPUs) + asm volatile( + // Release lock and allow other processors to use the stack. +@@ -160,7 +161,7 @@ smp_scan(void) + " jc 1b\n" + : "+m" (SMPLock), "+m" (SMPStack) + : : "cc", "memory"); +- yield(); ++ dprintf(1, "finish smp\n"); + + // Restore memory. + *(u64*)BUILD_AP_BOOT_ADDR = old; +-- +2.27.0 + diff --git a/seabios-fix-memory-leak-when-pci-check.patch b/seabios-fix-memory-leak-when-pci-check.patch new file mode 100644 index 0000000000000000000000000000000000000000..01d1ea06864f719c1bcd057b05506a546e9de4bc --- /dev/null +++ b/seabios-fix-memory-leak-when-pci-check.patch @@ -0,0 +1,34 @@ +From 73cb83af0649f958bb31b5b76f46c164c6f2952c Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Fri, 11 Feb 2022 16:28:55 +0800 +Subject: [PATCH 3/6] seabios: fix memory leak when pci check + +fix code memory leak when pci check failed +free busses memory when pci_bios_check_devices function returns error in pci_setup() + +Signed-off-by: liuxiangodng +Signed-off-by: jiangdongxu +--- + roms/seabios/src/fw/pciinit.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/roms/seabios/src/fw/pciinit.c b/roms/seabios/src/fw/pciinit.c +index d25931bb05..9df35d05d1 100644 +--- a/roms/seabios/src/fw/pciinit.c ++++ b/roms/seabios/src/fw/pciinit.c +@@ -1171,8 +1171,11 @@ pci_setup(void) + return; + } + memset(busses, 0, sizeof(*busses) * (MaxPCIBus + 1)); +- if (pci_bios_check_devices(busses)) ++ if (pci_bios_check_devices(busses)) { ++ dprintf(1, "pci_bios_check_devices(busses) failed!\n"); ++ free(busses); + return; ++ } + + dprintf(1, "=== PCI new allocation pass #2 ===\n"); + pci_bios_map_devices(busses); +-- +2.27.0 + diff --git a/seabios-increase-the-seabios-high-mem-zone-size.patch b/seabios-increase-the-seabios-high-mem-zone-size.patch new file mode 100644 index 0000000000000000000000000000000000000000..01c16d1db2827e6948158e9bcac0823467668554 --- /dev/null +++ b/seabios-increase-the-seabios-high-mem-zone-size.patch @@ -0,0 +1,34 @@ +From bf72a9439d06fe35e3c7246b60e1c5b7b8058459 Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Fri, 11 Feb 2022 16:34:23 +0800 +Subject: [PATCH 6/6] seabios: increase the seabios high mem zone size + +In terms of version and specification, under the maximum configuration +specification of the number of vcpus, virtio blocks and other features, +there exists bottleneck in seabios high_mem_zone, which results in the +memory application failure and causes the vm to fail to start. + +Increase BUILD_MAX_HIGHTABLE to 512k. + +Signed-off-by: liuxiangdong +Signed-off-by: jiangdongxu +--- + roms/seabios/src/config.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/roms/seabios/src/config.h b/roms/seabios/src/config.h +index 93c8dbc2d5..9abd43474e 100644 +--- a/roms/seabios/src/config.h ++++ b/roms/seabios/src/config.h +@@ -17,7 +17,7 @@ + // Maximum number of map entries in the e820 map + #define BUILD_MAX_E820 32 + // Space to reserve in high-memory for tables +-#define BUILD_MAX_HIGHTABLE (256*1024) ++#define BUILD_MAX_HIGHTABLE (512*1024) + // Largest supported externaly facing drive id + #define BUILD_MAX_EXTDRIVE 16 + // Number of bytes the smbios may be and still live in the f-segment +-- +2.27.0 + diff --git a/seabios-increase-the-seabios-minibiostable.patch b/seabios-increase-the-seabios-minibiostable.patch new file mode 100644 index 0000000000000000000000000000000000000000..bd3cfa461ecc6b436b43ac55775ece42b62d4aea --- /dev/null +++ b/seabios-increase-the-seabios-minibiostable.patch @@ -0,0 +1,33 @@ +From 764113a4a24e1d842a45fb62fc09279c87057616 Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Fri, 11 Feb 2022 16:33:04 +0800 +Subject: [PATCH 5/6] seabios: increase the seabios minibiostable + +Increase the BUILD_MIN_BIOSTABLE to 4096; +support 25 virtio-blk(data) + 1 virtio-scsi(sys) + 1 virtio-net + +Increase the BUILD_MIN_BIOSTABLE to 5120; +support 18 virtio-scsi while vm starts with IDE boot disk + +Signed-off-by: liuxiangdong +Signed-off-by: jiangdongxu +--- + roms/seabios/scripts/layoutrom.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/roms/seabios/scripts/layoutrom.py b/roms/seabios/scripts/layoutrom.py +index abebf0211f..e2732db8f9 100755 +--- a/roms/seabios/scripts/layoutrom.py ++++ b/roms/seabios/scripts/layoutrom.py +@@ -66,7 +66,7 @@ def setSectionsStart(sections, endaddr, minalign=1, segoffset=0): + BUILD_ROM_START = 0xc0000 + BUILD_LOWRAM_END = 0xa0000 + # Space to reserve in f-segment for dynamic allocations +-BUILD_MIN_BIOSTABLE = 2048 ++BUILD_MIN_BIOSTABLE = 5120 + + # Layout the 16bit code. This ensures sections with fixed offset + # requirements are placed in the correct location. It also places the +-- +2.27.0 + diff --git a/seqlock-fix-seqlock_write_unlock_impl-function.patch b/seqlock-fix-seqlock_write_unlock_impl-function.patch deleted file mode 100644 index f7f8c7cf6e044a663886db1b89f6c8bda36e2d25..0000000000000000000000000000000000000000 --- a/seqlock-fix-seqlock_write_unlock_impl-function.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 96e00e040cd8ae23cebf183cf3a8dc9cf1f6149d Mon Sep 17 00:00:00 2001 -From: Luc Michel -Date: Wed, 29 Jan 2020 15:49:48 +0100 -Subject: [PATCH] seqlock: fix seqlock_write_unlock_impl function -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The seqlock write unlock function was incorrectly calling -seqlock_write_begin() instead of seqlock_write_end(), and was releasing -the lock before incrementing the sequence. This could lead to a race -condition and a corrupted sequence number becoming odd even though the -lock is not held. - -Signed-off-by: Luc Michel -Reviewed-by: Philippe Mathieu-Daudé -Message-Id: <20200129144948.2161551-1-luc.michel@greensocs.com> -Fixes: 988fcafc73 ("seqlock: add QemuLockable support", 2018-08-23) -Signed-off-by: Paolo Bonzini ---- - include/qemu/seqlock.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/include/qemu/seqlock.h b/include/qemu/seqlock.h -index fd408b7ec5..8b6b4ee4bb 100644 ---- a/include/qemu/seqlock.h -+++ b/include/qemu/seqlock.h -@@ -55,11 +55,11 @@ static inline void seqlock_write_lock_impl(QemuSeqLock *sl, QemuLockable *lock) - #define seqlock_write_lock(sl, lock) \ - seqlock_write_lock_impl(sl, QEMU_MAKE_LOCKABLE(lock)) - --/* Lock out other writers and update the count. */ -+/* Update the count and release the lock. */ - static inline void seqlock_write_unlock_impl(QemuSeqLock *sl, QemuLockable *lock) - { -+ seqlock_write_end(sl); - qemu_lockable_unlock(lock); -- seqlock_write_begin(sl); - } - #define seqlock_write_unlock(sl, lock) \ - seqlock_write_unlock_impl(sl, QEMU_MAKE_LOCKABLE(lock)) --- -2.27.0 - diff --git a/slirp-check-pkt_len-before-reading-protocol-header.patch b/slirp-check-pkt_len-before-reading-protocol-header.patch deleted file mode 100644 index 506e31e1cb809bba769e857177c4e2ad70f4293f..0000000000000000000000000000000000000000 --- a/slirp-check-pkt_len-before-reading-protocol-header.patch +++ /dev/null @@ -1,61 +0,0 @@ -From c2df0d478b2605da10363ab57825cdbc34caa680 Mon Sep 17 00:00:00 2001 -From: Alex Chen -Date: Mon, 14 Dec 2020 15:39:46 +0800 -Subject: [PATCH] slirp: check pkt_len before reading protocol header -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -While processing ARP/NCSI packets in 'arp_input' or 'ncsi_input' -routines, ensure that pkt_len is large enough to accommodate the -respective protocol headers, lest it should do an OOB access. -Add check to avoid it. - -CVE-2020-29129 CVE-2020-29130 - QEMU: slirp: out-of-bounds access while processing ARP/NCSI packets - -> https://www.openwall.com/lists/oss-security/2020/11/27/1 - -Reported-by: Qiuhao Li -Signed-off-by: Prasad J Pandit -Message-Id: <20201126135706.273950-1-ppandit@redhat.com> -Reviewed-by: Marc-André Lureau -(cherry-picked from 2e1dcbc0) -Signed-off-by: Alex Chen ---- - slirp/src/ncsi.c | 4 ++++ - slirp/src/slirp.c | 4 ++++ - 2 files changed, 8 insertions(+) - -diff --git a/slirp/src/ncsi.c b/slirp/src/ncsi.c -index 6864b735..251c0d2b 100644 ---- a/slirp/src/ncsi.c -+++ b/slirp/src/ncsi.c -@@ -147,6 +147,10 @@ void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) - uint32_t checksum; - uint32_t *pchecksum; - -+ if (pkt_len < ETH_HLEN + sizeof(struct ncsi_pkt_hdr)) { -+ return; /* packet too short */ -+ } -+ - memset(ncsi_reply, 0, sizeof(ncsi_reply)); - - memset(reh->h_dest, 0xff, ETH_ALEN); -diff --git a/slirp/src/slirp.c b/slirp/src/slirp.c -index b0194cb3..86b0f52d 100644 ---- a/slirp/src/slirp.c -+++ b/slirp/src/slirp.c -@@ -700,6 +700,10 @@ static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) - return; - } - -+ if (pkt_len < ETH_HLEN + sizeof(struct slirp_arphdr)) { -+ return; /* packet too short */ -+ } -+ - ar_op = ntohs(ah->ar_op); - switch (ar_op) { - case ARPOP_REQUEST: --- -2.23.0 - diff --git a/slirp-tftp-restrict-relative-path-access.patch b/slirp-tftp-restrict-relative-path-access.patch deleted file mode 100644 index b7f09462525437c9048b4ab249b6e4208adda4ef..0000000000000000000000000000000000000000 --- a/slirp-tftp-restrict-relative-path-access.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 2fc07f4ce31a2cc9973cfb1c20897c6a4babd8b8 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Fri, 15 May 2020 16:45:28 +0800 -Subject: [PATCH] slirp: tftp: restrict relative path access - -tftp restricts relative or directory path access on Linux systems. -Apply same restrictions on Windows systems too. It helps to avoid -directory traversal issue. - -Fixes: https://bugs.launchpad.net/qemu/+bug/1812451Reported-by: default avatarPeter Maydell -Signed-off-by: default avatarPrasad J Pandit -Reviewed-by: Samuel Thibault's avatarSamuel Thibault -Message-Id: <20200113121431.156708-1-ppandit@redhat.com> - -diff --git a/slirp/src/tftp.c b/slirp/src/tftp.c -index 093c2e06..2b4176cc 100644 ---- a/slirp/src/tftp.c -+++ b/slirp/src/tftp.c -@@ -344,8 +344,13 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas, - k += 6; /* skipping octet */ - - /* do sanity checks on the filename */ -- if (!strncmp(req_fname, "../", 3) || -- req_fname[strlen(req_fname) - 1] == '/' || strstr(req_fname, "/../")) { -+ if ( -+#ifdef G_OS_WIN32 -+ strstr(req_fname, "..\\") || -+ req_fname[strlen(req_fname) - 1] == '\\' || -+#endif -+ strstr(req_fname, "../") || -+ req_fname[strlen(req_fname) -1] == '/') { - tftp_send_error(spt, 2, "Access violation", tp); - return; - } --- -2.23.0 - diff --git a/slirp-use-correct-size-while-emulating-IRC-commands.patch b/slirp-use-correct-size-while-emulating-IRC-commands.patch deleted file mode 100644 index 1b4039e1da3c0bcd08b97f4c61983ef3adac3823..0000000000000000000000000000000000000000 --- a/slirp-use-correct-size-while-emulating-IRC-commands.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 011880f527ff317a40769ea8673a6353e5db53ac Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Tue, 14 Apr 2020 18:23:23 +0800 -Subject: [PATCH] slirp: use correct size while emulating IRC commands - -While emulating IRC DCC commands, tcp_emu() uses 'mbuf' size -'m->m_size' to write DCC commands via snprintf(3). This may -lead to OOB write access, because 'bptr' points somewhere in -the middle of 'mbuf' buffer, not at the start. Use M_FREEROOM(m) -size to avoid OOB access. -Reported-by: default avatarVishnu Dev TJ -Signed-off-by: default avatarPrasad J Pandit -Reviewed-by: Samuel Thibault's avatarSamuel Thibault -Message-Id: <20200109094228.79764-2-ppandit@redhat.com> ---- - slirp/src/tcp_subr.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/slirp/src/tcp_subr.c b/slirp/src/tcp_subr.c -index 9c94c03a..2a15b16a 100644 ---- a/slirp/src/tcp_subr.c -+++ b/slirp/src/tcp_subr.c -@@ -778,7 +778,8 @@ int tcp_emu(struct socket *so, struct mbuf *m) - return 1; - } - m->m_len = bptr - m->m_data; /* Adjust length */ -- m->m_len += snprintf(bptr, m->m_size, "DCC CHAT chat %lu %u%c\n", -+ m->m_len += snprintf(bptr, M_FREEROOM(m), -+ "DCC CHAT chat %lu %u%c\n", - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), 1); - } else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, -@@ -789,7 +790,8 @@ int tcp_emu(struct socket *so, struct mbuf *m) - } - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += -- snprintf(bptr, m->m_size, "DCC SEND %s %lu %u %u%c\n", buff, -+ snprintf(bptr, M_FREEROOM(m), -+ "DCC SEND %s %lu %u %u%c\n", buff, - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), n1, 1); - } else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, -@@ -800,7 +802,8 @@ int tcp_emu(struct socket *so, struct mbuf *m) - } - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += -- snprintf(bptr, m->m_size, "DCC MOVE %s %lu %u %u%c\n", buff, -+ snprintf(bptr, M_FREEROOM(m), -+ "DCC MOVE %s %lu %u %u%c\n", buff, - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), n1, 1); - } --- -2.23.0 diff --git a/slirp-use-correct-size-while-emulating-commands.patch b/slirp-use-correct-size-while-emulating-commands.patch deleted file mode 100644 index 25f64e2738e2ae3cbff541719b726dff963007d2..0000000000000000000000000000000000000000 --- a/slirp-use-correct-size-while-emulating-commands.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 662aa4f1d168b32335a4dc40782e816329afcac0 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Tue, 14 Apr 2020 18:36:12 +0800 -Subject: [PATCH] slirp: use correct size while emulating commands - -While emulating services in tcp_emu(), it uses 'mbuf' size -'m->m_size' to write commands via snprintf(3). Use M_FREEROOM(m) -size to avoid possible OOB access. -Signed-off-by: default avatarPrasad J Pandit -Signed-off-by: Samuel Thibault's avatarSamuel Thibault -Message-Id: <20200109094228.79764-3-ppandit@redhat.com> ---- - slirp/src/tcp_subr.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/slirp/src/tcp_subr.c b/slirp/src/tcp_subr.c -index 2a15b16a..019b637a 100644 ---- a/slirp/src/tcp_subr.c -+++ b/slirp/src/tcp_subr.c -@@ -696,7 +696,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) - n4 = (laddr & 0xff); - - m->m_len = bptr - m->m_data; /* Adjust length */ -- m->m_len += snprintf(bptr, m->m_size - m->m_len, -+ m->m_len += snprintf(bptr, M_FREEROOM(m), - "ORT %d,%d,%d,%d,%d,%d\r\n%s", n1, n2, n3, n4, - n5, n6, x == 7 ? buff : ""); - return 1; -@@ -732,7 +732,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) - - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += -- snprintf(bptr, m->m_size - m->m_len, -+ snprintf(bptr, M_FREEROOM(m), - "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s", - n1, n2, n3, n4, n5, n6, x == 7 ? buff : ""); - -@@ -759,7 +759,8 @@ int tcp_emu(struct socket *so, struct mbuf *m) - (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr, - htons(lport), SS_FACCEPTONCE)) != NULL) - m->m_len = -- snprintf(m->m_data, m->m_size, "%d", ntohs(so->so_fport)) + 1; -+ snprintf(m->m_data, M_ROOM(m), -+ "%d", ntohs(so->so_fport)) + 1; - return 1; - - case EMU_IRC: --- -2.23.0 diff --git a/sm501-Clean-up-local-variables-in-sm501_2d_operation.patch b/sm501-Clean-up-local-variables-in-sm501_2d_operation.patch deleted file mode 100644 index 66e54cdd42053d31cfa05ffa9ee15fca183254ea..0000000000000000000000000000000000000000 --- a/sm501-Clean-up-local-variables-in-sm501_2d_operation.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 6186d3de416825e3a737dd3da31da475f50d66d0 Mon Sep 17 00:00:00 2001 -From: BALATON Zoltan -Date: Thu, 21 May 2020 21:39:44 +0200 -Subject: [PATCH] sm501: Clean up local variables in sm501_2d_operation -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Make variables local to the block they are used in to make it clearer -which operation they are needed for. - -Signed-off-by: BALATON Zoltan -Reviewed-by: Philippe Mathieu-Daudé -Message-id: ae59f8138afe7f6a5a4a82539d0f61496a906b06.1590089984.git.balaton@eik.bme.hu -Signed-off-by: Gerd Hoffmann ---- - hw/display/sm501.c | 31 ++++++++++++++++--------------- - 1 file changed, 16 insertions(+), 15 deletions(-) - -diff --git a/hw/display/sm501.c b/hw/display/sm501.c -index f3d11d0b23..98b3b97f7b 100644 ---- a/hw/display/sm501.c -+++ b/hw/display/sm501.c -@@ -699,28 +699,19 @@ static inline void hwc_invalidate(SM501State *s, int crt) - - static void sm501_2d_operation(SM501State *s) - { -- /* obtain operation parameters */ - int cmd = (s->twoD_control >> 16) & 0x1F; - int rtl = s->twoD_control & BIT(27); -- int src_x = (s->twoD_source >> 16) & 0x01FFF; -- int src_y = s->twoD_source & 0xFFFF; -- int dst_x = (s->twoD_destination >> 16) & 0x01FFF; -- int dst_y = s->twoD_destination & 0xFFFF; -- int width = (s->twoD_dimension >> 16) & 0x1FFF; -- int height = s->twoD_dimension & 0xFFFF; -- uint32_t color = s->twoD_foreground; - int format = (s->twoD_stretch >> 20) & 0x3; - int rop_mode = (s->twoD_control >> 15) & 0x1; /* 1 for rop2, else rop3 */ - /* 1 if rop2 source is the pattern, otherwise the source is the bitmap */ - int rop2_source_is_pattern = (s->twoD_control >> 14) & 0x1; - int rop = s->twoD_control & 0xFF; -- uint32_t src_base = s->twoD_source_base & 0x03FFFFFF; -+ int dst_x = (s->twoD_destination >> 16) & 0x01FFF; -+ int dst_y = s->twoD_destination & 0xFFFF; -+ int width = (s->twoD_dimension >> 16) & 0x1FFF; -+ int height = s->twoD_dimension & 0xFFFF; - uint32_t dst_base = s->twoD_destination_base & 0x03FFFFFF; -- -- /* get frame buffer info */ -- uint8_t *src = s->local_mem + src_base; - uint8_t *dst = s->local_mem + dst_base; -- int src_pitch = s->twoD_pitch & 0x1FFF; - int dst_pitch = (s->twoD_pitch >> 16) & 0x1FFF; - int crt = (s->dc_crt_control & SM501_DC_CRT_CONTROL_SEL) ? 1 : 0; - int fb_len = get_width(s, crt) * get_height(s, crt) * get_bpp(s, crt); -@@ -758,6 +749,13 @@ static void sm501_2d_operation(SM501State *s) - - switch (cmd) { - case 0x00: /* copy area */ -+ { -+ int src_x = (s->twoD_source >> 16) & 0x01FFF; -+ int src_y = s->twoD_source & 0xFFFF; -+ uint32_t src_base = s->twoD_source_base & 0x03FFFFFF; -+ uint8_t *src = s->local_mem + src_base; -+ int src_pitch = s->twoD_pitch & 0x1FFF; -+ - #define COPY_AREA(_bpp, _pixel_type, rtl) { \ - int y, x, index_d, index_s; \ - for (y = 0; y < height; y++) { \ -@@ -793,8 +791,11 @@ static void sm501_2d_operation(SM501State *s) - break; - } - break; -- -+ } - case 0x01: /* fill rectangle */ -+ { -+ uint32_t color = s->twoD_foreground; -+ - #define FILL_RECT(_bpp, _pixel_type) { \ - int y, x; \ - for (y = 0; y < height; y++) { \ -@@ -819,7 +820,7 @@ static void sm501_2d_operation(SM501State *s) - break; - } - break; -- -+ } - default: - qemu_log_mask(LOG_UNIMP, "sm501: not implemented 2D operation: %d\n", - cmd); --- -2.23.0 - diff --git a/sm501-Convert-printf-abort-to-qemu_log_mask.patch b/sm501-Convert-printf-abort-to-qemu_log_mask.patch deleted file mode 100644 index 14a530bd78510f91daf5f78e9b9103f1b729f9cf..0000000000000000000000000000000000000000 --- a/sm501-Convert-printf-abort-to-qemu_log_mask.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 428e3a78ddf1de3dfb914043d6a8668f73ef8bb3 Mon Sep 17 00:00:00 2001 -From: BALATON Zoltan -Date: Thu, 21 May 2020 21:39:44 +0200 -Subject: [PATCH] sm501: Convert printf + abort to qemu_log_mask -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Some places already use qemu_log_mask() to log unimplemented features -or errors but some others have printf() then abort(). Convert these to -qemu_log_mask() and avoid aborting to prevent guests to easily cause -denial of service. - -Signed-off-by: BALATON Zoltan -Reviewed-by: Philippe Mathieu-Daudé -Message-id: 305af87f59d81e92f2aaff09eb8a3603b8baa322.1590089984.git.balaton@eik.bme.hu -Signed-off-by: Gerd Hoffmann ---- - hw/display/sm501.c | 57 ++++++++++++++++++++++------------------------ - 1 file changed, 27 insertions(+), 30 deletions(-) - -diff --git a/hw/display/sm501.c b/hw/display/sm501.c -index 5918f59b2b..aa4b202a48 100644 ---- a/hw/display/sm501.c -+++ b/hw/display/sm501.c -@@ -727,8 +727,8 @@ static void sm501_2d_operation(SM501State *s) - int fb_len = get_width(s, crt) * get_height(s, crt) * get_bpp(s, crt); - - if (addressing != 0x0) { -- printf("%s: only XY addressing is supported.\n", __func__); -- abort(); -+ qemu_log_mask(LOG_UNIMP, "sm501: only XY addressing is supported.\n"); -+ return; - } - - if (rop_mode == 0) { -@@ -754,8 +754,8 @@ static void sm501_2d_operation(SM501State *s) - - if ((s->twoD_source_base & 0x08000000) || - (s->twoD_destination_base & 0x08000000)) { -- printf("%s: only local memory is supported.\n", __func__); -- abort(); -+ qemu_log_mask(LOG_UNIMP, "sm501: only local memory is supported.\n"); -+ return; - } - - switch (operation) { -@@ -823,9 +823,9 @@ static void sm501_2d_operation(SM501State *s) - break; - - default: -- printf("non-implemented SM501 2D operation. %d\n", operation); -- abort(); -- break; -+ qemu_log_mask(LOG_UNIMP, "sm501: not implemented 2D operation: %d\n", -+ operation); -+ return; - } - - if (dst_base >= get_fb_addr(s, crt) && -@@ -892,9 +892,8 @@ static uint64_t sm501_system_config_read(void *opaque, hwaddr addr, - break; - - default: -- printf("sm501 system config : not implemented register read." -- " addr=%x\n", (int)addr); -- abort(); -+ qemu_log_mask(LOG_UNIMP, "sm501: not implemented system config" -+ "register read. addr=%" HWADDR_PRIx "\n", addr); - } - - return ret; -@@ -948,15 +947,15 @@ static void sm501_system_config_write(void *opaque, hwaddr addr, - break; - case SM501_ENDIAN_CONTROL: - if (value & 0x00000001) { -- printf("sm501 system config : big endian mode not implemented.\n"); -- abort(); -+ qemu_log_mask(LOG_UNIMP, "sm501: system config big endian mode not" -+ " implemented.\n"); - } - break; - - default: -- printf("sm501 system config : not implemented register write." -- " addr=%x, val=%x\n", (int)addr, (uint32_t)value); -- abort(); -+ qemu_log_mask(LOG_UNIMP, "sm501: not implemented system config" -+ "register write. addr=%" HWADDR_PRIx -+ ", val=%" PRIx64 "\n", addr, value); - } - } - -@@ -1207,9 +1206,8 @@ static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr addr, - break; - - default: -- printf("sm501 disp ctrl : not implemented register read." -- " addr=%x\n", (int)addr); -- abort(); -+ qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register " -+ "read. addr=%" HWADDR_PRIx "\n", addr); - } - - return ret; -@@ -1345,9 +1343,9 @@ static void sm501_disp_ctrl_write(void *opaque, hwaddr addr, - break; - - default: -- printf("sm501 disp ctrl : not implemented register write." -- " addr=%x, val=%x\n", (int)addr, (unsigned)value); -- abort(); -+ qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register " -+ "write. addr=%" HWADDR_PRIx -+ ", val=%" PRIx64 "\n", addr, value); - } - } - -@@ -1433,9 +1431,8 @@ static uint64_t sm501_2d_engine_read(void *opaque, hwaddr addr, - ret = 0; /* Should return interrupt status */ - break; - default: -- printf("sm501 disp ctrl : not implemented register read." -- " addr=%x\n", (int)addr); -- abort(); -+ qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register " -+ "read. addr=%" HWADDR_PRIx "\n", addr); - } - - return ret; -@@ -1520,9 +1517,9 @@ static void sm501_2d_engine_write(void *opaque, hwaddr addr, - /* ignored, writing 0 should clear interrupt status */ - break; - default: -- printf("sm501 2d engine : not implemented register write." -- " addr=%x, val=%x\n", (int)addr, (unsigned)value); -- abort(); -+ qemu_log_mask(LOG_UNIMP, "sm501: not implemented 2d engine register " -+ "write. addr=%" HWADDR_PRIx -+ ", val=%" PRIx64 "\n", addr, value); - } - } - -@@ -1670,9 +1667,9 @@ static void sm501_update_display(void *opaque) - draw_line = draw_line32_funcs[dst_depth_index]; - break; - default: -- printf("sm501 update display : invalid control register value.\n"); -- abort(); -- break; -+ qemu_log_mask(LOG_GUEST_ERROR, "sm501: update display" -+ "invalid control register value.\n"); -+ return; - } - - /* set up to draw hardware cursor */ --- -2.23.0 - diff --git a/sm501-Replace-hand-written-implementation-with-pixma.patch b/sm501-Replace-hand-written-implementation-with-pixma.patch deleted file mode 100644 index 42fa23aa934b29c19921f869530b93f1f24e1def..0000000000000000000000000000000000000000 --- a/sm501-Replace-hand-written-implementation-with-pixma.patch +++ /dev/null @@ -1,261 +0,0 @@ -From bbbf2c2f4201eb84a5bcd07a92399fe166d682e9 Mon Sep 17 00:00:00 2001 -From: BALATON Zoltan -Date: Thu, 21 May 2020 21:39:44 +0200 -Subject: [PATCH] sm501: Replace hand written implementation with pixman where - possible - -Besides being faster this should also prevent malicious guests to -abuse 2D engine to overwrite data or cause a crash. - -Signed-off-by: BALATON Zoltan -Message-id: 58666389b6cae256e4e972a32c05cf8aa51bffc0.1590089984.git.balaton@eik.bme.hu -Signed-off-by: Gerd Hoffmann ---- - hw/display/sm501.c | 207 ++++++++++++++++++++++++++------------------- - 1 file changed, 119 insertions(+), 88 deletions(-) - -diff --git a/hw/display/sm501.c b/hw/display/sm501.c -index 98b3b97f7b..7dc4bb18b7 100644 ---- a/hw/display/sm501.c -+++ b/hw/display/sm501.c -@@ -706,13 +706,12 @@ static void sm501_2d_operation(SM501State *s) - /* 1 if rop2 source is the pattern, otherwise the source is the bitmap */ - int rop2_source_is_pattern = (s->twoD_control >> 14) & 0x1; - int rop = s->twoD_control & 0xFF; -- int dst_x = (s->twoD_destination >> 16) & 0x01FFF; -- int dst_y = s->twoD_destination & 0xFFFF; -- int width = (s->twoD_dimension >> 16) & 0x1FFF; -- int height = s->twoD_dimension & 0xFFFF; -+ unsigned int dst_x = (s->twoD_destination >> 16) & 0x01FFF; -+ unsigned int dst_y = s->twoD_destination & 0xFFFF; -+ unsigned int width = (s->twoD_dimension >> 16) & 0x1FFF; -+ unsigned int height = s->twoD_dimension & 0xFFFF; - uint32_t dst_base = s->twoD_destination_base & 0x03FFFFFF; -- uint8_t *dst = s->local_mem + dst_base; -- int dst_pitch = (s->twoD_pitch >> 16) & 0x1FFF; -+ unsigned int dst_pitch = (s->twoD_pitch >> 16) & 0x1FFF; - int crt = (s->dc_crt_control & SM501_DC_CRT_CONTROL_SEL) ? 1 : 0; - int fb_len = get_width(s, crt) * get_height(s, crt) * get_bpp(s, crt); - -@@ -721,104 +720,136 @@ static void sm501_2d_operation(SM501State *s) - return; - } - -- if (rop_mode == 0) { -- if (rop != 0xcc) { -- /* Anything other than plain copies are not supported */ -- qemu_log_mask(LOG_UNIMP, "sm501: rop3 mode with rop %x is not " -- "supported.\n", rop); -- } -- } else { -- if (rop2_source_is_pattern && rop != 0x5) { -- /* For pattern source, we support only inverse dest */ -- qemu_log_mask(LOG_UNIMP, "sm501: rop2 source being the pattern and " -- "rop %x is not supported.\n", rop); -- } else { -- if (rop != 0x5 && rop != 0xc) { -- /* Anything other than plain copies or inverse dest is not -- * supported */ -- qemu_log_mask(LOG_UNIMP, "sm501: rop mode %x is not " -- "supported.\n", rop); -- } -- } -- } -- - if (s->twoD_source_base & BIT(27) || s->twoD_destination_base & BIT(27)) { - qemu_log_mask(LOG_UNIMP, "sm501: only local memory is supported.\n"); - return; - } - -+ if (!dst_pitch) { -+ qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero dest pitch.\n"); -+ return; -+ } -+ -+ if (!width || !height) { -+ qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero size 2D op.\n"); -+ return; -+ } -+ -+ if (rtl) { -+ dst_x -= width - 1; -+ dst_y -= height - 1; -+ } -+ -+ if (dst_base >= get_local_mem_size(s) || dst_base + -+ (dst_x + width + (dst_y + height) * (dst_pitch + width)) * -+ (1 << format) >= get_local_mem_size(s)) { -+ qemu_log_mask(LOG_GUEST_ERROR, "sm501: 2D op dest is outside vram.\n"); -+ return; -+ } -+ - switch (cmd) { -- case 0x00: /* copy area */ -+ case 0: /* BitBlt */ - { -- int src_x = (s->twoD_source >> 16) & 0x01FFF; -- int src_y = s->twoD_source & 0xFFFF; -+ unsigned int src_x = (s->twoD_source >> 16) & 0x01FFF; -+ unsigned int src_y = s->twoD_source & 0xFFFF; - uint32_t src_base = s->twoD_source_base & 0x03FFFFFF; -- uint8_t *src = s->local_mem + src_base; -- int src_pitch = s->twoD_pitch & 0x1FFF; -- --#define COPY_AREA(_bpp, _pixel_type, rtl) { \ -- int y, x, index_d, index_s; \ -- for (y = 0; y < height; y++) { \ -- for (x = 0; x < width; x++) { \ -- _pixel_type val; \ -- \ -- if (rtl) { \ -- index_s = ((src_y - y) * src_pitch + src_x - x) * _bpp; \ -- index_d = ((dst_y - y) * dst_pitch + dst_x - x) * _bpp; \ -- } else { \ -- index_s = ((src_y + y) * src_pitch + src_x + x) * _bpp; \ -- index_d = ((dst_y + y) * dst_pitch + dst_x + x) * _bpp; \ -- } \ -- if (rop_mode == 1 && rop == 5) { \ -- /* Invert dest */ \ -- val = ~*(_pixel_type *)&dst[index_d]; \ -- } else { \ -- val = *(_pixel_type *)&src[index_s]; \ -- } \ -- *(_pixel_type *)&dst[index_d] = val; \ -- } \ -- } \ -- } -- switch (format) { -- case 0: -- COPY_AREA(1, uint8_t, rtl); -- break; -- case 1: -- COPY_AREA(2, uint16_t, rtl); -- break; -- case 2: -- COPY_AREA(4, uint32_t, rtl); -- break; -+ unsigned int src_pitch = s->twoD_pitch & 0x1FFF; -+ -+ if (!src_pitch) { -+ qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero src pitch.\n"); -+ return; -+ } -+ -+ if (rtl) { -+ src_x -= width - 1; -+ src_y -= height - 1; -+ } -+ -+ if (src_base >= get_local_mem_size(s) || src_base + -+ (src_x + width + (src_y + height) * (src_pitch + width)) * -+ (1 << format) >= get_local_mem_size(s)) { -+ qemu_log_mask(LOG_GUEST_ERROR, -+ "sm501: 2D op src is outside vram.\n"); -+ return; -+ } -+ -+ if ((rop_mode && rop == 0x5) || (!rop_mode && rop == 0x55)) { -+ /* Invert dest, is there a way to do this with pixman? */ -+ unsigned int x, y, i; -+ uint8_t *d = s->local_mem + dst_base; -+ -+ for (y = 0; y < height; y++) { -+ i = (dst_x + (dst_y + y) * dst_pitch) * (1 << format); -+ for (x = 0; x < width; x++, i += (1 << format)) { -+ switch (format) { -+ case 0: -+ d[i] = ~d[i]; -+ break; -+ case 1: -+ *(uint16_t *)&d[i] = ~*(uint16_t *)&d[i]; -+ break; -+ case 2: -+ *(uint32_t *)&d[i] = ~*(uint32_t *)&d[i]; -+ break; -+ } -+ } -+ } -+ } else { -+ /* Do copy src for unimplemented ops, better than unpainted area */ -+ if ((rop_mode && (rop != 0xc || rop2_source_is_pattern)) || -+ (!rop_mode && rop != 0xcc)) { -+ qemu_log_mask(LOG_UNIMP, -+ "sm501: rop%d op %x%s not implemented\n", -+ (rop_mode ? 2 : 3), rop, -+ (rop2_source_is_pattern ? -+ " with pattern source" : "")); -+ } -+ /* Check for overlaps, this could be made more exact */ -+ uint32_t sb, se, db, de; -+ sb = src_base + src_x + src_y * (width + src_pitch); -+ se = sb + width + height * (width + src_pitch); -+ db = dst_base + dst_x + dst_y * (width + dst_pitch); -+ de = db + width + height * (width + dst_pitch); -+ if (rtl && ((db >= sb && db <= se) || (de >= sb && de <= se))) { -+ /* regions may overlap: copy via temporary */ -+ int llb = width * (1 << format); -+ int tmp_stride = DIV_ROUND_UP(llb, sizeof(uint32_t)); -+ uint32_t *tmp = g_malloc(tmp_stride * sizeof(uint32_t) * -+ height); -+ pixman_blt((uint32_t *)&s->local_mem[src_base], tmp, -+ src_pitch * (1 << format) / sizeof(uint32_t), -+ tmp_stride, 8 * (1 << format), 8 * (1 << format), -+ src_x, src_y, 0, 0, width, height); -+ pixman_blt(tmp, (uint32_t *)&s->local_mem[dst_base], -+ tmp_stride, -+ dst_pitch * (1 << format) / sizeof(uint32_t), -+ 8 * (1 << format), 8 * (1 << format), -+ 0, 0, dst_x, dst_y, width, height); -+ g_free(tmp); -+ } else { -+ pixman_blt((uint32_t *)&s->local_mem[src_base], -+ (uint32_t *)&s->local_mem[dst_base], -+ src_pitch * (1 << format) / sizeof(uint32_t), -+ dst_pitch * (1 << format) / sizeof(uint32_t), -+ 8 * (1 << format), 8 * (1 << format), -+ src_x, src_y, dst_x, dst_y, width, height); -+ } - } - break; - } -- case 0x01: /* fill rectangle */ -+ case 1: /* Rectangle Fill */ - { - uint32_t color = s->twoD_foreground; - --#define FILL_RECT(_bpp, _pixel_type) { \ -- int y, x; \ -- for (y = 0; y < height; y++) { \ -- for (x = 0; x < width; x++) { \ -- int index = ((dst_y + y) * dst_pitch + dst_x + x) * _bpp; \ -- *(_pixel_type *)&dst[index] = (_pixel_type)color; \ -- } \ -- } \ -- } -- -- switch (format) { -- case 0: -- FILL_RECT(1, uint8_t); -- break; -- case 1: -- color = cpu_to_le16(color); -- FILL_RECT(2, uint16_t); -- break; -- case 2: -+ if (format == 2) { - color = cpu_to_le32(color); -- FILL_RECT(4, uint32_t); -- break; -+ } else if (format == 1) { -+ color = cpu_to_le16(color); - } -+ -+ pixman_fill((uint32_t *)&s->local_mem[dst_base], -+ dst_pitch * (1 << format) / sizeof(uint32_t), -+ 8 * (1 << format), dst_x, dst_y, width, height, color); - break; - } - default: --- -2.23.0 - diff --git a/sm501-Shorten-long-variable-names-in-sm501_2d_operat.patch b/sm501-Shorten-long-variable-names-in-sm501_2d_operat.patch deleted file mode 100644 index a2eefcba1e31e338ad6d934bf9e112a98d013b04..0000000000000000000000000000000000000000 --- a/sm501-Shorten-long-variable-names-in-sm501_2d_operat.patch +++ /dev/null @@ -1,134 +0,0 @@ -From bc472e56b985db1de73a7ddab5ea8568d6e7f327 Mon Sep 17 00:00:00 2001 -From: BALATON Zoltan -Date: Thu, 21 May 2020 21:39:44 +0200 -Subject: [PATCH] sm501: Shorten long variable names in sm501_2d_operation - -This increases readability and cleans up some confusing naming. - -Signed-off-by: BALATON Zoltan -Message-id: b9b67b94c46e945252a73c77dfd117132c63c4fb.1590089984.git.balaton@eik.bme.hu -Signed-off-by: Gerd Hoffmann ---- - hw/display/sm501.c | 45 ++++++++++++++++++++++----------------------- - 1 file changed, 22 insertions(+), 23 deletions(-) - -diff --git a/hw/display/sm501.c b/hw/display/sm501.c -index aa4b202a48..51e7ccc39d 100644 ---- a/hw/display/sm501.c -+++ b/hw/display/sm501.c -@@ -700,17 +700,16 @@ static inline void hwc_invalidate(SM501State *s, int crt) - static void sm501_2d_operation(SM501State *s) - { - /* obtain operation parameters */ -- int operation = (s->twoD_control >> 16) & 0x1f; -+ int cmd = (s->twoD_control >> 16) & 0x1F; - int rtl = s->twoD_control & 0x8000000; - int src_x = (s->twoD_source >> 16) & 0x01FFF; - int src_y = s->twoD_source & 0xFFFF; - int dst_x = (s->twoD_destination >> 16) & 0x01FFF; - int dst_y = s->twoD_destination & 0xFFFF; -- int operation_width = (s->twoD_dimension >> 16) & 0x1FFF; -- int operation_height = s->twoD_dimension & 0xFFFF; -+ int width = (s->twoD_dimension >> 16) & 0x1FFF; -+ int height = s->twoD_dimension & 0xFFFF; - uint32_t color = s->twoD_foreground; -- int format_flags = (s->twoD_stretch >> 20) & 0x3; -- int addressing = (s->twoD_stretch >> 16) & 0xF; -+ int format = (s->twoD_stretch >> 20) & 0x3; - int rop_mode = (s->twoD_control >> 15) & 0x1; /* 1 for rop2, else rop3 */ - /* 1 if rop2 source is the pattern, otherwise the source is the bitmap */ - int rop2_source_is_pattern = (s->twoD_control >> 14) & 0x1; -@@ -721,12 +720,12 @@ static void sm501_2d_operation(SM501State *s) - /* get frame buffer info */ - uint8_t *src = s->local_mem + src_base; - uint8_t *dst = s->local_mem + dst_base; -- int src_width = s->twoD_pitch & 0x1FFF; -- int dst_width = (s->twoD_pitch >> 16) & 0x1FFF; -+ int src_pitch = s->twoD_pitch & 0x1FFF; -+ int dst_pitch = (s->twoD_pitch >> 16) & 0x1FFF; - int crt = (s->dc_crt_control & SM501_DC_CRT_CONTROL_SEL) ? 1 : 0; - int fb_len = get_width(s, crt) * get_height(s, crt) * get_bpp(s, crt); - -- if (addressing != 0x0) { -+ if ((s->twoD_stretch >> 16) & 0xF) { - qemu_log_mask(LOG_UNIMP, "sm501: only XY addressing is supported.\n"); - return; - } -@@ -758,20 +757,20 @@ static void sm501_2d_operation(SM501State *s) - return; - } - -- switch (operation) { -+ switch (cmd) { - case 0x00: /* copy area */ - #define COPY_AREA(_bpp, _pixel_type, rtl) { \ - int y, x, index_d, index_s; \ -- for (y = 0; y < operation_height; y++) { \ -- for (x = 0; x < operation_width; x++) { \ -+ for (y = 0; y < height; y++) { \ -+ for (x = 0; x < width; x++) { \ - _pixel_type val; \ - \ - if (rtl) { \ -- index_s = ((src_y - y) * src_width + src_x - x) * _bpp; \ -- index_d = ((dst_y - y) * dst_width + dst_x - x) * _bpp; \ -+ index_s = ((src_y - y) * src_pitch + src_x - x) * _bpp; \ -+ index_d = ((dst_y - y) * dst_pitch + dst_x - x) * _bpp; \ - } else { \ -- index_s = ((src_y + y) * src_width + src_x + x) * _bpp; \ -- index_d = ((dst_y + y) * dst_width + dst_x + x) * _bpp; \ -+ index_s = ((src_y + y) * src_pitch + src_x + x) * _bpp; \ -+ index_d = ((dst_y + y) * dst_pitch + dst_x + x) * _bpp; \ - } \ - if (rop_mode == 1 && rop == 5) { \ - /* Invert dest */ \ -@@ -783,7 +782,7 @@ static void sm501_2d_operation(SM501State *s) - } \ - } \ - } -- switch (format_flags) { -+ switch (format) { - case 0: - COPY_AREA(1, uint8_t, rtl); - break; -@@ -799,15 +798,15 @@ static void sm501_2d_operation(SM501State *s) - case 0x01: /* fill rectangle */ - #define FILL_RECT(_bpp, _pixel_type) { \ - int y, x; \ -- for (y = 0; y < operation_height; y++) { \ -- for (x = 0; x < operation_width; x++) { \ -- int index = ((dst_y + y) * dst_width + dst_x + x) * _bpp; \ -+ for (y = 0; y < height; y++) { \ -+ for (x = 0; x < width; x++) { \ -+ int index = ((dst_y + y) * dst_pitch + dst_x + x) * _bpp; \ - *(_pixel_type *)&dst[index] = (_pixel_type)color; \ - } \ - } \ - } - -- switch (format_flags) { -+ switch (format) { - case 0: - FILL_RECT(1, uint8_t); - break; -@@ -824,14 +823,14 @@ static void sm501_2d_operation(SM501State *s) - - default: - qemu_log_mask(LOG_UNIMP, "sm501: not implemented 2D operation: %d\n", -- operation); -+ cmd); - return; - } - - if (dst_base >= get_fb_addr(s, crt) && - dst_base <= get_fb_addr(s, crt) + fb_len) { -- int dst_len = MIN(fb_len, ((dst_y + operation_height - 1) * dst_width + -- dst_x + operation_width) * (1 << format_flags)); -+ int dst_len = MIN(fb_len, ((dst_y + height - 1) * dst_pitch + -+ dst_x + width) * (1 << format)); - if (dst_len) { - memory_region_set_dirty(&s->local_mem_region, dst_base, dst_len); - } --- -2.23.0 - diff --git a/sm501-Use-BIT-x-macro-to-shorten-constant.patch b/sm501-Use-BIT-x-macro-to-shorten-constant.patch deleted file mode 100644 index 697d0ee61d5cba82611b05f037a25397de5073b6..0000000000000000000000000000000000000000 --- a/sm501-Use-BIT-x-macro-to-shorten-constant.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 9f1e9012047639121eb275a4f8f5693d340e91f6 Mon Sep 17 00:00:00 2001 -From: BALATON Zoltan -Date: Thu, 21 May 2020 21:39:44 +0200 -Subject: [PATCH] sm501: Use BIT(x) macro to shorten constant -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: BALATON Zoltan -Reviewed-by: Philippe Mathieu-Daudé -Message-id: 124bf5de8d7cf503b32b377d0445029a76bfbd49.1590089984.git.balaton@eik.bme.hu -Signed-off-by: Gerd Hoffmann ---- - hw/display/sm501.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/hw/display/sm501.c b/hw/display/sm501.c -index 51e7ccc39d..f3d11d0b23 100644 ---- a/hw/display/sm501.c -+++ b/hw/display/sm501.c -@@ -701,7 +701,7 @@ static void sm501_2d_operation(SM501State *s) - { - /* obtain operation parameters */ - int cmd = (s->twoD_control >> 16) & 0x1F; -- int rtl = s->twoD_control & 0x8000000; -+ int rtl = s->twoD_control & BIT(27); - int src_x = (s->twoD_source >> 16) & 0x01FFF; - int src_y = s->twoD_source & 0xFFFF; - int dst_x = (s->twoD_destination >> 16) & 0x01FFF; -@@ -751,8 +751,7 @@ static void sm501_2d_operation(SM501State *s) - } - } - -- if ((s->twoD_source_base & 0x08000000) || -- (s->twoD_destination_base & 0x08000000)) { -+ if (s->twoD_source_base & BIT(27) || s->twoD_destination_base & BIT(27)) { - qemu_log_mask(LOG_UNIMP, "sm501: only local memory is supported.\n"); - return; - } --- -2.23.0 - diff --git a/smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch b/smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch index cfd1842d3f199ec1db6e324e448df37b4553ea2a..f1f9e91b6c6fa36fe8e362c1001c6ef3c68af72c 100644 --- a/smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch +++ b/smbios-Add-missing-member-of-type-4-for-smbios-3.0.patch @@ -1,4 +1,4 @@ -From 2b8ad77678da175cb92c902955cb85827e661de3 Mon Sep 17 00:00:00 2001 +From 937e22eda2480a64095928ee8df0d37b3313bb64 Mon Sep 17 00:00:00 2001 From: Ying Fang Date: Tue, 14 Apr 2020 14:53:44 +0800 Subject: [PATCH] smbios: Add missing member of type 4 for smbios 3.0 @@ -16,16 +16,17 @@ The corresponding codes in kernel is like: } Signed-off-by: zhanghailiang +Signed-off-by: Yan Wang --- 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 7bcd67b0..51b00d44 100644 +index 7397e56737..66be9aee09 100644 --- a/hw/smbios/smbios.c +++ b/hw/smbios/smbios.c -@@ -603,7 +603,9 @@ static void smbios_build_type_4_table(MachineState *ms, unsigned instance) +@@ -688,7 +688,9 @@ static void smbios_build_type_4_table(MachineState *ms, unsigned instance) t->thread_count = ms->smp.threads; t->processor_characteristics = cpu_to_le16(0x02); /* Unknown */ t->processor_family2 = cpu_to_le16(0x01); /* Other */ @@ -37,7 +38,7 @@ index 7bcd67b0..51b00d44 100644 smbios_type4_count++; } diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h -index 02a0ced0..6887bca4 100644 +index 5a0dd0c8cf..5a696cf75a 100644 --- a/include/hw/firmware/smbios.h +++ b/include/hw/firmware/smbios.h @@ -193,6 +193,9 @@ struct smbios_type_4 { @@ -48,7 +49,8 @@ index 02a0ced0..6887bca4 100644 + uint16_t enabledcorecount2; + uint16_t threadcount2; } QEMU_PACKED; - + /* SMBIOS type 11 - OEM strings */ --- -2.23.0 +-- +2.27.0 + diff --git a/softmmu-device_tree-Remove-redundant-pointer-assignm.patch b/softmmu-device_tree-Remove-redundant-pointer-assignm.patch new file mode 100644 index 0000000000000000000000000000000000000000..c98a0588cbc31d5ff36d2e5216c8fd6d3f50d508 --- /dev/null +++ b/softmmu-device_tree-Remove-redundant-pointer-assignm.patch @@ -0,0 +1,58 @@ +From ebf1ac6c0ead3d6fbc32466028c286588333c1ea Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Tue, 11 Jan 2022 11:27:58 +0800 +Subject: [PATCH 22/24] softmmu/device_tree: Remove redundant pointer + assignment + +The pointer assignment "const char *p = path;" in function +qemu_fdt_add_path is unnecessary. Let's remove it and just +use the "path" passed in. No functional change. + +Suggested-by: Richard Henderson +Signed-off-by: Yanan Wang +Reviewed-by: Andrew Jones +Reviewed-by: Alistair Francis +Reviewed-by: Thomas Huth +Message-id: 20220111032758.27804-1-wangyanan55@huawei.com +Signed-off-by: Alistair Francis +--- + softmmu/device_tree.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c +index 9e96f5ecd5..8897c79ea4 100644 +--- a/softmmu/device_tree.c ++++ b/softmmu/device_tree.c +@@ -556,7 +556,6 @@ int qemu_fdt_add_subnode(void *fdt, const char *name) + int qemu_fdt_add_path(void *fdt, const char *path) + { + const char *name; +- const char *p = path; + int namelen, retval; + int parent = 0; + +@@ -565,9 +564,9 @@ int qemu_fdt_add_path(void *fdt, const char *path) + } + + do { +- name = p + 1; +- p = strchr(name, '/'); +- namelen = p != NULL ? p - name : strlen(name); ++ name = path + 1; ++ path = strchr(name, '/'); ++ namelen = path != NULL ? path - name : strlen(name); + + retval = fdt_subnode_offset_namelen(fdt, parent, name, namelen); + if (retval < 0 && retval != -FDT_ERR_NOTFOUND) { +@@ -584,7 +583,7 @@ int qemu_fdt_add_path(void *fdt, const char *path) + } + + parent = retval; +- } while (p); ++ } while (path); + + return retval; + } +-- +2.27.0 + diff --git a/softmmu-device_tree-Silence-compiler-warning-with-en.patch b/softmmu-device_tree-Silence-compiler-warning-with-en.patch new file mode 100644 index 0000000000000000000000000000000000000000..68030155312cb20beca50b0e133e4c4b2ab536f4 --- /dev/null +++ b/softmmu-device_tree-Silence-compiler-warning-with-en.patch @@ -0,0 +1,60 @@ +From ecc0eb93e8856321ad940a85970f0db14ab9f146 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 7 Jan 2022 14:38:44 +0100 +Subject: [PATCH 21/24] softmmu/device_tree: Silence compiler warning with + --enable-sanitizers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If I configure my build with --enable-sanitizers, my GCC (v8.5.0) +complains: + +.../softmmu/device_tree.c: In function ‘qemu_fdt_add_path’: +.../softmmu/device_tree.c:560:18: error: ‘retval’ may be used uninitialized + in this function [-Werror=maybe-uninitialized] + int namelen, retval; + ^~~~~~ + +It's a false warning since the while loop is always executed at least +once (p has to be non-NULL, otherwise the derefence in the if-statement +earlier will crash). Thus let's switch to a do-while loop here instead +to make the compiler happy in all cases. + +Signed-off-by: Thomas Huth +Reviewed-by: Andrew Jones +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Richard Henderson +Reviewed-by: Alistair Francis +Reviewed-by: Yanan Wang +Message-id: 20220107133844.145039-1-thuth@redhat.com +Signed-off-by: Alistair Francis +--- + softmmu/device_tree.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c +index 3965c834ca..9e96f5ecd5 100644 +--- a/softmmu/device_tree.c ++++ b/softmmu/device_tree.c +@@ -564,7 +564,7 @@ int qemu_fdt_add_path(void *fdt, const char *path) + return -1; + } + +- while (p) { ++ do { + name = p + 1; + p = strchr(name, '/'); + namelen = p != NULL ? p - name : strlen(name); +@@ -584,7 +584,7 @@ int qemu_fdt_add_path(void *fdt, const char *path) + } + + parent = retval; +- } ++ } while (p); + + return retval; + } +-- +2.27.0 + diff --git a/spapr-Implement-get_dt_compatible-callback.patch b/spapr-Implement-get_dt_compatible-callback.patch deleted file mode 100644 index e64a8746f498a68085824f6cace1bb2e958ce7c7..0000000000000000000000000000000000000000 --- a/spapr-Implement-get_dt_compatible-callback.patch +++ /dev/null @@ -1,68 +0,0 @@ -From c520d8e823431be94268daa2a911e224cab81521 Mon Sep 17 00:00:00 2001 -From: Stefan Berger -Date: Tue, 21 Jan 2020 10:29:31 -0500 -Subject: [PATCH 04/19] spapr: Implement get_dt_compatible() callback -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -For devices that cannot be statically initialized, implement a -get_dt_compatible() callback that allows us to ask the device for -the 'compatible' value. - -Signed-off-by: Stefan Berger -Reviewed-by: Marc-André Lureau -Reviewed-by: David Gibson -Message-Id: <20200121152935.649898-3-stefanb@linux.ibm.com> -Signed-off-by: David Gibson -Signed-off-by: jiangfangjie ---- - hw/ppc/spapr_vio.c | 11 +++++++++-- - include/hw/ppc/spapr_vio.h | 1 + - 2 files changed, 10 insertions(+), 2 deletions(-) - -diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c -index 583c13de..4e50916f 100644 ---- a/hw/ppc/spapr_vio.c -+++ b/hw/ppc/spapr_vio.c -@@ -89,6 +89,7 @@ static int vio_make_devnode(SpaprVioDevice *dev, - SpaprVioDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev); - int vdevice_off, node_off, ret; - char *dt_name; -+ const char *dt_compatible; - - vdevice_off = fdt_path_offset(fdt, "/vdevice"); - if (vdevice_off < 0) { -@@ -115,9 +116,15 @@ static int vio_make_devnode(SpaprVioDevice *dev, - } - } - -- if (pc->dt_compatible) { -+ if (pc->get_dt_compatible) { -+ dt_compatible = pc->get_dt_compatible(dev); -+ } else { -+ dt_compatible = pc->dt_compatible; -+ } -+ -+ if (dt_compatible) { - ret = fdt_setprop_string(fdt, node_off, "compatible", -- pc->dt_compatible); -+ dt_compatible); - if (ret < 0) { - return ret; - } -diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h -index 04609f21..97951fc6 100644 ---- a/include/hw/ppc/spapr_vio.h -+++ b/include/hw/ppc/spapr_vio.h -@@ -56,6 +56,7 @@ typedef struct SpaprVioDeviceClass { - void (*realize)(SpaprVioDevice *dev, Error **errp); - void (*reset)(SpaprVioDevice *dev); - int (*devnode)(SpaprVioDevice *dev, void *fdt, int node_off); -+ const char *(*get_dt_compatible)(SpaprVioDevice *dev); - } SpaprVioDeviceClass; - - struct SpaprVioDevice { --- -2.23.0 - diff --git a/spapr_pci-add-spapr-msi-read-method.patch b/spapr_pci-add-spapr-msi-read-method.patch deleted file mode 100644 index 2cc4994f09171252daf5a435832480151c458f4b..0000000000000000000000000000000000000000 --- a/spapr_pci-add-spapr-msi-read-method.patch +++ /dev/null @@ -1,61 +0,0 @@ -From cbbcd56e090a59d0eaa4e35ed0efb24d6dd1003e Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Thu, 25 Mar 2021 17:23:24 +0800 -Subject: [PATCH] spapr_pci: add spapr msi read method - -fix CVE-2020-15469 - -Add spapr msi mmio read method to avoid NULL pointer dereference -issue. - -Reported-by: Lei Sun -Acked-by: David Gibson -Reviewed-by: Li Qiang -Signed-off-by: Prasad J Pandit - -Signed-off-by: Jiajie Li ---- - hw/ppc/spapr_pci.c | 13 +++++++++++-- - 1 file changed, 11 insertions(+), 2 deletions(-) - -diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c -index 9003fe9010..1571e049ab 100644 ---- a/hw/ppc/spapr_pci.c -+++ b/hw/ppc/spapr_pci.c -@@ -50,6 +50,7 @@ - #include "sysemu/kvm.h" - #include "sysemu/hostmem.h" - #include "sysemu/numa.h" -+#include "qemu/log.h" - - /* Copied from the kernel arch/powerpc/platforms/pseries/msi.c */ - #define RTAS_QUERY_FN 0 -@@ -743,6 +744,12 @@ static PCIINTxRoute spapr_route_intx_pin_to_irq(void *opaque, int pin) - return route; - } - -+static uint64_t spapr_msi_read(void *opaque, hwaddr addr, unsigned size) -+{ -+ qemu_log_mask(LOG_UNIMP, "%s not implemented\n", __func__); -+ return 0; -+} -+ - /* - * MSI/MSIX memory region implementation. - * The handler handles both MSI and MSIX. -@@ -760,8 +767,10 @@ static void spapr_msi_write(void *opaque, hwaddr addr, - } - - static const MemoryRegionOps spapr_msi_ops = { -- /* There is no .read as the read result is undefined by PCI spec */ -- .read = NULL, -+ /* .read result is undefined by PCI spec -+ * define .read method to avoid assert failure in memory_region_init_io -+ */ -+ .read = spapr_msi_read, - .write = spapr_msi_write, - .endianness = DEVICE_LITTLE_ENDIAN - }; --- -2.27.0 - diff --git a/ssi-Fix-bad-printf-format-specifiers.patch b/ssi-Fix-bad-printf-format-specifiers.patch deleted file mode 100644 index 811a14da46a4e55ca324209309774973b563b70c..0000000000000000000000000000000000000000 --- a/ssi-Fix-bad-printf-format-specifiers.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 073457a45eaccd2beac3c94c53a449b8f683501e Mon Sep 17 00:00:00 2001 -From: AlexChen -Date: Wed, 4 Nov 2020 18:22:45 +0800 -Subject: [PATCH] ssi: Fix bad printf format specifiers - -We should use printf format specifier "%u" instead of "%d" for -argument of type "unsigned int". - -Reported-by: Euler Robot -Signed-off-by: Alex Chen -Reviewed-by: Alistair Francis -Message-id: 5FA280F5.8060902@huawei.com -Signed-off-by: Peter Maydell -(cherry-picked from commit 9df0a97298) ---- - hw/ssi/imx_spi.c | 2 +- - hw/ssi/xilinx_spi.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c -index 5cec9b5d05..0b3052bdf9 100644 ---- a/hw/ssi/imx_spi.c -+++ b/hw/ssi/imx_spi.c -@@ -52,7 +52,7 @@ static const char *imx_spi_reg_name(uint32_t reg) - case ECSPI_MSGDATA: - return "ECSPI_MSGDATA"; - default: -- sprintf(unknown, "%d ?", reg); -+ sprintf(unknown, "%u ?", reg); - return unknown; - } - } -diff --git a/hw/ssi/xilinx_spi.c b/hw/ssi/xilinx_spi.c -index 1379cb164b..d2b69d027a 100644 ---- a/hw/ssi/xilinx_spi.c -+++ b/hw/ssi/xilinx_spi.c -@@ -139,7 +139,7 @@ static void xlx_spi_update_irq(XilinxSPI *s) - irq chain unless things really changed. */ - if (pending != s->irqline) { - s->irqline = pending; -- DB_PRINT("irq_change of state %d ISR:%x IER:%X\n", -+ DB_PRINT("irq_change of state %u ISR:%x IER:%X\n", - pending, s->regs[R_IPISR], s->regs[R_IPIER]); - qemu_set_irq(s->irq, pending); - } --- -2.27.0 - diff --git a/sw_64-Add-sw64-architecture-support.patch b/sw_64-Add-sw64-architecture-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..4bffadfbd69453b5c58bc32e821ed88148d809e1 --- /dev/null +++ b/sw_64-Add-sw64-architecture-support.patch @@ -0,0 +1,18277 @@ +From d74713d8e656e8d0f7a5200122119802e639ff49 Mon Sep 17 00:00:00 2001 +From: Lu Feifei +Date: Mon, 14 Mar 2022 11:04:02 +0800 +Subject: [PATCH] sw_64: Add sw64 architecture support + +Signed-off-by: Lu Feifei +--- + configs/devices/sw64-softmmu/default.mak | 10 + + configs/targets/sw64-softmmu.mak | 8 + + configure | 7 + + disas.c | 2 + + disas/meson.build | 1 + + disas/sw64.c | 1242 +++++++ + hw/Kconfig | 1 + + hw/meson.build | 1 + + hw/rtc/sun4v-rtc.c | 11 + + hw/sw64/Kconfig | 11 + + hw/sw64/Makefile.objs | 1 + + hw/sw64/core.h | 25 + + hw/sw64/core3.c | 182 ++ + hw/sw64/core3_board.c | 493 +++ + hw/sw64/meson.build | 10 + + hw/sw64/sw64_iommu.c | 567 ++++ + hw/sw64/trace-events | 3 + + include/disas/dis-asm.h | 4 + + include/elf.h | 44 + + include/hw/sw64/sw64_iommu.h | 105 + + include/qemu/atomic.h | 2 + + include/qemu/timer.h | 10 + + include/sysemu/arch_init.h | 1 + + linux-headers/asm-sw64/kvm.h | 122 + + linux-headers/asm-sw64/unistd.h | 380 +++ + linux-user/meson.build | 1 + + linux-user/sw64/cpu_loop.c | 108 + + linux-user/sw64/signal.c | 273 ++ + linux-user/sw64/sockbits.h | 1 + + linux-user/sw64/syscall_nr.h | 471 +++ + linux-user/sw64/target_cpu.h | 38 + + linux-user/sw64/target_elf.h | 14 + + linux-user/sw64/target_fcntl.h | 11 + + linux-user/sw64/target_signal.h | 98 + + linux-user/sw64/target_structs.h | 47 + + linux-user/sw64/target_syscall.h | 121 + + linux-user/sw64/termbits.h | 265 ++ + meson.build | 12 +- + pc-bios/core3-hmcode | Bin 0 -> 225904 bytes + pc-bios/core3-reset | Bin 0 -> 5032 bytes + pc-bios/core4-hmcode | Bin 0 -> 243040 bytes + pc-bios/meson.build | 3 + + pc-bios/uefi-bios-sw | Bin 0 -> 3145728 bytes + qapi/machine.json | 2 +- + softmmu/qdev-monitor.c | 3 +- + target/Kconfig | 1 + + target/meson.build | 1 + + target/sw64/Kconfig | 2 + + target/sw64/Makefile.objs | 4 + + target/sw64/cpu-param.h | 24 + + target/sw64/cpu-qom.h | 47 + + target/sw64/cpu.c | 457 +++ + target/sw64/cpu.h | 406 +++ + target/sw64/exception.c | 76 + + target/sw64/float_helper.c | 846 +++++ + target/sw64/helper.c | 349 ++ + target/sw64/helper.h | 127 + + target/sw64/int_helper.c | 118 + + target/sw64/kvm.c | 215 ++ + target/sw64/kvm_sw64.h | 47 + + target/sw64/machine.c | 18 + + target/sw64/meson.build | 19 + + target/sw64/profile.c | 2342 +++++++++++++ + target/sw64/profile.h | 541 +++ + target/sw64/simd_helper.c | 1058 ++++++ + target/sw64/translate.c | 3798 ++++++++++++++++++++++ + target/sw64/translate.h | 60 + + tcg/sw64/tcg-target-con-set.h | 39 + + tcg/sw64/tcg-target-con-str.h | 28 + + tcg/sw64/tcg-target.c.inc | 2109 ++++++++++++ + tcg/sw64/tcg-target.h | 123 + + tcg/sw64/tcg-target.opc.h | 15 + + 72 files changed, 17578 insertions(+), 3 deletions(-) + create mode 100644 configs/devices/sw64-softmmu/default.mak + create mode 100644 configs/targets/sw64-softmmu.mak + create mode 100755 disas/sw64.c + create mode 100644 hw/sw64/Kconfig + create mode 100644 hw/sw64/Makefile.objs + create mode 100644 hw/sw64/core.h + create mode 100644 hw/sw64/core3.c + create mode 100644 hw/sw64/core3_board.c + create mode 100644 hw/sw64/meson.build + create mode 100644 hw/sw64/sw64_iommu.c + create mode 100644 hw/sw64/trace-events + create mode 100644 include/hw/sw64/sw64_iommu.h + create mode 100644 linux-headers/asm-sw64/kvm.h + create mode 100644 linux-headers/asm-sw64/unistd.h + create mode 100644 linux-user/sw64/cpu_loop.c + create mode 100644 linux-user/sw64/signal.c + create mode 100644 linux-user/sw64/sockbits.h + create mode 100644 linux-user/sw64/syscall_nr.h + create mode 100644 linux-user/sw64/target_cpu.h + create mode 100644 linux-user/sw64/target_elf.h + create mode 100644 linux-user/sw64/target_fcntl.h + create mode 100644 linux-user/sw64/target_signal.h + create mode 100644 linux-user/sw64/target_structs.h + create mode 100644 linux-user/sw64/target_syscall.h + create mode 100644 linux-user/sw64/termbits.h + create mode 100755 pc-bios/core3-hmcode + create mode 100755 pc-bios/core3-reset + create mode 100755 pc-bios/core4-hmcode + create mode 100755 pc-bios/uefi-bios-sw + create mode 100644 target/sw64/Kconfig + create mode 100644 target/sw64/Makefile.objs + create mode 100644 target/sw64/cpu-param.h + create mode 100644 target/sw64/cpu-qom.h + create mode 100644 target/sw64/cpu.c + create mode 100644 target/sw64/cpu.h + create mode 100644 target/sw64/exception.c + create mode 100644 target/sw64/float_helper.c + create mode 100644 target/sw64/helper.c + create mode 100644 target/sw64/helper.h + create mode 100644 target/sw64/int_helper.c + create mode 100644 target/sw64/kvm.c + create mode 100644 target/sw64/kvm_sw64.h + create mode 100644 target/sw64/machine.c + create mode 100644 target/sw64/meson.build + create mode 100644 target/sw64/profile.c + create mode 100644 target/sw64/profile.h + create mode 100644 target/sw64/simd_helper.c + create mode 100644 target/sw64/translate.c + create mode 100644 target/sw64/translate.h + create mode 100755 tcg/sw64/tcg-target-con-set.h + create mode 100755 tcg/sw64/tcg-target-con-str.h + create mode 100755 tcg/sw64/tcg-target.c.inc + create mode 100755 tcg/sw64/tcg-target.h + create mode 100755 tcg/sw64/tcg-target.opc.h + +diff --git a/configs/devices/sw64-softmmu/default.mak b/configs/devices/sw64-softmmu/default.mak +new file mode 100644 +index 0000000000..0b4d56b43e +--- /dev/null ++++ b/configs/devices/sw64-softmmu/default.mak +@@ -0,0 +1,10 @@ ++# Default configuration for sw64-softmmu ++ ++# Uncomment the following lines to disable these optional devices: ++# ++#CONFIG_PCI_DEVICES=n ++#CONFIG_TEST_DEVICES=n ++ ++# Boards: ++# ++CONFIG_CORE3=y +diff --git a/configs/targets/sw64-softmmu.mak b/configs/targets/sw64-softmmu.mak +new file mode 100644 +index 0000000000..37cc2e05a6 +--- /dev/null ++++ b/configs/targets/sw64-softmmu.mak +@@ -0,0 +1,8 @@ ++# Default configuration for sw64-softmmu ++ ++# Boards: ++# ++TARGET_ARCH=sw64 ++TARGET_BASE_ARCH=sw64 ++TARGET_ABI_DIR=sw64 ++TARGET_SUPPORTS_MTTCG=y +diff --git a/configure b/configure +index 48c21775f3..9569d7a3d0 100755 +--- a/configure ++++ b/configure +@@ -612,6 +612,9 @@ case "$cpu" in + sparc|sun4[cdmuv]) + cpu="sparc" + ;; ++ sw_64) ++ cpu="sw64" ++ ;; + *) + # This will result in either an error or falling back to TCI later + ARCH=unknown +@@ -3268,6 +3271,10 @@ alpha) + # Ensure there's only a single GP + QEMU_CFLAGS="-msmall-data $QEMU_CFLAGS" + ;; ++sw*) ++ # Ensure there's only a single GP ++ QEMU_CFLAGS="-msmall-data $QEMU_CFLAGS" ++;; + esac + + if test "$gprof" = "yes" ; then +diff --git a/disas.c b/disas.c +index 3dab4482d1..897de1d9a9 100644 +--- a/disas.c ++++ b/disas.c +@@ -207,6 +207,8 @@ static void initialize_debug_host(CPUDebug *s) + s->info.cap_insn_split = 6; + #elif defined(__hppa__) + s->info.print_insn = print_insn_hppa; ++#elif defined(__sw_64__) ++ s->info.print_insn = print_insn_sw_64; + #endif + } + +diff --git a/disas/meson.build b/disas/meson.build +index 449f99e1de..5c5daa69a7 100644 +--- a/disas/meson.build ++++ b/disas/meson.build +@@ -20,4 +20,5 @@ common_ss.add(when: 'CONFIG_S390_DIS', if_true: files('s390.c')) + common_ss.add(when: 'CONFIG_SH4_DIS', if_true: files('sh4.c')) + common_ss.add(when: 'CONFIG_SPARC_DIS', if_true: files('sparc.c')) + common_ss.add(when: 'CONFIG_XTENSA_DIS', if_true: files('xtensa.c')) ++common_ss.add(when: 'CONFIG_SW64_DIS', if_true: files('sw64.c')) + common_ss.add(when: capstone, if_true: files('capstone.c')) +diff --git a/disas/sw64.c b/disas/sw64.c +new file mode 100755 +index 0000000000..c5bd578e07 +--- /dev/null ++++ b/disas/sw64.c +@@ -0,0 +1,1242 @@ ++/* ++ * sw_64-dis.c -- Disassemble Sw_64 CORE3 instructions ++ * ++ * This file is part of libopcodes. ++ * ++ * This library 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 3, or (at your option) ++ * any later version. ++ * ++ * It 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 file; see the file COPYING. If not, write to the Free ++ * Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA ++ * 02110-1301, USA. ++ */ ++ ++#include "qemu/osdep.h" ++#include "disas/dis-asm.h" ++ ++#undef MAX ++ ++struct sw_64_opcode { ++ /* The opcode name. */ ++ const char *name; ++ ++ /* The opcode itself. Those bits which will be filled in with ++ operands are zeroes. */ ++ unsigned opcode; ++ ++ /* The opcode mask. This is used by the disassembler. This is a ++ mask containing ones indicating those bits which must match the ++ opcode field, and zeroes indicating those bits which need not ++ match (and are presumably filled in by operands). */ ++ unsigned mask; ++ ++ /* One bit flags for the opcode. These are primarily used to ++ indicate specific processors and environments support the ++ instructions. The defined values are listed below. */ ++ unsigned flags; ++ ++ /* An array of operand codes. Each code is an index into the ++ operand table. They appear in the order which the operands must ++ appear in assembly code, and are terminated by a zero. */ ++ unsigned char operands[5]; ++}; ++ ++/* The table itself is sorted by major opcode number, and is otherwise ++ in the order in which the disassembler should consider ++ instructions. */ ++extern const struct sw_64_opcode sw_64_opcodes[]; ++extern const unsigned sw_64_num_opcodes; ++ ++/* Values defined for the flags field of a struct sw_64_opcode. */ ++ ++/* CPU Availability */ ++#define SW_OPCODE_BASE 0x0001 /* Base architecture insns. */ ++#define SW_OPCODE_CORE3 0x0002 /* Core3 private insns. */ ++#define SW_LITOP(i) (((i) >> 26) & 0x3D) ++ ++#define SW_OPCODE_NOHM (~(SW_OPCODE_BASE|SW_OPCODE_CORE3)) ++ ++/* A macro to extract the major opcode from an instruction. */ ++#define SW_OP(i) (((i) >> 26) & 0x3F) ++ ++/* The total number of major opcodes. */ ++#define SW_NOPS 0x40 ++ ++/* The operands table is an array of struct sw_64_operand. */ ++ ++struct sw_64_operand { ++ /* The number of bits in the operand. */ ++ unsigned int bits : 5; ++ ++ /* How far the operand is left shifted in the instruction. */ ++ unsigned int shift : 5; ++ ++ /* The default relocation type for this operand. */ ++ signed int default_reloc : 16; ++ ++ /* One bit syntax flags. */ ++ unsigned int flags : 16; ++ ++ /* Insertion function. This is used by the assembler. To insert an ++ operand value into an instruction, check this field. ++ ++ If it is NULL, execute ++ i |= (op & ((1 << o->bits) - 1)) << o->shift; ++ (i is the instruction which we are filling in, o is a pointer to ++ this structure, and op is the opcode value; this assumes twos ++ complement arithmetic). ++ ++ If this field is not NULL, then simply call it with the ++ instruction and the operand value. It will return the new value ++ of the instruction. If the ERRMSG argument is not NULL, then if ++ the operand value is illegal, *ERRMSG will be set to a warning ++ string (the operand will be inserted in any case). If the ++ operand value is legal, *ERRMSG will be unchanged (most operands ++ can accept any value). */ ++ unsigned (*insert) (unsigned instruction, int op, const char **errmsg); ++ ++ /* Extraction function. This is used by the disassembler. To ++ extract this operand type from an instruction, check this field. ++ ++ If it is NULL, compute ++ op = ((i) >> o->shift) & ((1 << o->bits) - 1); ++ if ((o->flags & SW_OPERAND_SIGNED) != 0 ++ && (op & (1 << (o->bits - 1))) != 0) ++ op -= 1 << o->bits; ++ (i is the instruction, o is a pointer to this structure, and op ++ is the result; this assumes twos complement arithmetic). ++ ++ If this field is not NULL, then simply call it with the ++ instruction value. It will return the value of the operand. If ++ the INVALID argument is not NULL, *INVALID will be set to ++ non-zero if this operand type can not actually be extracted from ++ this operand (i.e., the instruction does not match). If the ++ operand is valid, *INVALID will not be changed. */ ++ int (*extract) (unsigned instruction, int *invalid); ++}; ++ ++/* Elements in the table are retrieved by indexing with values from ++ the operands field of the sw_64_opcodes table. */ ++ ++extern const struct sw_64_operand sw_64_operands[]; ++extern const unsigned sw_64_num_operands; ++/* Values defined for the flags field of a struct sw_64_operand. */ ++ ++/* Mask for selecting the type for typecheck purposes */ ++#define SW_OPERAND_TYPECHECK_MASK \ ++ (SW_OPERAND_PARENS | SW_OPERAND_COMMA | SW_OPERAND_IR | \ ++ SW_OPERAND_FPR | SW_OPERAND_RELATIVE | SW_OPERAND_SIGNED | \ ++ SW_OPERAND_UNSIGNED) ++ ++/* This operand does not actually exist in the assembler input. This ++ is used to support extended mnemonics, for which two operands fields ++ are identical. The assembler should call the insert function with ++ any op value. The disassembler should call the extract function, ++ ignore the return value, and check the value placed in the invalid ++ argument. */ ++#define SW_OPERAND_FAKE 01 ++ ++/* The operand should be wrapped in parentheses rather than separated ++ from the previous by a comma. This is used for the load and store ++ instructions which want their operands to look like "Ra,disp(Rb)". */ ++#define SW_OPERAND_PARENS 02 ++ ++/* Used in combination with PARENS, this supresses the supression of ++ the comma. This is used for "jmp Ra,(Rb),hint". */ ++#define SW_OPERAND_COMMA 04 ++ ++/* This operand names an integer register. */ ++#define SW_OPERAND_IR 010 ++ ++/* This operand names a floating point register. */ ++#define SW_OPERAND_FPR 020 ++ ++/* This operand is a relative branch displacement. The disassembler ++ prints these symbolically if possible. */ ++#define SW_OPERAND_RELATIVE 040 ++ ++/* This operand takes signed values. */ ++#define SW_OPERAND_SIGNED 0100 ++ ++/* This operand takes unsigned values. This exists primarily so that ++ a flags value of 0 can be treated as end-of-arguments. */ ++#define SW_OPERAND_UNSIGNED 0200 ++ ++/* Supress overflow detection on this field. This is used for hints. */ ++#define SW_OPERAND_NOOVERFLOW 0400 ++ ++/* Mask for optional argument default value. */ ++#define SW_OPERAND_OPTIONAL_MASK 07000 ++ ++/* This operand defaults to zero. This is used for jump hints. */ ++#define SW_OPERAND_DEFAULT_ZERO 01000 ++ ++/* This operand should default to the first (real) operand and is used ++ in conjunction with SW_OPERAND_OPTIONAL. This allows ++ "and $0,3,$0" to be written as "and $0,3", etc. I don't like ++ it, but it's what DEC does. */ ++#define SW_OPERAND_DEFAULT_FIRST 02000 ++ ++/* Similarly, this operand should default to the second (real) operand. ++ This allows "negl $0" instead of "negl $0,$0". */ ++#define SW_OPERAND_DEFAULT_SECOND 04000 ++ ++/* Register common names */ ++ ++#define SW_REG_V0 0 ++#define SW_REG_T0 1 ++#define SW_REG_T1 2 ++#define SW_REG_T2 3 ++#define SW_REG_T3 4 ++#define SW_REG_T4 5 ++#define SW_REG_T5 6 ++#define SW_REG_T6 7 ++#define SW_REG_T7 8 ++#define SW_REG_S0 9 ++#define SW_REG_S1 10 ++#define SW_REG_S2 11 ++#define SW_REG_S3 12 ++#define SW_REG_S4 13 ++#define SW_REG_S5 14 ++#define SW_REG_FP 15 ++#define SW_REG_A0 16 ++#define SW_REG_A1 17 ++#define SW_REG_A2 18 ++#define SW_REG_A3 19 ++#define SW_REG_A4 20 ++#define SW_REG_A5 21 ++#define SW_REG_T8 22 ++#define SW_REG_T9 23 ++#define SW_REG_T10 24 ++#define SW_REG_T11 25 ++#define SW_REG_RA 26 ++#define SW_REG_PV 27 ++#define SW_REG_T12 27 ++#define SW_REG_AT 28 ++#define SW_REG_GP 29 ++#define SW_REG_SP 30 ++#define SW_REG_ZERO 31 ++ ++enum bfd_reloc_code_real { ++ BFD_RELOC_23_PCREL_S2, ++ BFD_RELOC_SW_64_HINT ++}; ++ ++static unsigned insert_rba(unsigned insn, int value ATTRIBUTE_UNUSED, ++ const char **errmsg ATTRIBUTE_UNUSED) ++{ ++ return insn | (((insn >> 21) & 0x1f) << 16); ++} ++ ++static int extract_rba(unsigned insn, int *invalid) ++{ ++ if (invalid != (int *) NULL ++ && ((insn >> 21) & 0x1f) != ((insn >> 16) & 0x1f)) ++ *invalid = 1; ++ return 0; ++} ++ ++/* The same for the RC field. */ ++static unsigned insert_rca(unsigned insn, int value ATTRIBUTE_UNUSED, ++ const char **errmsg ATTRIBUTE_UNUSED) ++{ ++ return insn | ((insn >> 21) & 0x1f); ++} ++ ++static unsigned insert_rdc(unsigned insn, int value ATTRIBUTE_UNUSED, ++ const char **errmsg ATTRIBUTE_UNUSED) ++{ ++ return insn | ((insn >> 5) & 0x1f); ++} ++ ++static int extract_rdc(unsigned insn, int *invalid) ++{ ++ if (invalid != (int *) NULL ++ && ((insn >> 5) & 0x1f) != (insn & 0x1f)) ++ *invalid = 1; ++ return 0; ++} ++ ++static int extract_rca(unsigned insn, int *invalid) ++{ ++ if (invalid != (int *) NULL ++ && ((insn >> 21) & 0x1f) != (insn & 0x1f)) ++ *invalid = 1; ++ return 0; ++} ++ ++/* Fake arguments in which the registers must be set to ZERO. */ ++static unsigned insert_za(unsigned insn, int value ATTRIBUTE_UNUSED, ++ const char **errmsg ATTRIBUTE_UNUSED) ++{ ++ return insn | (31 << 21); ++} ++ ++static int extract_za(unsigned insn, int *invalid) ++{ ++ if (invalid != (int *) NULL && ((insn >> 21) & 0x1f) != 31) ++ *invalid = 1; ++ return 0; ++} ++ ++static unsigned insert_zb(unsigned insn, int value ATTRIBUTE_UNUSED, ++ const char **errmsg ATTRIBUTE_UNUSED) ++{ ++ return insn | (31 << 16); ++} ++ ++static int extract_zb(unsigned insn, int *invalid) ++{ ++ if (invalid != (int *) NULL && ((insn >> 16) & 0x1f) != 31) ++ *invalid = 1; ++ return 0; ++} ++ ++static unsigned insert_zc(unsigned insn, int value ATTRIBUTE_UNUSED, ++ const char **errmsg ATTRIBUTE_UNUSED) ++{ ++ return insn | 31; ++} ++ ++static int extract_zc(unsigned insn, int *invalid) ++{ ++ if (invalid != (int *) NULL && (insn & 0x1f) != 31) ++ *invalid = 1; ++ return 0; ++} ++ ++ ++/* The displacement field of a Branch format insn. */ ++ ++static unsigned insert_bdisp(unsigned insn, int value, const char **errmsg) ++{ ++ if (errmsg != (const char **)NULL && (value & 3)) ++ *errmsg = "branch operand unaligned"; ++ return insn | ((value / 4) & 0x1FFFFF); ++} ++ ++static int extract_bdisp(unsigned insn, int *invalid ATTRIBUTE_UNUSED) ++{ ++ return 4 * (((insn & 0x1FFFFF) ^ 0x100000) - 0x100000); ++} ++ ++static unsigned insert_bdisp26(unsigned insn, int value, const char **errmsg) ++{ ++ if (errmsg != (const char **)NULL && (value & 3)) ++ *errmsg = "branch operand unaligned"; ++ return insn | ((value / 4) & 0x3FFFFFF); ++} ++ ++static int extract_bdisp26(unsigned insn, int *invalid ATTRIBUTE_UNUSED) ++{ ++ return 4 * (((insn & 0x3FFFFFF) ^ 0x2000000) - 0x2000000); ++} ++ ++/* The hint field of a JMP/JSR insn. */ ++/* sw use 16 bits hint disp. */ ++static unsigned insert_jhint(unsigned insn, int value, const char **errmsg) ++{ ++ if (errmsg != (const char **)NULL && (value & 3)) ++ *errmsg = "jump hint unaligned"; ++ return insn | ((value / 4) & 0xFFFF); ++} ++ ++static int extract_jhint(unsigned insn, int *invalid ATTRIBUTE_UNUSED) ++{ ++ return 4 * (((insn & 0xFFFF) ^ 0x8000) - 0x8000); ++} ++ ++/* The hint field of an CORE3 HW_JMP/JSR insn. */ ++ ++static unsigned insert_sw4hwjhint(unsigned insn, int value, const char **errmsg) ++{ ++ if (errmsg != (const char **)NULL && (value & 3)) ++ *errmsg = "jump hint unaligned"; ++ return insn | ((value / 4) & 0x1FFF); ++} ++ ++static int extract_sw4hwjhint(unsigned insn, int *invalid ATTRIBUTE_UNUSED) ++{ ++ return 4 * (((insn & 0x1FFF) ^ 0x1000) - 0x1000); ++} ++ ++/* The operands table. */ ++ ++const struct sw_64_operand sw_64_operands[] = { ++ /* The fields are bits, shift, insert, extract, flags */ ++ /* The zero index is used to indicate end-of-list */ ++#define UNUSED 0 ++ { 0, 0, 0, 0, 0, 0 }, ++ ++ /* The plain integer register fields. */ ++#define RA (UNUSED + 1) ++ { 5, 21, 0, SW_OPERAND_IR, 0, 0 }, ++#define RB (RA + 1) ++ { 5, 16, 0, SW_OPERAND_IR, 0, 0 }, ++#define RC (RB + 1) ++ { 5, 0, 0, SW_OPERAND_IR, 0, 0 }, ++ ++ /* The plain fp register fields. */ ++#define FA (RC + 1) ++ { 5, 21, 0, SW_OPERAND_FPR, 0, 0 }, ++#define FB (FA + 1) ++ { 5, 16, 0, SW_OPERAND_FPR, 0, 0 }, ++#define FC (FB + 1) ++ { 5, 0, 0, SW_OPERAND_FPR, 0, 0 }, ++ ++ /* The integer registers when they are ZERO. */ ++#define ZA (FC + 1) ++ { 5, 21, 0, SW_OPERAND_FAKE, insert_za, extract_za }, ++#define ZB (ZA + 1) ++ { 5, 16, 0, SW_OPERAND_FAKE, insert_zb, extract_zb }, ++#define ZC (ZB + 1) ++ { 5, 0, 0, SW_OPERAND_FAKE, insert_zc, extract_zc }, ++ ++ /* The RB field when it needs parentheses. */ ++#define PRB (ZC + 1) ++ { 5, 16, 0, SW_OPERAND_IR | SW_OPERAND_PARENS, 0, 0 }, ++ ++ /* The RB field when it needs parentheses _and_ a preceding comma. */ ++#define CPRB (PRB + 1) ++ { 5, 16, 0, ++ SW_OPERAND_IR | SW_OPERAND_PARENS | SW_OPERAND_COMMA, 0, 0 }, ++ ++ /* The RB field when it must be the same as the RA field. */ ++#define RBA (CPRB + 1) ++ { 5, 16, 0, SW_OPERAND_FAKE, insert_rba, extract_rba }, ++ ++ /* The RC field when it must be the same as the RB field. */ ++#define RCA (RBA + 1) ++ { 5, 0, 0, SW_OPERAND_FAKE, insert_rca, extract_rca }, ++ ++#define RDC (RCA + 1) ++ { 5, 0, 0, SW_OPERAND_FAKE, insert_rdc, extract_rdc }, ++ ++ /* The RC field when it can *default* to RA. */ ++#define DRC1 (RDC + 1) ++ { 5, 0, 0, ++ SW_OPERAND_IR | SW_OPERAND_DEFAULT_FIRST, 0, 0 }, ++ ++ /* The RC field when it can *default* to RB. */ ++#define DRC2 (DRC1 + 1) ++ { 5, 0, 0, ++ SW_OPERAND_IR | SW_OPERAND_DEFAULT_SECOND, 0, 0 }, ++ ++ /* The FC field when it can *default* to RA. */ ++#define DFC1 (DRC2 + 1) ++ { 5, 0, 0, ++ SW_OPERAND_FPR | SW_OPERAND_DEFAULT_FIRST, 0, 0 }, ++ ++ /* The FC field when it can *default* to RB. */ ++#define DFC2 (DFC1 + 1) ++ { 5, 0, 0, ++ SW_OPERAND_FPR | SW_OPERAND_DEFAULT_SECOND, 0, 0 }, ++ ++ /* The unsigned 8-bit literal of Operate format insns. */ ++#define LIT (DFC2 + 1) ++ { 8, 13, -LIT, SW_OPERAND_UNSIGNED, 0, 0 }, ++ ++ /* The signed 16-bit displacement of Memory format insns. From here ++ we can't tell what relocation should be used, so don't use a default. */ ++#define MDISP (LIT + 1) ++ { 16, 0, -MDISP, SW_OPERAND_SIGNED, 0, 0 }, ++ ++ /* The signed "23-bit" aligned displacement of Branch format insns. */ ++#define BDISP (MDISP + 1) ++ { 21, 0, BFD_RELOC_23_PCREL_S2, ++ SW_OPERAND_RELATIVE, insert_bdisp, extract_bdisp }, ++ ++ /* The 26-bit hmcode function for sys_call and sys_call / b. */ ++#define HMFN (BDISP + 1) ++ { 25, 0, -HMFN, SW_OPERAND_UNSIGNED, 0, 0 }, ++ ++ /* sw jsr/ret insntructions has no function bits. */ ++ /* The optional signed "16-bit" aligned displacement of the JMP/JSR hint. */ ++#define JMPHINT (HMFN + 1) ++ { 16, 0, BFD_RELOC_SW_64_HINT, ++ SW_OPERAND_RELATIVE | SW_OPERAND_DEFAULT_ZERO | SW_OPERAND_NOOVERFLOW, ++ insert_jhint, extract_jhint }, ++ ++ /* The optional hint to RET/JSR_COROUTINE. */ ++#define RETHINT (JMPHINT + 1) ++ { 16, 0, -RETHINT, ++ SW_OPERAND_UNSIGNED | SW_OPERAND_DEFAULT_ZERO, 0, 0 }, ++ ++ /* The 12-bit displacement for the core3 hw_{ld,st} (pal1b/pal1f) insns. */ ++#define HWDISP (RETHINT + 1) ++ { 12, 0, -HWDISP, SW_OPERAND_SIGNED, 0, 0 }, ++ ++ /* The 16-bit combined index/scoreboard mask for the core3 ++ hw_m[ft]pr (pal19/pal1d) insns. */ ++#define HWINDEX (HWDISP + 1) ++ { 16, 0, -HWINDEX, SW_OPERAND_UNSIGNED, 0, 0 }, ++ ++ /* The 13-bit branch hint for the core3 hw_jmp/jsr (pal1e) insn. */ ++#define HWJMPHINT (HWINDEX + 1) ++ { 8, 0, -HWJMPHINT, ++ SW_OPERAND_RELATIVE | SW_OPERAND_DEFAULT_ZERO | SW_OPERAND_NOOVERFLOW, ++ insert_sw4hwjhint, extract_sw4hwjhint }, ++ ++ /* for the third operand of ternary operands integer insn. */ ++#define R3 (HWJMPHINT + 1) ++ { 5, 5, 0, SW_OPERAND_IR, 0, 0 }, ++ /* The plain fp register fields */ ++#define F3 (R3 + 1) ++ { 5, 5, 0, SW_OPERAND_FPR, 0, 0 }, ++ /* sw simd settle instruction lit */ ++#define FMALIT (F3 + 1) ++ { 5, 5, -FMALIT, SW_OPERAND_UNSIGNED, 0, 0 }, //V1.1 ++#define LMDISP (FMALIT + 1) ++ { 15, 0, -LMDISP, SW_OPERAND_UNSIGNED, 0, 0 }, ++#define RPIINDEX (LMDISP + 1) ++ { 8, 0, -RPIINDEX, SW_OPERAND_UNSIGNED, 0, 0 }, ++#define ATMDISP (RPIINDEX + 1) ++ { 12, 0, -ATMDISP, SW_OPERAND_SIGNED, 0, 0 }, ++#define DISP13 (ATMDISP + 1) ++ { 13, 13, -DISP13, SW_OPERAND_SIGNED, 0, 0}, ++#define BDISP26 (DISP13 + 1) ++ { 26, 0, 222, ++ SW_OPERAND_RELATIVE, insert_bdisp26, extract_bdisp26 }, ++#define DPFTH (BDISP26 + 1) ++ { 5, 21, -DPFTH, SW_OPERAND_UNSIGNED, 0, 0} ++}; ++ ++const unsigned sw_64_num_operands = sizeof(sw_64_operands) / sizeof(*sw_64_operands); ++ ++/* Macros used to form opcodes. */ ++ ++/* The main opcode. */ ++#define OP(x) (((x) & 0x3F) << 26) ++#define OP_MASK 0xFC000000 ++ ++/* Branch format instructions. */ ++#define BRA_(oo) OP(oo) ++#define BRA_MASK OP_MASK ++#define BRA(oo) BRA_(oo), BRA_MASK ++ ++#ifdef HUANGLM20171113 ++/* Floating point format instructions. */ ++#define FP_(oo,fff) (OP(oo) | (((fff) & 0x7FF) << 5)) ++#define FP_MASK (OP_MASK | 0xFFE0) ++#define FP(oo,fff) FP_(oo,fff), FP_MASK ++ ++#else ++/* Floating point format instructions. */ ++#define FP_(oo,fff) (OP(oo) | (((fff) & 0xFF) << 5)) ++#define FP_MASK (OP_MASK | 0x1FE0) ++#define FP(oo,fff) FP_(oo,fff), FP_MASK ++ ++#define FMA_(oo,fff) (OP(oo) | (((fff) & 0x3F) << 10 )) ++#define FMA_MASK (OP_MASK | 0xFC00) ++#define FMA(oo,fff) FMA_(oo,fff), FMA_MASK ++#endif ++ ++/* Memory format instructions. */ ++#define MEM_(oo) OP(oo) ++#define MEM_MASK OP_MASK ++#define MEM(oo) MEM_(oo), MEM_MASK ++ ++/* Memory/Func Code format instructions. */ ++#define MFC_(oo,ffff) (OP(oo) | ((ffff) & 0xFFFF)) ++#define MFC_MASK (OP_MASK | 0xFFFF) ++#define MFC(oo,ffff) MFC_(oo,ffff), MFC_MASK ++ ++/* Memory/Branch format instructions. */ ++#define MBR_(oo,h) (OP(oo) | (((h) & 3) << 14)) ++#define MBR_MASK (OP_MASK | 0xC000) ++#define MBR(oo,h) MBR_(oo,h), MBR_MASK ++ ++/* Now sw Operate format instructions is different with SW1. */ ++#define OPR_(oo,ff) (OP(oo) | (((ff) & 0xFF) << 5)) ++#define OPRL_(oo,ff) (OPR_((oo), (ff)) ) ++#define OPR_MASK (OP_MASK | 0x1FE0) ++#define OPR(oo,ff) OPR_(oo,ff), OPR_MASK ++#define OPRL(oo,ff) OPRL_(oo,ff), OPR_MASK ++ ++/* sw ternary operands Operate format instructions. */ ++#define TOPR_(oo,ff) (OP(oo) | (((ff) & 0x07) << 10)) ++#define TOPRL_(oo,ff) (TOPR_((oo), (ff))) ++#define TOPR_MASK (OP_MASK | 0x1C00) ++#define TOPR(oo,ff) TOPR_(oo,ff), TOPR_MASK ++#define TOPRL(oo,ff) TOPRL_(oo,ff), TOPR_MASK ++ ++/* sw atom instructions. */ ++#define ATMEM_(oo,h) (OP(oo) | (((h) & 0xF) << 12)) ++#define ATMEM_MASK (OP_MASK | 0xF000) ++#define ATMEM(oo,h) ATMEM_(oo,h), ATMEM_MASK ++ ++/* sw privilege instructions. */ ++#define PRIRET_(oo,h) (OP(oo) | (((h) & 0x1) << 20)) ++#define PRIRET_MASK (OP_MASK | 0x100000) ++#define PRIRET(oo,h) PRIRET_(oo,h), PRIRET_MASK ++ ++/* sw rpi_rcsr,rpi_wcsr. */ ++#define CSR_(oo,ff) (OP(oo) | (((ff) & 0xFF) << 8)) ++#define CSR_MASK (OP_MASK | 0xFF00) ++#define CSR(oo,ff) CSR_(oo,ff), CSR_MASK ++ ++#define PCD_(oo,ff) (OP(oo) | (ff << 25)) ++#define PCD_MASK OP_MASK ++#define PCD(oo,ff) PCD_(oo,ff), PCD_MASK ++ ++/* Hardware memory (hw_{ld,st}) instructions. */ ++#define HWMEM_(oo,f) (OP(oo) | (((f) & 0xF) << 12)) ++#define HWMEM_MASK (OP_MASK | 0xF000) ++#define HWMEM(oo,f) HWMEM_(oo,f), HWMEM_MASK ++ ++#define LOGX_(oo,ff) (OP(oo) | (((ff) & 0x3F) << 10)) ++#define LOGX_MASK (0xF0000000) ++#define LOGX(oo,ff) LOGX_(oo,ff), LOGX_MASK ++ ++/* Abbreviations for instruction subsets. */ ++#define BASE SW_OPCODE_BASE ++#define CORE3 SW_OPCODE_CORE3 ++ ++/* Common combinations of arguments. */ ++#define ARG_NONE { 0 } ++#define ARG_BRA { RA, BDISP } ++#define ARG_FBRA { FA, BDISP } ++#define ARG_FP { FA, FB, DFC1 } ++#define ARG_FPZ1 { ZA, FB, DFC1 } ++#define ARG_MEM { RA, MDISP, PRB } ++#define ARG_FMEM { FA, MDISP, PRB } ++#define ARG_OPR { RA, RB, DRC1 } ++ ++#define ARG_OPRCAS { RA, RB, RC } ++ ++#define ARG_OPRL { RA, LIT, DRC1 } ++#define ARG_OPRZ1 { ZA, RB, DRC1 } ++#define ARG_OPRLZ1 { ZA, LIT, RC } ++#define ARG_PCD { HMFN } ++#define ARG_HWMEM { RA, HWDISP, PRB } ++#define ARG_FPL { FA,LIT, DFC1 } ++#define ARG_FMA { FA,FB,F3, DFC1 } ++#define ARG_PREFETCH { ZA, MDISP, PRB } ++#define ARG_TOPR { RA, RB,R3, DRC1 } ++#define ARG_TOPRL { RA, LIT, R3,DRC1 } ++#define ARG_FMAL { FA,FB,FMALIT, DFC1 } ++#define ARG_ATMEM { RA, ATMDISP, PRB } ++#define ARG_VUAMEM { FA, ATMDISP, PRB } ++#define ARG_OPRLZ3 { RA, LIT, ZC } ++ ++#define ARG_DISP13 {DISP13, RC} ++ ++/* The opcode table. ++ ++ The format of the opcode table is: ++ ++ NAME OPCODE MASK { OPERANDS } ++ ++ NAME is the name of the instruction. ++ ++ OPCODE is the instruction opcode. ++ ++ MASK is the opcode mask; this is used to tell the disassembler ++ which bits in the actual opcode must match OPCODE. ++ ++ OPERANDS is the list of operands. ++ ++ The preceding macros merge the text of the OPCODE and MASK fields. ++ ++ The disassembler reads the table in order and prints the first ++ instruction which matches, so this table is sorted to put more ++ specific instructions before more general instructions. ++ ++ Otherwise, it is sorted by major opcode and minor function code. ++ */ ++ ++const struct sw_64_opcode sw_64_opcodes[] = { ++ { "sys_call/b", PCD(0x00,0x00), BASE, ARG_PCD }, ++ { "sys_call", PCD(0x00,0x01), BASE, ARG_PCD }, ++ ++ { "call", MEM(0x01), BASE, { RA, CPRB, JMPHINT } }, ++ { "ret", MEM(0x02), BASE, { RA, CPRB, RETHINT } }, ++ { "jmp", MEM(0x03), BASE, { RA, CPRB, JMPHINT } }, ++ { "br", BRA(0x04), BASE, { ZA, BDISP } }, ++ { "br", BRA(0x04), BASE, ARG_BRA }, ++ { "bsr", BRA(0x05), BASE, ARG_BRA }, ++ { "memb", MFC(0x06,0x0000), BASE, ARG_NONE }, ++ { "imemb", MFC(0x06,0x0001), BASE, ARG_NONE }, ++ { "rtc", MFC(0x06,0x0020), BASE, { RA, ZB } }, ++ { "rtc", MFC(0x06,0x0020), BASE, { RA, RB } }, ++ { "rcid", MFC(0x06,0x0040), BASE, { RA , ZB} }, ++ { "halt", MFC(0x06,0x0080), BASE, { ZA, ZB } }, ++ { "rd_f", MFC(0x06,0x1000), CORE3, { RA, ZB } }, ++ { "wr_f", MFC(0x06,0x1020), CORE3, { RA, ZB } }, ++ { "rtid", MFC(0x06,0x1040), BASE, { RA } }, ++ { "pri_rcsr", CSR(0x06,0xFE), CORE3, { RA, RPIINDEX ,ZB } }, ++ { "pri_wcsr", CSR(0x06,0xFF), CORE3, { RA, RPIINDEX ,ZB } }, ++ { "pri_ret", PRIRET(0x07,0x0), BASE, { RA } }, ++ { "pri_ret/b", PRIRET(0x07,0x1), BASE, { RA } }, ++ { "lldw", ATMEM(0x08,0x0), BASE, ARG_ATMEM }, ++ { "lldl", ATMEM(0x08,0x1), BASE, ARG_ATMEM }, ++ { "ldw_inc", ATMEM(0x08,0x2), CORE3, ARG_ATMEM }, ++ { "ldl_inc", ATMEM(0x08,0x3), CORE3, ARG_ATMEM }, ++ { "ldw_dec", ATMEM(0x08,0x4), CORE3, ARG_ATMEM }, ++ { "ldl_dec", ATMEM(0x08,0x5), CORE3, ARG_ATMEM }, ++ { "ldw_set", ATMEM(0x08,0x6), CORE3, ARG_ATMEM }, ++ { "ldl_set", ATMEM(0x08,0x7), CORE3, ARG_ATMEM }, ++ { "lstw", ATMEM(0x08,0x8), BASE, ARG_ATMEM }, ++ { "lstl", ATMEM(0x08,0x9), BASE, ARG_ATMEM }, ++ { "ldw_nc", ATMEM(0x08,0xA), BASE, ARG_ATMEM }, ++ { "ldl_nc", ATMEM(0x08,0xB), BASE, ARG_ATMEM }, ++ { "ldd_nc", ATMEM(0x08,0xC), BASE, ARG_VUAMEM }, ++ { "stw_nc", ATMEM(0x08,0xD), BASE, ARG_ATMEM }, ++ { "stl_nc", ATMEM(0x08,0xE), BASE, ARG_ATMEM }, ++ { "std_nc", ATMEM(0x08,0xF), BASE, ARG_VUAMEM }, ++ { "fillcs", MEM(0x09), BASE, ARG_PREFETCH }, ++ { "ldwe", MEM(0x09), BASE, ARG_FMEM }, ++ { "e_fillcs", MEM(0x0A), BASE, ARG_PREFETCH }, ++ { "ldse", MEM(0x0A), BASE, ARG_FMEM }, ++ { "fillcs_e", MEM(0x0B), BASE, ARG_PREFETCH }, ++ { "ldde", MEM(0x0B), BASE, ARG_FMEM }, ++ { "vlds", MEM(0x0C), BASE, ARG_FMEM }, ++ { "vldd", MEM(0x0D), BASE, ARG_FMEM }, ++ { "vsts", MEM(0x0E), BASE, ARG_FMEM }, ++ { "vstd", MEM(0x0F), BASE, ARG_FMEM }, ++ { "addw", OPR(0x10,0x00), BASE, ARG_OPR }, ++ { "addw", OPRL(0x12,0x00), BASE, ARG_OPRL }, ++ { "subw", OPR(0x10,0x01), BASE, ARG_OPR }, ++ { "subw", OPRL(0x12,0x01), BASE, ARG_OPRL }, ++ { "s4addw", OPR(0x10,0x02), BASE, ARG_OPR }, ++ { "s4addw", OPRL(0x12,0x02), BASE, ARG_OPRL }, ++ { "s4subw", OPR(0x10,0x03), BASE, ARG_OPR }, ++ { "s4subw", OPRL(0x12,0x03), BASE, ARG_OPRL }, ++ { "s8addw", OPR(0x10,0x04), BASE, ARG_OPR }, ++ { "s8addw", OPRL(0x12,0x04), BASE, ARG_OPRL }, ++ { "s8subw", OPR(0x10,0x05), BASE, ARG_OPR }, ++ { "s8subw", OPRL(0x12,0x05), BASE, ARG_OPRL }, ++ { "addl", OPR(0x10,0x08), BASE, ARG_OPR }, ++ { "addl", OPRL(0x12,0x08), BASE, ARG_OPRL }, ++ { "subl", OPR(0x10,0x09), BASE, ARG_OPR }, ++ { "subl", OPRL(0x12,0x09), BASE, ARG_OPRL }, ++ { "s4addl", OPR(0x10,0x0A), BASE, ARG_OPR }, ++ { "s4addl", OPRL(0x12,0x0A), BASE, ARG_OPRL }, ++ { "s4subl", OPR(0x10,0x0B), BASE, ARG_OPR }, ++ { "s4subl", OPRL(0x12,0x0B), BASE, ARG_OPRL }, ++ { "s8addl", OPR(0x10,0x0C), BASE, ARG_OPR }, ++ { "s8addl", OPRL(0x12,0x0C), BASE, ARG_OPRL }, ++ { "s8subl", OPR(0x10,0x0D), BASE, ARG_OPR }, ++ { "s8subl", OPRL(0x12,0x0D), BASE, ARG_OPRL }, ++ { "mulw", OPR(0x10,0x10), BASE, ARG_OPR }, ++ { "mulw", OPRL(0x12,0x10), BASE, ARG_OPRL }, ++ { "mull", OPR(0x10,0x18), BASE, ARG_OPR }, ++ { "mull", OPRL(0x12,0x18), BASE, ARG_OPRL }, ++ { "umulh", OPR(0x10,0x19), BASE, ARG_OPR }, ++ { "umulh", OPRL(0x12,0x19), BASE, ARG_OPRL }, ++ { "cmpeq", OPR(0x10,0x28), BASE, ARG_OPR }, ++ { "cmpeq", OPRL(0x12,0x28), BASE, ARG_OPRL }, ++ { "cmplt", OPR(0x10,0x29), BASE, ARG_OPR }, ++ { "cmplt", OPRL(0x12,0x29), BASE, ARG_OPRL }, ++ { "cmple", OPR(0x10,0x2A), BASE, ARG_OPR }, ++ { "cmple", OPRL(0x12,0x2A), BASE, ARG_OPRL }, ++ { "cmpult", OPR(0x10,0x2B), BASE, ARG_OPR }, ++ { "cmpult", OPRL(0x12,0x2B), BASE, ARG_OPRL }, ++ { "cmpule", OPR(0x10,0x2C), BASE, ARG_OPR }, ++ { "cmpule", OPRL(0x12,0x2C), BASE, ARG_OPRL }, ++ ++ { "and", OPR(0x10,0x38), BASE, ARG_OPR }, ++ { "and", OPRL(0x12,0x38),BASE, ARG_OPRL }, ++ { "bic", OPR(0x10,0x39), BASE, ARG_OPR }, ++ { "bic", OPRL(0x12,0x39),BASE, ARG_OPRL }, ++ { "bis", OPR(0x10,0x3A), BASE, ARG_OPR }, ++ { "bis", OPRL(0x12,0x3A),BASE, ARG_OPRL }, ++ { "ornot", OPR(0x10,0x3B), BASE, ARG_OPR }, ++ { "ornot", OPRL(0x12,0x3B),BASE, ARG_OPRL }, ++ { "xor", OPR(0x10,0x3C), BASE, ARG_OPR }, ++ { "xor", OPRL(0x12,0x3C),BASE, ARG_OPRL }, ++ { "eqv", OPR(0x10,0x3D), BASE, ARG_OPR }, ++ { "eqv", OPRL(0x12,0x3D),BASE, ARG_OPRL }, ++ { "inslb", OPR(0x10,0x40), BASE, ARG_OPR }, ++ { "inslb", OPRL(0x12,0x40),BASE, ARG_OPRL }, ++ { "inslh", OPR(0x10,0x41), BASE, ARG_OPR }, ++ { "inslh", OPRL(0x12,0x41),BASE, ARG_OPRL }, ++ { "inslw", OPR(0x10,0x42), BASE, ARG_OPR }, ++ { "inslw", OPRL(0x12,0x42),BASE, ARG_OPRL }, ++ { "insll", OPR(0x10,0x43), BASE, ARG_OPR }, ++ { "insll", OPRL(0x12,0x43),BASE, ARG_OPRL }, ++ { "inshb", OPR(0x10,0x44), BASE, ARG_OPR }, ++ { "inshb", OPRL(0x12,0x44),BASE, ARG_OPRL }, ++ { "inshh", OPR(0x10,0x45), BASE, ARG_OPR }, ++ { "inshh", OPRL(0x12,0x45),BASE, ARG_OPRL }, ++ { "inshw", OPR(0x10,0x46), BASE, ARG_OPR }, ++ { "inshw", OPRL(0x12,0x46),BASE, ARG_OPRL }, ++ { "inshl", OPR(0x10,0x47), BASE, ARG_OPR }, ++ { "inshl", OPRL(0x12,0x47),BASE, ARG_OPRL }, ++ ++ { "sll", OPR(0x10,0x48), BASE, ARG_OPR }, ++ { "sll", OPRL(0x12,0x48),BASE, ARG_OPRL }, ++ { "srl", OPR(0x10,0x49), BASE, ARG_OPR }, ++ { "srl", OPRL(0x12,0x49),BASE, ARG_OPRL }, ++ { "sra", OPR(0x10,0x4A), BASE, ARG_OPR }, ++ { "sra", OPRL(0x12,0x4A),BASE, ARG_OPRL }, ++ { "extlb", OPR(0x10,0x50), BASE, ARG_OPR }, ++ { "extlb", OPRL(0x12,0x50),BASE, ARG_OPRL }, ++ { "extlh", OPR(0x10,0x51), BASE, ARG_OPR }, ++ { "extlh", OPRL(0x12,0x51),BASE, ARG_OPRL }, ++ { "extlw", OPR(0x10,0x52), BASE, ARG_OPR }, ++ { "extlw", OPRL(0x12,0x52),BASE, ARG_OPRL }, ++ { "extll", OPR(0x10,0x53), BASE, ARG_OPR }, ++ { "extll", OPRL(0x12,0x53),BASE, ARG_OPRL }, ++ { "exthb", OPR(0x10,0x54), BASE, ARG_OPR }, ++ { "exthb", OPRL(0x12,0x54),BASE, ARG_OPRL }, ++ { "exthh", OPR(0x10,0x55), BASE, ARG_OPR }, ++ { "exthh", OPRL(0x12,0x55),BASE, ARG_OPRL }, ++ { "exthw", OPR(0x10,0x56), BASE, ARG_OPR }, ++ { "exthw", OPRL(0x12,0x56),BASE, ARG_OPRL }, ++ { "exthl", OPR(0x10,0x57), BASE, ARG_OPR }, ++ { "exthl", OPRL(0x12,0x57),BASE, ARG_OPRL }, ++ { "ctpop", OPR(0x10,0x58), BASE, ARG_OPRZ1 }, ++ { "ctlz", OPR(0x10,0x59), BASE, ARG_OPRZ1 }, ++ { "cttz", OPR(0x10,0x5A), BASE, ARG_OPRZ1 }, ++ { "masklb", OPR(0x10,0x60), BASE, ARG_OPR }, ++ { "masklb", OPRL(0x12,0x60),BASE, ARG_OPRL }, ++ { "masklh", OPR(0x10,0x61), BASE, ARG_OPR }, ++ { "masklh", OPRL(0x12,0x61),BASE, ARG_OPRL }, ++ { "masklw", OPR(0x10,0x62), BASE, ARG_OPR }, ++ { "masklw", OPRL(0x12,0x62),BASE, ARG_OPRL }, ++ { "maskll", OPR(0x10,0x63), BASE, ARG_OPR }, ++ { "maskll", OPRL(0x12,0x63),BASE, ARG_OPRL }, ++ { "maskhb", OPR(0x10,0x64), BASE, ARG_OPR }, ++ { "maskhb", OPRL(0x12,0x64),BASE, ARG_OPRL }, ++ { "maskhh", OPR(0x10,0x65), BASE, ARG_OPR }, ++ { "maskhh", OPRL(0x12,0x65),BASE, ARG_OPRL }, ++ { "maskhw", OPR(0x10,0x66), BASE, ARG_OPR }, ++ { "maskhw", OPRL(0x12,0x66),BASE, ARG_OPRL }, ++ { "maskhl", OPR(0x10,0x67), BASE, ARG_OPR }, ++ { "maskhl", OPRL(0x12,0x67),BASE, ARG_OPRL }, ++ { "zap", OPR(0x10,0x68), BASE, ARG_OPR }, ++ { "zap", OPRL(0x12,0x68),BASE, ARG_OPRL }, ++ { "zapnot", OPR(0x10,0x69), BASE, ARG_OPR }, ++ { "zapnot", OPRL(0x12,0x69),BASE, ARG_OPRL }, ++ { "sextb", OPR(0x10,0x6A), BASE, ARG_OPRZ1}, ++ { "sextb", OPRL(0x12,0x6A),BASE, ARG_OPRLZ1 }, ++ { "sexth", OPR(0x10,0x6B), BASE, ARG_OPRZ1 }, ++ { "sexth", OPRL(0x12,0x6B),BASE, ARG_OPRLZ1 }, ++ { "cmpgeb", OPR(0x10,0x6C), BASE, ARG_OPR }, ++ { "cmpgeb", OPRL(0x12,0x6C),BASE, ARG_OPRL }, ++ { "fimovs", OPR(0x10,0x70), BASE, { FA, ZB, RC } }, ++ { "fimovd", OPR(0x10,0x78), BASE, { FA, ZB, RC } }, ++ { "seleq", TOPR(0x11,0x0), BASE, ARG_TOPR }, ++ { "seleq", TOPRL(0x13,0x0),BASE, ARG_TOPRL }, ++ { "selge", TOPR(0x11,0x1), BASE, ARG_TOPR }, ++ { "selge", TOPRL(0x13,0x1),BASE, ARG_TOPRL }, ++ { "selgt", TOPR(0x11,0x2), BASE, ARG_TOPR }, ++ { "selgt", TOPRL(0x13,0x2),BASE, ARG_TOPRL }, ++ { "selle", TOPR(0x11,0x3), BASE, ARG_TOPR }, ++ { "selle", TOPRL(0x13,0x3),BASE, ARG_TOPRL }, ++ { "sellt", TOPR(0x11,0x4), BASE, ARG_TOPR }, ++ { "sellt", TOPRL(0x13,0x4),BASE, ARG_TOPRL }, ++ { "selne", TOPR(0x11,0x5), BASE, ARG_TOPR }, ++ { "selne", TOPRL(0x13,0x5),BASE, ARG_TOPRL }, ++ { "sellbc", TOPR(0x11,0x6), BASE, ARG_TOPR }, ++ { "sellbc", TOPRL(0x13,0x6),BASE, ARG_TOPRL }, ++ { "sellbs", TOPR(0x11,0x7), BASE, ARG_TOPR }, ++ { "sellbs", TOPRL(0x13,0x7),BASE, ARG_TOPRL }, ++ { "vlog", LOGX(0x14,0x00), BASE, ARG_FMA }, ++ ++ { "fadds", FP(0x18,0x00), BASE, ARG_FP }, ++ { "faddd", FP(0x18,0x01), BASE, ARG_FP }, ++ { "fsubs", FP(0x18,0x02), BASE, ARG_FP }, ++ { "fsubd", FP(0x18,0x03), BASE, ARG_FP }, ++ { "fmuls", FP(0x18,0x04), BASE, ARG_FP }, ++ { "fmuld", FP(0x18,0x05), BASE, ARG_FP }, ++ { "fdivs", FP(0x18,0x06), BASE, ARG_FP }, ++ { "fdivd", FP(0x18,0x07), BASE, ARG_FP }, ++ { "fsqrts", FP(0x18,0x08), BASE, ARG_FPZ1 }, ++ { "fsqrtd", FP(0x18,0x09), BASE, ARG_FPZ1 }, ++ { "fcmpeq", FP(0x18,0x10), BASE, ARG_FP }, ++ { "fcmple", FP(0x18,0x11), BASE, ARG_FP }, ++ { "fcmplt", FP(0x18,0x12), BASE, ARG_FP }, ++ { "fcmpun", FP(0x18,0x13), BASE, ARG_FP }, ++ ++ { "fcvtsd", FP(0x18,0x20), BASE, ARG_FPZ1 }, ++ { "fcvtds", FP(0x18,0x21), BASE, ARG_FPZ1 }, ++ { "fcvtdl_g", FP(0x18,0x22), BASE, ARG_FPZ1 }, ++ { "fcvtdl_p", FP(0x18,0x23), BASE, ARG_FPZ1 }, ++ { "fcvtdl_z", FP(0x18,0x24), BASE, ARG_FPZ1 }, ++ { "fcvtdl_n", FP(0x18,0x25), BASE, ARG_FPZ1 }, ++ { "fcvtdl", FP(0x18,0x27), BASE, ARG_FPZ1 }, ++ { "fcvtwl", FP(0x18,0x28), BASE, ARG_FPZ1 }, ++ { "fcvtlw", FP(0x18,0x29), BASE, ARG_FPZ1 }, ++ { "fcvtls", FP(0x18,0x2d), BASE, ARG_FPZ1 }, ++ { "fcvtld", FP(0x18,0x2f), BASE, ARG_FPZ1 }, ++ { "fcpys", FP(0x18,0x30), BASE, ARG_FP }, ++ { "fcpyse", FP(0x18,0x31), BASE, ARG_FP }, ++ { "fcpysn", FP(0x18,0x32), BASE, ARG_FP }, ++ { "ifmovs", FP(0x18,0x40), BASE, { RA, ZB, FC } }, ++ { "ifmovd", FP(0x18,0x41), BASE, { RA, ZB, FC } }, ++ { "rfpcr", FP(0x18,0x50), BASE, { FA, RBA, RCA } }, ++ { "wfpcr", FP(0x18,0x51), BASE, { FA, RBA, RCA } }, ++ { "setfpec0", FP(0x18,0x54), BASE, ARG_NONE }, ++ { "setfpec1", FP(0x18,0x55), BASE, ARG_NONE }, ++ { "setfpec2", FP(0x18,0x56), BASE, ARG_NONE }, ++ { "setfpec3", FP(0x18,0x57), BASE, ARG_NONE }, ++ { "fmas", FMA(0x19,0x00), BASE, ARG_FMA }, ++ { "fmad", FMA(0x19,0x01), BASE, ARG_FMA }, ++ { "fmss", FMA(0x19,0x02), BASE, ARG_FMA }, ++ { "fmsd", FMA(0x19,0x03), BASE, ARG_FMA }, ++ { "fnmas", FMA(0x19,0x04), BASE, ARG_FMA }, ++ { "fnmad", FMA(0x19,0x05), BASE, ARG_FMA }, ++ { "fnmss", FMA(0x19,0x06), BASE, ARG_FMA }, ++ { "fnmsd", FMA(0x19,0x07), BASE, ARG_FMA }, ++ { "fseleq", FMA(0x19,0x10), BASE, ARG_FMA }, ++ { "fselne", FMA(0x19,0x11), BASE, ARG_FMA }, ++ { "fsellt", FMA(0x19,0x12), BASE, ARG_FMA }, ++ { "fselle", FMA(0x19,0x13), BASE, ARG_FMA }, ++ { "fselgt", FMA(0x19,0x14), BASE, ARG_FMA }, ++ { "fselge", FMA(0x19,0x15), BASE, ARG_FMA }, ++ { "vaddw", FP(0x1A,0x00), BASE, ARG_FP }, ++ { "vaddw", FP(0x1A,0x20), BASE, ARG_FPL }, ++ { "vsubw", FP(0x1A,0x01), BASE, ARG_FP }, ++ { "vsubw", FP(0x1A,0x21), BASE, ARG_FPL }, ++ { "vcmpgew", FP(0x1A,0x02), BASE, ARG_FP }, ++ { "vcmpgew", FP(0x1A,0x22), BASE, ARG_FPL }, ++ { "vcmpeqw", FP(0x1A,0x03), BASE, ARG_FP }, ++ { "vcmpeqw", FP(0x1A,0x23), BASE, ARG_FPL }, ++ { "vcmplew", FP(0x1A,0x04), BASE, ARG_FP }, ++ { "vcmplew", FP(0x1A,0x24), BASE, ARG_FPL }, ++ { "vcmpltw", FP(0x1A,0x05), BASE, ARG_FP }, ++ { "vcmpltw", FP(0x1A,0x25), BASE, ARG_FPL }, ++ { "vcmpulew", FP(0x1A,0x06), BASE, ARG_FP }, ++ { "vcmpulew", FP(0x1A,0x26), BASE, ARG_FPL }, ++ { "vcmpultw", FP(0x1A,0x07), BASE, ARG_FP }, ++ { "vcmpultw", FP(0x1A,0x27), BASE, ARG_FPL }, ++ ++ { "vsllw", FP(0x1A,0x08), BASE, ARG_FP }, ++ { "vsllw", FP(0x1A,0x28), BASE, ARG_FPL }, ++ { "vsrlw", FP(0x1A,0x09), BASE, ARG_FP }, ++ { "vsrlw", FP(0x1A,0x29), BASE, ARG_FPL }, ++ { "vsraw", FP(0x1A,0x0A), BASE, ARG_FP }, ++ { "vsraw", FP(0x1A,0x2A), BASE, ARG_FPL }, ++ { "vrolw", FP(0x1A,0x0B), BASE, ARG_FP }, ++ { "vrolw", FP(0x1A,0x2B), BASE, ARG_FPL }, ++ { "sllow", FP(0x1A,0x0C), BASE, ARG_FP }, ++ { "sllow", FP(0x1A,0x2C), BASE, ARG_FPL }, ++ { "srlow", FP(0x1A,0x0D), BASE, ARG_FP }, ++ { "srlow", FP(0x1A,0x2D), BASE, ARG_FPL }, ++ { "vaddl", FP(0x1A,0x0E), BASE, ARG_FP }, ++ { "vaddl", FP(0x1A,0x2E), BASE, ARG_FPL }, ++ { "vsubl", FP(0x1A,0x0F), BASE, ARG_FP }, ++ { "vsubl", FP(0x1A,0x2F), BASE, ARG_FPL }, ++ { "ctpopow", FP(0x1A,0x18), BASE, { FA, ZB, DFC1 } }, ++ { "ctlzow", FP(0x1A,0x19), BASE, { FA, ZB, DFC1 } }, ++ { "vucaddw", FP(0x1A,0x40), BASE, ARG_FP }, ++ { "vucaddw", FP(0x1A,0x60), BASE, ARG_FPL }, ++ { "vucsubw", FP(0x1A,0x41), BASE, ARG_FP }, ++ { "vucsubw", FP(0x1A,0x61), BASE, ARG_FPL }, ++ { "vucaddh", FP(0x1A,0x42), BASE, ARG_FP }, ++ { "vucaddh", FP(0x1A,0x62), BASE, ARG_FPL }, ++ { "vucsubh", FP(0x1A,0x43), BASE, ARG_FP }, ++ { "vucsubh", FP(0x1A,0x63), BASE, ARG_FPL }, ++ { "vucaddb", FP(0x1A,0x44), BASE, ARG_FP }, ++ { "vucaddb", FP(0x1A,0x64), BASE, ARG_FPL }, ++ { "vucsubb", FP(0x1A,0x45), BASE, ARG_FP }, ++ { "vucsubb", FP(0x1A,0x65), BASE, ARG_FPL }, ++ { "vadds", FP(0x1A,0x80), BASE, ARG_FP }, ++ { "vaddd", FP(0x1A,0x81), BASE, ARG_FP }, ++ { "vsubs", FP(0x1A,0x82), BASE, ARG_FP }, ++ { "vsubd", FP(0x1A,0x83), BASE, ARG_FP }, ++ { "vmuls", FP(0x1A,0x84), BASE, ARG_FP }, ++ { "vmuld", FP(0x1A,0x85), BASE, ARG_FP }, ++ { "vdivs", FP(0x1A,0x86), BASE, ARG_FP }, ++ { "vdivd", FP(0x1A,0x87), BASE, ARG_FP }, ++ { "vsqrts", FP(0x1A,0x88), BASE, ARG_FPZ1 }, ++ { "vsqrtd", FP(0x1A,0x89), BASE, ARG_FPZ1 }, ++ { "vfcmpeq", FP(0x1A,0x8C), BASE, ARG_FP }, ++ { "vfcmple", FP(0x1A,0x8D), BASE, ARG_FP }, ++ { "vfcmplt", FP(0x1A,0x8E), BASE, ARG_FP }, ++ { "vfcmpun", FP(0x1A,0x8F), BASE, ARG_FP }, ++ { "vcpys", FP(0x1A,0x90), BASE, ARG_FP }, ++ { "vcpyse", FP(0x1A,0x91), BASE, ARG_FP }, ++ { "vcpysn", FP(0x1A,0x92), BASE, ARG_FP }, ++ { "vmas", FMA(0x1B,0x00), BASE, ARG_FMA }, ++ { "vmad", FMA(0x1B,0x01), BASE, ARG_FMA }, ++ { "vmss", FMA(0x1B,0x02), BASE, ARG_FMA }, ++ { "vmsd", FMA(0x1B,0x03), BASE, ARG_FMA }, ++ { "vnmas", FMA(0x1B,0x04), BASE, ARG_FMA }, ++ { "vnmad", FMA(0x1B,0x05), BASE, ARG_FMA }, ++ { "vnmss", FMA(0x1B,0x06), BASE, ARG_FMA }, ++ { "vnmsd", FMA(0x1B,0x07), BASE, ARG_FMA }, ++ { "vfseleq", FMA(0x1B,0x10), BASE, ARG_FMA }, ++ { "vfsellt", FMA(0x1B,0x12), BASE, ARG_FMA }, ++ { "vfselle", FMA(0x1B,0x13), BASE, ARG_FMA }, ++ { "vseleqw", FMA(0x1B,0x18), BASE, ARG_FMA }, ++ { "vseleqw", FMA(0x1B,0x38), BASE, ARG_FMAL }, ++ { "vsellbcw", FMA(0x1B,0x19), BASE, ARG_FMA }, ++ { "vsellbcw", FMA(0x1B,0x39), BASE, ARG_FMAL }, ++ { "vselltw", FMA(0x1B,0x1A), BASE, ARG_FMA }, ++ { "vselltw", FMA(0x1B,0x3A), BASE, ARG_FMAL }, ++ { "vsellew", FMA(0x1B,0x1B), BASE, ARG_FMA }, ++ { "vsellew", FMA(0x1B,0x3B), BASE, ARG_FMAL }, ++ { "vinsw", FMA(0x1B,0x20), BASE, ARG_FMAL }, ++ { "vinsf", FMA(0x1B,0x21), BASE, ARG_FMAL }, ++ { "vextw", FMA(0x1B,0x22), BASE, { FA, FMALIT, DFC1 }}, ++ { "vextf", FMA(0x1B,0x23), BASE, { FA, FMALIT, DFC1 }}, ++ { "vcpyw", FMA(0x1B,0x24), BASE, { FA, DFC1 }}, ++ { "vcpyf", FMA(0x1B,0x25), BASE, { FA, DFC1 }}, ++ { "vconw", FMA(0x1B,0x26), BASE, ARG_FMA }, ++ { "vshfw", FMA(0x1B,0x27), BASE, ARG_FMA }, ++ { "vcons", FMA(0x1B,0x28), BASE, ARG_FMA }, ++ { "vcond", FMA(0x1B,0x29), BASE, ARG_FMA }, ++ { "vldw_u", ATMEM(0x1C,0x0), BASE, ARG_VUAMEM }, ++ { "vstw_u", ATMEM(0x1C,0x1), BASE, ARG_VUAMEM }, ++ { "vlds_u", ATMEM(0x1C,0x2), BASE, ARG_VUAMEM }, ++ { "vsts_u", ATMEM(0x1C,0x3), BASE, ARG_VUAMEM }, ++ { "vldd_u", ATMEM(0x1C,0x4), BASE, ARG_VUAMEM }, ++ { "vstd_u", ATMEM(0x1C,0x5), BASE, ARG_VUAMEM }, ++ { "vstw_ul", ATMEM(0x1C,0x8), BASE, ARG_VUAMEM }, ++ { "vstw_uh", ATMEM(0x1C,0x9), BASE, ARG_VUAMEM }, ++ { "vsts_ul", ATMEM(0x1C,0xA), BASE, ARG_VUAMEM }, ++ { "vsts_uh", ATMEM(0x1C,0xB), BASE, ARG_VUAMEM }, ++ { "vstd_ul", ATMEM(0x1C,0xC), BASE, ARG_VUAMEM }, ++ { "vstd_uh", ATMEM(0x1C,0xD), BASE, ARG_VUAMEM }, ++ { "vldd_nc", ATMEM(0x1C,0xE), BASE, ARG_VUAMEM }, ++ { "vstd_nc", ATMEM(0x1C,0xF), BASE, ARG_VUAMEM }, ++ ++ { "flushd", MEM(0x20), BASE, ARG_PREFETCH }, ++ { "ldbu", MEM(0x20), BASE, ARG_MEM }, ++ { "evictdg", MEM(0x21), BASE, ARG_PREFETCH }, ++ { "ldhu", MEM(0x21), BASE, ARG_MEM }, ++ { "s_fillcs", MEM(0x22), BASE, ARG_PREFETCH }, ++ { "ldw", MEM(0x22), BASE, ARG_MEM }, ++ { "s_fillde", MEM(0x23), BASE, ARG_PREFETCH }, ++ { "ldl", MEM(0x23), BASE, ARG_MEM }, ++ { "evictdl", MEM(0x24), BASE, ARG_PREFETCH }, ++ { "ldl_u", MEM(0x24), BASE, ARG_MEM }, ++ { "pri_ldw/p", HWMEM(0x25,0x0), BASE, ARG_HWMEM }, ++ { "pri_ldw/v", HWMEM(0x25,0x8), BASE, ARG_HWMEM }, ++ { "pri_ldl/p", HWMEM(0x25,0x1), BASE, ARG_HWMEM }, ++ { "pri_ldl/v", HWMEM(0x25,0x9), BASE, ARG_HWMEM }, ++ { "fillde", MEM(0x26), BASE, ARG_PREFETCH }, ++ { "flds", MEM(0x26), BASE, ARG_FMEM }, ++ { "fillde_e", MEM(0x27), BASE, ARG_PREFETCH }, ++ { "fldd", MEM(0x27), BASE, ARG_FMEM }, ++ ++ { "stb", MEM(0x28), BASE, ARG_MEM }, ++ { "sth", MEM(0x29), BASE, ARG_MEM }, ++ { "stw", MEM(0x2A), BASE, ARG_MEM }, ++ { "stl", MEM(0x2B), BASE, ARG_MEM }, ++ { "stl_u", MEM(0x2C), BASE, ARG_MEM }, ++ { "pri_stw/p", HWMEM(0x2D,0x0), BASE, ARG_HWMEM }, ++ { "pri_stw/v", HWMEM(0x2D,0x8), BASE, ARG_HWMEM }, ++ { "pri_stl/p", HWMEM(0x2D,0x1), BASE, ARG_HWMEM }, ++ { "pri_stl/v", HWMEM(0x2D,0x9), BASE, ARG_HWMEM }, ++ { "fsts", MEM(0x2E), BASE, ARG_FMEM }, ++ { "fstd", MEM(0x2F), BASE, ARG_FMEM }, ++ { "beq", BRA(0x30), BASE, ARG_BRA }, ++ { "bne", BRA(0x31), BASE, ARG_BRA }, ++ { "blt", BRA(0x32), BASE, ARG_BRA }, ++ { "ble", BRA(0x33), BASE, ARG_BRA }, ++ { "bgt", BRA(0x34), BASE, ARG_BRA }, ++ { "bge", BRA(0x35), BASE, ARG_BRA }, ++ { "blbc", BRA(0x36), BASE, ARG_BRA }, ++ { "blbs", BRA(0x37), BASE, ARG_BRA }, ++ ++ { "fbeq", BRA(0x38), BASE, ARG_FBRA }, ++ { "fbne", BRA(0x39), BASE, ARG_FBRA }, ++ { "fblt", BRA(0x3A), BASE, ARG_FBRA }, ++ { "fble", BRA(0x3B), BASE, ARG_FBRA }, ++ { "fbgt", BRA(0x3C), BASE, ARG_FBRA }, ++ { "fbge", BRA(0x3D), BASE, ARG_FBRA }, ++ { "ldi", MEM(0x3E), BASE, ARG_MEM }, ++ { "ldih", MEM(0x3F), BASE, ARG_MEM }, ++}; ++ ++const unsigned sw_64_num_opcodes = sizeof(sw_64_opcodes) / sizeof(*sw_64_opcodes); ++ ++/* OSF register names. */ ++ ++static const char * const osf_regnames[64] = { ++ "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6", ++ "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp", ++ "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9", ++ "t10", "t11", "ra", "t12", "at", "gp", "sp", "zero", ++ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", ++ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", ++ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", ++ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31" ++}; ++ ++/* VMS register names. */ ++ ++static const char * const vms_regnames[64] = { ++ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", ++ "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", ++ "R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23", ++ "R24", "AI", "RA", "PV", "AT", "FP", "SP", "RZ", ++ "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", ++ "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", ++ "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", ++ "F24", "F25", "F26", "F27", "F28", "F29", "F30", "FZ" ++}; ++ ++int print_insn_sw_64(bfd_vma memaddr, struct disassemble_info *info) ++{ ++ static const struct sw_64_opcode *opcode_index[SW_NOPS + 1]; ++ const char * const * regnames; ++ const struct sw_64_opcode *opcode, *opcode_end; ++ const unsigned char *opindex; ++ unsigned insn, op, isa_mask; ++ int need_comma; ++ ++ /* Initialize the majorop table the first time through */ ++ if (!opcode_index[0]) { ++ opcode = sw_64_opcodes; ++ opcode_end = opcode + sw_64_num_opcodes; ++ ++ for (op = 0; op < SW_NOPS; ++op) { ++ opcode_index[op] = opcode; ++ if ((SW_LITOP (opcode->opcode) != 0x10) && (SW_LITOP (opcode->opcode) != 0x11)) { ++ while (opcode < opcode_end && op == SW_OP (opcode->opcode)) ++ ++opcode; ++ } else { ++ while (opcode < opcode_end && op == SW_LITOP (opcode->opcode)) ++ ++opcode; ++ } ++ } ++ opcode_index[op] = opcode; ++ } ++ ++ if (info->flavour == bfd_target_evax_flavour) ++ regnames = vms_regnames; ++ else ++ regnames = osf_regnames; ++ isa_mask = SW_OPCODE_NOHM; ++ switch (info->mach) { ++ case bfd_mach_sw_64_core3: ++ isa_mask |= SW_OPCODE_BASE | SW_OPCODE_CORE3; ++ break; ++ } ++ ++ /* Read the insn into a host word */ ++ { ++ bfd_byte buffer[4]; ++ int status = (*info->read_memory_func) (memaddr, buffer, 4, info); ++ if (status != 0) { ++ (*info->memory_error_func) (status, memaddr, info); ++ return -1; ++ } ++ insn = bfd_getl32 (buffer); ++ } ++ ++ /* Get the major opcode of the instruction. */ ++ if ((SW_LITOP (insn) == 0x10) || (SW_LITOP (insn) == 0x11)) ++ op = SW_LITOP (insn); ++ else if ((SW_OP(insn) & 0x3C) == 0x14 ) ++ op = 0x14; ++ else ++ op = SW_OP (insn); ++ ++ /* Find the first match in the opcode table. */ ++ opcode_end = opcode_index[op + 1]; ++ for (opcode = opcode_index[op]; opcode < opcode_end; ++opcode) { ++ if ((insn ^ opcode->opcode) & opcode->mask) ++ continue; ++ ++ if (!(opcode->flags & isa_mask)) ++ continue; ++ ++ /* Make two passes over the operands. First see if any of them ++ have extraction functions, and, if they do, make sure the ++ instruction is valid. */ ++ { ++ int invalid = 0; ++ for (opindex = opcode->operands; *opindex != 0; opindex++) { ++ const struct sw_64_operand *operand = sw_64_operands + *opindex; ++ if (operand->extract) ++ (*operand->extract) (insn, &invalid); ++ } ++ if (invalid) ++ continue; ++ } ++ ++ /* The instruction is valid. */ ++ goto found; ++ } ++ ++ /* No instruction found */ ++ (*info->fprintf_func) (info->stream, ".long %#08x", insn); ++ ++ return 4; ++ ++found: ++ if (!strncmp("sys_call",opcode->name,8)) { ++ if (insn & (0x1 << 25)) ++ (*info->fprintf_func) (info->stream, "%s", "sys_call"); ++ else ++ (*info->fprintf_func) (info->stream, "%s", "sys_call/b"); ++ } else ++ (*info->fprintf_func) (info->stream, "%s", opcode->name); ++ ++ /* get zz[7:6] and zz[5:0] to form truth for vlog */ ++ if (!strcmp(opcode->name, "vlog")) ++ { ++ unsigned int truth; ++ char tr[4]; ++ truth=(SW_OP(insn) & 3) << 6; ++ truth = truth | ((insn & 0xFC00) >> 10); ++ sprintf(tr,"%x",truth); ++ (*info->fprintf_func) (info->stream, "%s", tr); ++ } ++ if (opcode->operands[0] != 0) ++ (*info->fprintf_func) (info->stream, "\t"); ++ ++ /* Now extract and print the operands. */ ++ need_comma = 0; ++ for (opindex = opcode->operands; *opindex != 0; opindex++) { ++ const struct sw_64_operand *operand = sw_64_operands + *opindex; ++ int value; ++ ++ /* Operands that are marked FAKE are simply ignored. We ++ already made sure that the extract function considered ++ the instruction to be valid. */ ++ if ((operand->flags & SW_OPERAND_FAKE) != 0) ++ continue; ++ ++ /* Extract the value from the instruction. */ ++ if (operand->extract) ++ value = (*operand->extract) (insn, (int *) NULL); ++ else { ++ value = (insn >> operand->shift) & ((1 << operand->bits) - 1); ++ if (operand->flags & SW_OPERAND_SIGNED) { ++ int signbit = 1 << (operand->bits - 1); ++ value = (value ^ signbit) - signbit; ++ } ++ } ++ ++ if (need_comma && ++ ((operand->flags & (SW_OPERAND_PARENS | SW_OPERAND_COMMA)) ++ != SW_OPERAND_PARENS)) { ++ (*info->fprintf_func) (info->stream, ","); ++ } ++ if (operand->flags & SW_OPERAND_PARENS) ++ (*info->fprintf_func) (info->stream, "("); ++ ++ /* Print the operand as directed by the flags. */ ++ if (operand->flags & SW_OPERAND_IR) ++ (*info->fprintf_func) (info->stream, "%s", regnames[value]); ++ else if (operand->flags & SW_OPERAND_FPR) ++ (*info->fprintf_func) (info->stream, "%s", regnames[value + 32]); ++ else if (operand->flags & SW_OPERAND_RELATIVE) ++ (*info->print_address_func) (memaddr + 4 + value, info); ++ else if (operand->flags & SW_OPERAND_SIGNED) ++ (*info->fprintf_func) (info->stream, "%d", value); ++ else ++ (*info->fprintf_func) (info->stream, "%#x", value); ++ ++ if (operand->flags & SW_OPERAND_PARENS) ++ (*info->fprintf_func) (info->stream, ")"); ++ need_comma = 1; ++ } ++ ++ return 4; ++} +diff --git a/hw/Kconfig b/hw/Kconfig +index ad20cce0a9..5f3957be0f 100644 +--- a/hw/Kconfig ++++ b/hw/Kconfig +@@ -63,6 +63,7 @@ source sparc/Kconfig + source sparc64/Kconfig + source tricore/Kconfig + source xtensa/Kconfig ++source sw64/Kconfig + + # Symbols used by multiple targets + config TEST_DEVICES +diff --git a/hw/meson.build b/hw/meson.build +index b3366c888e..f39c1f7e70 100644 +--- a/hw/meson.build ++++ b/hw/meson.build +@@ -62,5 +62,6 @@ subdir('s390x') + subdir('sh4') + subdir('sparc') + subdir('sparc64') ++subdir('sw64') + subdir('tricore') + subdir('xtensa') +diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c +index e037acd1b5..58a0cff483 100644 +--- a/hw/rtc/sun4v-rtc.c ++++ b/hw/rtc/sun4v-rtc.c +@@ -32,10 +32,17 @@ static uint64_t sun4v_rtc_read(void *opaque, hwaddr addr, + unsigned size) + { + uint64_t val = get_clock_realtime() / NANOSECONDS_PER_SECOND; ++#if defined(__sw_64__) ++ if (addr & 4ULL) { ++ /* accessing the high 32 bits */ ++ val >>= 32; ++ } ++#else + if (!(addr & 4ULL)) { + /* accessing the high 32 bits */ + val >>= 32; + } ++#endif + trace_sun4v_rtc_read(addr, val); + return val; + } +@@ -49,7 +56,11 @@ static void sun4v_rtc_write(void *opaque, hwaddr addr, + static const MemoryRegionOps sun4v_rtc_ops = { + .read = sun4v_rtc_read, + .write = sun4v_rtc_write, ++#if defined(__sw_64__) ++ .endianness = DEVICE_LITTLE_ENDIAN, ++#else + .endianness = DEVICE_NATIVE_ENDIAN, ++#endif + }; + + void sun4v_rtc_init(hwaddr addr) +diff --git a/hw/sw64/Kconfig b/hw/sw64/Kconfig +new file mode 100644 +index 0000000000..2bf19e8234 +--- /dev/null ++++ b/hw/sw64/Kconfig +@@ -0,0 +1,11 @@ ++config CORE3 ++ bool ++ imply PCI_DEVICES ++ imply TEST_DEVICES ++ imply E1000_PCI ++ select PCI_EXPRESS ++ select SUN4V_RTC ++ select VIRTIO_MMIO ++ select SERIAL ++ select IDE_CMD646 ++ select VIRTIO_VGA +diff --git a/hw/sw64/Makefile.objs b/hw/sw64/Makefile.objs +new file mode 100644 +index 0000000000..73add9a91d +--- /dev/null ++++ b/hw/sw64/Makefile.objs +@@ -0,0 +1 @@ ++obj-y += core3.o core3_board.o +diff --git a/hw/sw64/core.h b/hw/sw64/core.h +new file mode 100644 +index 0000000000..4923382229 +--- /dev/null ++++ b/hw/sw64/core.h +@@ -0,0 +1,25 @@ ++#ifndef HW_SW64_SYS_H ++#define HW_SW64_SYS_H ++ ++typedef struct boot_params { ++ unsigned long initrd_size; /* size of initrd */ ++ unsigned long initrd_start; /* logical address of initrd */ ++ unsigned long dtb_start; /* logical address of dtb */ ++ unsigned long efi_systab; /* logical address of EFI system table */ ++ unsigned long efi_memmap; /* logical address of EFI memory map */ ++ unsigned long efi_memmap_size; /* size of EFI memory map */ ++ unsigned long efi_memdesc_size; /* size of an EFI memory map descriptor */ ++ unsigned long efi_memdesc_version; /* memory descriptor version */ ++ unsigned long cmdline; /* logical address of cmdline */ ++} BOOT_PARAMS; ++ ++void core3_board_init(SW64CPU *cpus[4], MemoryRegion *ram); ++#endif ++ ++#define MAX_CPUS 64 ++ ++#ifdef CONFIG_KVM ++#define MAX_CPUS_CORE3 64 ++#else ++#define MAX_CPUS_CORE3 32 ++#endif +diff --git a/hw/sw64/core3.c b/hw/sw64/core3.c +new file mode 100644 +index 0000000000..dbe4ed6fa1 +--- /dev/null ++++ b/hw/sw64/core3.c +@@ -0,0 +1,182 @@ ++/* ++ * QEMU CORE3 hardware system emulator. ++ * ++ * Copyright (c) 2021 Lu Feifei ++ * ++ * This work is licensed under the GNU GPL license version 2 or later. ++ */ ++ ++#include "qemu/osdep.h" ++#include "qemu-common.h" ++#include "qemu/datadir.h" ++#include "cpu.h" ++#include "hw/hw.h" ++#include "elf.h" ++#include "hw/loader.h" ++#include "hw/boards.h" ++#include "qemu/error-report.h" ++#include "sysemu/sysemu.h" ++#include "sysemu/kvm.h" ++#include "sysemu/reset.h" ++#include "hw/ide.h" ++#include "hw/char/serial.h" ++#include "qemu/cutils.h" ++#include "ui/console.h" ++#include "core.h" ++#include "hw/boards.h" ++#include "sysemu/numa.h" ++ ++static uint64_t cpu_sw64_virt_to_phys(void *opaque, uint64_t addr) ++{ ++ return addr &= ~0xffffffff80000000 ; ++} ++ ++static CpuInstanceProperties ++sw64_cpu_index_to_props(MachineState *ms, unsigned cpu_index) ++{ ++ MachineClass *mc = MACHINE_GET_CLASS(ms); ++ const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms); ++ ++ assert(cpu_index < possible_cpus->len); ++ return possible_cpus->cpus[cpu_index].props; ++} ++ ++static int64_t sw64_get_default_cpu_node_id(const MachineState *ms, int idx) ++{ ++ int nb_numa_nodes = ms->numa_state->num_nodes; ++ return idx % nb_numa_nodes; ++} ++ ++static const CPUArchIdList *sw64_possible_cpu_arch_ids(MachineState *ms) ++{ ++ int i; ++ unsigned int max_cpus = ms->smp.max_cpus; ++ ++ if (ms->possible_cpus) { ++ /* ++ * make sure that max_cpus hasn't changed since the first use, i.e. ++ * -smp hasn't been parsed after it ++ */ ++ assert(ms->possible_cpus->len == max_cpus); ++ return ms->possible_cpus; ++ } ++ ++ ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + ++ sizeof(CPUArchId) * max_cpus); ++ ms->possible_cpus->len = max_cpus; ++ for (i = 0; i < ms->possible_cpus->len; i++) { ++ ms->possible_cpus->cpus[i].type = ms->cpu_type; ++ ms->possible_cpus->cpus[i].vcpus_count = 1; ++ ms->possible_cpus->cpus[i].arch_id = i; ++ ms->possible_cpus->cpus[i].props.has_thread_id = true; ++ ms->possible_cpus->cpus[i].props.core_id = i; ++ } ++ ++ return ms->possible_cpus; ++} ++ ++static void core3_cpu_reset(void *opaque) ++{ ++ SW64CPU *cpu = opaque; ++ ++ cpu_reset(CPU(cpu)); ++} ++ ++static void core3_init(MachineState *machine) ++{ ++ ram_addr_t ram_size = machine->ram_size; ++ ram_addr_t buf; ++ SW64CPU *cpus[machine->smp.max_cpus]; ++ long i, size; ++ const char *kernel_filename = machine->kernel_filename; ++ const char *kernel_cmdline = machine->kernel_cmdline; ++ char *hmcode_filename; ++ char *uefi_filename; ++ uint64_t hmcode_entry, hmcode_low, hmcode_high; ++ uint64_t kernel_entry, kernel_low, kernel_high; ++ BOOT_PARAMS *core3_boot_params = g_new0(BOOT_PARAMS, 1); ++ uint64_t param_offset; ++ ++ memset(cpus, 0, sizeof(cpus)); ++ ++ for (i = 0; i < machine->smp.cpus; ++i) { ++ cpus[i] = SW64_CPU(cpu_create(machine->cpu_type)); ++ cpus[i]->env.csr[CID] = i; ++ qemu_register_reset(core3_cpu_reset, cpus[i]); ++ } ++ core3_board_init(cpus, machine->ram); ++ if (kvm_enabled()) ++ buf = ram_size; ++ else ++ buf = ram_size | (1UL << 63); ++ ++ rom_add_blob_fixed("ram_size", (char *)&buf, 0x8, 0x2040); ++ ++ param_offset = 0x90B000UL; ++ core3_boot_params->cmdline = param_offset | 0xfff0000000000000UL; ++ rom_add_blob_fixed("core3_boot_params", (core3_boot_params), 0x48, 0x90A100); ++ ++ hmcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, kvm_enabled() ? "core3-reset":"core3-hmcode"); ++ if (hmcode_filename == NULL) { ++ if (kvm_enabled()) ++ error_report("no core3-reset provided"); ++ else ++ error_report("no core3-hmcode provided"); ++ exit(1); ++ } ++ size = load_elf(hmcode_filename, NULL, cpu_sw64_virt_to_phys, NULL, ++ &hmcode_entry, &hmcode_low, &hmcode_high, NULL, 0, EM_SW64, 0, 0); ++ if (size < 0) { ++ if (kvm_enabled()) ++ error_report("could not load core3-reset: '%s'", hmcode_filename); ++ else ++ error_report("could not load core3-hmcode: '%s'", hmcode_filename); ++ exit(1); ++ } ++ g_free(hmcode_filename); ++ ++ /* Start all cpus at the hmcode RESET entry point. */ ++ for (i = 0; i < machine->smp.cpus; ++i) { ++ cpus[i]->env.pc = hmcode_entry; ++ cpus[i]->env.hm_entry = hmcode_entry; ++ } ++ ++ if (!kernel_filename) { ++ uefi_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "uefi-bios-sw"); ++ load_image_targphys(uefi_filename, 0x2f00000UL, -1); ++ g_free(uefi_filename); ++ } else { ++ /* Load a kernel. */ ++ size = load_elf(kernel_filename, NULL, cpu_sw64_virt_to_phys, NULL, ++ &kernel_entry, &kernel_low, &kernel_high, NULL, 0, EM_SW64, 0, 0); ++ if (size < 0) { ++ error_report("could not load kernel '%s'", kernel_filename); ++ exit(1); ++ } ++ cpus[0]->env.trap_arg1 = kernel_entry; ++ if (kernel_cmdline) ++ pstrcpy_targphys("cmdline", param_offset, 0x400, kernel_cmdline); ++ } ++} ++ ++static void board_reset(MachineState *state) ++{ ++ qemu_devices_reset(); ++} ++ ++static void core3_machine_init(MachineClass *mc) ++{ ++ mc->desc = "core3 BOARD"; ++ mc->init = core3_init; ++ mc->block_default_type = IF_IDE; ++ mc->max_cpus = MAX_CPUS_CORE3; ++ mc->is_default = 0; ++ mc->reset = board_reset; ++ mc->possible_cpu_arch_ids = sw64_possible_cpu_arch_ids; ++ mc->cpu_index_to_instance_props = sw64_cpu_index_to_props; ++ mc->default_cpu_type = SW64_CPU_TYPE_NAME("core3"); ++ mc->default_ram_id = "ram"; ++ mc->get_default_cpu_node_id = sw64_get_default_cpu_node_id; ++} ++ ++DEFINE_MACHINE("core3", core3_machine_init) +diff --git a/hw/sw64/core3_board.c b/hw/sw64/core3_board.c +new file mode 100644 +index 0000000000..7853e01edb +--- /dev/null ++++ b/hw/sw64/core3_board.c +@@ -0,0 +1,493 @@ ++#include "qemu/osdep.h" ++#include "qapi/error.h" ++#include "cpu.h" ++#include "core.h" ++#include "hw/hw.h" ++#include "hw/boards.h" ++#include "sysemu/sysemu.h" ++#include "exec/address-spaces.h" ++#include "hw/pci/pci_host.h" ++#include "hw/pci/pci.h" ++#include "hw/char/serial.h" ++#include "hw/irq.h" ++#include "net/net.h" ++#include "hw/usb.h" ++#include "hw/ide/pci.h" ++#include "hw/ide/ahci.h" ++#include "sysemu/numa.h" ++#include "sysemu/kvm.h" ++#include "hw/rtc/sun4v-rtc.h" ++#include "hw/pci/msi.h" ++#include "hw/sw64/sw64_iommu.h" ++ ++#define TYPE_SWBOARD_PCI_HOST_BRIDGE "core_board-pcihost" ++#define SWBOARD_PCI_HOST_BRIDGE(obj) \ ++ OBJECT_CHECK(BoardState, (obj), TYPE_SWBOARD_PCI_HOST_BRIDGE) ++ ++#define MAX_IDE_BUS 2 ++#define SW_PIN_TO_IRQ 16 ++ ++typedef struct SWBoard { ++ SW64CPU *cpu[MAX_CPUS_CORE3]; ++} SWBoard; ++ ++typedef struct BoardState { ++ PCIHostState parent_obj; ++ ++ SWBoard sboard; ++ uint64_t expire_time; ++} BoardState; ++ ++typedef struct TimerState { ++ void *opaque; ++ int order; ++} TimerState; ++ ++#ifndef CONFIG_KVM ++static void swboard_alarm_timer(void *opaque) ++{ ++ TimerState *ts = (TimerState *)((uintptr_t)opaque); ++ BoardState *bs = (BoardState *)((uintptr_t)ts->opaque); ++ ++ int cpu = ts->order; ++ cpu_interrupt(CPU(bs->sboard.cpu[cpu]), CPU_INTERRUPT_TIMER); ++} ++#endif ++ ++static PCIINTxRoute sw_route_intx_pin_to_irq(void *opaque, int pin) ++{ ++ PCIINTxRoute route; ++ ++ route.mode = PCI_INTX_ENABLED; ++ route.irq = SW_PIN_TO_IRQ; ++ return route; ++} ++ ++static uint64_t convert_bit(int n) ++{ ++ uint64_t ret = (1UL << n) - 1; ++ ++ if (n == 64) ++ ret = 0xffffffffffffffffUL; ++ return ret; ++} ++ ++static uint64_t mcu_read(void *opaque, hwaddr addr, unsigned size) ++{ ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ unsigned int smp_cpus = ms->smp.cpus; ++ uint64_t ret = 0; ++ switch (addr) { ++ case 0x0000: ++ /* CG_ONLINE */ ++ { ++ int i; ++ for (i = 0; i < smp_cpus; i = i + 4) ++ ret |= (1UL << i); ++ } ++ break; ++ /*IO_START*/ ++ case 0x1300: ++ ret = 0x1; ++ break; ++ case 0x3780: ++ /* MC_ONLINE */ ++ ret = convert_bit(smp_cpus); ++ break; ++ case 0x0900: ++ /* CPUID */ ++ ret = 0; ++ break; ++ case 0x1180: ++ /* LONGTIME */ ++ ret = qemu_clock_get_ns(QEMU_CLOCK_HOST) / 80; ++ break; ++ case 0x4900: ++ /* MC_CONFIG */ ++ break; ++ case 0x0780: ++ /* CORE_ONLINE */ ++ ret = convert_bit(smp_cpus); ++ break; ++ case 0x0680: ++ /* INIT_CTL */ ++ ret = 0x000003AE00000D28; ++ break; ++ default: ++ fprintf(stderr, "Unsupported MCU addr: 0x%04lx\n", addr); ++ return -1; ++ } ++ return ret; ++} ++ ++static void mcu_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) ++{ ++#ifndef CONFIG_KVM ++#ifdef CONFIG_DUMP_PRINTK ++ uint64_t print_addr; ++ uint32_t len; ++ int i; ++ ++ if (addr == 0x40000) { ++ print_addr = val & 0x7fffffff; ++ len = (uint32_t)(val >> 32); ++ uint8_t *buf; ++ buf = malloc(len + 10); ++ memset(buf, 0, len + 10); ++ cpu_physical_memory_rw(print_addr, buf, len, 0); ++ for (i = 0; i < len; i++) ++ printf("%c", buf[i]); ++ ++ free(buf); ++ return; ++ } ++#endif ++#endif ++} ++ ++static const MemoryRegionOps mcu_ops = { ++ .read = mcu_read, ++ .write = mcu_write, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++ .valid = ++ { ++ .min_access_size = 8, ++ .max_access_size = 8, ++ }, ++ .impl = ++ { ++ .min_access_size = 8, ++ .max_access_size = 8, ++ }, ++}; ++ ++static uint64_t intpu_read(void *opaque, hwaddr addr, unsigned size) ++{ ++ uint64_t ret = 0; ++#ifndef CONFIG_KVM ++ switch (addr) { ++ case 0x180: ++ /* LONGTIME */ ++ ret = qemu_clock_get_ns(QEMU_CLOCK_HOST) / 32; ++ break; ++ } ++#endif ++ return ret; ++} ++ ++static void intpu_write(void *opaque, hwaddr addr, uint64_t val, ++ unsigned size) ++{ ++#ifndef CONFIG_KVM ++ BoardState *bs = (BoardState *)opaque; ++ SW64CPU *cpu; ++ switch (addr) { ++ case 0x00: ++ val &= 0x1f; ++ cpu = bs->sboard.cpu[val]; ++ cpu->env.csr[II_REQ] = 0x100000; ++ cpu_interrupt(CPU(cpu),CPU_INTERRUPT_IIMAIL); ++ break; ++ default: ++ fprintf(stderr, "Unsupported IPU addr: 0x%04lx\n", addr); ++ break; ++ } ++#endif ++} ++ ++static const MemoryRegionOps intpu_ops = { ++ .read = intpu_read, ++ .write = intpu_write, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++ .valid = ++ { ++ .min_access_size = 8, ++ .max_access_size = 8, ++ }, ++ .impl = ++ { ++ .min_access_size = 8, ++ .max_access_size = 8, ++ }, ++}; ++ ++static MemTxResult msi_read(void *opaque, hwaddr addr, ++ uint64_t *data, unsigned size, ++ MemTxAttrs attrs) ++{ ++ return MEMTX_OK; ++} ++ ++MemTxResult msi_write(void *opaque, hwaddr addr, ++ uint64_t value, unsigned size, ++ MemTxAttrs attrs) ++{ ++#ifdef CONFIG_KVM ++ int ret = 0; ++ MSIMessage msg = {}; ++ ++ msg.address = (uint64_t) addr + 0x8000fee00000; ++ msg.data = (uint32_t) value; ++ ++ ret = kvm_irqchip_send_msi(kvm_state, msg); ++ if (ret < 0) { ++ fprintf(stderr, "KVM: injection failed, MSI lost (%s)\n", ++ strerror(-ret)); ++ } ++#endif ++ return MEMTX_OK; ++} ++ ++static const MemoryRegionOps msi_ops = { ++ .read_with_attrs = msi_read, ++ .write_with_attrs = msi_write, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++ .valid = ++ { ++ .min_access_size = 1, ++ .max_access_size = 8, ++ }, ++ .impl = ++ { ++ .min_access_size = 1, ++ .max_access_size = 8, ++ }, ++}; ++ ++static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size) ++{ ++ return 1; ++} ++ ++static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size) ++{ ++} ++ ++const MemoryRegionOps core3_pci_ignore_ops = { ++ .read = ignore_read, ++ .write = ignore_write, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++ .valid = ++ { ++ .min_access_size = 1, ++ .max_access_size = 8, ++ }, ++ .impl = ++ { ++ .min_access_size = 1, ++ .max_access_size = 8, ++ }, ++}; ++ ++static uint64_t config_read(void *opaque, hwaddr addr, unsigned size) ++{ ++ PCIBus *b = opaque; ++ uint32_t trans_addr = 0; ++ trans_addr |= ((addr >> 16) & 0xffff) << 8; ++ trans_addr |= (addr & 0xff); ++ return pci_data_read(b, trans_addr, size); ++} ++ ++static void config_write(void *opaque, hwaddr addr, uint64_t val, ++ unsigned size) ++{ ++ PCIBus *b = opaque; ++ uint32_t trans_addr = 0; ++ trans_addr |= ((addr >> 16) & 0xffff) << 8; ++ trans_addr |= (addr & 0xff); ++ pci_data_write(b, trans_addr, val, size); ++} ++ ++const MemoryRegionOps core3_pci_config_ops = { ++ .read = config_read, ++ .write = config_write, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++ .valid = ++ { ++ .min_access_size = 1, ++ .max_access_size = 8, ++ }, ++ .impl = ++ { ++ .min_access_size = 1, ++ .max_access_size = 8, ++ }, ++}; ++ ++static void cpu_irq_change(SW64CPU *cpu, uint64_t req) ++{ ++ if (cpu != NULL) { ++ CPUState *cs = CPU(cpu); ++ if (req) ++ cpu_interrupt(cs, CPU_INTERRUPT_HARD); ++ else ++ cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); ++ } ++} ++ ++static void swboard_set_irq(void *opaque, int irq, int level) ++{ ++ BoardState *bs = opaque; ++ SW64CPU *cpu; ++ int i; ++ ++ if (kvm_enabled()) { ++ if (level == 0) ++ return; ++ kvm_set_irq(kvm_state, irq, level); ++ return; ++ } ++ ++ for (i = 0; i < 1; i++) { ++ cpu = bs->sboard.cpu[i]; ++ if (cpu != NULL) { ++ CPUState *cs = CPU(cpu); ++ if (level) ++ cpu_interrupt(cs, CPU_INTERRUPT_PCIE); ++ else ++ cpu_reset_interrupt(cs, CPU_INTERRUPT_PCIE); ++ } ++ } ++} ++ ++static int swboard_map_irq(PCIDevice *d, int irq_num) ++{ ++ /* In fact,the return value is the interrupt type passed to kernel, ++ * so it must keep same with the type in do_entInt in kernel. ++ */ ++ return 16; ++} ++ ++static void serial_set_irq(void *opaque, int irq, int level) ++{ ++ BoardState *bs = (BoardState *)opaque; ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ unsigned int smp_cpus = ms->smp.cpus; ++ int i; ++ if (level == 0) ++ return; ++ if (kvm_enabled()) { ++ kvm_set_irq(kvm_state, irq, level); ++ return; ++ } ++ for (i = 0; i < smp_cpus; i++) { ++ if (bs->sboard.cpu[i]) ++ cpu_irq_change(bs->sboard.cpu[i], 1); ++ } ++} ++ ++void core3_board_init(SW64CPU *cpus[MAX_CPUS], MemoryRegion *ram) ++{ ++ DeviceState *dev; ++ BoardState *bs; ++#ifndef CONFIG_KVM ++ TimerState *ts; ++#endif ++ MemoryRegion *io_mcu = g_new(MemoryRegion, 1); ++ MemoryRegion *io_intpu = g_new(MemoryRegion, 1); ++ MemoryRegion *msi_ep = g_new(MemoryRegion, 1); ++ qemu_irq serial_irq; ++ uint64_t MB = 1024 * 1024; ++ MemoryRegion *mem_ep = g_new(MemoryRegion, 1); ++ MemoryRegion *mem_ep64 = g_new(MemoryRegion, 1); ++ MemoryRegion *conf_piu0 = g_new(MemoryRegion, 1); ++ MemoryRegion *io_ep = g_new(MemoryRegion, 1); ++ ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ unsigned int smp_cpus = ms->smp.cpus; ++ ++ PCIBus *b; ++ PCIHostState *phb; ++ uint64_t GB = 1024 * MB; ++ ++ int i; ++ dev = qdev_new(TYPE_SWBOARD_PCI_HOST_BRIDGE); ++ phb = PCI_HOST_BRIDGE(dev); ++ bs = SWBOARD_PCI_HOST_BRIDGE(dev); ++ ++#ifdef CONFIG_KVM ++ if (kvm_has_gsi_routing()) ++ msi_nonbroken = true; ++#endif ++ ++ for (i = 0; i < smp_cpus; ++i) { ++ if (cpus[i] == NULL) ++ continue; ++ bs->sboard.cpu[i] = cpus[i]; ++#ifndef CONFIG_KVM ++ ts = g_new(TimerState, 1); ++ ts->opaque = (void *) ((uintptr_t)bs); ++ ts->order = i; ++ cpus[i]->alarm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &swboard_alarm_timer, ts); ++#endif ++ } ++ memory_region_add_subregion(get_system_memory(), 0, ram); ++ ++ memory_region_init_io(io_mcu, NULL, &mcu_ops, bs, "io_mcu", 16 * MB); ++ memory_region_add_subregion(get_system_memory(), 0x803000000000ULL, io_mcu); ++ ++ memory_region_init_io(io_intpu, NULL, &intpu_ops, bs, "io_intpu", 1 * MB); ++ memory_region_add_subregion(get_system_memory(), 0x802a00000000ULL, ++ io_intpu); ++ ++ memory_region_init_io(msi_ep, NULL, &msi_ops, bs, "msi_ep", 1 * MB); ++ memory_region_add_subregion(get_system_memory(), 0x8000fee00000ULL, msi_ep); ++ ++ memory_region_init(mem_ep, OBJECT(bs), "pci0-mem", 0x890000000000ULL); ++ memory_region_add_subregion(get_system_memory(), 0x880000000000ULL, mem_ep); ++ ++ memory_region_init_alias(mem_ep64, NULL, "mem_ep64", mem_ep, 0x888000000000ULL, 1ULL << 39); ++ memory_region_add_subregion(get_system_memory(), 0x888000000000ULL, mem_ep64); ++ ++ memory_region_init_io(io_ep, OBJECT(bs), &core3_pci_ignore_ops, NULL, ++ "pci0-io-ep", 4 * GB); ++ ++ memory_region_add_subregion(get_system_memory(), 0x880100000000ULL, io_ep); ++ b = pci_register_root_bus(dev, "pcie.0", swboard_set_irq, swboard_map_irq, bs, ++ mem_ep, io_ep, 0, 537, TYPE_PCIE_BUS); ++ phb->bus = b; ++ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); ++ pci_bus_set_route_irq_fn(b, sw_route_intx_pin_to_irq); ++ memory_region_init_io(conf_piu0, OBJECT(bs), &core3_pci_config_ops, b, ++ "pci0-ep-conf-io", 4 * GB); ++ memory_region_add_subregion(get_system_memory(), 0x880600000000ULL, ++ conf_piu0); ++#ifdef SW64_VT_IOMMU ++ sw64_vt_iommu_init(b); ++#endif ++ for (i = 0; i < nb_nics; i++) { ++ pci_nic_init_nofail(&nd_table[i], b, "e1000", NULL); ++ } ++ ++ pci_vga_init(b); ++#define MAX_SATA_PORTS 6 ++ PCIDevice *ahci; ++ DriveInfo *hd[MAX_SATA_PORTS]; ++ ahci = pci_create_simple_multifunction(b, PCI_DEVFN(0x1f, 0), true, ++ TYPE_ICH9_AHCI); ++ g_assert(MAX_SATA_PORTS == ahci_get_num_ports(ahci)); ++ ide_drive_get(hd, ahci_get_num_ports(ahci)); ++ ahci_ide_create_devs(ahci, hd); ++ ++ serial_irq = qemu_allocate_irq(serial_set_irq, bs, 12); ++ if (serial_hd(0)) { ++ serial_mm_init(get_system_memory(), 0x3F8 + 0x880100000000ULL, 0, ++ serial_irq, (1843200 >> 4), serial_hd(0), ++ DEVICE_LITTLE_ENDIAN); ++ } ++ pci_create_simple(phb->bus, -1, "nec-usb-xhci"); ++ sun4v_rtc_init(0x804910000000ULL); ++} ++ ++static const TypeInfo swboard_pcihost_info = { ++ .name = TYPE_SWBOARD_PCI_HOST_BRIDGE, ++ .parent = TYPE_PCI_HOST_BRIDGE, ++ .instance_size = sizeof(BoardState), ++}; ++ ++static void swboard_register_types(void) ++{ ++ type_register_static(&swboard_pcihost_info); ++} ++ ++type_init(swboard_register_types) +diff --git a/hw/sw64/meson.build b/hw/sw64/meson.build +new file mode 100644 +index 0000000000..8abb18222a +--- /dev/null ++++ b/hw/sw64/meson.build +@@ -0,0 +1,10 @@ ++sw64_ss = ss.source_set() ++ ++sw64_ss.add(files('sw64_iommu.c')) ++ ++sw64_ss.add(when: 'CONFIG_CORE3', if_true: files( ++ 'core3.c', ++ 'core3_board.c', ++)) ++ ++hw_arch += {'sw64': sw64_ss} +diff --git a/hw/sw64/sw64_iommu.c b/hw/sw64/sw64_iommu.c +new file mode 100644 +index 0000000000..8ded65f213 +--- /dev/null ++++ b/hw/sw64/sw64_iommu.c +@@ -0,0 +1,567 @@ ++/* ++ * QEMU sw64 IOMMU emulation ++ * ++ * Copyright (c) 2021 Lu Feifei ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#include "qemu/osdep.h" ++#include "hw/sysbus.h" ++#include "exec/address-spaces.h" ++#include "qemu/log.h" ++#include "qapi/error.h" ++#include "hw/sw64/sw64_iommu.h" ++#include "sysemu/kvm.h" ++ ++#define IOMMU_PAGE_SHIFT 13 ++#define IOMMU_PAGE_SIZE_8K (1ULL << IOMMU_PAGE_SHIFT) ++#define IOMMU_PAGE_MASK_8K (~(IOMMU_PAGE_SIZE_8K - 1)) ++#define IOMMU_IOVA_SHIFT 16 ++#define SW64IOMMU_PTIOTLB_MAX_SIZE 256 ++ ++static MemTxResult swvt_msi_read(void *opaque, hwaddr addr, ++ uint64_t *data, unsigned size, MemTxAttrs attrs) ++{ ++ return MEMTX_OK; ++} ++ ++static MemTxResult swvt_msi_write(void *opaque, hwaddr addr, ++ uint64_t value, unsigned size, ++ MemTxAttrs attrs) ++{ ++ MemTxResult ret; ++ ++ ret = msi_write(opaque, addr, value, size, attrs); ++ ++ return ret; ++} ++ ++static const MemoryRegionOps swvt_msi_ops = { ++ .read_with_attrs = swvt_msi_read, ++ .write_with_attrs = swvt_msi_write, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++ .valid = { ++ .min_access_size = 1, ++ .max_access_size = 8, ++ }, ++ .impl = { ++ .min_access_size = 1, ++ .max_access_size = 8, ++ }, ++}; ++ ++SWVTAddressSpace *iommu_find_add_as(SW64IOMMUState *s, PCIBus *bus, int devfn) ++{ ++ uintptr_t key = (uintptr_t)bus; ++ SWVTBus *swvt_bus = g_hash_table_lookup(s->swvtbus_as_by_busptr, &key); ++ SWVTAddressSpace *swvt_dev_as; ++ char name[128]; ++ ++ if (!swvt_bus) { ++ uintptr_t *new_key = g_malloc(sizeof(*new_key)); ++ *new_key = (uintptr_t)bus; ++ /* No corresponding free() */ ++ swvt_bus = g_malloc0(sizeof(SWVTBus) + sizeof(SWVTAddressSpace *) * \ ++ PCI_DEVFN_MAX); ++ swvt_bus->bus = bus; ++ g_hash_table_insert(s->swvtbus_as_by_busptr, new_key, swvt_bus); ++ } ++ swvt_dev_as = swvt_bus->dev_as[devfn]; ++ if (!swvt_dev_as) { ++ snprintf(name, sizeof(name), "sw64_iommu_devfn_%d", devfn); ++ swvt_bus->dev_as[devfn] = swvt_dev_as = g_malloc0(sizeof(SWVTAddressSpace)); ++ ++ swvt_dev_as->bus = bus; ++ swvt_dev_as->devfn = (uint8_t)devfn; ++ swvt_dev_as->iommu_state = s; ++ ++ memory_region_init_iommu(&swvt_dev_as->iommu, sizeof(swvt_dev_as->iommu), ++ TYPE_SW64_IOMMU_MEMORY_REGION, OBJECT(s), ++ "sw64_iommu_dmar", ++ 1UL << 32); ++ memory_region_init_io(&swvt_dev_as->msi, OBJECT(s), ++ &swvt_msi_ops, s, "sw_msi", 1 * 1024 * 1024); ++ memory_region_init(&swvt_dev_as->root, OBJECT(s), ++ "swvt_root", UINT64_MAX); ++ memory_region_add_subregion_overlap(&swvt_dev_as->root, ++ 0x8000fee00000ULL, ++ &swvt_dev_as->msi, 64); ++ address_space_init(&swvt_dev_as->as, &swvt_dev_as->root, name); ++ memory_region_add_subregion_overlap(&swvt_dev_as->root, 0, ++ MEMORY_REGION(&swvt_dev_as->iommu), ++ 1); ++ } ++ ++ memory_region_set_enabled(MEMORY_REGION(&swvt_dev_as->iommu), true); ++ ++ return swvt_dev_as; ++} ++ ++/** ++ * get_pte - Get the content of a page table entry located at ++ * @base_addr[@index] ++ */ ++static int get_pte(dma_addr_t baseaddr, uint64_t *pte) ++{ ++ int ret; ++ ++ /* TODO: guarantee 64-bit single-copy atomicity */ ++ ret = dma_memory_read(&address_space_memory, baseaddr, ++ (uint8_t *)pte, sizeof(*pte)); ++ ++ if (ret != MEMTX_OK) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static bool swvt_do_iommu_translate(SWVTAddressSpace *swvt_as, PCIBus *bus, ++ uint8_t devfn, hwaddr addr, IOMMUTLBEntry *entry) ++{ ++ SW64IOMMUState *s = swvt_as->iommu_state; ++ uint8_t bus_num = pci_bus_num(bus); ++ unsigned long dtbbaseaddr, dtbbasecond; ++ unsigned long pdebaseaddr, ptebaseaddr; ++ unsigned long pte; ++ uint16_t source_id; ++ SW64DTIOTLBEntry *dtcached_entry = NULL; ++ SW64DTIOTLBKey dtkey, *new_key; ++ ++ dtcached_entry = g_hash_table_lookup(s->dtiotlb, &dtkey); ++ ++ if (unlikely(!dtcached_entry)) { ++ dtbbaseaddr = s->dtbr + (bus_num << 3); ++ ++ if (get_pte(dtbbaseaddr, &pte)) ++ goto error; ++ ++ dtbbasecond = (pte & (~(SW_IOMMU_ENTRY_VALID))) + (devfn << 3); ++ if (get_pte(dtbbasecond, &pte)) ++ goto error; ++ ++ source_id = ((bus_num & 0xffUL) << 8) | (devfn & 0xffUL); ++ dtcached_entry = g_new0(SW64DTIOTLBEntry, 1); ++ dtcached_entry->ptbase_addr = pte & (~(SW_IOMMU_ENTRY_VALID)); ++ dtcached_entry->source_id = source_id; ++ ++ new_key = g_new0(SW64DTIOTLBKey, 1); ++ new_key->source_id = source_id; ++ ++ g_hash_table_insert(s->dtiotlb, new_key, dtcached_entry); ++ } ++ ++ pdebaseaddr = dtcached_entry->ptbase_addr; ++ pdebaseaddr += ((addr >> 23) & SW_IOMMU_LEVEL1_OFFSET) << 3; ++ ++ if (get_pte(pdebaseaddr, &pte)) ++ goto error; ++ ++ ptebaseaddr = pte & (~(SW_IOMMU_ENTRY_VALID)); ++ ptebaseaddr += ((addr >> IOMMU_PAGE_SHIFT) & SW_IOMMU_LEVEL2_OFFSET) << 3; ++ ++ if (get_pte(ptebaseaddr, &pte)) ++ goto error; ++ ++ pte &= ~(SW_IOMMU_ENTRY_VALID | SW_IOMMU_GRN | SW_IOMMU_ENABLE); ++ entry->translated_addr = pte; ++ entry->addr_mask = IOMMU_PAGE_SIZE_8K - 1; ++ ++ return 0; ++ ++error: ++ entry->perm = IOMMU_NONE; ++ return -EINVAL; ++} ++ ++static void swvt_ptiotlb_inv_all(SW64IOMMUState *s) ++{ ++ g_hash_table_remove_all(s->ptiotlb); ++} ++ ++static void swvt_lookup_ptiotlb(SW64IOMMUState *s, uint16_t source_id, ++ hwaddr addr, IOMMUTLBEntry *entry) ++{ ++ SW64PTIOTLBKey ptkey; ++ ++ ptkey.source_id = source_id; ++ ptkey.iova = addr; ++ ++ entry = g_hash_table_lookup(s->ptiotlb, &ptkey); ++} ++ ++static IOMMUTLBEntry sw64_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr, ++ IOMMUAccessFlags flag, int iommu_idx) ++{ ++ SWVTAddressSpace *swvt_as = container_of(iommu, SWVTAddressSpace, iommu); ++ SW64IOMMUState *s = swvt_as->iommu_state; ++ IOMMUTLBEntry *cached_entry = NULL; ++ IOMMUTLBEntry entry = { ++ .target_as = &address_space_memory, ++ .iova = addr, ++ .translated_addr = addr, ++ .addr_mask = ~(hwaddr)0, ++ .perm = IOMMU_NONE, ++ }; ++ uint8_t bus_num = pci_bus_num(swvt_as->bus); ++ uint16_t source_id; ++ SW64PTIOTLBKey *new_ptkey; ++ hwaddr aligned_addr; ++ ++ source_id = ((bus_num & 0xffUL) << 8) | (swvt_as->devfn & 0xffUL); ++ ++ qemu_mutex_lock(&s->iommu_lock); ++ ++ aligned_addr = addr & IOMMU_PAGE_MASK_8K; ++ ++ swvt_lookup_ptiotlb(s, aligned_addr, source_id, cached_entry); ++ ++ if (cached_entry) ++ goto out; ++ ++ if (g_hash_table_size(s->ptiotlb) >= SW64IOMMU_PTIOTLB_MAX_SIZE) { ++ swvt_ptiotlb_inv_all(s); ++ } ++ ++ cached_entry = g_new0(IOMMUTLBEntry, 1); ++ ++ if (swvt_do_iommu_translate(swvt_as, swvt_as->bus, swvt_as->devfn, ++ addr, cached_entry)) { ++ g_free(cached_entry); ++ qemu_mutex_unlock(&s->iommu_lock); ++ printf("%s: detected translation failure " ++ "(busnum=%d, devfn=%#x, iova=%#lx.\n", ++ __func__, pci_bus_num(swvt_as->bus), swvt_as->devfn, ++ entry.iova); ++ entry.iova = 0; ++ entry.translated_addr = 0; ++ entry.addr_mask = 0; ++ entry.perm = IOMMU_NONE; ++ ++ return entry; ++ } else { ++ new_ptkey = g_new0(SW64PTIOTLBKey, 1); ++ new_ptkey->source_id = source_id; ++ new_ptkey->iova = aligned_addr; ++ g_hash_table_insert(s->ptiotlb, new_ptkey, cached_entry); ++ } ++ ++out: ++ qemu_mutex_unlock(&s->iommu_lock); ++ entry.perm = flag; ++ entry.translated_addr = cached_entry->translated_addr + ++ (addr & (IOMMU_PAGE_SIZE_8K - 1)); ++ entry.addr_mask = cached_entry->addr_mask; ++ ++ return entry; ++} ++ ++static void swvt_ptiotlb_inv_iova(SW64IOMMUState *s, uint16_t source_id, dma_addr_t iova) ++{ ++ SW64PTIOTLBKey key = {.source_id = source_id, .iova = iova}; ++ ++ qemu_mutex_lock(&s->iommu_lock); ++ g_hash_table_remove(s->ptiotlb, &key); ++ qemu_mutex_unlock(&s->iommu_lock); ++} ++ ++void swvt_address_space_unmap_iova(SW64IOMMUState *s, unsigned long val) ++{ ++ SWVTAddressSpace *swvt_as; ++ IOMMUNotifier *n; ++ uint16_t source_id; ++ dma_addr_t iova; ++ IOMMUTLBEvent event; ++ ++ source_id = val & 0xffff; ++ iova = (val >> IOMMU_IOVA_SHIFT) << IOMMU_PAGE_SHIFT; ++ ++ swvt_ptiotlb_inv_iova(s, source_id, iova); ++ ++ QLIST_FOREACH(swvt_as, &s->swvt_as_with_notifiers, next) { ++ uint8_t bus_num = pci_bus_num(swvt_as->bus); ++ uint16_t as_sourceid = ((bus_num & 0xffUL) << 8) | (swvt_as->devfn & 0xffUL); ++ ++ if (as_sourceid == source_id) { ++ IOMMU_NOTIFIER_FOREACH(n, &swvt_as->iommu) { ++ event.type = IOMMU_NOTIFIER_UNMAP; ++ event.entry.target_as = &address_space_memory; ++ event.entry.iova = iova & IOMMU_PAGE_MASK_8K; ++ event.entry.translated_addr = 0; ++ event.entry.perm = IOMMU_NONE; ++ event.entry.addr_mask = IOMMU_PAGE_SIZE_8K - 1; ++ ++ memory_region_notify_iommu(&swvt_as->iommu, 0, event); ++ } ++ } ++ } ++} ++ ++/* Unmap the whole range in the notifier's scope. */ ++static void swvt_address_space_unmap(SWVTAddressSpace *as, IOMMUNotifier *n) ++{ ++ IOMMUTLBEvent event; ++ hwaddr size; ++ hwaddr start = n->start; ++ hwaddr end = n->end; ++ ++ assert(start <= end); ++ size = end - start; ++ ++ event.entry.target_as = &address_space_memory; ++ /* Adjust iova for the size */ ++ event.entry.iova = n->start & ~(size - 1); ++ /* This field is meaningless for unmap */ ++ event.entry.translated_addr = 0; ++ event.entry.perm = IOMMU_NONE; ++ event.entry.addr_mask = size - 1; ++ ++ memory_region_notify_iommu_one(n, &event); ++} ++ ++void swvt_address_space_map_iova(SW64IOMMUState *s, unsigned long val) ++{ ++ SWVTAddressSpace *swvt_as; ++ IOMMUNotifier *n; ++ uint16_t source_id; ++ dma_addr_t iova; ++ IOMMUTLBEvent event; ++ int ret; ++ ++ source_id = val & 0xffff; ++ iova = (val >> IOMMU_IOVA_SHIFT) << IOMMU_PAGE_SHIFT; ++ ++ swvt_ptiotlb_inv_iova(s, source_id, iova); ++ ++ QLIST_FOREACH(swvt_as, &s->swvt_as_with_notifiers, next) { ++ uint8_t bus_num = pci_bus_num(swvt_as->bus); ++ uint16_t as_sourceid = ((bus_num & 0xffUL) << 8) | (swvt_as->devfn & 0xffUL); ++ ++ if (as_sourceid == source_id) { ++ IOMMU_NOTIFIER_FOREACH(n, &swvt_as->iommu) { ++ event.type = IOMMU_NOTIFIER_UNMAP; ++ event.entry.target_as = &address_space_memory; ++ event.entry.iova = iova & IOMMU_PAGE_MASK_8K; ++ event.entry.perm = IOMMU_RW; ++ ++ ret = swvt_do_iommu_translate(swvt_as, swvt_as->bus, ++ swvt_as->devfn, iova, &event.entry); ++ if (ret) ++ goto out; ++ ++ memory_region_notify_iommu(&swvt_as->iommu, 0, event); ++ } ++ } ++ } ++out: ++ return; ++} ++ ++void swvt_address_space_invalidate_iova(SW64IOMMUState *s, unsigned long val) ++{ ++ int map_flag; ++ ++ map_flag = val >> 36; ++ ++ if (map_flag) ++ swvt_address_space_map_iova(s, val & 0xfffffffff); ++ else ++ swvt_address_space_unmap_iova(s, val); ++ ++ return; ++} ++ ++static AddressSpace *sw64_dma_iommu(PCIBus *bus, void *opaque, int devfn) ++{ ++ SW64IOMMUState *s = opaque; ++ SWVTAddressSpace *swvt_as; ++ ++ assert(0 <= devfn && devfn < PCI_DEVFN_MAX); ++ ++ swvt_as = iommu_find_add_as(s, bus, devfn); ++ return &swvt_as->as; ++} ++ ++static uint64_t piu0_read(void *opaque, hwaddr addr, unsigned size) ++{ ++ uint64_t ret = 0; ++ switch (addr) { ++ default: ++ break; ++ } ++ return ret; ++} ++ ++static void piu0_write(void *opaque, hwaddr addr, uint64_t val, ++ unsigned size) ++{ ++ SW64IOMMUState *s = (SW64IOMMUState *)opaque; ++ ++ switch (addr) { ++ case 0xb000: ++ /* DTBaseAddr */ ++ s->dtbr = val; ++ break; ++ case 0xb280: ++ /* PTLB_FlushVAddr */ ++ swvt_address_space_invalidate_iova(s, val); ++ break; ++ default: ++ break; ++ } ++} ++ ++const MemoryRegionOps core3_pci_piu0_ops = { ++ .read = piu0_read, ++ .write = piu0_write, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++ .valid = { ++ .min_access_size = 1, ++ .max_access_size = 8, ++ }, ++ .impl = { ++ .min_access_size = 1, ++ .max_access_size = 8, ++ }, ++}; ++ ++void sw64_vt_iommu_init(PCIBus *b) ++{ ++ DeviceState *dev_iommu; ++ SW64IOMMUState *s; ++ MemoryRegion *io_piu0 = g_new(MemoryRegion, 1); ++ ++ dev_iommu = qdev_new(TYPE_SW64_IOMMU); ++ s = SW64_IOMMU(dev_iommu); ++ ++ s->pci_bus = b; ++ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev_iommu), &error_fatal); ++ ++ pci_setup_iommu(b, sw64_dma_iommu, dev_iommu); ++ ++ memory_region_init_io(io_piu0, OBJECT(s), &core3_pci_piu0_ops, s, ++ "pci0-piu0-io", 4 * 1024 * 1024); ++ memory_region_add_subregion(get_system_memory(), 0x880200000000ULL, ++ io_piu0); ++} ++ ++static int swvt_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu, ++ IOMMUNotifierFlag old, ++ IOMMUNotifierFlag new, ++ Error **errp) ++{ ++ SWVTAddressSpace *swvt_as = container_of(iommu, SWVTAddressSpace, iommu); ++ SW64IOMMUState *s = swvt_as->iommu_state; ++ ++ /* Update per-address-space notifier flags */ ++ swvt_as->notifier_flags = new; ++ ++ if (new & IOMMU_NOTIFIER_DEVIOTLB_UNMAP) { ++ error_setg(errp, "swvt does not support dev-iotlb yet"); ++ return -EINVAL; ++ } ++ ++ if (old == IOMMU_NOTIFIER_NONE) { ++ QLIST_INSERT_HEAD(&s->swvt_as_with_notifiers, swvt_as, next); ++ } else if (new == IOMMU_NOTIFIER_NONE) { ++ QLIST_REMOVE(swvt_as, next); ++ } ++ return 0; ++} ++ ++static void swvt_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n) ++{ ++ SWVTAddressSpace *swvt_as = container_of(iommu_mr, SWVTAddressSpace, iommu); ++ ++ /* ++ * The replay can be triggered by either a invalidation or a newly ++ * created entry. No matter what, we release existing mappings ++ * (it means flushing caches for UNMAP-only registers). ++ */ ++ swvt_address_space_unmap(swvt_as, n); ++} ++ ++/* GHashTable functions */ ++static gboolean swvt_uint64_equal(gconstpointer v1, gconstpointer v2) ++{ ++ return *((const uint64_t *)v1) == *((const uint64_t *)v2); ++} ++ ++static guint swvt_uint64_hash(gconstpointer v) ++{ ++ return (guint)*(const uint64_t *)v; ++} ++ ++static void iommu_realize(DeviceState *d, Error **errp) ++{ ++ SW64IOMMUState *s = SW64_IOMMU(d); ++ ++ QLIST_INIT(&s->swvt_as_with_notifiers); ++ qemu_mutex_init(&s->iommu_lock); ++ ++ s->dtiotlb = g_hash_table_new_full(swvt_uint64_hash, swvt_uint64_equal, ++ g_free, g_free); ++ s->ptiotlb = g_hash_table_new_full(swvt_uint64_hash, swvt_uint64_equal, ++ g_free, g_free); ++ ++ s->swvtbus_as_by_busptr = g_hash_table_new(NULL, NULL); ++} ++ ++static void iommu_reset(DeviceState *d) ++{ ++} ++ ++static void sw64_iommu_class_init(ObjectClass *klass, void *data) ++{ ++ DeviceClass *dc = DEVICE_CLASS(klass); ++ ++ dc->reset = iommu_reset; ++ dc->realize = iommu_realize; ++} ++ ++static void sw64_iommu_memory_region_class_init(ObjectClass *klass, void *data) ++{ ++ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); ++ ++ imrc->translate = sw64_translate_iommu; ++ imrc->notify_flag_changed = swvt_iommu_notify_flag_changed; ++ imrc->replay = swvt_iommu_replay; ++} ++ ++static const TypeInfo sw64_iommu_info = { ++ .name = TYPE_SW64_IOMMU, ++ .parent = TYPE_SYS_BUS_DEVICE, ++ .instance_size = sizeof(SW64IOMMUState), ++ .class_init = sw64_iommu_class_init, ++ .class_size = sizeof(SW64IOMMUClass), ++}; ++ ++static const TypeInfo sw64_iommu_memory_region_info = { ++ .parent = TYPE_IOMMU_MEMORY_REGION, ++ .name = TYPE_SW64_IOMMU_MEMORY_REGION, ++ .class_init = sw64_iommu_memory_region_class_init, ++}; ++ ++static void sw64_iommu_register_types(void) ++{ ++ type_register_static(&sw64_iommu_info); ++ type_register_static(&sw64_iommu_memory_region_info); ++} ++ ++type_init(sw64_iommu_register_types) +diff --git a/hw/sw64/trace-events b/hw/sw64/trace-events +new file mode 100644 +index 0000000000..1aa744c984 +--- /dev/null ++++ b/hw/sw64/trace-events +@@ -0,0 +1,3 @@ ++# See docs/devel/tracing.rst for syntax documentation. ++ ++# pci.c +diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h +index 08e1beec85..4590bcc968 100644 +--- a/include/disas/dis-asm.h ++++ b/include/disas/dis-asm.h +@@ -191,6 +191,9 @@ enum bfd_architecture + #define bfd_mach_alpha_ev4 0x10 + #define bfd_mach_alpha_ev5 0x20 + #define bfd_mach_alpha_ev6 0x30 ++ bfd_arch_sw_64, /* Dec Sw_64 */ ++#define bfd_mach_sw_64 1 ++#define bfd_mach_sw_64_core3 1621 + bfd_arch_arm, /* Advanced Risc Machines ARM */ + #define bfd_mach_arm_unknown 0 + #define bfd_mach_arm_2 1 +@@ -429,6 +432,7 @@ int print_insn_h8500 (bfd_vma, disassemble_info*); + int print_insn_arm_a64 (bfd_vma, disassemble_info*); + int print_insn_alpha (bfd_vma, disassemble_info*); + disassembler_ftype arc_get_disassembler (int, int); ++int print_insn_sw_64 (bfd_vma, disassemble_info*); + int print_insn_arm (bfd_vma, disassemble_info*); + int print_insn_sparc (bfd_vma, disassemble_info*); + int print_insn_big_a29k (bfd_vma, disassemble_info*); +diff --git a/include/elf.h b/include/elf.h +index 811bf4a1cb..79c188b62f 100644 +--- a/include/elf.h ++++ b/include/elf.h +@@ -207,6 +207,8 @@ typedef struct mips_elf_abiflags_v0 { + + #define EF_AVR_MACH 0x7F /* Mask for AVR e_flags to get core type */ + ++#define EM_SW64 0x9916 /* SW64 */ ++ + /* This is the info that is needed to parse the dynamic section of the file */ + #define DT_NULL 0 + #define DT_NEEDED 1 +@@ -1417,6 +1419,48 @@ typedef struct { + #define EF_RISCV_RVE 0x0008 + #define EF_RISCV_TSO 0x0010 + ++/* ++ SW_64 ELF relocation types ++ */ ++#define EM_SW_64 0x9916 ++#define R_SW_64_NONE 0 /* No reloc */ ++#define R_SW_64_REFLONG 1 /* Direct 32 bit */ ++#define R_SW_64_REFQUAD 2 /* Direct 64 bit */ ++#define R_SW_64_GPREL32 3 /* GP relative 32 bit */ ++#define R_SW_64_LITERAL 4 /* GP relative 16 bit w/optimization */ ++#define R_SW_64_LITUSE 5 /* Optimization hint for LITERAL */ ++#define R_SW_64_GPDISP 6 /* Add displacement to GP */ ++#define R_SW_64_BRADDR 7 /* PC+4 relative 23 bit shifted */ ++#define R_SW_64_HINT 8 /* PC+4 relative 16 bit shifted */ ++#define R_SW_64_SREL16 9 /* PC relative 16 bit */ ++#define R_SW_64_SREL32 10 /* PC relative 32 bit */ ++#define R_SW_64_SREL64 11 /* PC relative 64 bit */ ++#define R_SW_64_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ ++#define R_SW_64_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ ++#define R_SW_64_GPREL16 19 /* GP relative 16 bit */ ++#define R_SW_64_COPY 24 /* Copy symbol at runtime */ ++#define R_SW_64_GLOB_DAT 25 /* Create GOT entry */ ++#define R_SW_64_JMP_SLOT 26 /* Create PLT entry */ ++#define R_SW_64_RELATIVE 27 /* Adjust by program base */ ++#define R_SW_64_TLS_GD_HI 28 ++#define R_SW_64_TLSGD 29 ++#define R_SW_64_TLS_LDM 30 ++#define R_SW_64_DTPMOD64 31 ++#define R_SW_64_GOTDTPREL 32 ++#define R_SW_64_DTPREL64 33 ++#define R_SW_64_DTPRELHI 34 ++#define R_SW_64_DTPRELLO 35 ++#define R_SW_64_DTPREL16 36 ++#define R_SW_64_GOTTPREL 37 ++#define R_SW_64_TPREL64 38 ++#define R_SW_64_TPRELHI 39 ++#define R_SW_64_TPRELLO 40 ++#define R_SW_64_TPREL16 41 ++/* Keep this the last entry. */ ++#define R_SW_64_NUM 46 ++/* Legal values for sh_flags field of Elf64_Shdr. */ ++#define SHF_SW_64_GPREL 0x10000000 ++ + typedef struct elf32_rel { + Elf32_Addr r_offset; + Elf32_Word r_info; +diff --git a/include/hw/sw64/sw64_iommu.h b/include/hw/sw64/sw64_iommu.h +new file mode 100644 +index 0000000000..7191876083 +--- /dev/null ++++ b/include/hw/sw64/sw64_iommu.h +@@ -0,0 +1,105 @@ ++/* ++ * Copyright (C) 2021-2025 Wuxi Institute of Advanced Technology ++ * Written by Lu Feifei ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * 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 . ++ */ ++ ++#ifndef HW_SW64_IOMMU_H ++#define HW_SW64_IOMMU_H ++ ++#include "hw/sysbus.h" ++#include "hw/pci/pci.h" ++ ++#define TYPE_SW64_IOMMU_MEMORY_REGION "sw64-iommu-memory-region" ++#define SW_IOMMU_ENTRY_VALID ((1UL) << 63) ++#define SW_IOMMU_LEVEL1_OFFSET 0x1ff ++#define SW_IOMMU_LEVEL2_OFFSET 0x3ff ++#define SW_IOMMU_ENABLE 3 ++#define SW_IOMMU_GRN ((0UL) << 4) ++#define SWVT_PCI_BUS_MAX 256 ++ ++typedef struct SW64IOMMUClass SW64IOMMUClass; ++typedef struct SW64IOMMUState SW64IOMMUState; ++typedef struct SWVTAddressSpace SWVTAddressSpace; ++typedef struct SW64DTIOTLBKey SW64DTIOTLBKey; ++typedef struct SW64PTIOTLBKey SW64PTIOTLBKey; ++typedef struct SW64DTIOTLBEntry SW64DTIOTLBEntry; ++typedef struct SWVTBus SWVTBus; ++ ++struct SW64DTIOTLBEntry { ++ uint16_t source_id; ++ unsigned long ptbase_addr; ++}; ++ ++struct SW64DTIOTLBKey { ++ uint16_t source_id; ++}; ++ ++struct SW64PTIOTLBKey { ++ uint16_t source_id; ++ dma_addr_t iova; ++}; ++ ++struct SWVTAddressSpace { ++ PCIBus *bus; ++ uint8_t devfn; ++ AddressSpace as; ++ IOMMUMemoryRegion iommu; ++ MemoryRegion root; ++ MemoryRegion msi; /* Interrupt region: 0xfeeXXXXX */ ++ SW64IOMMUState *iommu_state; ++ QLIST_ENTRY(SWVTAddressSpace) next; ++ /* Superset of notifier flags that this address space has */ ++ IOMMUNotifierFlag notifier_flags; ++}; ++ ++struct SWVTBus { ++ PCIBus* bus; /* A reference to the bus to provide translation for */ ++ SWVTAddressSpace *dev_as[0]; /* A table of SWVTAddressSpace objects indexed by devfn */ ++}; ++ ++struct SW64IOMMUState { ++ SysBusDevice busdev; ++ dma_addr_t dtbr; /* Current root table pointer */ ++ GHashTable *dtiotlb; /* IOTLB for device table */ ++ GHashTable *ptiotlb; /* IOTLB for page table */ ++ ++ GHashTable *swvtbus_as_by_busptr; ++ /* list of registered notifiers */ ++ QLIST_HEAD(, SWVTAddressSpace) swvt_as_with_notifiers; ++ ++ PCIBus *pci_bus; ++ QemuMutex iommu_lock; ++}; ++ ++struct SW64IOMMUClass { ++ SysBusDeviceClass parent; ++ DeviceRealize realize; ++}; ++ ++#define TYPE_SW64_IOMMU "sw64-iommu" ++#define SW64_IOMMU(obj) \ ++ OBJECT_CHECK(SW64IOMMUState, (obj), TYPE_SW64_IOMMU) ++#define SW64_IOMMU_CLASS(klass) \ ++ OBJECT_CLASS_CHECK(SW64IOMMUClass, (klass), TYPE_SW64_IOMMU) ++#define SW64_IOMMU_GET_CLASS(obj) \ ++ OBJECT_GET_CLASS(SW64IOMMUClass, (obj), TYPE_SW64_IOMMU) ++extern void sw64_vt_iommu_init(PCIBus *b); ++extern void swvt_address_space_invalidate_iova(SW64IOMMUState *s, unsigned long val); ++extern void swvt_address_space_unmap_iova(SW64IOMMUState *s, unsigned long val); ++extern void swvt_address_space_map_iova(SW64IOMMUState *s, unsigned long val); ++extern SWVTAddressSpace *iommu_find_add_as(SW64IOMMUState *s, PCIBus *bus, int devfn); ++extern MemTxResult msi_write(void *opaque, hwaddr addr, uint64_t value, unsigned size, ++ MemTxAttrs attrs); ++#endif +diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h +index 112a29910b..6141122308 100644 +--- a/include/qemu/atomic.h ++++ b/include/qemu/atomic.h +@@ -85,6 +85,8 @@ + #define smp_read_barrier_depends() ({ barrier(); __atomic_thread_fence(__ATOMIC_CONSUME); }) + #elif defined(__alpha__) + #define smp_read_barrier_depends() asm volatile("mb":::"memory") ++#elif defined(__sw_64__) ++#define smp_read_barrier_depends() asm volatile("memb":::"memory") + #else + #define smp_read_barrier_depends() barrier() + #endif +diff --git a/include/qemu/timer.h b/include/qemu/timer.h +index d263fad9a4..e6d442abee 100644 +--- a/include/qemu/timer.h ++++ b/include/qemu/timer.h +@@ -1007,6 +1007,16 @@ static inline int64_t cpu_get_host_ticks(void) + return cur - ofs; + } + ++#elif defined(__sw_64__) ++ ++static inline int64_t cpu_get_host_ticks(void) ++{ ++ uint64_t cc; ++ ++ asm volatile("rtc %0" : "=r"(cc)); ++ return cc; ++} ++ + #else + /* The host CPU doesn't have an easily accessible cycle counter. + Just return a monotonically increasing value. This will be +diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h +index 70c579560a..1cf27baa7c 100644 +--- a/include/sysemu/arch_init.h ++++ b/include/sysemu/arch_init.h +@@ -24,6 +24,7 @@ enum { + QEMU_ARCH_RX = (1 << 20), + QEMU_ARCH_AVR = (1 << 21), + QEMU_ARCH_HEXAGON = (1 << 22), ++ QEMU_ARCH_SW64 = (1 << 23), + }; + + extern const uint32_t arch_type; +diff --git a/linux-headers/asm-sw64/kvm.h b/linux-headers/asm-sw64/kvm.h +new file mode 100644 +index 0000000000..b0ce2ca346 +--- /dev/null ++++ b/linux-headers/asm-sw64/kvm.h +@@ -0,0 +1,122 @@ ++#ifndef __LINUX_KVM_SW64_H ++#define __LINUX_KVM_SW64_H ++ ++#include ++/* ++ * for KVM_GET_REGS and KVM_SET_REGS ++ */ ++struct kvm_regs { ++ unsigned long r0; ++ unsigned long r1; ++ unsigned long r2; ++ unsigned long r3; ++ ++ unsigned long r4; ++ unsigned long r5; ++ unsigned long r6; ++ unsigned long r7; ++ ++ unsigned long r8; ++ unsigned long r9; ++ unsigned long r10; ++ unsigned long r11; ++ ++ unsigned long r12; ++ unsigned long r13; ++ unsigned long r14; ++ unsigned long r15; ++ ++ unsigned long r19; ++ unsigned long r20; ++ unsigned long r21; ++ unsigned long r22; ++ ++ unsigned long r23; ++ unsigned long r24; ++ unsigned long r25; ++ unsigned long r26; ++ ++ unsigned long r27; ++ unsigned long r28; ++ unsigned long __padding0; ++ unsigned long fpcr; ++ ++ unsigned long fp[124]; ++ /* These are saved by hmcode: */ ++ unsigned long ps; ++ unsigned long pc; ++ unsigned long gp; ++ unsigned long r16; ++ unsigned long r17; ++ unsigned long r18; ++}; ++ ++struct vcpucb { ++ unsigned long go_flag; ++ unsigned long pcbb; ++ unsigned long ksp; ++ unsigned long usp; ++ unsigned long kgp; ++ unsigned long ent_arith; ++ unsigned long ent_if; ++ unsigned long ent_int; ++ unsigned long ent_mm; ++ unsigned long ent_sys; ++ unsigned long ent_una; ++ unsigned long stack_pc; ++ unsigned long new_a0; ++ unsigned long new_a1; ++ unsigned long new_a2; ++ unsigned long whami; ++ unsigned long csr_save; ++ unsigned long wakeup_magic; ++ unsigned long host_vcpucb; ++ unsigned long upcr; ++ unsigned long vpcr; ++ unsigned long dtb_pcr; ++ unsigned long guest_ksp; ++ unsigned long guest_usp; ++ unsigned long vcpu_irq_disabled; ++ unsigned long vcpu_irq; ++ unsigned long ptbr; ++ unsigned long int_stat0; ++ unsigned long int_stat1; ++ unsigned long int_stat2; ++ unsigned long int_stat3; ++ unsigned long reset_entry; ++ unsigned long pvcpu; ++ unsigned long exit_reason; ++ unsigned long ipaddr; ++ unsigned long vcpu_irq_vector; ++}; ++ ++/* ++ * for KVM_GET_FPU and KVM_SET_FPU ++ */ ++struct kvm_fpu { ++}; ++ ++/* ++ * KVM SW_64 specific structures and definitions ++ */ ++struct kvm_debug_exit_arch { ++}; ++ ++/* for KVM_SET_GUEST_DEBUG */ ++struct kvm_guest_debug_arch { ++}; ++ ++/* definition of registers in kvm_run */ ++struct kvm_sync_regs { ++}; ++ ++/* dummy definition */ ++struct kvm_sregs { ++}; ++ ++#define KVM_SW64_VCPU_INIT _IO(KVMIO, 0xba) ++#define KVM_SW64_USE_SLAVE _IO(KVMIO, 0xbb) ++#define KVM_SW64_GET_VCB _IO(KVMIO, 0xbc) ++#define KVM_SW64_SET_VCB _IO(KVMIO, 0xbd) ++ ++#endif /* __LINUX_KVM_SW64_H */ +diff --git a/linux-headers/asm-sw64/unistd.h b/linux-headers/asm-sw64/unistd.h +new file mode 100644 +index 0000000000..affe297e73 +--- /dev/null ++++ b/linux-headers/asm-sw64/unistd.h +@@ -0,0 +1,380 @@ ++#ifndef _UAPI_ASM_SW64_UNISTD_64_H ++#define _UAPI_ASM_SW64_UNISTD_64_H ++ ++#define __NR_exit 1 ++#define __NR_fork 2 ++#define __NR_read 3 ++#define __NR_write 4 ++#define __NR_close 6 ++#define __NR_osf_wait4 7 ++#define __NR_link 9 ++#define __NR_unlink 10 ++#define __NR_chdir 12 ++#define __NR_fchdir 13 ++#define __NR_mknod 14 ++#define __NR_chmod 15 ++#define __NR_chown 16 ++#define __NR_brk 17 ++#define __NR_lseek 19 ++#define __NR_getxpid 20 ++#define __NR_osf_mount 21 ++#define __NR_umount2 22 ++#define __NR_setuid 23 ++#define __NR_getxuid 24 ++#define __NR_ptrace 26 ++#define __NR_access 33 ++#define __NR_sync 36 ++#define __NR_kill 37 ++#define __NR_setpgid 39 ++#define __NR_dup 41 ++#define __NR_pipe 42 ++#define __NR_osf_set_program_attributes 43 ++#define __NR_open 45 ++#define __NR_getxgid 47 ++#define __NR_osf_sigprocmask 48 ++#define __NR_acct 51 ++#define __NR_sigpending 52 ++#define __NR_ioctl 54 ++#define __NR_symlink 57 ++#define __NR_readlink 58 ++#define __NR_execve 59 ++#define __NR_umask 60 ++#define __NR_chroot 61 ++#define __NR_getpgrp 63 ++#define __NR_getpagesize 64 ++#define __NR_vfork 66 ++#define __NR_stat 67 ++#define __NR_lstat 68 ++#define __NR_mmap 71 ++#define __NR_munmap 73 ++#define __NR_mprotect 74 ++#define __NR_madvise 75 ++#define __NR_vhangup 76 ++#define __NR_getgroups 79 ++#define __NR_setgroups 80 ++#define __NR_setpgrp 82 ++#define __NR_osf_setitimer 83 ++#define __NR_osf_getitimer 86 ++#define __NR_gethostname 87 ++#define __NR_sethostname 88 ++#define __NR_getdtablesize 89 ++#define __NR_dup2 90 ++#define __NR_fstat 91 ++#define __NR_fcntl 92 ++#define __NR_osf_select 93 ++#define __NR_poll 94 ++#define __NR_fsync 95 ++#define __NR_setpriority 96 ++#define __NR_socket 97 ++#define __NR_connect 98 ++#define __NR_accept 99 ++#define __NR_getpriority 100 ++#define __NR_send 101 ++#define __NR_recv 102 ++#define __NR_sigreturn 103 ++#define __NR_bind 104 ++#define __NR_setsockopt 105 ++#define __NR_listen 106 ++#define __NR_sigsuspend 111 ++#define __NR_osf_sigstack 112 ++#define __NR_recvmsg 113 ++#define __NR_sendmsg 114 ++#define __NR_osf_gettimeofday 116 ++#define __NR_osf_getrusage 117 ++#define __NR_getsockopt 118 ++#define __NR_socketcall 119 ++#define __NR_readv 120 ++#define __NR_writev 121 ++#define __NR_osf_settimeofday 122 ++#define __NR_fchown 123 ++#define __NR_fchmod 124 ++#define __NR_recvfrom 125 ++#define __NR_setreuid 126 ++#define __NR_setregid 127 ++#define __NR_rename 128 ++#define __NR_truncate 129 ++#define __NR_ftruncate 130 ++#define __NR_flock 131 ++#define __NR_setgid 132 ++#define __NR_sendto 133 ++#define __NR_shutdown 134 ++#define __NR_socketpair 135 ++#define __NR_mkdir 136 ++#define __NR_rmdir 137 ++#define __NR_osf_utimes 138 ++#define __NR_getpeername 141 ++#define __NR_getrlimit 144 ++#define __NR_setrlimit 145 ++#define __NR_setsid 147 ++#define __NR_quotactl 148 ++#define __NR_getsockname 150 ++#define __NR_sigaction 156 ++#define __NR_osf_getdirentries 159 ++#define __NR_osf_statfs 160 ++#define __NR_osf_fstatfs 161 ++#define __NR_osf_getdomainname 165 ++#define __NR_setdomainname 166 ++#define __NR_bpf 170 ++#define __NR_userfaultfd 171 ++#define __NR_membarrier 172 ++#define __NR_mlock2 173 ++#define __NR_getpid 174 ++#define __NR_getppid 175 ++#define __NR_getuid 176 ++#define __NR_geteuid 177 ++#define __NR_getgid 178 ++#define __NR_getegid 179 ++#define __NR_osf_swapon 199 ++#define __NR_msgctl 200 ++#define __NR_msgget 201 ++#define __NR_msgrcv 202 ++#define __NR_msgsnd 203 ++#define __NR_semctl 204 ++#define __NR_semget 205 ++#define __NR_semop 206 ++#define __NR_osf_utsname 207 ++#define __NR_lchown 208 ++#define __NR_shmat 209 ++#define __NR_shmctl 210 ++#define __NR_shmdt 211 ++#define __NR_shmget 212 ++#define __NR_msync 217 ++#define __NR_osf_stat 224 ++#define __NR_osf_lstat 225 ++#define __NR_osf_fstat 226 ++#define __NR_osf_statfs64 227 ++#define __NR_osf_fstatfs64 228 ++#define __NR_statfs64 229 ++#define __NR_fstatfs64 230 ++#define __NR_getpgid 233 ++#define __NR_getsid 234 ++#define __NR_sigaltstack 235 ++#define __NR_osf_sysinfo 241 ++#define __NR_osf_proplist_syscall 244 ++#define __NR_osf_usleep_thread 251 ++#define __NR_sysfs 254 ++#define __NR_osf_getsysinfo 256 ++#define __NR_osf_setsysinfo 257 ++#define __NR_bdflush 300 ++#define __NR_sethae 301 ++#define __NR_mount 302 ++#define __NR_old_adjtimex 303 ++#define __NR_swapoff 304 ++#define __NR_getdents 305 ++#define __NR_create_module 306 ++#define __NR_init_module 307 ++#define __NR_delete_module 308 ++#define __NR_get_kernel_syms 309 ++#define __NR_syslog 310 ++#define __NR_reboot 311 ++#define __NR_clone 312 ++#define __NR_uselib 313 ++#define __NR_mlock 314 ++#define __NR_munlock 315 ++#define __NR_mlockall 316 ++#define __NR_munlockall 317 ++#define __NR_sysinfo 318 ++#define __NR__sysctl 319 ++#define __NR_oldumount 321 ++#define __NR_swapon 322 ++#define __NR_times 323 ++#define __NR_personality 324 ++#define __NR_setfsuid 325 ++#define __NR_setfsgid 326 ++#define __NR_ustat 327 ++#define __NR_statfs 328 ++#define __NR_fstatfs 329 ++#define __NR_sched_setparam 330 ++#define __NR_sched_getparam 331 ++#define __NR_sched_setscheduler 332 ++#define __NR_sched_getscheduler 333 ++#define __NR_sched_yield 334 ++#define __NR_sched_get_priority_max 335 ++#define __NR_sched_get_priority_min 336 ++#define __NR_sched_rr_get_interval 337 ++#define __NR_afs_syscall 338 ++#define __NR_uname 339 ++#define __NR_nanosleep 340 ++#define __NR_mremap 341 ++#define __NR_nfsservctl 342 ++#define __NR_setresuid 343 ++#define __NR_getresuid 344 ++#define __NR_pciconfig_read 345 ++#define __NR_pciconfig_write 346 ++#define __NR_query_module 347 ++#define __NR_prctl 348 ++#define __NR_pread64 349 ++#define __NR_pwrite64 350 ++#define __NR_rt_sigreturn 351 ++#define __NR_rt_sigaction 352 ++#define __NR_rt_sigprocmask 353 ++#define __NR_rt_sigpending 354 ++#define __NR_rt_sigtimedwait 355 ++#define __NR_rt_sigqueueinfo 356 ++#define __NR_rt_sigsuspend 357 ++#define __NR_select 358 ++#define __NR_gettimeofday 359 ++#define __NR_settimeofday 360 ++#define __NR_getitimer 361 ++#define __NR_setitimer 362 ++#define __NR_utimes 363 ++#define __NR_getrusage 364 ++#define __NR_wait4 365 ++#define __NR_adjtimex 366 ++#define __NR_getcwd 367 ++#define __NR_capget 368 ++#define __NR_capset 369 ++#define __NR_sendfile 370 ++#define __NR_setresgid 371 ++#define __NR_getresgid 372 ++#define __NR_dipc 373 ++#define __NR_pivot_root 374 ++#define __NR_mincore 375 ++#define __NR_pciconfig_iobase 376 ++#define __NR_getdents64 377 ++#define __NR_gettid 378 ++#define __NR_readahead 379 ++#define __NR_tkill 381 ++#define __NR_setxattr 382 ++#define __NR_lsetxattr 383 ++#define __NR_fsetxattr 384 ++#define __NR_getxattr 385 ++#define __NR_lgetxattr 386 ++#define __NR_fgetxattr 387 ++#define __NR_listxattr 388 ++#define __NR_llistxattr 389 ++#define __NR_flistxattr 390 ++#define __NR_removexattr 391 ++#define __NR_lremovexattr 392 ++#define __NR_fremovexattr 393 ++#define __NR_futex 394 ++#define __NR_sched_setaffinity 395 ++#define __NR_sched_getaffinity 396 ++#define __NR_tuxcall 397 ++#define __NR_io_setup 398 ++#define __NR_io_destroy 399 ++#define __NR_io_getevents 400 ++#define __NR_io_submit 401 ++#define __NR_io_cancel 402 ++#define __NR_io_pgetevents 403 ++#define __NR_rseq 404 ++#define __NR_exit_group 405 ++#define __NR_lookup_dcookie 406 ++#define __NR_epoll_create 407 ++#define __NR_epoll_ctl 408 ++#define __NR_epoll_wait 409 ++#define __NR_remap_file_pages 410 ++#define __NR_set_tid_address 411 ++#define __NR_restart_syscall 412 ++#define __NR_fadvise64 413 ++#define __NR_timer_create 414 ++#define __NR_timer_settime 415 ++#define __NR_timer_gettime 416 ++#define __NR_timer_getoverrun 417 ++#define __NR_timer_delete 418 ++#define __NR_clock_settime 419 ++#define __NR_clock_gettime 420 ++#define __NR_clock_getres 421 ++#define __NR_clock_nanosleep 422 ++#define __NR_semtimedop 423 ++#define __NR_tgkill 424 ++#define __NR_stat64 425 ++#define __NR_lstat64 426 ++#define __NR_fstat64 427 ++#define __NR_vserver 428 ++#define __NR_mbind 429 ++#define __NR_get_mempolicy 430 ++#define __NR_set_mempolicy 431 ++#define __NR_mq_open 432 ++#define __NR_mq_unlink 433 ++#define __NR_mq_timedsend 434 ++#define __NR_mq_timedreceive 435 ++#define __NR_mq_notify 436 ++#define __NR_mq_getsetattr 437 ++#define __NR_waitid 438 ++#define __NR_add_key 439 ++#define __NR_request_key 440 ++#define __NR_keyctl 441 ++#define __NR_ioprio_set 442 ++#define __NR_ioprio_get 443 ++#define __NR_inotify_init 444 ++#define __NR_inotify_add_watch 445 ++#define __NR_inotify_rm_watch 446 ++#define __NR_fdatasync 447 ++#define __NR_kexec_load 448 ++#define __NR_migrate_pages 449 ++#define __NR_openat 450 ++#define __NR_mkdirat 451 ++#define __NR_mknodat 452 ++#define __NR_fchownat 453 ++#define __NR_futimesat 454 ++#define __NR_fstatat64 455 ++#define __NR_unlinkat 456 ++#define __NR_renameat 457 ++#define __NR_linkat 458 ++#define __NR_symlinkat 459 ++#define __NR_readlinkat 460 ++#define __NR_fchmodat 461 ++#define __NR_faccessat 462 ++#define __NR_pselect6 463 ++#define __NR_ppoll 464 ++#define __NR_unshare 465 ++#define __NR_set_robust_list 466 ++#define __NR_get_robust_list 467 ++#define __NR_splice 468 ++#define __NR_sync_file_range 469 ++#define __NR_tee 470 ++#define __NR_vmsplice 471 ++#define __NR_move_pages 472 ++#define __NR_getcpu 473 ++#define __NR_epoll_pwait 474 ++#define __NR_utimensat 475 ++#define __NR_signalfd 476 ++#define __NR_timerfd 477 ++#define __NR_eventfd 478 ++#define __NR_recvmmsg 479 ++#define __NR_fallocate 480 ++#define __NR_timerfd_create 481 ++#define __NR_timerfd_settime 482 ++#define __NR_timerfd_gettime 483 ++#define __NR_signalfd4 484 ++#define __NR_eventfd2 485 ++#define __NR_epoll_create1 486 ++#define __NR_dup3 487 ++#define __NR_pipe2 488 ++#define __NR_inotify_init1 489 ++#define __NR_preadv 490 ++#define __NR_pwritev 491 ++#define __NR_rt_tgsigqueueinfo 492 ++#define __NR_perf_event_open 493 ++#define __NR_fanotify_init 494 ++#define __NR_fanotify_mark 495 ++#define __NR_prlimit64 496 ++#define __NR_name_to_handle_at 497 ++#define __NR_open_by_handle_at 498 ++#define __NR_clock_adjtime 499 ++#define __NR_syncfs 500 ++#define __NR_setns 501 ++#define __NR_accept4 502 ++#define __NR_sendmmsg 503 ++#define __NR_process_vm_readv 504 ++#define __NR_process_vm_writev 505 ++#define __NR_kcmp 506 ++#define __NR_finit_module 507 ++#define __NR_sched_setattr 508 ++#define __NR_sched_getattr 509 ++#define __NR_renameat2 510 ++#define __NR_getrandom 511 ++#define __NR_memfd_create 512 ++#define __NR_execveat 513 ++#define __NR_seccomp 514 ++#define __NR_copy_file_range 515 ++#define __NR_preadv2 516 ++#define __NR_pwritev2 517 ++#define __NR_statx 518 ++ ++#ifdef __KERNEL__ ++#define __NR_syscalls 519 ++#endif ++ ++#endif /* _UAPI_ASM_SW64_UNISTD_64_H */ +diff --git a/linux-user/meson.build b/linux-user/meson.build +index bf62c13e37..4f4196ed13 100644 +--- a/linux-user/meson.build ++++ b/linux-user/meson.build +@@ -37,5 +37,6 @@ subdir('ppc') + subdir('s390x') + subdir('sh4') + subdir('sparc') ++subdir('sw64') + subdir('x86_64') + subdir('xtensa') +diff --git a/linux-user/sw64/cpu_loop.c b/linux-user/sw64/cpu_loop.c +new file mode 100644 +index 0000000000..3f2fde0fba +--- /dev/null ++++ b/linux-user/sw64/cpu_loop.c +@@ -0,0 +1,108 @@ ++/* ++ * qemu user cpu loop ++ * ++ * Copyright (c) 2003-2008 Fabrice Bellard ++ * ++ * 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 . ++ */ ++ ++#include "qemu/osdep.h" ++#include "qemu.h" ++#include "cpu_loop-common.h" ++ ++void cpu_loop(CPUSW64State *env) ++{ ++ CPUState *cs = CPU(sw64_env_get_cpu(env)); ++ int trapnr; ++ target_siginfo_t info; ++ abi_long sysret; ++ ++ while (1) { ++ cpu_exec_start(cs); ++ trapnr = cpu_exec(cs); ++ cpu_exec_end(cs); ++ process_queued_cpu_work(cs); ++ ++ switch (trapnr) { ++ case EXCP_OPCDEC: ++ cpu_abort(cs, "ILLEGAL SW64 insn at line %d!", __LINE__); ++ case EXCP_CALL_SYS: ++ switch (env->error_code) { ++ case 0x83: ++ /* CALLSYS */ ++ trapnr = env->ir[IDX_V0]; ++ sysret = do_syscall(env, trapnr, ++ env->ir[IDX_A0], env->ir[IDX_A1], ++ env->ir[IDX_A2], env->ir[IDX_A3], ++ env->ir[IDX_A4], env->ir[IDX_A5], ++ 0, 0); ++ if (sysret == -TARGET_ERESTARTSYS) { ++ env->pc -= 4; ++ break; ++ } ++ if (sysret == -TARGET_QEMU_ESIGRETURN) { ++ break; ++ } ++ /* Syscall writes 0 to V0 to bypass error check, similar ++ to how this is handled internal to Linux kernel. ++ (Ab)use trapnr temporarily as boolean indicating error. */ ++ trapnr = (env->ir[IDX_V0] != 0 && sysret < 0); ++ env->ir[IDX_V0] = (trapnr ? -sysret : sysret); ++ env->ir[IDX_A3] = trapnr; ++ break; ++ default: ++ printf("UNDO sys_call %lx\n", env->error_code); ++ exit(-1); ++ } ++ break; ++ case EXCP_MMFAULT: ++ info.si_signo = TARGET_SIGSEGV; ++ info.si_errno = 0; ++ info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID ++ ? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR); ++ info._sifields._sigfault._addr = env->trap_arg0; ++ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); ++ break; ++ case EXCP_ARITH: ++ info.si_signo = TARGET_SIGFPE; ++ info.si_errno = 0; ++ info.si_code = TARGET_FPE_FLTINV; ++ info._sifields._sigfault._addr = env->pc; ++ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); ++ break; ++ case EXCP_INTERRUPT: ++ /* just indicate that signals should be handled asap */ ++ break; ++ default: ++ cpu_abort(cs, "UNDO"); ++ } ++ process_pending_signals (env); ++ ++ /* Most of the traps imply a transition through HMcode, which ++ implies an REI instruction has been executed. Which means ++ that RX and LOCK_ADDR should be cleared. But there are a ++ few exceptions for traps internal to QEMU. */ ++ } ++} ++ ++void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) ++{ ++ int i; ++ ++ for(i = 0; i < 28; i++) { ++ env->ir[i] = ((abi_ulong *)regs)[i]; ++ } ++ env->ir[IDX_SP] = regs->usp; ++ env->pc = regs->pc; ++} +diff --git a/linux-user/sw64/signal.c b/linux-user/sw64/signal.c +new file mode 100644 +index 0000000000..5822e808d3 +--- /dev/null ++++ b/linux-user/sw64/signal.c +@@ -0,0 +1,273 @@ ++/* ++ * Emulation of Linux signals ++ * ++ * Copyright (c) 2003 Fabrice Bellard ++ * ++ * 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 . ++ */ ++#include "qemu/osdep.h" ++#include "qemu.h" ++#include "signal-common.h" ++#include "linux-user/trace.h" ++ ++struct target_sigcontext { ++ abi_long sc_onstack; ++ abi_long sc_mask; ++ abi_long sc_pc; ++ abi_long sc_ps; ++ abi_long sc_regs[32]; ++ abi_long sc_ownedfp; ++ abi_long sc_fpregs[32]; ++ abi_ulong sc_fpcr; ++ abi_ulong sc_fp_control; ++ abi_ulong sc_reserved1; ++ abi_ulong sc_reserved2; ++ abi_ulong sc_ssize; ++ abi_ulong sc_sbase; ++ abi_ulong sc_traparg_a0; ++ abi_ulong sc_traparg_a1; ++ abi_ulong sc_traparg_a2; ++ abi_ulong sc_fp_trap_pc; ++ abi_ulong sc_fp_trigger_sum; ++ abi_ulong sc_fp_trigger_inst; ++}; ++ ++struct target_ucontext { ++ abi_ulong tuc_flags; ++ abi_ulong tuc_link; ++ abi_ulong tuc_osf_sigmask; ++ target_stack_t tuc_stack; ++ struct target_sigcontext tuc_mcontext; ++ target_sigset_t tuc_sigmask; ++}; ++ ++struct target_sigframe { ++ struct target_sigcontext sc; ++ unsigned int retcode[3]; ++}; ++ ++struct target_rt_sigframe { ++ target_siginfo_t info; ++ struct target_ucontext uc; ++ unsigned int retcode[3]; ++}; ++ ++#define INSN_MOV_R30_R16 0x47fe0410 ++#define INSN_LDI_R0 0x201f0000 ++#define INSN_CALLSYS 0x00000083 ++ ++static void setup_sigcontext(struct target_sigcontext *sc, CPUSW64State *env, ++ abi_ulong frame_addr, target_sigset_t *set) ++{ ++ int i; ++ ++ __put_user(on_sig_stack(frame_addr), &sc->sc_onstack); ++ __put_user(set->sig[0], &sc->sc_mask); ++ __put_user(env->pc, &sc->sc_pc); ++ __put_user(8, &sc->sc_ps); ++ ++ for (i = 0; i < 31; ++i) { ++ __put_user(env->ir[i], &sc->sc_regs[i]); ++ } ++ __put_user(0, &sc->sc_regs[31]); ++ ++ for (i = 0; i < 31; ++i) { ++ __put_user(env->fr[i], &sc->sc_fpregs[i]); ++ } ++ __put_user(0, &sc->sc_fpregs[31]); ++ __put_user(cpu_sw64_load_fpcr(env), &sc->sc_fpcr); ++ ++ __put_user(0, &sc->sc_traparg_a0); /* FIXME */ ++ __put_user(0, &sc->sc_traparg_a1); /* FIXME */ ++ __put_user(0, &sc->sc_traparg_a2); /* FIXME */ ++} ++ ++static void restore_sigcontext(CPUSW64State *env, ++ struct target_sigcontext *sc) ++{ ++ uint64_t fpcr; ++ int i; ++ ++ __get_user(env->pc, &sc->sc_pc); ++ ++ for (i = 0; i < 31; ++i) { ++ __get_user(env->ir[i], &sc->sc_regs[i]); ++ } ++ for (i = 0; i < 31; ++i) { ++ __get_user(env->fr[i], &sc->sc_fpregs[i]); ++ } ++ ++ __get_user(fpcr, &sc->sc_fpcr); ++ cpu_sw64_store_fpcr(env, fpcr); ++} ++ ++static inline abi_ulong get_sigframe(struct target_sigaction *sa, ++ CPUSW64State *env, ++ unsigned long framesize) ++{ ++ abi_ulong sp; ++ ++ sp = target_sigsp(get_sp_from_cpustate(env), sa); ++ ++ return (sp - framesize) & -32; ++} ++ ++void setup_frame(int sig, struct target_sigaction *ka, ++ target_sigset_t *set, CPUSW64State *env) ++{ ++ abi_ulong frame_addr, r26; ++ struct target_sigframe *frame; ++ int err = 0; ++ ++ frame_addr = get_sigframe(ka, env, sizeof(*frame)); ++ trace_user_setup_frame(env, frame_addr); ++ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { ++ goto give_sigsegv; ++ } ++ ++ setup_sigcontext(&frame->sc, env, frame_addr, set); ++ ++ if (ka->sa_restorer) { ++ r26 = ka->sa_restorer; ++ } else { ++ __put_user(INSN_MOV_R30_R16, &frame->retcode[0]); ++ __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn, ++ &frame->retcode[1]); ++ __put_user(INSN_CALLSYS, &frame->retcode[2]); ++ /* imb() */ ++ r26 = frame_addr + offsetof(struct target_sigframe, retcode); ++ } ++ ++ unlock_user_struct(frame, frame_addr, 1); ++ ++ if (err) { ++give_sigsegv: ++ force_sigsegv(sig); ++ return; ++ } ++ ++ env->ir[IDX_RA] = r26; ++ env->ir[IDX_PV] = env->pc = ka->_sa_handler; ++ env->ir[IDX_A0] = sig; ++ env->ir[IDX_A1] = 0; ++ env->ir[IDX_A2] = frame_addr + offsetof(struct target_sigframe, sc); ++ env->ir[IDX_SP] = frame_addr; ++} ++ ++void setup_rt_frame(int sig, struct target_sigaction *ka, ++ target_siginfo_t *info, ++ target_sigset_t *set, CPUSW64State *env) ++{ ++ abi_ulong frame_addr, r26; ++ struct target_rt_sigframe *frame; ++ int i, err = 0; ++ ++ frame_addr = get_sigframe(ka, env, sizeof(*frame)); ++ trace_user_setup_rt_frame(env, frame_addr); ++ if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { ++ goto give_sigsegv; ++ } ++ ++ tswap_siginfo(&frame->info, info); ++ ++ __put_user(0, &frame->uc.tuc_flags); ++ __put_user(0, &frame->uc.tuc_link); ++ __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask); ++ ++ target_save_altstack(&frame->uc.tuc_stack, env); ++ ++ setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set); ++ for (i = 0; i < TARGET_NSIG_WORDS; ++i) { ++ __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); ++ } ++ ++ if (ka->sa_restorer) { ++ r26 = ka->sa_restorer; ++ } else { ++ __put_user(INSN_MOV_R30_R16, &frame->retcode[0]); ++ __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn, ++ &frame->retcode[1]); ++ __put_user(INSN_CALLSYS, &frame->retcode[2]); ++ r26 = frame_addr + offsetof(struct target_sigframe, retcode); ++ } ++ ++ if (err) { ++give_sigsegv: ++ force_sigsegv(sig); ++ return; ++ } ++ ++ env->ir[IDX_RA] = r26; ++ env->ir[IDX_PV] = env->pc = ka->_sa_handler; ++ env->ir[IDX_A0] = sig; ++ env->ir[IDX_A1] = frame_addr + offsetof(struct target_rt_sigframe, info); ++ env->ir[IDX_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc); ++ env->ir[IDX_SP] = frame_addr; ++} ++ ++long do_sigreturn(CPUSW64State *env) ++{ ++ struct target_sigcontext *sc; ++ abi_ulong sc_addr = env->ir[IDX_A0]; ++ target_sigset_t target_set; ++ sigset_t set; ++ ++ if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) { ++ goto badframe; ++ } ++ ++ target_sigemptyset(&target_set); ++ __get_user(target_set.sig[0], &sc->sc_mask); ++ ++ target_to_host_sigset_internal(&set, &target_set); ++ set_sigmask(&set); ++ ++ restore_sigcontext(env, sc); ++ unlock_user_struct(sc, sc_addr, 0); ++ return -TARGET_QEMU_ESIGRETURN; ++ ++badframe: ++ force_sig(TARGET_SIGSEGV); ++ return -TARGET_QEMU_ESIGRETURN; ++} ++ ++long do_rt_sigreturn(CPUSW64State *env) ++{ ++ abi_ulong frame_addr = env->ir[IDX_A0]; ++ struct target_rt_sigframe *frame; ++ sigset_t set; ++ ++ trace_user_do_rt_sigreturn(env, frame_addr); ++ if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { ++ goto badframe; ++ } ++ target_to_host_sigset(&set, &frame->uc.tuc_sigmask); ++ set_sigmask(&set); ++ ++ restore_sigcontext(env, &frame->uc.tuc_mcontext); ++ if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe, ++ uc.tuc_stack), ++ 0, env->ir[IDX_SP]) == -EFAULT) { ++ goto badframe; ++ } ++ ++ unlock_user_struct(frame, frame_addr, 0); ++ return -TARGET_QEMU_ESIGRETURN; ++ ++ ++badframe: ++ unlock_user_struct(frame, frame_addr, 0); ++ force_sig(TARGET_SIGSEGV); ++ return -TARGET_QEMU_ESIGRETURN; ++} +diff --git a/linux-user/sw64/sockbits.h b/linux-user/sw64/sockbits.h +new file mode 100644 +index 0000000000..0e4c8f012d +--- /dev/null ++++ b/linux-user/sw64/sockbits.h +@@ -0,0 +1 @@ ++#include "../generic/sockbits.h" +diff --git a/linux-user/sw64/syscall_nr.h b/linux-user/sw64/syscall_nr.h +new file mode 100644 +index 0000000000..91737af322 +--- /dev/null ++++ b/linux-user/sw64/syscall_nr.h +@@ -0,0 +1,471 @@ ++/* ++ * This file contains the system call numbers. ++ */ ++#define TARGET_NR_osf_syscall 0 /* not implemented */ ++#define TARGET_NR_exit 1 ++#define TARGET_NR_fork 2 ++#define TARGET_NR_read 3 ++#define TARGET_NR_write 4 ++#define TARGET_NR_osf_old_open 5 /* not implemented */ ++#define TARGET_NR_close 6 ++#define TARGET_NR_osf_wait4 7 ++#define TARGET_NR_osf_old_creat 8 /* not implemented */ ++#define TARGET_NR_link 9 ++#define TARGET_NR_unlink 10 ++#define TARGET_NR_osf_execve 11 /* not implemented */ ++#define TARGET_NR_chdir 12 ++#define TARGET_NR_fchdir 13 ++#define TARGET_NR_mknod 14 ++#define TARGET_NR_chmod 15 ++#define TARGET_NR_chown 16 ++#define TARGET_NR_brk 17 ++#define TARGET_NR_osf_getfsstat 18 /* not implemented */ ++#define TARGET_NR_lseek 19 ++#define TARGET_NR_getxpid 20 ++#define TARGET_NR_osf_mount 21 ++#define TARGET_NR_umount 22 ++#define TARGET_NR_setuid 23 ++#define TARGET_NR_getxuid 24 ++#define TARGET_NR_exec_with_loader 25 /* not implemented */ ++#define TARGET_NR_ptrace 26 ++#define TARGET_NR_osf_nrecvmsg 27 /* not implemented */ ++#define TARGET_NR_osf_nsendmsg 28 /* not implemented */ ++#define TARGET_NR_osf_nrecvfrom 29 /* not implemented */ ++#define TARGET_NR_osf_naccept 30 /* not implemented */ ++#define TARGET_NR_osf_ngetpeername 31 /* not implemented */ ++#define TARGET_NR_osf_ngetsockname 32 /* not implemented */ ++#define TARGET_NR_access 33 ++#define TARGET_NR_osf_chflags 34 /* not implemented */ ++#define TARGET_NR_osf_fchflags 35 /* not implemented */ ++#define TARGET_NR_sync 36 ++#define TARGET_NR_kill 37 ++#define TARGET_NR_osf_old_stat 38 /* not implemented */ ++#define TARGET_NR_setpgid 39 ++#define TARGET_NR_osf_old_lstat 40 /* not implemented */ ++#define TARGET_NR_dup 41 ++#define TARGET_NR_pipe 42 ++#define TARGET_NR_osf_set_program_attributes 43 ++#define TARGET_NR_osf_profil 44 /* not implemented */ ++#define TARGET_NR_open 45 ++#define TARGET_NR_osf_old_sigaction 46 /* not implemented */ ++#define TARGET_NR_getxgid 47 ++#define TARGET_NR_osf_sigprocmask 48 ++#define TARGET_NR_osf_getlogin 49 /* not implemented */ ++#define TARGET_NR_osf_setlogin 50 /* not implemented */ ++#define TARGET_NR_acct 51 ++#define TARGET_NR_sigpending 52 ++ ++#define TARGET_NR_ioctl 54 ++#define TARGET_NR_osf_reboot 55 /* not implemented */ ++#define TARGET_NR_osf_revoke 56 /* not implemented */ ++#define TARGET_NR_symlink 57 ++#define TARGET_NR_readlink 58 ++#define TARGET_NR_execve 59 ++#define TARGET_NR_umask 60 ++#define TARGET_NR_chroot 61 ++#define TARGET_NR_osf_old_fstat 62 /* not implemented */ ++#define TARGET_NR_getpgrp 63 ++#define TARGET_NR_getpagesize 64 ++#define TARGET_NR_osf_mremap 65 /* not implemented */ ++#define TARGET_NR_vfork 66 ++#define TARGET_NR_stat 67 ++#define TARGET_NR_lstat 68 ++#define TARGET_NR_osf_sbrk 69 /* not implemented */ ++#define TARGET_NR_osf_sstk 70 /* not implemented */ ++#define TARGET_NR_mmap 71 /* OSF/1 mmap is superset of Linux */ ++#define TARGET_NR_osf_old_vadvise 72 /* not implemented */ ++#define TARGET_NR_munmap 73 ++#define TARGET_NR_mprotect 74 ++#define TARGET_NR_madvise 75 ++#define TARGET_NR_vhangup 76 ++#define TARGET_NR_osf_kmodcall 77 /* not implemented */ ++#define TARGET_NR_osf_mincore 78 /* not implemented */ ++#define TARGET_NR_getgroups 79 ++#define TARGET_NR_setgroups 80 ++#define TARGET_NR_osf_old_getpgrp 81 /* not implemented */ ++#define TARGET_NR_setpgrp 82 /* BSD alias for setpgid */ ++#define TARGET_NR_osf_setitimer 83 ++#define TARGET_NR_osf_old_wait 84 /* not implemented */ ++#define TARGET_NR_osf_table 85 /* not implemented */ ++#define TARGET_NR_osf_getitimer 86 ++#define TARGET_NR_gethostname 87 ++#define TARGET_NR_sethostname 88 ++#define TARGET_NR_getdtablesize 89 ++#define TARGET_NR_dup2 90 ++#define TARGET_NR_fstat 91 ++#define TARGET_NR_fcntl 92 ++#define TARGET_NR_osf_select 93 ++#define TARGET_NR_poll 94 ++#define TARGET_NR_fsync 95 ++#define TARGET_NR_setpriority 96 ++#define TARGET_NR_socket 97 ++#define TARGET_NR_connect 98 ++#define TARGET_NR_accept 99 ++#define TARGET_NR_getpriority 100 ++#define TARGET_NR_send 101 ++#define TARGET_NR_recv 102 ++#define TARGET_NR_sigreturn 103 ++#define TARGET_NR_bind 104 ++#define TARGET_NR_setsockopt 105 ++#define TARGET_NR_listen 106 ++#define TARGET_NR_osf_plock 107 /* not implemented */ ++#define TARGET_NR_osf_old_sigvec 108 /* not implemented */ ++#define TARGET_NR_osf_old_sigblock 109 /* not implemented */ ++#define TARGET_NR_osf_old_sigsetmask 110 /* not implemented */ ++#define TARGET_NR_sigsuspend 111 ++#define TARGET_NR_osf_sigstack 112 ++#define TARGET_NR_recvmsg 113 ++#define TARGET_NR_sendmsg 114 ++#define TARGET_NR_osf_old_vtrace 115 /* not implemented */ ++#define TARGET_NR_osf_gettimeofday 116 ++#define TARGET_NR_osf_getrusage 117 ++#define TARGET_NR_getsockopt 118 ++ ++#define TARGET_NR_readv 120 ++#define TARGET_NR_writev 121 ++#define TARGET_NR_osf_settimeofday 122 ++#define TARGET_NR_fchown 123 ++#define TARGET_NR_fchmod 124 ++#define TARGET_NR_recvfrom 125 ++#define TARGET_NR_setreuid 126 ++#define TARGET_NR_setregid 127 ++#define TARGET_NR_rename 128 ++#define TARGET_NR_truncate 129 ++#define TARGET_NR_ftruncate 130 ++#define TARGET_NR_flock 131 ++#define TARGET_NR_setgid 132 ++#define TARGET_NR_sendto 133 ++#define TARGET_NR_shutdown 134 ++#define TARGET_NR_socketpair 135 ++#define TARGET_NR_mkdir 136 ++#define TARGET_NR_rmdir 137 ++#define TARGET_NR_osf_utimes 138 ++#define TARGET_NR_osf_old_sigreturn 139 /* not implemented */ ++#define TARGET_NR_osf_adjtime 140 /* not implemented */ ++#define TARGET_NR_getpeername 141 ++#define TARGET_NR_osf_gethostid 142 /* not implemented */ ++#define TARGET_NR_osf_sethostid 143 /* not implemented */ ++#define TARGET_NR_getrlimit 144 ++#define TARGET_NR_setrlimit 145 ++#define TARGET_NR_osf_old_killpg 146 /* not implemented */ ++#define TARGET_NR_setsid 147 ++#define TARGET_NR_quotactl 148 ++#define TARGET_NR_osf_oldquota 149 /* not implemented */ ++#define TARGET_NR_getsockname 150 ++ ++#define TARGET_NR_osf_pid_block 153 /* not implemented */ ++#define TARGET_NR_osf_pid_unblock 154 /* not implemented */ ++ ++#define TARGET_NR_sigaction 156 ++#define TARGET_NR_osf_sigwaitprim 157 /* not implemented */ ++#define TARGET_NR_osf_nfssvc 158 /* not implemented */ ++#define TARGET_NR_osf_getdirentries 159 ++#define TARGET_NR_osf_statfs 160 ++#define TARGET_NR_osf_fstatfs 161 ++ ++#define TARGET_NR_osf_asynch_daemon 163 /* not implemented */ ++#define TARGET_NR_osf_getfh 164 /* not implemented */ ++#define TARGET_NR_osf_getdomainname 165 ++#define TARGET_NR_setdomainname 166 ++ ++#define TARGET_NR_osf_exportfs 169 /* not implemented */ ++ ++#define TARGET_NR_osf_alt_plock 181 /* not implemented */ ++ ++#define TARGET_NR_osf_getmnt 184 /* not implemented */ ++ ++#define TARGET_NR_osf_alt_sigpending 187 /* not implemented */ ++#define TARGET_NR_osf_alt_setsid 188 /* not implemented */ ++ ++#define TARGET_NR_osf_swapon 199 ++#define TARGET_NR_msgctl 200 ++#define TARGET_NR_msgget 201 ++#define TARGET_NR_msgrcv 202 ++#define TARGET_NR_msgsnd 203 ++#define TARGET_NR_semctl 204 ++#define TARGET_NR_semget 205 ++#define TARGET_NR_semop 206 ++#define TARGET_NR_osf_utsname 207 ++#define TARGET_NR_lchown 208 ++#define TARGET_NR_osf_shmat 209 ++#define TARGET_NR_shmctl 210 ++#define TARGET_NR_shmdt 211 ++#define TARGET_NR_shmget 212 ++#define TARGET_NR_osf_mvalid 213 /* not implemented */ ++#define TARGET_NR_osf_getaddressconf 214 /* not implemented */ ++#define TARGET_NR_osf_msleep 215 /* not implemented */ ++#define TARGET_NR_osf_mwakeup 216 /* not implemented */ ++#define TARGET_NR_msync 217 ++#define TARGET_NR_osf_signal 218 /* not implemented */ ++#define TARGET_NR_osf_utc_gettime 219 /* not implemented */ ++#define TARGET_NR_osf_utc_adjtime 220 /* not implemented */ ++ ++#define TARGET_NR_osf_security 222 /* not implemented */ ++#define TARGET_NR_osf_kloadcall 223 /* not implemented */ ++ ++#define TARGET_NR_osf_stat 224 ++#define TARGET_NR_osf_lstat 225 ++#define TARGET_NR_osf_fstat 226 ++#define TARGET_NR_osf_statfs64 227 ++#define TARGET_NR_osf_fstatfs64 228 ++ ++#define TARGET_NR_getpgid 233 ++#define TARGET_NR_getsid 234 ++#define TARGET_NR_sigaltstack 235 ++#define TARGET_NR_osf_waitid 236 /* not implemented */ ++#define TARGET_NR_osf_priocntlset 237 /* not implemented */ ++#define TARGET_NR_osf_sigsendset 238 /* not implemented */ ++#define TARGET_NR_osf_set_speculative 239 /* not implemented */ ++#define TARGET_NR_osf_msfs_syscall 240 /* not implemented */ ++#define TARGET_NR_osf_sysinfo 241 ++#define TARGET_NR_osf_uadmin 242 /* not implemented */ ++#define TARGET_NR_osf_fuser 243 /* not implemented */ ++#define TARGET_NR_osf_proplist_syscall 244 ++#define TARGET_NR_osf_ntp_adjtime 245 /* not implemented */ ++#define TARGET_NR_osf_ntp_gettime 246 /* not implemented */ ++#define TARGET_NR_osf_pathconf 247 /* not implemented */ ++#define TARGET_NR_osf_fpathconf 248 /* not implemented */ ++ ++#define TARGET_NR_osf_uswitch 250 /* not implemented */ ++#define TARGET_NR_osf_usleep_thread 251 ++#define TARGET_NR_osf_audcntl 252 /* not implemented */ ++#define TARGET_NR_osf_audgen 253 /* not implemented */ ++#define TARGET_NR_sysfs 254 ++#define TARGET_NR_osf_subsys_info 255 /* not implemented */ ++#define TARGET_NR_osf_getsysinfo 256 ++#define TARGET_NR_osf_setsysinfo 257 ++#define TARGET_NR_osf_afs_syscall 258 /* not implemented */ ++#define TARGET_NR_osf_swapctl 259 /* not implemented */ ++#define TARGET_NR_osf_memcntl 260 /* not implemented */ ++#define TARGET_NR_osf_fdatasync 261 /* not implemented */ ++ ++/* ++ * Ignore legacy syscalls that we don't use. ++ */ ++#define TARGET_IGNORE_alarm ++#define TARGET_IGNORE_creat ++#define TARGET_IGNORE_getegid ++#define TARGET_IGNORE_geteuid ++#define TARGET_IGNORE_getgid ++#define TARGET_IGNORE_getpid ++#define TARGET_IGNORE_getppid ++#define TARGET_IGNORE_getuid ++#define TARGET_IGNORE_pause ++#define TARGET_IGNORE_time ++#define TARGET_IGNORE_utime ++#define TARGET_IGNORE_umount2 ++ ++/* ++ * Linux-specific system calls begin at 300 ++ */ ++#define TARGET_NR_bdflush 300 ++#define TARGET_NR_sethae 301 ++#define TARGET_NR_mount 302 ++#define TARGET_NR_old_adjtimex 303 ++#define TARGET_NR_swapoff 304 ++#define TARGET_NR_getdents 305 ++#define TARGET_NR_create_module 306 ++#define TARGET_NR_init_module 307 ++#define TARGET_NR_delete_module 308 ++#define TARGET_NR_get_kernel_syms 309 ++#define TARGET_NR_syslog 310 ++#define TARGET_NR_reboot 311 ++#define TARGET_NR_clone 312 ++#define TARGET_NR_uselib 313 ++#define TARGET_NR_mlock 314 ++#define TARGET_NR_munlock 315 ++#define TARGET_NR_mlockall 316 ++#define TARGET_NR_munlockall 317 ++#define TARGET_NR_sysinfo 318 ++#define TARGET_NR__sysctl 319 ++/* 320 was sysTARGETidle. */ ++#define TARGET_NR_oldumount 321 ++#define TARGET_NR_swapon 322 ++#define TARGET_NR_times 323 ++#define TARGET_NR_personality 324 ++#define TARGET_NR_setfsuid 325 ++#define TARGET_NR_setfsgid 326 ++#define TARGET_NR_ustat 327 ++#define TARGET_NR_statfs 328 ++#define TARGET_NR_fstatfs 329 ++#define TARGET_NR_sched_setparam 330 ++#define TARGET_NR_sched_getparam 331 ++#define TARGET_NR_sched_setscheduler 332 ++#define TARGET_NR_sched_getscheduler 333 ++#define TARGET_NR_sched_yield 334 ++#define TARGET_NR_sched_get_priority_max 335 ++#define TARGET_NR_sched_get_priority_min 336 ++#define TARGET_NR_sched_rr_get_interval 337 ++#define TARGET_NR_afs_syscall 338 ++#define TARGET_NR_uname 339 ++#define TARGET_NR_nanosleep 340 ++#define TARGET_NR_mremap 341 ++#define TARGET_NR_nfsservctl 342 ++#define TARGET_NR_setresuid 343 ++#define TARGET_NR_getresuid 344 ++#define TARGET_NR_pciconfig_read 345 ++#define TARGET_NR_pciconfig_write 346 ++#define TARGET_NR_query_module 347 ++#define TARGET_NR_prctl 348 ++#define TARGET_NR_pread64 349 ++#define TARGET_NR_pwrite64 350 ++#define TARGET_NR_rt_sigreturn 351 ++#define TARGET_NR_rt_sigaction 352 ++#define TARGET_NR_rt_sigprocmask 353 ++#define TARGET_NR_rt_sigpending 354 ++#define TARGET_NR_rt_sigtimedwait 355 ++#define TARGET_NR_rt_sigqueueinfo 356 ++#define TARGET_NR_rt_sigsuspend 357 ++#define TARGET_NR_select 358 ++#define TARGET_NR_gettimeofday 359 ++#define TARGET_NR_settimeofday 360 ++#define TARGET_NR_getitimer 361 ++#define TARGET_NR_setitimer 362 ++#define TARGET_NR_utimes 363 ++#define TARGET_NR_getrusage 364 ++#define TARGET_NR_wait4 365 ++#define TARGET_NR_adjtimex 366 ++#define TARGET_NR_getcwd 367 ++#define TARGET_NR_capget 368 ++#define TARGET_NR_capset 369 ++#define TARGET_NR_sendfile 370 ++#define TARGET_NR_setresgid 371 ++#define TARGET_NR_getresgid 372 ++#define TARGET_NR_dipc 373 ++#define TARGET_NR_pivot_root 374 ++#define TARGET_NR_mincore 375 ++#define TARGET_NR_pciconfig_iobase 376 ++#define TARGET_NR_getdents64 377 ++#define TARGET_NR_gettid 378 ++#define TARGET_NR_readahead 379 ++/* 380 is unused */ ++#define TARGET_NR_tkill 381 ++#define TARGET_NR_setxattr 382 ++#define TARGET_NR_lsetxattr 383 ++#define TARGET_NR_fsetxattr 384 ++#define TARGET_NR_getxattr 385 ++#define TARGET_NR_lgetxattr 386 ++#define TARGET_NR_fgetxattr 387 ++#define TARGET_NR_listxattr 388 ++#define TARGET_NR_llistxattr 389 ++#define TARGET_NR_flistxattr 390 ++#define TARGET_NR_removexattr 391 ++#define TARGET_NR_lremovexattr 392 ++#define TARGET_NR_fremovexattr 393 ++#define TARGET_NR_futex 394 ++#define TARGET_NR_sched_setaffinity 395 ++#define TARGET_NR_sched_getaffinity 396 ++#define TARGET_NR_tuxcall 397 ++#define TARGET_NR_io_setup 398 ++#define TARGET_NR_io_destroy 399 ++#define TARGET_NR_io_getevents 400 ++#define TARGET_NR_io_submit 401 ++#define TARGET_NR_io_cancel 402 ++#define TARGET_NR_exit_group 405 ++#define TARGET_NR_lookup_dcookie 406 ++#define TARGET_NR_epoll_create 407 ++#define TARGET_NR_epoll_ctl 408 ++#define TARGET_NR_epoll_wait 409 ++/* Feb 2007: These three sysTARGETepoll defines shouldn't be here but culling ++ * them would break userspace apps ... we'll kill them off in 2010 :) */ ++#define TARGET_NR_sys_epoll_create TARGET_NR_epoll_create ++#define TARGET_NR_sys_epoll_ctl TARGET_NR_epoll_ctl ++#define TARGET_NR_sys_epoll_wait TARGET_NR_epoll_wait ++#define TARGET_NR_remap_file_pages 410 ++#define TARGET_NR_set_tid_address 411 ++#define TARGET_NR_restart_syscall 412 ++#define TARGET_NR_fadvise64 413 ++#define TARGET_NR_timer_create 414 ++#define TARGET_NR_timer_settime 415 ++#define TARGET_NR_timer_gettime 416 ++#define TARGET_NR_timer_getoverrun 417 ++#define TARGET_NR_timer_delete 418 ++#define TARGET_NR_clock_settime 419 ++#define TARGET_NR_clock_gettime 420 ++#define TARGET_NR_clock_getres 421 ++#define TARGET_NR_clock_nanosleep 422 ++#define TARGET_NR_semtimedop 423 ++#define TARGET_NR_tgkill 424 ++#define TARGET_NR_stat64 425 ++#define TARGET_NR_lstat64 426 ++#define TARGET_NR_fstat64 427 ++#define TARGET_NR_vserver 428 ++#define TARGET_NR_mbind 429 ++#define TARGET_NR_get_mempolicy 430 ++#define TARGET_NR_set_mempolicy 431 ++#define TARGET_NR_mq_open 432 ++#define TARGET_NR_mq_unlink 433 ++#define TARGET_NR_mq_timedsend 434 ++#define TARGET_NR_mq_timedreceive 435 ++#define TARGET_NR_mq_notify 436 ++#define TARGET_NR_mq_getsetattr 437 ++#define TARGET_NR_waitid 438 ++#define TARGET_NR_add_key 439 ++#define TARGET_NR_request_key 440 ++#define TARGET_NR_keyctl 441 ++#define TARGET_NR_ioprio_set 442 ++#define TARGET_NR_ioprio_get 443 ++#define TARGET_NR_inotify_init 444 ++#define TARGET_NR_inotify_add_watch 445 ++#define TARGET_NR_inotify_rm_watch 446 ++#define TARGET_NR_fdatasync 447 ++#define TARGET_NR_kexec_load 448 ++#define TARGET_NR_migrate_pages 449 ++#define TARGET_NR_openat 450 ++#define TARGET_NR_mkdirat 451 ++#define TARGET_NR_mknodat 452 ++#define TARGET_NR_fchownat 453 ++#define TARGET_NR_futimesat 454 ++#define TARGET_NR_fstatat64 455 ++#define TARGET_NR_unlinkat 456 ++#define TARGET_NR_renameat 457 ++#define TARGET_NR_linkat 458 ++#define TARGET_NR_symlinkat 459 ++#define TARGET_NR_readlinkat 460 ++#define TARGET_NR_fchmodat 461 ++#define TARGET_NR_faccessat 462 ++#define TARGET_NR_pselect6 463 ++#define TARGET_NR_ppoll 464 ++#define TARGET_NR_unshare 465 ++#define TARGET_NR_set_robust_list 466 ++#define TARGET_NR_get_robust_list 467 ++#define TARGET_NR_splice 468 ++#define TARGET_NR_sync_file_range 469 ++#define TARGET_NR_tee 470 ++#define TARGET_NR_vmsplice 471 ++#define TARGET_NR_move_pages 472 ++#define TARGET_NR_getcpu 473 ++#define TARGET_NR_epoll_pwait 474 ++#define TARGET_NR_utimensat 475 ++#define TARGET_NR_signalfd 476 ++#define TARGET_NR_timerfd 477 ++#define TARGET_NR_eventfd 478 ++#define TARGET_NR_recvmmsg 479 ++#define TARGET_NR_fallocate 480 ++#define TARGET_NR_timerfd_create 481 ++#define TARGET_NR_timerfd_settime 482 ++#define TARGET_NR_timerfd_gettime 483 ++#define TARGET_NR_signalfd4 484 ++#define TARGET_NR_eventfd2 485 ++#define TARGET_NR_epoll_create1 486 ++#define TARGET_NR_dup3 487 ++#define TARGET_NR_pipe2 488 ++#define TARGET_NR_inotify_init1 489 ++#define TARGET_NR_preadv 490 ++#define TARGET_NR_pwritev 491 ++#define TARGET_NR_rt_tgsigqueueinfo 492 ++#define TARGET_NR_perf_event_open 493 ++#define TARGET_NR_fanotify_init 494 ++#define TARGET_NR_fanotify_mark 495 ++#define TARGET_NR_prlimit64 496 ++#define TARGET_NR_name_to_handle_at 497 ++#define TARGET_NR_open_by_handle_at 498 ++#define TARGET_NR_clock_adjtime 499 ++#define TARGET_NR_syncfs 500 ++#define TARGET_NR_setns 501 ++#define TARGET_NR_accept4 502 ++#define TARGET_NR_sendmmsg 503 ++#define TARGET_NR_process_vm_readv 504 ++#define TARGET_NR_process_vm_writev 505 ++#define TARGET_NR_sw_slave_rwperfmons 506 ++#define TARGET_NR_sys_get_vmflags 507 +diff --git a/linux-user/sw64/target_cpu.h b/linux-user/sw64/target_cpu.h +new file mode 100644 +index 0000000000..1b87c8ba6d +--- /dev/null ++++ b/linux-user/sw64/target_cpu.h +@@ -0,0 +1,38 @@ ++/* ++ * SW64 specific CPU ABI and functions for linux-user ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++#ifndef SW64_TARGET_CPU_H ++#define SW64_TARGET_CPU_H ++ ++static inline void cpu_clone_regs(CPUSW64State *env, target_ulong newsp) ++{ ++ if (newsp) { ++ env->ir[IDX_SP] = newsp; ++ } ++ env->ir[IDX_V0] = 0; ++ env->ir[IDX_A3] = 0; ++} ++ ++static inline void cpu_set_tls(CPUSW64State *env, target_ulong newtls) ++{ ++ env->unique = newtls; ++} ++ ++static inline abi_ulong get_sp_from_cpustate(CPUSW64State *state) ++{ ++ return state->ir[IDX_SP]; ++} ++#endif +diff --git a/linux-user/sw64/target_elf.h b/linux-user/sw64/target_elf.h +new file mode 100644 +index 0000000000..be48b6dee3 +--- /dev/null ++++ b/linux-user/sw64/target_elf.h +@@ -0,0 +1,14 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation, or (at your option) any ++ * later version. See the COPYING file in the top-level directory. ++ */ ++ ++#ifndef SW64_TARGET_ELF_H ++#define SW64_TARGET_ELF_H ++static inline const char *cpu_get_model(uint32_t eflags) ++{ ++ return "any"; ++} ++#endif +diff --git a/linux-user/sw64/target_fcntl.h b/linux-user/sw64/target_fcntl.h +new file mode 100644 +index 0000000000..9721e3de39 +--- /dev/null ++++ b/linux-user/sw64/target_fcntl.h +@@ -0,0 +1,11 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation, or (at your option) any ++ * later version. See the COPYING file in the top-level directory. ++ */ ++ ++#ifndef SW64_TARGET_FCNTL_H ++#define sw64_TARGET_FCNTL_H ++#include "../generic/fcntl.h" ++#endif +diff --git a/linux-user/sw64/target_signal.h b/linux-user/sw64/target_signal.h +new file mode 100644 +index 0000000000..6393a7542f +--- /dev/null ++++ b/linux-user/sw64/target_signal.h +@@ -0,0 +1,98 @@ ++#ifndef SW64_TARGET_SIGNAL_H ++#define SW64_TARGET_SIGNAL_H ++ ++#include "cpu.h" ++ ++#define TARGET_SIGHUP 1 ++#define TARGET_SIGINT 2 ++#define TARGET_SIGQUIT 3 ++#define TARGET_SIGILL 4 ++#define TARGET_SIGTRAP 5 ++#define TARGET_SIGABRT 6 ++#define TARGET_SIGSTKFLT 7 /* actually SIGEMT */ ++#define TARGET_SIGFPE 8 ++#define TARGET_SIGKILL 9 ++#define TARGET_SIGBUS 10 ++#define TARGET_SIGSEGV 11 ++#define TARGET_SIGSYS 12 ++#define TARGET_SIGPIPE 13 ++#define TARGET_SIGALRM 14 ++#define TARGET_SIGTERM 15 ++#define TARGET_SIGURG 16 ++#define TARGET_SIGSTOP 17 ++#define TARGET_SIGTSTP 18 ++#define TARGET_SIGCONT 19 ++#define TARGET_SIGCHLD 20 ++#define TARGET_SIGTTIN 21 ++#define TARGET_SIGTTOU 22 ++#define TARGET_SIGIO 23 ++#define TARGET_SIGXCPU 24 ++#define TARGET_SIGXFSZ 25 ++#define TARGET_SIGVTALRM 26 ++#define TARGET_SIGPROF 27 ++#define TARGET_SIGWINCH 28 ++#define TARGET_SIGPWR 29 /* actually SIGINFO */ ++#define TARGET_SIGUSR1 30 ++#define TARGET_SIGUSR2 31 ++#define TARGET_SIGRTMIN 32 ++ ++#define TARGET_SIG_BLOCK 1 ++#define TARGET_SIG_UNBLOCK 2 ++#define TARGET_SIG_SETMASK 3 ++ ++/* this struct defines a stack used during syscall handling */ ++ ++typedef struct target_sigaltstack { ++ abi_ulong ss_sp; ++ int32_t ss_flags; ++ int32_t dummy; ++ abi_ulong ss_size; ++} target_stack_t; ++ ++ ++/* ++ * sigaltstack controls ++ */ ++#define TARGET_SS_ONSTACK 1 ++#define TARGET_SS_DISABLE 2 ++ ++#define TARGET_SA_ONSTACK 0x00000001 ++#define TARGET_SA_RESTART 0x00000002 ++#define TARGET_SA_NOCLDSTOP 0x00000004 ++#define TARGET_SA_NODEFER 0x00000008 ++#define TARGET_SA_RESETHAND 0x00000010 ++#define TARGET_SA_NOCLDWAIT 0x00000020 /* not supported yet */ ++#define TARGET_SA_SIGINFO 0x00000040 ++ ++#define TARGET_MINSIGSTKSZ 4096 ++#define TARGET_SIGSTKSZ 16384 ++ ++/* From . */ ++#define TARGET_GEN_INTOVF -1 /* integer overflow */ ++#define TARGET_GEN_INTDIV -2 /* integer division by zero */ ++#define TARGET_GEN_FLTOVF -3 /* fp overflow */ ++#define TARGET_GEN_FLTDIV -4 /* fp division by zero */ ++#define TARGET_GEN_FLTUND -5 /* fp underflow */ ++#define TARGET_GEN_FLTINV -6 /* invalid fp operand */ ++#define TARGET_GEN_FLTINE -7 /* inexact fp operand */ ++#define TARGET_GEN_DECOVF -8 /* decimal overflow (for COBOL??) */ ++#define TARGET_GEN_DECDIV -9 /* decimal division by zero */ ++#define TARGET_GEN_DECINV -10 /* invalid decimal operand */ ++#define TARGET_GEN_ROPRAND -11 /* reserved operand */ ++#define TARGET_GEN_ASSERTERR -12 /* assertion error */ ++#define TARGET_GEN_NULPTRERR -13 /* null pointer error */ ++#define TARGET_GEN_STKOVF -14 /* stack overflow */ ++#define TARGET_GEN_STRLENERR -15 /* string length error */ ++#define TARGET_GEN_SUBSTRERR -16 /* substring error */ ++#define TARGET_GEN_RANGERR -17 /* range error */ ++#define TARGET_GEN_SUBRNG -18 ++#define TARGET_GEN_SUBRNG1 -19 ++#define TARGET_GEN_SUBRNG2 -20 ++#define TARGET_GEN_SUBRNG3 -21 ++#define TARGET_GEN_SUBRNG4 -22 ++#define TARGET_GEN_SUBRNG5 -23 ++#define TARGET_GEN_SUBRNG6 -24 ++#define TARGET_GEN_SUBRNG7 -25 ++ ++#define TARGET_ARCH_HAS_SETUP_FRAME ++#endif /* SW64_TARGET_SIGNAL_H */ +diff --git a/linux-user/sw64/target_structs.h b/linux-user/sw64/target_structs.h +new file mode 100644 +index 0000000000..7c13dc4bac +--- /dev/null ++++ b/linux-user/sw64/target_structs.h +@@ -0,0 +1,47 @@ ++/* ++ * SW64 specific structures for linux-user ++ * ++ * Copyright (c) 2018 Lin Hainan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ */ ++#ifndef SW64_TARGET_STRUCTS_H ++#define SW64_TARGET_STRUCTS_H ++ ++/* TODO: Maybe it should be update. now it's different from other arch */ ++struct target_ipc_perm { ++ abi_int __key; /* Key. */ ++ abi_uint uid; /* Owner's user ID. */ ++ abi_uint gid; /* Owner's group ID. */ ++ abi_uint cuid; /* Creator's user ID. */ ++ abi_uint cgid; /* Creator's group ID. */ ++ abi_uint mode; /* Read/write permission. */ ++ abi_ushort __seq; /* Sequence number. */ ++ abi_ushort __pad1; ++ abi_ulong __unused1; ++ abi_ulong __unused2; ++}; ++ ++struct target_shmid_ds { ++ struct target_ipc_perm shm_perm; /* operation permission struct */ ++ abi_long shm_segsz; /* size of segment in bytes */ ++ abi_ulong shm_atime; /* time of last shmat() */ ++ abi_ulong shm_dtime; /* time of last shmdt() */ ++ abi_ulong shm_ctime; /* time of last change by shmctl() */ ++ abi_int shm_cpid; /* pid of creator */ ++ abi_int shm_lpid; /* pid of last shmop */ ++ abi_ulong shm_nattch; /* number of current attaches */ ++ abi_ulong __unused1; ++ abi_ulong __unused2; ++}; ++ ++#endif +diff --git a/linux-user/sw64/target_syscall.h b/linux-user/sw64/target_syscall.h +new file mode 100644 +index 0000000000..c901ae95d8 +--- /dev/null ++++ b/linux-user/sw64/target_syscall.h +@@ -0,0 +1,121 @@ ++#ifndef SW64_TARGET_SYSCALL_H ++#define SW64_TARGET_SYSCALL_H ++ ++/* TODO */ ++struct target_pt_regs { ++ abi_ulong r0; ++ abi_ulong r1; ++ abi_ulong r2; ++ abi_ulong r3; ++ abi_ulong r4; ++ abi_ulong r5; ++ abi_ulong r6; ++ abi_ulong r7; ++ abi_ulong r8; ++ abi_ulong r19; ++ abi_ulong r20; ++ abi_ulong r21; ++ abi_ulong r22; ++ abi_ulong r23; ++ abi_ulong r24; ++ abi_ulong r25; ++ abi_ulong r26; ++ abi_ulong r27; ++ abi_ulong r28; ++ abi_ulong hae; ++/* JRP - These are the values provided to a0-a2 by HMcode */ ++ abi_ulong trap_a0; ++ abi_ulong trap_a1; ++ abi_ulong trap_a2; ++/* These are saved by HMcode: */ ++ abi_ulong ps; ++ abi_ulong pc; ++ abi_ulong gp; ++ abi_ulong r16; ++ abi_ulong r17; ++ abi_ulong r18; ++}; ++ ++#define TARGET_MLOCKALL_MCL_CURRENT 0x2000 ++#define TARGET_MLOCKALL_MCL_FUTURE 0x4000 ++ ++ ++#define UNAME_MACHINE "sw64" ++#define UNAME_MINIMUM_RELEASE "2.6.32" ++#undef TARGET_EOPNOTSUPP ++#define TARGET_EOPNOTSUPP 45 /* Operation not supported on transport endpoint */ ++#define SWCR_STATUS_INV0 (1UL<<17) ++#define SWCR_STATUS_DZE0 (1UL<<18) ++#define SWCR_STATUS_OVF0 (1UL<<19) ++#define SWCR_STATUS_UNF0 (1UL<<20) ++#define SWCR_STATUS_INE0 (1UL<<21) ++#define SWCR_STATUS_DNO0 (1UL<<22) ++ ++#define SWCR_STATUS_MASK0 (SWCR_STATUS_INV0 | SWCR_STATUS_DZE0 | \ ++ SWCR_STATUS_OVF0 | SWCR_STATUS_UNF0 | \ ++ SWCR_STATUS_INE0 | SWCR_STATUS_DNO0) ++ ++#define SWCR_STATUS0_TO_EXCSUM_SHIFT 16 ++ ++#define SWCR_STATUS_INV1 (1UL<<23) ++#define SWCR_STATUS_DZE1 (1UL<<24) ++#define SWCR_STATUS_OVF1 (1UL<<25) ++#define SWCR_STATUS_UNF1 (1UL<<26) ++#define SWCR_STATUS_INE1 (1UL<<27) ++#define SWCR_STATUS_DNO1 (1UL<<28) ++ ++#define SWCR_STATUS_MASK1 (SWCR_STATUS_INV1 | SWCR_STATUS_DZE1 | \ ++ SWCR_STATUS_OVF1 | SWCR_STATUS_UNF1 | \ ++ SWCR_STATUS_INE1 | SWCR_STATUS_DNO1) ++ ++#define SWCR_STATUS1_TO_EXCSUM_SHIFT 22 ++#define SWCR_STATUS_INV2 (1UL<<34) ++#define SWCR_STATUS_DZE2 (1UL<<35) ++#define SWCR_STATUS_OVF2 (1UL<<36) ++#define SWCR_STATUS_UNF2 (1UL<<37) ++#define SWCR_STATUS_INE2 (1UL<<38) ++#define SWCR_STATUS_DNO2 (1UL<<39) ++ ++#define SWCR_STATUS_MASK2 (SWCR_STATUS_INV2 | SWCR_STATUS_DZE2 | \ ++ SWCR_STATUS_OVF2 | SWCR_STATUS_UNF2 | \ ++ SWCR_STATUS_INE2 | SWCR_STATUS_DNO2) ++#define SWCR_STATUS_INV3 (1UL<<40) ++#define SWCR_STATUS_DZE3 (1UL<<41) ++#define SWCR_STATUS_OVF3 (1UL<<42) ++#define SWCR_STATUS_UNF3 (1UL<<43) ++#define SWCR_STATUS_INE3 (1UL<<44) ++#define SWCR_STATUS_DNO3 (1UL<<45) ++ ++#define SWCR_STATUS_MASK3 (SWCR_STATUS_INV3 | SWCR_STATUS_DZE3 | \ ++ SWCR_STATUS_OVF3 | SWCR_STATUS_UNF3 | \ ++ SWCR_STATUS_INE3 | SWCR_STATUS_DNO3) ++#define SWCR_TRAP_ENABLE_INV (1UL<<1) /* invalid op */ ++#define SWCR_TRAP_ENABLE_DZE (1UL<<2) /* division by zero */ ++#define SWCR_TRAP_ENABLE_OVF (1UL<<3) /* overflow */ ++#define SWCR_TRAP_ENABLE_UNF (1UL<<4) /* underflow */ ++#define SWCR_TRAP_ENABLE_INE (1UL<<5) /* inexact */ ++#define SWCR_TRAP_ENABLE_DNO (1UL<<6) /* denorm */ ++#define SWCR_TRAP_ENABLE_MASK (SWCR_TRAP_ENABLE_INV | SWCR_TRAP_ENABLE_DZE | \ ++ SWCR_TRAP_ENABLE_OVF | SWCR_TRAP_ENABLE_UNF | \ ++ SWCR_TRAP_ENABLE_INE | SWCR_TRAP_ENABLE_DNO) ++ ++/* Denorm and Underflow flushing */ ++#define SWCR_MAP_DMZ (1UL<<12) /* Map denorm inputs to zero */ ++#define SWCR_MAP_UMZ (1UL<<13) /* Map underflowed outputs to zero */ ++ ++#define SWCR_MAP_MASK (SWCR_MAP_DMZ | SWCR_MAP_UMZ) ++ ++/* status bits coming from fpcr: */ ++#define SWCR_STATUS_INV (1UL<<17) ++#define SWCR_STATUS_DZE (1UL<<18) ++#define SWCR_STATUS_OVF (1UL<<19) ++#define SWCR_STATUS_UNF (1UL<<20) ++#define SWCR_STATUS_INE (1UL<<21) ++#define SWCR_STATUS_DNO (1UL<<22) ++ ++#define SWCR_STATUS_MASK (SWCR_STATUS_INV | SWCR_STATUS_DZE | \ ++ SWCR_STATUS_OVF | SWCR_STATUS_UNF | \ ++ SWCR_STATUS_INE | SWCR_STATUS_DNO) ++#define TARGET_GSI_IEEE_FP_CONTROL 45 ++#define TARGET_SSI_IEEE_FP_CONTROL 14 ++#endif +diff --git a/linux-user/sw64/termbits.h b/linux-user/sw64/termbits.h +new file mode 100644 +index 0000000000..37dd77120c +--- /dev/null ++++ b/linux-user/sw64/termbits.h +@@ -0,0 +1,265 @@ ++typedef unsigned char target_cc_t; ++typedef unsigned int target_speed_t; ++typedef unsigned int target_tcflag_t; ++ ++#define TARGET_NCCS 19 ++struct target_termios { ++ target_tcflag_t c_iflag; /* input mode flags */ ++ target_tcflag_t c_oflag; /* output mode flags */ ++ target_tcflag_t c_cflag; /* control mode flags */ ++ target_tcflag_t c_lflag; /* local mode flags */ ++ target_cc_t c_cc[TARGET_NCCS]; /* control characters */ ++ target_cc_t c_line; /* line discipline (== c_cc[19]) */ ++ target_speed_t c_ispeed; /* input speed */ ++ target_speed_t c_ospeed; /* output speed */ ++}; ++ ++/* c_cc characters */ ++#define TARGET_VEOF 0 ++#define TARGET_VEOL 1 ++#define TARGET_VEOL2 2 ++#define TARGET_VERASE 3 ++#define TARGET_VWERASE 4 ++#define TARGET_VKILL 5 ++#define TARGET_VREPRINT 6 ++#define TARGET_VSWTC 7 ++#define TARGET_VINTR 8 ++#define TARGET_VQUIT 9 ++#define TARGET_VSUSP 10 ++#define TARGET_VSTART 12 ++#define TARGET_VSTOP 13 ++#define TARGET_VLNEXT 14 ++#define TARGET_VDISCARD 15 ++#define TARGET_VMIN 16 ++#define TARGET_VTIME 17 ++ ++/* c_iflag bits */ ++#define TARGET_IGNBRK 0000001 ++#define TARGET_BRKINT 0000002 ++#define TARGET_IGNPAR 0000004 ++#define TARGET_PARMRK 0000010 ++#define TARGET_INPCK 0000020 ++#define TARGET_ISTRIP 0000040 ++#define TARGET_INLCR 0000100 ++#define TARGET_IGNCR 0000200 ++#define TARGET_ICRNL 0000400 ++#define TARGET_IXON 0001000 ++#define TARGET_IXOFF 0002000 ++#define TARGET_IXANY 0004000 ++#define TARGET_IUCLC 0010000 ++#define TARGET_IMAXBEL 0020000 ++#define TARGET_IUTF8 0040000 ++ ++/* c_oflag bits */ ++#define TARGET_OPOST 0000001 ++#define TARGET_ONLCR 0000002 ++#define TARGET_OLCUC 0000004 ++ ++#define TARGET_OCRNL 0000010 ++#define TARGET_ONOCR 0000020 ++#define TARGET_ONLRET 0000040 ++ ++#define TARGET_OFILL 00000100 ++#define TARGET_OFDEL 00000200 ++#define TARGET_NLDLY 00001400 ++#define TARGET_NL0 00000000 ++#define TARGET_NL1 00000400 ++#define TARGET_NL2 00001000 ++#define TARGET_NL3 00001400 ++#define TARGET_TABDLY 00006000 ++#define TARGET_TAB0 00000000 ++#define TARGET_TAB1 00002000 ++#define TARGET_TAB2 00004000 ++#define TARGET_TAB3 00006000 ++#define TARGET_CRDLY 00030000 ++#define TARGET_CR0 00000000 ++#define TARGET_CR1 00010000 ++#define TARGET_CR2 00020000 ++#define TARGET_CR3 00030000 ++#define TARGET_FFDLY 00040000 ++#define TARGET_FF0 00000000 ++#define TARGET_FF1 00040000 ++#define TARGET_BSDLY 00100000 ++#define TARGET_BS0 00000000 ++#define TARGET_BS1 00100000 ++#define TARGET_VTDLY 00200000 ++#define TARGET_VT0 00000000 ++#define TARGET_VT1 00200000 ++#define TARGET_XTABS 01000000 /* Hmm.. Linux/i386 considers this part of TABDLY.. */ ++ ++/* c_cflag bit meaning */ ++#define TARGET_CBAUD 0000037 ++#define TARGET_B0 0000000 /* hang up */ ++#define TARGET_B50 0000001 ++#define TARGET_B75 0000002 ++#define TARGET_B110 0000003 ++#define TARGET_B134 0000004 ++#define TARGET_B150 0000005 ++#define TARGET_B200 0000006 ++#define TARGET_B300 0000007 ++#define TARGET_B600 0000010 ++#define TARGET_B1200 0000011 ++#define TARGET_B1800 0000012 ++#define TARGET_B2400 0000013 ++#define TARGET_B4800 0000014 ++#define TARGET_B9600 0000015 ++#define TARGET_B19200 0000016 ++#define TARGET_B38400 0000017 ++#define TARGET_EXTA B19200 ++#define TARGET_EXTB B38400 ++#define TARGET_CBAUDEX 0000000 ++#define TARGET_B57600 00020 ++#define TARGET_B115200 00021 ++#define TARGET_B230400 00022 ++#define TARGET_B460800 00023 ++#define TARGET_B500000 00024 ++#define TARGET_B576000 00025 ++#define TARGET_B921600 00026 ++#define TARGET_B1000000 00027 ++#define TARGET_B1152000 00030 ++#define TARGET_B1500000 00031 ++#define TARGET_B2000000 00032 ++#define TARGET_B2500000 00033 ++#define TARGET_B3000000 00034 ++#define TARGET_B3500000 00035 ++#define TARGET_B4000000 00036 ++ ++#define TARGET_CSIZE 00001400 ++#define TARGET_CS5 00000000 ++#define TARGET_CS6 00000400 ++#define TARGET_CS7 00001000 ++#define TARGET_CS8 00001400 ++ ++#define TARGET_CSTOPB 00002000 ++#define TARGET_CREAD 00004000 ++#define TARGET_PARENB 00010000 ++#define TARGET_PARODD 00020000 ++#define TARGET_HUPCL 00040000 ++ ++#define TARGET_CLOCAL 00100000 ++#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ ++#define TARGET_CRTSCTS 020000000000 /* flow control */ ++ ++/* c_lflag bits */ ++#define TARGET_ISIG 0x00000080 ++#define TARGET_ICANON 0x00000100 ++#define TARGET_XCASE 0x00004000 ++#define TARGET_ECHO 0x00000008 ++#define TARGET_ECHOE 0x00000002 ++#define TARGET_ECHOK 0x00000004 ++#define TARGET_ECHONL 0x00000010 ++#define TARGET_NOFLSH 0x80000000 ++#define TARGET_TOSTOP 0x00400000 ++#define TARGET_ECHOCTL 0x00000040 ++#define TARGET_ECHOPRT 0x00000020 ++#define TARGET_ECHOKE 0x00000001 ++#define TARGET_FLUSHO 0x00800000 ++#define TARGET_PENDIN 0x20000000 ++#define TARGET_IEXTEN 0x00000400 ++ ++#define TARGET_FIOCLEX TARGET_IO('f', 1) ++#define TARGET_FIONCLEX TARGET_IO('f', 2) ++#define TARGET_FIOASYNC TARGET_IOW('f', 125, int) ++#define TARGET_FIONBIO TARGET_IOW('f', 126, int) ++#define TARGET_FIONREAD TARGET_IOR('f', 127, int) ++#define TARGET_TIOCINQ FIONREAD ++#define TARGET_FIOQSIZE TARGET_IOR('f', 128, loff_t) ++ ++#define TARGET_TIOCGETP TARGET_IOR('t', 8, struct target_sgttyb) ++#define TARGET_TIOCSETP TARGET_IOW('t', 9, struct target_sgttyb) ++#define TARGET_TIOCSETN TARGET_IOW('t', 10, struct target_sgttyb) /* TIOCSETP wo flush */ ++ ++#define TARGET_TIOCSETC TARGET_IOW('t', 17, struct target_tchars) ++#define TARGET_TIOCGETC TARGET_IOR('t', 18, struct target_tchars) ++#define TARGET_TCGETS TARGET_IOR('t', 19, struct target_termios) ++#define TARGET_TCSETS TARGET_IOW('t', 20, struct target_termios) ++#define TARGET_TCSETSW TARGET_IOW('t', 21, struct target_termios) ++#define TARGET_TCSETSF TARGET_IOW('t', 22, struct target_termios) ++ ++#define TARGET_TCGETA TARGET_IOR('t', 23, struct target_termio) ++#define TARGET_TCSETA TARGET_IOW('t', 24, struct target_termio) ++#define TARGET_TCSETAW TARGET_IOW('t', 25, struct target_termio) ++#define TARGET_TCSETAF TARGET_IOW('t', 28, struct target_termio) ++ ++#define TARGET_TCSBRK TARGET_IO('t', 29) ++#define TARGET_TCXONC TARGET_IO('t', 30) ++#define TARGET_TCFLSH TARGET_IO('t', 31) ++ ++#define TARGET_TIOCSWINSZ TARGET_IOW('t', 103, struct target_winsize) ++#define TARGET_TIOCGWINSZ TARGET_IOR('t', 104, struct target_winsize) ++#define TARGET_TIOCSTART TARGET_IO('t', 110) /* start output, like ^Q */ ++#define TARGET_TIOCSTOP TARGET_IO('t', 111) /* stop output, like ^S */ ++#define TARGET_TIOCOUTQ TARGET_IOR('t', 115, int) /* output queue size */ ++ ++#define TARGET_TIOCGLTC TARGET_IOR('t', 116, struct target_ltchars) ++#define TARGET_TIOCSLTC TARGET_IOW('t', 117, struct target_ltchars) ++#define TARGET_TIOCSPGRP TARGET_IOW('t', 118, int) ++#define TARGET_TIOCGPGRP TARGET_IOR('t', 119, int) ++ ++#define TARGET_TIOCEXCL 0x540C ++#define TARGET_TIOCNXCL 0x540D ++#define TARGET_TIOCSCTTY 0x540E ++ ++#define TARGET_TIOCSTI 0x5412 ++#define TARGET_TIOCMGET 0x5415 ++#define TARGET_TIOCMBIS 0x5416 ++#define TARGET_TIOCMBIC 0x5417 ++#define TARGET_TIOCMSET 0x5418 ++# define TARGET_TIOCM_LE 0x001 ++# define TARGET_TIOCM_DTR 0x002 ++# define TARGET_TIOCM_RTS 0x004 ++# define TARGET_TIOCM_ST 0x008 ++# define TARGET_TIOCM_SR 0x010 ++# define TARGET_TIOCM_CTS 0x020 ++# define TARGET_TIOCM_CAR 0x040 ++# define TARGET_TIOCM_RNG 0x080 ++# define TARGET_TIOCM_DSR 0x100 ++# define TARGET_TIOCM_CD TIOCM_CAR ++# define TARGET_TIOCM_RI TIOCM_RNG ++# define TARGET_TIOCM_OUT1 0x2000 ++# define TARGET_TIOCM_OUT2 0x4000 ++# define TARGET_TIOCM_LOOP 0x8000 ++ ++#define TARGET_TIOCGSOFTCAR 0x5419 ++#define TARGET_TIOCSSOFTCAR 0x541A ++#define TARGET_TIOCLINUX 0x541C ++#define TARGET_TIOCCONS 0x541D ++#define TARGET_TIOCGSERIAL 0x541E ++#define TARGET_TIOCSSERIAL 0x541F ++#define TARGET_TIOCPKT 0x5420 ++# define TARGET_TIOCPKT_DATA 0 ++# define TARGET_TIOCPKT_FLUSHREAD 1 ++# define TARGET_TIOCPKT_FLUSHWRITE 2 ++# define TARGET_TIOCPKT_STOP 4 ++# define TARGET_TIOCPKT_START 8 ++# define TARGET_TIOCPKT_NOSTOP 16 ++# define TARGET_TIOCPKT_DOSTOP 32 ++ ++ ++#define TARGET_TIOCNOTTY 0x5422 ++#define TARGET_TIOCSETD 0x5423 ++#define TARGET_TIOCGETD 0x5424 ++#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ ++#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */ ++#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */ ++#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */ ++#define TARGET_TIOCGPTN TARGET_IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ ++#define TARGET_TIOCSPTLCK TARGET_IOW('T', 0x31, int) /* Lock/unlock Pty */ ++#define TARGET_TIOCGPTPEER TARGET_IO('T', 0x41) /* Safely open the slave */ ++ ++#define TARGET_TIOCSERCONFIG 0x5453 ++#define TARGET_TIOCSERGWILD 0x5454 ++#define TARGET_TIOCSERSWILD 0x5455 ++#define TARGET_TIOCGLCKTRMIOS 0x5456 ++#define TARGET_TIOCSLCKTRMIOS 0x5457 ++#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */ ++#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */ ++ /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ ++# define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */ ++#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */ ++#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ ++ ++#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ ++#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ ++#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ ++#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ +diff --git a/meson.build b/meson.build +index 96de1a6ef9..d0bbceffe1 100644 +--- a/meson.build ++++ b/meson.build +@@ -56,7 +56,7 @@ python = import('python').find_installation() + + supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux'] + supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv', 'x86', 'x86_64', +- 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64'] ++ 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64', 'sw64'] + + cpu = host_machine.cpu_family() + +@@ -65,6 +65,10 @@ if cpu in ['riscv32', 'riscv64'] + cpu = 'riscv' + endif + ++if cpu == 'sw_64' ++ cpu = 'sw64' ++endif ++ + targetos = host_machine.system() + + if cpu in ['x86', 'x86_64'] +@@ -77,6 +81,8 @@ elif cpu in ['ppc', 'ppc64'] + kvm_targets = ['ppc-softmmu', 'ppc64-softmmu'] + elif cpu in ['mips', 'mips64'] + kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu'] ++elif cpu == 'sw64' ++ kvm_targets = ['sw64-softmmu'] + else + kvm_targets = [] + endif +@@ -359,6 +365,8 @@ if not get_option('tcg').disabled() + tcg_arch = 'i386' + elif config_host['ARCH'] == 'ppc64' + tcg_arch = 'ppc' ++ elif config_host['ARCH'] in ['sw64'] ++ tcg_arch = 'sw64' + endif + add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch, + language: ['c', 'cpp', 'objc']) +@@ -1814,6 +1822,7 @@ disassemblers = { + 'sh4' : ['CONFIG_SH4_DIS'], + 'sparc' : ['CONFIG_SPARC_DIS'], + 'xtensa' : ['CONFIG_XTENSA_DIS'], ++ 'sw64' : ['CONFIG_SW64_DIS'], + } + if link_language == 'cpp' + disassemblers += { +@@ -2466,6 +2475,7 @@ if have_system + 'hw/sparc', + 'hw/sparc64', + 'hw/ssi', ++ 'hw/sw64', + 'hw/timer', + 'hw/tpm', + 'hw/usb', +diff --git a/pc-bios/meson.build b/pc-bios/meson.build +index b40ff3f2bd..05e9065ad6 100644 +--- a/pc-bios/meson.build ++++ b/pc-bios/meson.build +@@ -38,6 +38,9 @@ blobs = files( + 'vgabios-ramfb.bin', + 'vgabios-bochs-display.bin', + 'vgabios-ati.bin', ++ 'uefi-bios-sw', ++ 'core3-reset', ++ 'core3-hmcode', + 'openbios-sparc32', + 'openbios-sparc64', + 'openbios-ppc', +diff --git a/qapi/machine.json b/qapi/machine.json +index 6822cafe2e..6ed8488255 100644 +--- a/qapi/machine.json ++++ b/qapi/machine.json +@@ -29,7 +29,7 @@ + # Since: 3.0 + ## + { 'enum' : 'SysEmuTarget', +- 'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'cris', 'hppa', 'i386', ++ 'data' : [ 'aarch64', 'alpha', 'sw64', 'arm', 'avr', 'cris', 'hppa', 'i386', + 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64', + 'mips64el', 'mipsel', 'nios2', 'or1k', 'ppc', + 'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4', +diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c +index 05e1d88d99..142352b24e 100644 +--- a/softmmu/qdev-monitor.c ++++ b/softmmu/qdev-monitor.c +@@ -61,7 +61,8 @@ typedef struct QDevAlias + QEMU_ARCH_HPPA | QEMU_ARCH_I386 | \ + QEMU_ARCH_MIPS | QEMU_ARCH_PPC | \ + QEMU_ARCH_RISCV | QEMU_ARCH_SH4 | \ +- QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA) ++ QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA | \ ++ QEMU_ARCH_SW64) + #define QEMU_ARCH_VIRTIO_CCW (QEMU_ARCH_S390X) + #define QEMU_ARCH_VIRTIO_MMIO (QEMU_ARCH_M68K) + +diff --git a/target/Kconfig b/target/Kconfig +index ae7f24fc66..a8d6cb1e97 100644 +--- a/target/Kconfig ++++ b/target/Kconfig +@@ -17,3 +17,4 @@ source sh4/Kconfig + source sparc/Kconfig + source tricore/Kconfig + source xtensa/Kconfig ++source sw64/Kconfig +diff --git a/target/meson.build b/target/meson.build +index 2f6940255e..ec6bc97331 100644 +--- a/target/meson.build ++++ b/target/meson.build +@@ -16,5 +16,6 @@ subdir('rx') + subdir('s390x') + subdir('sh4') + subdir('sparc') ++subdir('sw64') + subdir('tricore') + subdir('xtensa') +diff --git a/target/sw64/Kconfig b/target/sw64/Kconfig +new file mode 100644 +index 0000000000..ad50b9677e +--- /dev/null ++++ b/target/sw64/Kconfig +@@ -0,0 +1,2 @@ ++config SW64 ++ bool +diff --git a/target/sw64/Makefile.objs b/target/sw64/Makefile.objs +new file mode 100644 +index 0000000000..1e549d141c +--- /dev/null ++++ b/target/sw64/Makefile.objs +@@ -0,0 +1,4 @@ ++obj-$(CONFIG_SOFTMMU) += machine.o ++obj-y += cpu.o translate.o profile.o helper.o ++obj-y += int_helper.o float_helper.o simd_helper.o helper.o exception.o ++obj-$(CONFIG_KVM) += kvm.o +diff --git a/target/sw64/cpu-param.h b/target/sw64/cpu-param.h +new file mode 100644 +index 0000000000..978a3cd572 +--- /dev/null ++++ b/target/sw64/cpu-param.h +@@ -0,0 +1,24 @@ ++/* ++ * SW64 cpu parameters for qemu. ++ * ++ * Copyright (c) 2018 Lin Hainan ++ */ ++ ++#ifndef SW64_CPU_PARAM_H ++#define SW64_CPU_PARAM_H 1 ++ ++#define TARGET_LONG_BITS 64 /* if use th-1 ,TARGET_PAGE_BITS is 12 */ ++#define TARGET_PAGE_BITS 13 ++ ++#ifdef CONFIG_USER_ONLY ++#define TARGET_VIRT_ADDR_SPACE_BITS 64 ++#else ++#define TARGET_PHYS_ADDR_SPACE_BITS 48 ++#define TARGET_VIRT_ADDR_SPACE_BITS 64 ++#endif ++ ++#ifndef CONFIG_USER_ONLY ++#define NB_MMU_MODES 4 ++#endif ++ ++#endif +diff --git a/target/sw64/cpu-qom.h b/target/sw64/cpu-qom.h +new file mode 100644 +index 0000000000..b093c2bec8 +--- /dev/null ++++ b/target/sw64/cpu-qom.h +@@ -0,0 +1,47 @@ ++/* ++ * QEMU SW64 CPU ++ * ++ * Copyright (c) 2018 Lin Hainan ++ * ++ * 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. ++ * ++ */ ++#ifndef QEMU_SW64_CPU_QOM ++#define QEMU_SW64_CPU_QOM ++ ++#include "hw/core/cpu.h" ++ ++#define TYPE_SW64_CPU "sw64-cpu" ++ ++#define SW64_CPU_CLASS(kclass) \ ++ OBJECT_CLASS_CHECK(SW64CPUClass, (kclass), TYPE_SW64_CPU) ++#define SW64_CPU(obj) \ ++ OBJECT_CHECK(SW64CPU, (obj), TYPE_SW64_CPU) ++#define SW64_CPU_GET_CLASS(obj) \ ++ OBJECT_GET_CLASS(SW64CPUClass, (obj), TYPE_SW64_CPU) ++ ++/** ++ * SW64CPUClass: ++ * @parent_realize: The parent class' realize handler. ++ * @parent_reset: The parent class' reset handler. ++ * ++ * An SW64 CPU model. ++ */ ++typedef struct SW64CPUClass { ++ /* private */ ++ CPUClass parent_class; ++ /* public */ ++ DeviceRealize parent_realize; ++ DeviceReset parent_reset; ++} SW64CPUClass; ++ ++typedef struct SW64CPU SW64CPU; ++#endif +diff --git a/target/sw64/cpu.c b/target/sw64/cpu.c +new file mode 100644 +index 0000000000..89c21850e1 +--- /dev/null ++++ b/target/sw64/cpu.c +@@ -0,0 +1,457 @@ ++/* ++ * QEMU SW64 CPU ++ * ++ * Copyright (c) 2018 Lin Hainan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ */ ++ ++#include "qemu/osdep.h" ++#include "qapi/error.h" ++#include "qemu/qemu-print.h" ++#include "cpu.h" ++#include "exec/exec-all.h" ++#include "sysemu/kvm.h" ++#include "disas/dis-asm.h" ++#include "kvm_sw64.h" ++#include "sysemu/reset.h" ++#include "hw/qdev-properties.h" ++ ++ ++static void sw64_cpu_set_pc(CPUState *cs, vaddr value) ++{ ++ SW64CPU *cpu = SW64_CPU(cs); ++ ++ cpu->env.pc = value; ++} ++ ++static void sw64_cpu_dump_state(CPUState *cs, FILE *f, int flags) ++{ ++#ifndef CONFIG_KVM ++ SW64CPU *cpu = SW64_CPU(cs); ++ CPUSW64State *env = &cpu->env; ++ int i; ++ ++ static const char ireg_names[31][4] = { ++ "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "s0", "s1", ++ "s2", "s3", "s4", "s5", "fp", "a0", "a1", "a2", "a3", "a4", "a5", ++ "t8", "t9", "t10", "t11", "ra", "t12", "at", "gp", "sp"}; ++ static const char freg_names[128][4] = { ++ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", ++ "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", ++ "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", ++ "f30", "f31", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", ++ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", ++ "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", ++ "f28", "f29", "f30", "f31", "f0", "f1", "f2", "f3", "f4", "f5", ++ "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", ++ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", ++ "f26", "f27", "f28", "f29", "f30", "f31", "f0", "f1", "f2", "f3", ++ "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", ++ "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", ++ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"}; ++ qemu_fprintf(f, "PC=%016" PRIx64 " SP=%016" PRIx64 "\n", env->pc, ++ env->ir[IDX_SP]); ++ for (i = 0; i < 31; i++) { ++ qemu_fprintf(f, "%s=%016" PRIx64, ireg_names[i], env->ir[i]); ++ if ((i % 4) == 3) { ++ qemu_fprintf(f, "\n"); ++ } else { ++ qemu_fprintf(f, " "); ++ } ++ } ++ qemu_fprintf(f, "\n"); ++#ifndef CONFIG_USER_ONLY ++ static const char sreg_names[10][4] = {"p1", "p2", "p4", "p5", "p6", ++ "p7", "p20", "p21", "p22", "p23"}; ++ for (i = 0; i < 10; i++) { ++ qemu_fprintf(f, "%s=%016" PRIx64, sreg_names[i], env->sr[i]); ++ if ((i % 4) == 3) { ++ qemu_fprintf(f, "\n"); ++ } else { ++ qemu_fprintf(f, " "); ++ } ++ } ++ qemu_fprintf(f, "\n"); ++#endif ++ for (i = 0; i < 32; i++) { ++ qemu_fprintf(f, "%s=%016" PRIx64, freg_names[i + 96], env->fr[i + 96]); ++ qemu_fprintf(f, " %016" PRIx64, env->fr[i + 64]); ++ qemu_fprintf(f, " %016" PRIx64, env->fr[i + 32]); ++ qemu_fprintf(f, " %016" PRIx64, env->fr[i]); ++ qemu_fprintf(f, "\n"); ++ } ++ qemu_fprintf(f, "\n"); ++#endif ++} ++ ++#ifndef CONFIG_USER_ONLY ++static void sw64_machine_cpu_reset(void *opaque) ++{ ++ SW64CPU *cpu = opaque; ++ ++ cpu_reset(CPU(cpu)); ++} ++#endif ++ ++static void sw64_cpu_realizefn(DeviceState *dev, Error **errp) ++{ ++ CPUState *cs = CPU(dev); ++ SW64CPUClass *scc = SW64_CPU_GET_CLASS(dev); ++ Error *local_err = NULL; ++ ++ cpu_exec_realizefn(cs, &local_err); ++ if (local_err != NULL) { ++ error_propagate(errp, local_err); ++ return; ++ } ++#ifndef CONFIG_USER_ONLY ++ qemu_register_reset(sw64_machine_cpu_reset, cs); ++#endif ++ ++ qemu_init_vcpu(cs); ++ ++ scc->parent_realize(dev, errp); ++} ++ ++static void sw64_cpu_disas_set_info(CPUState *cs, disassemble_info *info) ++{ ++ info->mach = bfd_mach_sw_64_core3; ++ info->print_insn = print_insn_sw_64; ++} ++ ++#include "fpu/softfloat.h" ++ ++static void core3_init(Object *obj) ++{ ++ CPUState *cs = CPU(obj); ++ CPUSW64State *env = cs->env_ptr; ++#ifdef CONFIG_USER_ONLY ++ env->fpcr = 0x680e800000000000; ++ parallel_cpus = true; ++#endif ++ set_feature(env, SW64_FEATURE_CORE3); ++} ++ ++static ObjectClass *sw64_cpu_class_by_name(const char *cpu_model) ++{ ++ ObjectClass *oc; ++ char *typename; ++ char **cpuname; ++ ++ cpuname = g_strsplit(cpu_model, ",", 1); ++ typename = g_strdup_printf(SW64_CPU_TYPE_NAME("%s"), cpu_model); ++ ++ oc = object_class_by_name(typename); ++ g_strfreev(cpuname); ++ g_free(typename); ++ ++ if (oc && object_class_dynamic_cast(oc, TYPE_SW64_CPU) && ++ !object_class_is_abstract(oc)) { ++ return oc; ++ } ++ return NULL; ++} ++ ++bool sw64_cpu_has_work(CPUState *cs) ++{ ++ /* If CPU has gotten into asleep(halt), then it may be ++ * wake up by hard interrupt, timer, ii, mail or mchk. ++ */ ++ return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER | ++ CPU_INTERRUPT_IIMAIL | CPU_INTERRUPT_MCHK); ++} ++ ++static void sw64_cpu_initfn(Object *obj) ++{ ++ CPUState *cs = CPU(obj); ++ SW64CPU *cpu = SW64_CPU(obj); ++ CPUSW64State *env = &cpu->env; ++ ++ cpu_set_cpustate_pointers(cpu); ++ ++ cs->env_ptr = env; ++#ifndef CONFIG_USER_ONLY ++ env->flags = ENV_FLAG_HM_MODE; ++#else ++ env->flags = ENV_FLAG_PS_USER; ++#endif ++ tlb_flush(cs); ++} ++ ++#ifndef CONFIG_USER_ONLY ++static void sw64_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, ++ unsigned size, MMUAccessType access_type, ++ int mmu_idx, MemTxAttrs attrs, ++ MemTxResult response, uintptr_t retaddr) ++{ ++#ifdef DEBUG_TRANS ++ if (retaddr) { ++ cpu_restore_state(cs, retaddr, true); ++ } ++ fprintf(stderr, "PC = %lx, Wrong IO addr. Hwaddr = %lx, vaddr = %lx, access_type = %d\n", ++ env->pc, physaddr, addr, access_type); ++#endif ++} ++#endif ++ ++#define a0(func) (((func & 0xFF) >> 6) & 0x1) ++#define a1(func) ((((func & 0xFF) >> 6) & 0x2) >> 1) ++ ++#define t(func) ((a0(func) ^ a1(func)) & 0x1) ++#define b0(func) (t(func) | a0(func)) ++#define b1(func) ((~t(func) & 1) | a1(func)) ++ ++#define START_SYS_CALL_ADDR(func) \ ++ (b1(func) << 14) | (b0(func) << 13) | ((func & 0x3F) << 7) ++ ++static void sw64_cpu_do_interrupt(CPUState *cs) ++{ ++ int i = cs->exception_index; ++ ++ cs->exception_index = -1; ++#if !defined(CONFIG_USER_ONLY) ++ SW64CPU *cpu = SW64_CPU(cs); ++ CPUSW64State *env = &cpu->env; ++ switch (i) { ++ case EXCP_OPCDEC: ++ cpu_abort(cs, "ILLEGAL INSN"); ++ break; ++ case EXCP_CALL_SYS: ++ i = START_SYS_CALL_ADDR(env->error_code); ++ if (i <= 0x3F) { ++ i += 0x4000; ++ } else if (i >= 0x40 && i <= 0x7F) { ++ i += 0x2000; ++ } else if (i >= 0x80 && i <= 0x8F) { ++ i += 0x6000; ++ } ++ break; ++ case EXCP_ARITH: ++ env->error_code = -1; ++ env->csr[EXC_PC] = env->pc - 4; ++ env->csr[EXC_SUM] = 1; ++ i = 0xB80; ++ break; ++ case EXCP_UNALIGN: ++ i = 0xB00; ++ env->csr[EXC_PC] = env->pc - 4; ++ break; ++ case EXCP_CLK_INTERRUPT: ++ case EXCP_DEV_INTERRUPT: ++ i = 0xE80; ++ break; ++ case EXCP_MMFAULT: ++ i = 0x980; ++ env->csr[EXC_PC] = env->pc; ++ break; ++ case EXCP_IIMAIL: ++ env->csr[EXC_PC] = env->pc; ++ i = 0xE00; ++ break; ++ default: ++ break; ++ } ++ env->pc = env->hm_entry + i; ++ env->flags = ENV_FLAG_HM_MODE; ++#else ++ switch (i) { ++ case EXCP_OPCDEC: ++ cpu_abort(cs, "ILLEGAL INSN"); ++ break; ++ case EXCP_CALL_SYS: ++ default: ++ break; ++ } ++#endif ++} ++ ++#ifndef CONFIG_USER_ONLY ++static bool sw64_cpu_exec_interrupt(CPUState *cs, int interrupt_request) ++{ ++ SW64CPU *cpu = SW64_CPU(cs); ++ CPUSW64State *env = &cpu->env; ++ int idx = -1; ++ /* We never take interrupts while in Hardmode. */ ++ if (env->flags & ENV_FLAG_HM_MODE) ++ return false; ++ ++ if (interrupt_request & CPU_INTERRUPT_IIMAIL) { ++ idx = EXCP_IIMAIL; ++ env->csr[INT_STAT] |= 1UL << 6; ++ if ((env->csr[IER] & env->csr[INT_STAT]) == 0) ++ return false; ++ cs->interrupt_request &= ~CPU_INTERRUPT_IIMAIL; ++ goto done; ++ } ++ ++ if (interrupt_request & CPU_INTERRUPT_TIMER) { ++ idx = EXCP_CLK_INTERRUPT; ++ env->csr[INT_STAT] |= 1UL << 4; ++ if ((env->csr[IER] & env->csr[INT_STAT]) == 0) ++ return false; ++ cs->interrupt_request &= ~CPU_INTERRUPT_TIMER; ++ goto done; ++ } ++ ++ if (interrupt_request & CPU_INTERRUPT_HARD) { ++ idx = EXCP_DEV_INTERRUPT; ++ env->csr[INT_STAT] |= 1UL << 12; ++ if ((env->csr[IER] & env->csr[INT_STAT]) == 0) ++ return false; ++ cs->interrupt_request &= ~CPU_INTERRUPT_HARD; ++ goto done; ++ } ++ ++ if (interrupt_request & CPU_INTERRUPT_PCIE) { ++ idx = EXCP_DEV_INTERRUPT; ++ env->csr[INT_STAT] |= 1UL << 1; ++ env->csr[INT_PCI_INT] = 0x10; ++ if ((env->csr[IER] & env->csr[INT_STAT]) == 0) ++ return false; ++ cs->interrupt_request &= ~CPU_INTERRUPT_PCIE; ++ goto done; ++ } ++ ++done: ++ if (idx >= 0) { ++ cs->exception_index = idx; ++ env->error_code = 0; ++ env->csr[EXC_PC] = env->pc; ++ sw64_cpu_do_interrupt(cs); ++ return true; ++ } ++ return false; ++} ++#endif ++ ++static void sw64_cpu_reset(DeviceState *dev) ++{ ++ CPUState *s = CPU(dev); ++ SW64CPU *cpu = SW64_CPU(s); ++ SW64CPUClass *scc = SW64_CPU_GET_CLASS(cpu); ++ ++ scc->parent_reset(dev); ++ ++#ifndef CONFIG_USER_ONLY ++ if (kvm_enabled()) { ++ kvm_sw64_reset_vcpu(cpu); ++ } ++#endif ++} ++ ++static Property sw64_cpu_properties[] = { ++#ifdef CONFIG_USER_ONLY ++ /* apic_id = 0 by default for *-user, see commit 9886e834 */ ++ DEFINE_PROP_UINT32("cid", SW64CPU, cid, 0), ++#else ++ DEFINE_PROP_UINT32("cid", SW64CPU, cid, 0xFFFFFFFF), ++#endif ++ DEFINE_PROP_END_OF_LIST() ++}; ++ ++#ifndef CONFIG_USER_ONLY ++#include "hw/core/sysemu-cpu-ops.h" ++ ++static const struct SysemuCPUOps sw64_sysemu_ops = { ++ .get_phys_page_debug = sw64_cpu_get_phys_page_debug, ++}; ++#endif ++ ++#include "hw/core/tcg-cpu-ops.h" ++ ++static const struct TCGCPUOps sw64_tcg_ops = { ++#ifdef CONFIG_TCG ++ .initialize = sw64_translate_init, ++ .tlb_fill = sw64_cpu_tlb_fill, ++#endif /* CONFIG_TCG */ ++ ++#if !defined(CONFIG_USER_ONLY) ++ .do_unaligned_access = sw64_cpu_do_unaligned_access, ++ .cpu_exec_interrupt = sw64_cpu_exec_interrupt, ++ .do_transaction_failed = sw64_cpu_do_transaction_failed, ++#endif /* !CONFIG_USER_ONLY */ ++ .do_interrupt = sw64_cpu_do_interrupt, ++}; ++ ++static void sw64_cpu_class_init(ObjectClass *oc, void *data) ++{ ++ DeviceClass *dc = DEVICE_CLASS(oc); ++ CPUClass *cc = CPU_CLASS(oc); ++ SW64CPUClass *scc = SW64_CPU_CLASS(oc); ++ ++ device_class_set_parent_realize(dc, sw64_cpu_realizefn, ++ &scc->parent_realize); ++ device_class_set_parent_reset(dc, sw64_cpu_reset, &scc->parent_reset); ++ device_class_set_props(dc, sw64_cpu_properties); ++ ++ cc->class_by_name = sw64_cpu_class_by_name; ++ dc->vmsd = &vmstate_sw64_cpu; ++ cc->has_work = sw64_cpu_has_work; ++ cc->set_pc = sw64_cpu_set_pc; ++ cc->disas_set_info = sw64_cpu_disas_set_info; ++ cc->dump_state = sw64_cpu_dump_state; ++ cc->tcg_ops = &sw64_tcg_ops; ++#ifndef CONFIG_USER_ONLY ++ cc->sysemu_ops = &sw64_sysemu_ops; ++#endif ++} ++ ++static const SW64CPUInfo sw64_cpus[] = ++{ ++ { ++ .name = "core3", ++ .initfn = core3_init, ++ }, ++ { ++ .name = NULL ++ }, ++}; ++ ++static void cpu_register(const SW64CPUInfo *info) ++{ ++ TypeInfo type_info = { ++ .parent = TYPE_SW64_CPU, ++ .instance_size = sizeof(SW64CPU), ++ .instance_init = info->initfn, ++ .class_size = sizeof(SW64CPUClass), ++ .class_init = info->class_init, ++ }; ++ ++ type_info.name = g_strdup_printf("%s-" TYPE_SW64_CPU, info->name); ++ type_register(&type_info); ++ g_free((void*)type_info.name); ++} ++ ++static const TypeInfo sw64_cpu_type_info = { ++ .name = TYPE_SW64_CPU, ++ .parent = TYPE_CPU, ++ .instance_size = sizeof(SW64CPU), ++ .instance_init = sw64_cpu_initfn, ++ .abstract = true, ++ .class_size = sizeof(SW64CPUClass), ++ .class_init = sw64_cpu_class_init, ++}; ++ ++static void sw64_cpu_register_types(void) ++{ ++ const SW64CPUInfo *info = sw64_cpus; ++ ++ type_register_static(&sw64_cpu_type_info); ++ ++ while (info->name) { ++ cpu_register(info); ++ info++; ++ } ++} ++ ++type_init(sw64_cpu_register_types) +diff --git a/target/sw64/cpu.h b/target/sw64/cpu.h +new file mode 100644 +index 0000000000..5a490e2b4a +--- /dev/null ++++ b/target/sw64/cpu.h +@@ -0,0 +1,406 @@ ++/* ++ * SW64 emulation cpu definitions for qemu. ++ * ++ * Copyright (c) 2018 Lin Hainan ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ */ ++#ifndef SW64_CPU_H ++#define SW64_CPU_H ++ ++#include "cpu-qom.h" ++#include "fpu/softfloat.h" ++#include "profile.h" ++ ++/* QEMU addressing/paging config */ ++#define TARGET_PAGE_BITS 13 ++#define TARGET_LONG_BITS 64 ++#define TARGET_LEVEL_BITS 10 ++//#define ALIGNED_ONLY ++ ++#include "exec/cpu-defs.h" ++ ++/* FIXME: LOCKFIX */ ++#define SW64_FIXLOCK 1 ++ ++/* swcore processors have a weak memory model */ ++#define TCG_GUEST_DEFAULT_MO (0) ++ ++#define SOFTMMU 1 ++ ++#ifndef CONFIG_USER_ONLY ++#define MMU_MODE0_SUFFIX _phys ++#define MMU_MODE3_SUFFIX _user ++#define MMU_MODE2_SUFFIX _kernel ++#endif ++#define MMU_PHYS_IDX 0 ++#define MMU_KERNEL_IDX 2 ++#define MMU_USER_IDX 3 ++ ++/* FIXME:Bits 4 and 5 are the mmu mode. The VMS hmcode uses all 4 modes; ++ The Unix hmcode only uses bit 4. */ ++#define PS_USER_MODE 8u ++ ++#define ENV_FLAG_HM_SHIFT 0 ++#define ENV_FLAG_PS_SHIFT 8 ++#define ENV_FLAG_FEN_SHIFT 24 ++ ++#define ENV_FLAG_HM_MODE (1u << ENV_FLAG_HM_SHIFT) ++#define ENV_FLAG_PS_USER (PS_USER_MODE << ENV_FLAG_PS_SHIFT) ++#define ENV_FLAG_FEN (1u << ENV_FLAG_FEN_SHIFT) ++ ++#define MCU_CLOCK 25000000 ++ ++typedef struct CPUSW64State CPUSW64State; ++typedef CPUSW64State CPUArchState; ++typedef SW64CPU ArchCPU; ++ ++struct CPUSW64State { ++ uint64_t ir[32]; ++ uint64_t fr[128]; ++ uint64_t pc; ++ bool is_slave; ++ ++ uint64_t csr[0x100]; ++ uint64_t fpcr; ++ uint64_t fpcr_exc_enable; ++ uint8_t fpcr_round_mode; ++ uint8_t fpcr_flush_to_zero; ++ ++ float_status fp_status; ++ ++ uint64_t hm_entry; ++ ++#if !defined(CONFIG_USER_ONLY) ++ uint64_t sr[10]; /* shadow regs 1,2,4-7,20-23 */ ++#endif ++ ++ uint32_t flags; ++ uint64_t error_code; ++ uint64_t unique; ++ uint64_t lock_addr; ++ uint64_t lock_valid; ++ uint64_t lock_flag; ++ uint64_t lock_success; ++#ifdef SW64_FIXLOCK ++ uint64_t lock_value; ++#endif ++ ++ uint64_t trap_arg0; ++ uint64_t trap_arg1; ++ uint64_t trap_arg2; ++ ++ uint64_t features; ++ uint64_t insn_count[537]; ++ ++ /* reserve for slave */ ++ uint64_t ca[4]; ++ uint64_t scala_gpr[64]; ++ uint64_t vec_gpr[224]; ++ uint64_t fpcr_base; ++ uint64_t fpcr_ext; ++ uint64_t pendding_flag; ++ uint64_t pendding_status; ++ uint64_t synr_pendding_status; ++ uint64_t sync_pendding_status; ++ uint8_t vlenma_idxa; ++ uint8_t stable; ++}; ++#define SW64_FEATURE_CORE3 0x2 ++ ++static inline void set_feature(CPUSW64State *env, int feature) ++{ ++ env->features |= feature; ++} ++ ++/** ++ * SW64CPU: ++ * @env: #CPUSW64State ++ * ++ * An SW64 CPU ++ */ ++struct SW64CPU { ++ /*< private >*/ ++ CPUState parent_obj; ++ /*< public >*/ ++ CPUNegativeOffsetState neg; ++ CPUSW64State env; ++ ++ uint64_t k_regs[158]; ++ uint64_t k_vcb[36]; ++ QEMUTimer *alarm_timer; ++ target_ulong irq; ++ uint32_t cid; ++}; ++ ++enum { ++ IDX_V0 = 0, ++ IDX_T0 = 1, ++ IDX_T1 = 2, ++ IDX_T2 = 3, ++ IDX_T3 = 4, ++ IDX_T4 = 5, ++ IDX_T5 = 6, ++ IDX_T6 = 7, ++ IDX_T7 = 8, ++ IDX_S0 = 9, ++ IDX_S1 = 10, ++ IDX_S2 = 11, ++ IDX_S3 = 12, ++ IDX_S4 = 13, ++ IDX_S5 = 14, ++ IDX_S6 = 15, ++ IDX_FP = IDX_S6, ++ IDX_A0 = 16, ++ IDX_A1 = 17, ++ IDX_A2 = 18, ++ IDX_A3 = 19, ++ IDX_A4 = 20, ++ IDX_A5 = 21, ++ IDX_T8 = 22, ++ IDX_T9 = 23, ++ IDX_T10 = 24, ++ IDX_T11 = 25, ++ IDX_RA = 26, ++ IDX_T12 = 27, ++ IDX_PV = IDX_T12, ++ IDX_AT = 28, ++ IDX_GP = 29, ++ IDX_SP = 30, ++ IDX_ZERO = 31, ++}; ++ ++enum { ++ MM_K_TNV = 0x0, ++ MM_K_ACV = 0x1, ++ MM_K_FOR = 0x2, ++ MM_K_FOE = 0x3, ++ MM_K_FOW = 0x4 ++}; ++ ++enum { ++ PTE_VALID = 0x0001, ++ PTE_FOR = 0x0002, /* used for page protection (fault on read) */ ++ PTE_FOW = 0x0004, /* used for page protection (fault on write) */ ++ PTE_FOE = 0x0008, ++ PTE_KS = 0x0010, ++ PTE_PSE = 0x0040, ++ PTE_GH = 0x0060, ++ PTE_HRE = 0x0100, ++ PTE_VRE = 0x0200, ++ PTE_KRE = 0x0400, ++ PTE_URE = 0x0800, ++ PTE_HWE = 0x1000, ++ PTE_VWE = 0x2000, ++ PTE_KWE = 0x4000, ++ PTE_UWE = 0x8000 ++}; ++ ++static inline int cpu_mmu_index(CPUSW64State *env, bool ifetch) ++{ ++ int ret = env->flags & ENV_FLAG_PS_USER ? MMU_USER_IDX : MMU_KERNEL_IDX; ++ if (env->flags & ENV_FLAG_HM_MODE) { ++ ret = MMU_PHYS_IDX; ++ } ++ return ret; ++} ++ ++static inline SW64CPU *sw64_env_get_cpu(CPUSW64State *env) ++{ ++ return container_of(env, SW64CPU, env); ++} ++ ++#define ENV_GET_CPU(e) CPU(sw64_env_get_cpu(e)) ++#define ENV_OFFSET offsetof(SW64CPU, env) ++ ++#define cpu_init(cpu_model) cpu_generic_init(TYPE_SW64_CPU, cpu_model) ++ ++#define SW64_CPU_TYPE_SUFFIX "-" TYPE_SW64_CPU ++#define SW64_CPU_TYPE_NAME(name) (name SW64_CPU_TYPE_SUFFIX) ++int cpu_sw64_signal_handler(int host_signum, void *pinfo, void *puc); ++bool sw64_cpu_tlb_fill(CPUState *cs, vaddr address, int size, ++ MMUAccessType access_type, int mmu_idx, ++ bool probe, uintptr_t retaddr); ++uint64_t sw64_ldl_phys(CPUState *cs, hwaddr addr); ++hwaddr sw64_cpu_get_phys_page_debug(CPUState *cs, vaddr addr); ++void sw64_stl_phys(CPUState *cs, hwaddr addr, uint64_t val); ++uint64_t sw64_ldw_phys(CPUState *cs, hwaddr addr); ++void sw64_stw_phys(CPUState *cs, hwaddr addr, uint64_t val); ++uint64_t cpu_sw64_load_fpcr(CPUSW64State *env); ++void cpu_sw64_store_fpcr(CPUSW64State *env, uint64_t val); ++void sw64_cpu_do_unaligned_access(CPUState *cs, vaddr addr, ++ MMUAccessType access_type, int mmu_idx, ++ uintptr_t retaddr) QEMU_NORETURN; ++bool sw64_cpu_has_work(CPUState *cs); ++extern struct VMStateDescription vmstate_sw64_cpu; ++ ++/* SW64-specific interrupt pending bits */ ++#define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_EXT_0 ++#define CPU_INTERRUPT_IIMAIL CPU_INTERRUPT_TGT_EXT_1 ++#define CPU_INTERRUPT_MCHK CPU_INTERRUPT_TGT_EXT_2 ++#define CPU_INTERRUPT_PCIE CPU_INTERRUPT_TGT_EXT_3 ++#define CPU_INTERRUPT_WAKEUP CPU_INTERRUPT_TGT_EXT_3 ++#define CPU_INTERRUPT_SLAVE CPU_INTERRUPT_TGT_EXT_4 ++ ++#define cpu_signal_handler cpu_sw64_signal_handler ++#define CPU_RESOLVING_TYPE TYPE_SW64_CPU ++ ++#define SWCSR(x, y) x = y ++enum { ++ SWCSR(ITB_TAG, 0x0), ++ SWCSR(ITB_PTE, 0x1), ++ SWCSR(ITB_IA, 0x2), ++ SWCSR(ITB_IV, 0x3), ++ SWCSR(ITB_IVP, 0x4), ++ SWCSR(ITB_IU, 0x5), ++ SWCSR(ITB_IS, 0x6), ++ SWCSR(EXC_SUM, 0xd), ++ SWCSR(EXC_PC, 0xe), ++ SWCSR(DS_STAT, 0x48), ++ SWCSR(CID, 0xc4), ++ SWCSR(TID, 0xc7), ++ ++ SWCSR(DTB_TAG, 0x40), ++ SWCSR(DTB_PTE, 0x41), ++ SWCSR(DTB_IA, 0x42), ++ SWCSR(DTB_IV, 0x43), ++ SWCSR(DTB_IVP, 0x44), ++ SWCSR(DTB_IU, 0x45), ++ SWCSR(DTB_IS, 0x46), ++ SWCSR(II_REQ, 0x82), ++ ++ SWCSR(PTBR, 0x8), ++ SWCSR(PRI_BASE, 0x10), ++ SWCSR(TIMER_CTL, 0x2a), ++ SWCSR(INT_STAT, 0x30), ++ SWCSR(INT_CLR, 0x31), ++ SWCSR(IER, 0x32), ++ SWCSR(INT_PCI_INT, 0x33), ++ SWCSR(DVA, 0x4e), ++}; ++ ++#include "exec/cpu-all.h" ++static inline void cpu_get_tb_cpu_state(CPUSW64State *env, target_ulong *pc, ++ target_ulong *cs_base, uint32_t *pflags) ++{ ++ *pc = env->pc; ++ *cs_base = 0; ++ *pflags = env->flags; ++} ++ ++void sw64_translate_init(void); ++ ++enum { ++ EXCP_NONE, ++ EXCP_HALT, ++ EXCP_IIMAIL, ++ EXCP_OPCDEC, ++ EXCP_CALL_SYS, ++ EXCP_ARITH, ++ EXCP_UNALIGN, ++#ifdef SOFTMMU ++ EXCP_MMFAULT, ++#else ++ EXCP_DTBD, ++ EXCP_DTBS_U, ++ EXCP_DTBS_K, ++ EXCP_ITB_U, ++ EXCP_ITB_K, ++#endif ++ EXCP_CLK_INTERRUPT, ++ EXCP_DEV_INTERRUPT, ++ EXCP_SLAVE, ++}; ++ ++#define CSR_SHIFT_AND_MASK(name, func, shift, bits) \ ++ name##_##func##_S = shift, \ ++ name##_##func##_V = bits, \ ++ name##_##func##_M = (1UL << bits) - 1 ++ ++#define FPCR_MASK(name) ((uint64_t)FPCR_##name##_M << FPCR_##name##_S) ++/* FPCR */ ++enum { ++ CSR_SHIFT_AND_MASK(FPCR, EXC_CTL, 0, 2), ++ CSR_SHIFT_AND_MASK(FPCR, EXC_CTL_WEN, 2, 1), ++ CSR_SHIFT_AND_MASK(FPCR, RSV0, 3, 1), ++ CSR_SHIFT_AND_MASK(FPCR, INV3, 4, 1), ++ CSR_SHIFT_AND_MASK(FPCR, ZERO0, 5, 1), ++ CSR_SHIFT_AND_MASK(FPCR, OVF3, 6, 1), ++ CSR_SHIFT_AND_MASK(FPCR, UNF3, 7, 1), ++ CSR_SHIFT_AND_MASK(FPCR, INE3, 8, 1), ++ CSR_SHIFT_AND_MASK(FPCR, ZERO1, 9, 1), ++ CSR_SHIFT_AND_MASK(FPCR, RSV1, 10, 10), ++ CSR_SHIFT_AND_MASK(FPCR, INV2, 20, 1), ++ CSR_SHIFT_AND_MASK(FPCR, ZERO2, 21, 1), ++ CSR_SHIFT_AND_MASK(FPCR, OVF2, 22, 1), ++ CSR_SHIFT_AND_MASK(FPCR, UNF2, 23, 1), ++ CSR_SHIFT_AND_MASK(FPCR, INE2, 24, 1), ++ CSR_SHIFT_AND_MASK(FPCR, ZERO3, 25, 1), ++ CSR_SHIFT_AND_MASK(FPCR, RSV2, 26, 10), ++ CSR_SHIFT_AND_MASK(FPCR, INV1, 36, 1), ++ CSR_SHIFT_AND_MASK(FPCR, ZERO4, 37, 1), ++ CSR_SHIFT_AND_MASK(FPCR, OVF1, 38, 1), ++ CSR_SHIFT_AND_MASK(FPCR, UNF1, 39, 1), ++ CSR_SHIFT_AND_MASK(FPCR, INE1, 40, 1), ++ CSR_SHIFT_AND_MASK(FPCR, ZERO5, 41, 1), ++ CSR_SHIFT_AND_MASK(FPCR, RSV3, 42, 6), ++ CSR_SHIFT_AND_MASK(FPCR, DNZ, 48, 1), ++ CSR_SHIFT_AND_MASK(FPCR, INVD, 49, 1), ++ CSR_SHIFT_AND_MASK(FPCR, DZED, 50, 1), ++ CSR_SHIFT_AND_MASK(FPCR, OVFD, 51, 1), ++ CSR_SHIFT_AND_MASK(FPCR, INV0, 52, 1), ++ CSR_SHIFT_AND_MASK(FPCR, DZE0, 53, 1), ++ CSR_SHIFT_AND_MASK(FPCR, OVF0, 54, 1), ++ CSR_SHIFT_AND_MASK(FPCR, UNF0, 55, 1), ++ CSR_SHIFT_AND_MASK(FPCR, INE0, 56, 1), ++ CSR_SHIFT_AND_MASK(FPCR, OVI0, 57, 1), ++ CSR_SHIFT_AND_MASK(FPCR, DYN, 58, 2), ++ CSR_SHIFT_AND_MASK(FPCR, UNDZ, 60, 1), ++ CSR_SHIFT_AND_MASK(FPCR, UNFD, 61, 1), ++ CSR_SHIFT_AND_MASK(FPCR, INED, 62, 1), ++ CSR_SHIFT_AND_MASK(FPCR, SUM, 63, 1), ++}; ++ ++/* Arithmetic exception (entArith) constants. */ ++#define EXC_M_SWC 1 /* Software completion */ ++#define EXC_M_INV 2 /* Invalid operation */ ++#define EXC_M_DZE 4 /* Division by zero */ ++#define EXC_M_OVF 8 /* Overflow */ ++#define EXC_M_UNF 16 /* Underflow */ ++#define EXC_M_INE 32 /* Inexact result */ ++#define EXC_M_IOV 64 /* Integer Overflow */ ++#define EXC_M_DNO 128 /* Denomal operation */ ++ ++void QEMU_NORETURN dynamic_excp(CPUSW64State *env, uintptr_t retaddr, int excp, ++ int error); ++void QEMU_NORETURN arith_excp(CPUSW64State *env, uintptr_t retaddr, int exc, ++ uint64_t mask); ++ ++#define DEBUG_ARCH ++#ifdef DEBUG_ARCH ++#define arch_assert(x) \ ++ do { \ ++ g_assert(x); /*fprintf(stderr, "+6b %d\n", __LINE__); */ \ ++ } while (0) ++#else ++#define arch_assert(x) ++#endif ++ ++typedef struct SW64CPUInfo { ++ const char *name; ++ void (*initfn)(Object *obj); ++ void (*class_init)(ObjectClass *oc, void *data); ++} SW64CPUInfo; ++#define test_feature(env, x) (env->features & (x)) ++ ++/* Slave */ ++#endif +diff --git a/target/sw64/exception.c b/target/sw64/exception.c +new file mode 100644 +index 0000000000..a2df1cd329 +--- /dev/null ++++ b/target/sw64/exception.c +@@ -0,0 +1,76 @@ ++#include "qemu/osdep.h" ++#include "qemu/timer.h" ++ ++#include "cpu.h" ++#include "exec/exec-all.h" ++#include "fpu/softfloat.h" ++#include "exec/helper-proto.h" ++#include "hw/core/cpu.h" ++ ++#ifndef CONFIG_USER_ONLY ++void QEMU_NORETURN sw64_cpu_do_unaligned_access(CPUState *cs, vaddr addr, ++ MMUAccessType access_type, ++ int mmu_idx, uintptr_t retaddr) ++{ ++ SW64CPU *cpu = SW64_CPU(cs); ++ CPUSW64State *env = &cpu->env; ++ uint32_t insn = 0; ++ ++ if (retaddr) { ++ cpu_restore_state(cs, retaddr, true); ++ } ++ ++ fprintf(stderr, "Error %s addr = %lx\n", __func__, addr); ++ env->csr[DVA] = addr; ++ ++ env->csr[EXC_SUM] = ((insn >> 21) & 31) << 8; /* opcode */ ++ env->csr[DS_STAT] = (insn >> 26) << 4; /* dest regno */ ++ cs->exception_index = EXCP_UNALIGN; ++ env->error_code = 0; ++ cpu_loop_exit(cs); ++} ++ ++#endif ++ ++/* This should only be called from translate, via gen_excp. ++ We expect that ENV->PC has already been updated. */ ++void QEMU_NORETURN helper_excp(CPUSW64State *env, int excp, int error) ++{ ++ SW64CPU *cpu = sw64_env_get_cpu(env); ++ CPUState *cs = CPU(cpu); ++ ++ cs->exception_index = excp; ++ env->error_code = error; ++ cpu_loop_exit(cs); ++} ++ ++/* This may be called from any of the helpers to set up EXCEPTION_INDEX. */ ++void QEMU_NORETURN dynamic_excp(CPUSW64State *env, uintptr_t retaddr, int excp, ++ int error) ++{ ++ SW64CPU *cpu = sw64_env_get_cpu(env); ++ CPUState *cs = CPU(cpu); ++ ++ cs->exception_index = excp; ++ env->error_code = error; ++ if (retaddr) { ++ /* FIXME: Not jump to another tb, but jump to next insn emu */ ++ cpu_restore_state(cs, retaddr, true); ++ /* Floating-point exceptions (our only users) point to the next PC. */ ++ env->pc += 4; ++ } ++ cpu_loop_exit(cs); ++} ++ ++void QEMU_NORETURN arith_excp(CPUSW64State *env, uintptr_t retaddr, int exc, ++ uint64_t mask) ++{ ++ env->csr[EXC_SUM] = exc; ++ dynamic_excp(env, retaddr, EXCP_ARITH, 0); ++} ++ ++ ++void helper_trace_mem(CPUSW64State *env, uint64_t addr, uint64_t val) ++{ ++ /* printf("pc = %lx: Access mem addr =%lx, val = %lx\n", env->pc, addr,val); */ ++} +diff --git a/target/sw64/float_helper.c b/target/sw64/float_helper.c +new file mode 100644 +index 0000000000..ad1c3cce48 +--- /dev/null ++++ b/target/sw64/float_helper.c +@@ -0,0 +1,846 @@ ++#include "qemu/osdep.h" ++#include "cpu.h" ++#include "exec/exec-all.h" ++#include "exec/helper-proto.h" ++#include "fpu/softfloat.h" ++ ++static inline uint32_t extractFloat16Frac(float16 a) ++{ ++ return float16_val(a) & 0x3ff; ++} ++ ++/*---------------------------------------------------------------------------- ++| Returns the exponent bits of the half-precision floating-point value `a'. ++*----------------------------------------------------------------------------*/ ++ ++static inline int extractFloat16Exp(float16 a) ++{ ++ return (float16_val(a) >> 10) & 0x1f; ++} ++ ++/*---------------------------------------------------------------------------- ++| Returns the sign bit of the single-precision floating-point value `a'. ++*----------------------------------------------------------------------------*/ ++ ++static inline uint8_t extractFloat16Sign(float16 a) ++{ ++ return float16_val(a) >> 15; ++} ++ ++#define FP_STATUS (env->fp_status) ++ ++#define CONVERT_BIT(X, SRC, DST) \ ++ (SRC > DST ? (X) / (SRC / DST) & (DST) : ((X)&SRC) * (DST / SRC)) ++ ++static uint64_t soft_to_errcode_exc(CPUSW64State *env) ++{ ++ uint8_t exc = get_float_exception_flags(&FP_STATUS); ++ ++ if (unlikely(exc)) { ++ set_float_exception_flags(0, &FP_STATUS); ++ } ++ return exc; ++} ++ ++static inline uint64_t float32_to_s_int(uint32_t fi) ++{ ++ uint32_t frac = fi & 0x7fffff; ++ uint32_t sign = (fi >> 31) & 1; ++ uint32_t exp_msb = (fi >> 30) & 1; ++ uint32_t exp_low = (fi >> 23) & 0x7f; ++ uint32_t exp; ++ ++ exp = (exp_msb << 10) | exp_low; ++ if (exp_msb) { ++ if (exp_low == 0x7f) { ++ exp = 0x7ff; ++ } ++ } else { ++ if (exp_low != 0x00) { ++ exp |= 0x380; ++ } ++ } ++ ++ return (((uint64_t)sign << 63) | ((uint64_t)exp << 52) | ++ ((uint64_t)frac << 29)); ++} ++ ++static inline uint64_t float32_to_s(float32 fa) ++{ ++ CPU_FloatU a; ++ a.f = fa; ++ return float32_to_s_int(a.l); ++} ++static inline uint32_t s_to_float32_int(uint64_t a) ++{ ++ return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff); ++} ++ ++static inline float32 s_to_float32(uint64_t a) ++{ ++ CPU_FloatU r; ++ r.l = s_to_float32_int(a); ++ return r.f; ++} ++ ++uint32_t helper_s_to_memory(uint64_t a) ++{ ++ return s_to_float32(a); ++} ++ ++uint64_t helper_memory_to_s(uint32_t a) ++{ ++ return float32_to_s(a); ++} ++ ++uint64_t helper_fcvtls(CPUSW64State *env, uint64_t a) ++{ ++ float32 fr = int64_to_float32(a, &FP_STATUS); ++ env->error_code = soft_to_errcode_exc(env); ++ return float32_to_s(fr); ++} ++ ++uint64_t helper_fcvtld(CPUSW64State *env, uint64_t a) ++{ ++ float64 fr = int64_to_float64(a, &FP_STATUS); ++ env->error_code = soft_to_errcode_exc(env); ++ return (uint64_t)fr; ++} ++ ++static uint64_t do_fcvtdl(CPUSW64State *env, uint64_t a, uint64_t roundmode) ++{ ++ uint64_t frac, ret = 0; ++ uint32_t exp, sign, exc = 0; ++ int shift; ++ ++ sign = (a >> 63); ++ exp = (uint32_t)(a >> 52) & 0x7ff; ++ frac = a & 0xfffffffffffffull; ++ ++ if (exp == 0) { ++ if (unlikely(frac != 0) && !env->fp_status.flush_inputs_to_zero) { ++ goto do_underflow; ++ } ++ } else if (exp == 0x7ff) { ++ exc = float_flag_invalid; ++ } else { ++ /* Restore implicit bit. */ ++ frac |= 0x10000000000000ull; ++ ++ shift = exp - 1023 - 52; ++ if (shift >= 0) { ++ /* In this case the number is so large that we must shift ++ the fraction left. There is no rounding to do. */ ++ if (shift < 64) { ++ ret = frac << shift; ++ } ++ /* Check for overflow. Note the special case of -0x1p63. */ ++ if (shift >= 11 && a != 0xC3E0000000000000ull) { ++ exc = float_flag_inexact; ++ } ++ } else { ++ uint64_t round; ++ ++ /* In this case the number is smaller than the fraction as ++ represented by the 52 bit number. Here we must think ++ about rounding the result. Handle this by shifting the ++ fractional part of the number into the high bits of ROUND. ++ This will let us efficiently handle round-to-nearest. */ ++ shift = -shift; ++ if (shift < 63) { ++ ret = frac >> shift; ++ round = frac << (64 - shift); ++ } else { ++ /* The exponent is so small we shift out everything. ++ Leave a sticky bit for proper rounding below. */ ++ do_underflow: ++ round = 1; ++ } ++ ++ if (round) { ++ exc = float_flag_inexact; ++ switch (roundmode) { ++ case float_round_nearest_even: ++ if (round == (1ull << 63)) { ++ /* Fraction is exactly 0.5; round to even. */ ++ ret += (ret & 1); ++ } else if (round > (1ull << 63)) { ++ ret += 1; ++ } ++ break; ++ case float_round_to_zero: ++ break; ++ case float_round_up: ++ ret += 1 - sign; ++ break; ++ case float_round_down: ++ ret += sign; ++ break; ++ } ++ } ++ } ++ if (sign) { ++ ret = -ret; ++ } ++ } ++ env->error_code = exc; ++ ++ return ret; ++} ++ ++/* TODO: */ ++uint64_t helper_fris(CPUSW64State *env, uint64_t a, uint64_t roundmode) ++{ ++ uint64_t ir; ++ float32 fr; ++ ++ if (roundmode == 5) ++ roundmode = env->fpcr_round_mode; ++ ir = do_fcvtdl(env, a, roundmode); ++ fr = int64_to_float32(ir, &FP_STATUS); ++ return float32_to_s(fr); ++} ++ ++/* TODO: */ ++uint64_t helper_frid(CPUSW64State *env, uint64_t a, uint64_t roundmode) ++{ ++ if (roundmode == 5) ++ roundmode = env->fpcr_round_mode; ++ return int64_to_float64(do_fcvtdl(env, a, roundmode), &FP_STATUS); ++} ++ ++uint64_t helper_fcvtdl(CPUSW64State *env, uint64_t a, uint64_t roundmode) ++{ ++ return do_fcvtdl(env, a, roundmode); ++} ++ ++uint64_t helper_fcvtdl_dyn(CPUSW64State *env, uint64_t a) ++{ ++ uint64_t roundmode = (uint64_t)(env->fpcr_round_mode); ++ return do_fcvtdl(env, a, roundmode); ++} ++ ++uint64_t helper_fcvtsd(CPUSW64State *env, uint64_t a) ++{ ++ float32 fa; ++ float64 fr; ++ ++ fa = s_to_float32(a); ++ fr = float32_to_float64(fa, &FP_STATUS); ++ ++ return fr; ++} ++ ++uint64_t helper_fcvtds(CPUSW64State *env, uint64_t a) ++{ ++ float32 fa; ++ ++ fa = float64_to_float32((float64)a, &FP_STATUS); ++ ++ return float32_to_s(fa); ++} ++ ++uint64_t helper_fcvtwl(CPUSW64State *env, uint64_t a) ++{ ++ int32_t ret; ++ ret = (a >> 29) & 0x3fffffff; ++ ret |= ((a >> 62) & 0x3) << 30; ++ return (uint64_t)(int64_t)ret; //int32_t to int64_t as Sign-Extend ++} ++ ++uint64_t helper_fcvtlw(CPUSW64State *env, uint64_t a) ++{ ++ uint64_t ret; ++ ret = (a & 0x3fffffff) << 29; ++ ret |= ((a >> 30) & 0x3) << 62; ++ return ret; ++} ++ ++uint64_t helper_fadds(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float32 fa, fb, fr; ++ ++ fa = s_to_float32(a); ++ fb = s_to_float32(b); ++#if 1 ++ fr = float32_add(fa, fb, &FP_STATUS); ++ ++ env->error_code = soft_to_errcode_exc(env); ++#else ++ *(float*)&fr = *(float*)&fb + *(float*)&fa; ++#endif ++ return float32_to_s(fr); ++} ++ ++/* Input handing without software completion. Trap for all ++ non-finite numbers. */ ++uint64_t helper_faddd(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float64 fa, fb, fr; ++ ++ fa = (float64)a; ++ fb = (float64)b; ++#if 1 ++ fr = float64_add(fa, fb, &FP_STATUS); ++ env->error_code = soft_to_errcode_exc(env); ++#else ++ *(double*)&fr = *(double*)&fb + *(double*)&fa; ++#endif ++ return (uint64_t)fr; ++} ++ ++uint64_t helper_fsubs(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float32 fa, fb, fr; ++ ++ fa = s_to_float32(a); ++ fb = s_to_float32(b); ++#if 1 ++ fr = float32_sub(fa, fb, &FP_STATUS); ++ env->error_code = soft_to_errcode_exc(env); ++#else ++ *(float*)&fr = *(float*)&fa - *(float*)&fb; ++#endif ++ return float32_to_s(fr); ++} ++ ++uint64_t helper_fsubd(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float64 fa, fb, fr; ++ ++ fa = (float64)a; ++ fb = (float64)b; ++#if 1 ++ fr = float64_sub(fa, fb, &FP_STATUS); ++ env->error_code = soft_to_errcode_exc(env); ++#else ++ *(double*)&fr = *(double*)&fa - *(double*)&fb; ++#endif ++ return (uint64_t)fr; ++} ++ ++uint64_t helper_fmuls(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float32 fa, fb, fr; ++ ++ fa = s_to_float32(a); ++ fb = s_to_float32(b); ++#if 1 ++ fr = float32_mul(fa, fb, &FP_STATUS); ++ env->error_code = soft_to_errcode_exc(env); ++#else ++ *(float*)&fr = *(float*)&fa * *(float*)&fb; ++#endif ++ return float32_to_s(fr); ++} ++ ++uint64_t helper_fmuld(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float64 fa, fb, fr; ++ ++ fa = (float64)a; ++ fb = (float64)b; ++#if 1 ++ fr = float64_mul(fa, fb, &FP_STATUS); ++ env->error_code = soft_to_errcode_exc(env); ++#else ++ *(double*)&fr = *(double*)&fa * *(double*)&fb; ++#endif ++ return (uint64_t)fr; ++} ++ ++uint64_t helper_fdivs(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float32 fa, fb, fr; ++ ++ fa = s_to_float32(a); ++ fb = s_to_float32(b); ++#if 1 ++ fr = float32_div(fa, fb, &FP_STATUS); ++ env->error_code = soft_to_errcode_exc(env); ++#else ++ *(float*)&fr = *(float*)&fa / *(float*)&fb; ++#endif ++ return float32_to_s(fr); ++} ++ ++uint64_t helper_fdivd(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float64 fa, fb, fr; ++ ++ fa = (float64)a; ++ fb = (float64)b; ++#if 1 ++ fr = float64_div(fa, fb, &FP_STATUS); ++ env->error_code = soft_to_errcode_exc(env); ++#else ++ *(double*)&fr = *(double*)&fa / *(double*)&fb; ++#endif ++ ++ return (uint64_t)fr; ++} ++ ++uint64_t helper_frecs(CPUSW64State *env, uint64_t a) ++{ ++ float32 fa, fb, fr; ++ ++ fa = s_to_float32(a); ++ fb = int64_to_float32(1, &FP_STATUS); ++#if 1 ++ fr = float32_div(fb, fa, &FP_STATUS); ++ env->error_code = soft_to_errcode_exc(env); ++#else ++ *(float*)&fr = *(float*)&fb / *(float*)&fa; ++#endif ++ return float32_to_s(fr); ++} ++ ++uint64_t helper_frecd(CPUSW64State *env, uint64_t a) ++{ ++ float64 fa, fb, fr; ++ ++ fa = (float64)a; ++ fb = int64_to_float64(1, &FP_STATUS); ++#if 1 ++ fr = float64_div(fb, fa, &FP_STATUS); ++ env->error_code = soft_to_errcode_exc(env); ++#else ++ *(double*)&fr = *(double*)&fb / *(double*)&fa; ++#endif ++ ++ return (uint64_t)fr; ++} ++ ++uint64_t helper_fsqrts(CPUSW64State *env, uint64_t b) ++{ ++ float32 fb, fr; ++#if 1 ++ fb = s_to_float32(b); ++ fr = float32_sqrt(fb, &FP_STATUS); ++ env->error_code = soft_to_errcode_exc(env); ++#else ++#include ++ *(double*)&fr = sqrt(*(double*)&b); ++#endif ++ ++ return float32_to_s(fr); ++} ++ ++uint64_t helper_fsqrt(CPUSW64State *env, uint64_t b) ++{ ++ float64 fr; ++ ++#if 1 ++ fr = float64_sqrt(b, &FP_STATUS); ++ env->error_code = soft_to_errcode_exc(env); ++#else ++#include ++ *(double*)&fr = sqrt(*(double*)&b); ++#endif ++ ++ return (uint64_t)fr; ++} ++ ++ ++uint64_t helper_fmas(CPUSW64State *env, uint64_t a, uint64_t b, uint64_t c) ++{ ++ float32 fa, fb, fc, fr; ++ fa = s_to_float32(a); ++ fb = s_to_float32(b); ++ fc = s_to_float32(c); ++ ++ fr = float32_muladd(fa, fb, fc, 0, &FP_STATUS); ++ ++ return float32_to_s(fr); ++} ++ ++uint64_t helper_fmad(CPUSW64State *env, uint64_t a, uint64_t b, uint64_t c) ++{ ++ float64 fr; ++ ++ fr = float64_muladd(a, b, c, 0, &FP_STATUS); ++ ++ return fr; ++} ++ ++ ++uint64_t helper_fmss(CPUSW64State *env, uint64_t a, uint64_t b, uint64_t c) ++{ ++ float32 fa, fb, fc, fr; ++ fa = s_to_float32(a); ++ fb = s_to_float32(b); ++ fc = s_to_float32(c); ++ ++ fr = float32_muladd(fa, fb, fc, float_muladd_negate_c, &FP_STATUS); ++ ++ return float32_to_s(fr); ++} ++ ++uint64_t helper_fmsd(CPUSW64State *env, uint64_t a, uint64_t b, uint64_t c) ++{ ++ float64 fr; ++ ++ fr = float64_muladd(a, b, c, float_muladd_negate_c, &FP_STATUS); ++ ++ return fr; ++} ++ ++ ++uint64_t helper_fnmas(CPUSW64State *env, uint64_t a, uint64_t b, uint64_t c) ++{ ++ float32 fa, fb, fc, fr; ++ fa = s_to_float32(a); ++ fb = s_to_float32(b); ++ fc = s_to_float32(c); ++ int flag = float_muladd_negate_product; ++ ++ fr = float32_muladd(fa, fb, fc, flag, &FP_STATUS); ++ ++ return float32_to_s(fr); ++} ++ ++uint64_t helper_fnmad(CPUSW64State *env, uint64_t a, uint64_t b, uint64_t c) ++{ ++ float64 fr; ++ int flag = float_muladd_negate_product; ++ ++ fr = float64_muladd(a, b, c, flag, &FP_STATUS); ++ ++ return fr; ++} ++ ++uint64_t helper_fnmss(CPUSW64State *env, uint64_t a, uint64_t b, uint64_t c) ++{ ++ float32 fa, fb, fc, fr; ++ fa = s_to_float32(a); ++ fb = s_to_float32(b); ++ fc = s_to_float32(c); ++ int flag = float_muladd_negate_product | float_muladd_negate_c; ++ ++ fr = float32_muladd(fa, fb, fc, flag, &FP_STATUS); ++ ++ return float32_to_s(fr); ++} ++ ++uint64_t helper_fnmsd(CPUSW64State *env, uint64_t a, uint64_t b, uint64_t c) ++{ ++ float64 fr; ++ int flag = float_muladd_negate_product | float_muladd_negate_c; ++ ++ fr = float64_muladd(a, b, c, flag, &FP_STATUS); ++ ++ return fr; ++} ++uint64_t helper_load_fpcr(CPUSW64State *env) ++{ ++ return cpu_sw64_load_fpcr(env); ++} ++ ++static void update_fpcr_status_mask(CPUSW64State *env) ++{ ++ uint64_t t = 0; ++ ++ /* Don't mask the inv excp: ++ * EXC_CTL1 = 1 ++ * EXC_CTL1 = 0, input denormal, DNZ=0 ++ * EXC_CTL1 = 0, no input denormal or DNZ=1, INVD = 0 ++ */ ++ if ((env->fpcr & FPCR_MASK(EXC_CTL) & 0x2)) { ++ if (env->fpcr & FPCR_MASK(EXC_CTL) & 0x1) { ++ t |= (EXC_M_INE | EXC_M_UNF | EXC_M_IOV); ++ } else { ++ t |= EXC_M_INE; ++ } ++ } else { ++ /* INV and DNO mask */ ++ if (env->fpcr & FPCR_MASK(DNZ)) t |= EXC_M_DNO; ++ if (env->fpcr & FPCR_MASK(INVD)) t |= EXC_M_INV; ++ if (env->fpcr & FPCR_MASK(OVFD)) t |= EXC_M_OVF; ++ if (env->fpcr & FPCR_MASK(UNFD)) { ++ t |= EXC_M_UNF; ++ } ++ if (env->fpcr & FPCR_MASK(DZED)) t |= EXC_M_DZE; ++ if (env->fpcr & FPCR_MASK(INED)) t |= EXC_M_INE; ++ } ++ ++ env->fpcr_exc_enable = t; ++} ++ ++void helper_store_fpcr(CPUSW64State *env, uint64_t val) ++{ ++ uint64_t fpcr = val; ++ uint8_t ret; ++ ++ switch ((fpcr & FPCR_MASK(DYN)) >> FPCR_DYN_S) { ++ case 0x0: ++ ret = float_round_to_zero; ++ break; ++ case 0x1: ++ ret = float_round_down; ++ break; ++ case 0x2: ++ ret = float_round_nearest_even; ++ break; ++ case 0x3: ++ ret = float_round_up; ++ break; ++ default: ++ ret = float_round_nearest_even; ++ break; ++ } ++ ++ env->fpcr_round_mode = ret; ++ ++ env->fp_status.float_rounding_mode = ret; ++ ++ env->fpcr_flush_to_zero = ++ (fpcr & FPCR_MASK(UNFD)) && (fpcr & FPCR_MASK(UNDZ)); ++ env->fp_status.flush_to_zero = env->fpcr_flush_to_zero; ++ ++ /* FIXME: Now the DNZ flag does not work int C3A. */ ++ //set_flush_inputs_to_zero((val & FPCR_MASK(DNZ)) != 0? 1 : 0, &FP_STATUS); ++ ++ val &= ~0x3UL; ++ val |= env->fpcr & 0x3UL; ++ env->fpcr = val; ++ update_fpcr_status_mask(env); ++} ++ ++void helper_setfpcrx(CPUSW64State *env, uint64_t val) ++{ ++ if (env->fpcr & FPCR_MASK(EXC_CTL_WEN)) { ++ env->fpcr &= ~3UL; ++ env->fpcr |= val & 0x3; ++ update_fpcr_status_mask(env); ++ } ++} ++#ifndef CONFIG_USER_ONLY ++static uint32_t soft_to_exc_type(uint64_t exc) ++{ ++ uint32_t ret = 0; ++ ++ if (unlikely(exc)) { ++ ret |= CONVERT_BIT(exc, float_flag_invalid, EXC_M_INV); ++ ret |= CONVERT_BIT(exc, float_flag_divbyzero, EXC_M_DZE); ++ ret |= CONVERT_BIT(exc, float_flag_overflow, EXC_M_OVF); ++ ret |= CONVERT_BIT(exc, float_flag_underflow, EXC_M_UNF); ++ ret |= CONVERT_BIT(exc, float_flag_inexact, EXC_M_INE); ++ } ++ ++ return ret; ++} ++static void fp_exc_raise1(CPUSW64State *env, uintptr_t retaddr, uint64_t exc, ++ uint32_t regno) ++{ ++ if (!likely(exc)) ++ return; ++ arith_excp(env, retaddr, exc, 1ull << regno); ++} ++ ++void helper_fp_exc_raise(CPUSW64State *env, uint32_t regno) ++{ ++ uint64_t exc = env->error_code; ++ uint32_t exc_type = soft_to_exc_type(exc); ++ ++ if (exc_type) { ++ exc_type &= ~(env->fpcr_exc_enable); ++ if (exc_type) fp_exc_raise1(env, GETPC(), exc_type | EXC_M_SWC, regno); ++ } ++} ++#endif ++ ++void helper_ieee_input(CPUSW64State *env, uint64_t val) ++{ ++#ifndef CONFIG_USER_ONLY ++ uint32_t exp = (uint32_t)(val >> 52) & 0x7ff; ++ uint64_t frac = val & 0xfffffffffffffull; ++ ++ if (exp == 0x7ff) { ++ /* Infinity or NaN. */ ++ uint32_t exc_type = EXC_M_INV; ++ ++ if (exc_type) { ++ exc_type &= ~(env->fpcr_exc_enable); ++ if (exc_type) ++ fp_exc_raise1(env, GETPC(), exc_type | EXC_M_SWC, 32); ++ } ++ } ++#endif ++} ++ ++void helper_ieee_input_s(CPUSW64State *env, uint64_t val) ++{ ++ if (unlikely(2 * val - 1 < 0x1fffffffffffffull) && ++ !env->fp_status.flush_inputs_to_zero) { ++ } ++} ++ ++static inline float64 t_to_float64(uint64_t a) ++{ ++ /* Memory format is the same as float64 */ ++ CPU_DoubleU r; ++ r.ll = a; ++ return r.d; ++} ++ ++uint64_t helper_fcmpun(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float64 fa, fb; ++ uint64_t ret = 0; ++ ++ fa = t_to_float64(a); ++ fb = t_to_float64(b); ++ ++ if (float64_unordered_quiet(fa, fb, &FP_STATUS)) { ++ ret = 0x4000000000000000ULL; ++ } ++ env->error_code = soft_to_errcode_exc(env); ++ ++ return ret; ++} ++ ++uint64_t helper_fcmpeq(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float64 fa, fb; ++ uint64_t ret = 0; ++ ++ fa = t_to_float64(a); ++ fb = t_to_float64(b); ++ ++ if (float64_eq_quiet(fa, fb, &FP_STATUS)) { ++ ret = 0x4000000000000000ULL; ++ } ++ env->error_code = soft_to_errcode_exc(env); ++ ++ return ret; ++} ++ ++uint64_t helper_fcmple(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float64 fa, fb; ++ uint64_t ret = 0; ++ ++ fa = t_to_float64(a); ++ fb = t_to_float64(b); ++ ++ if (float64_le_quiet(fa, fb, &FP_STATUS)) { ++ ret = 0x4000000000000000ULL; ++ } ++ env->error_code = soft_to_errcode_exc(env); ++ ++ return ret; ++} ++ ++uint64_t helper_fcmplt(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float64 fa, fb; ++ uint64_t ret = 0; ++ ++ fa = t_to_float64(a); ++ fb = t_to_float64(b); ++ ++ if (float64_lt_quiet(fa, fb, &FP_STATUS)) { ++ ret = 0x4000000000000000ULL; ++ } ++ env->error_code = soft_to_errcode_exc(env); ++ ++ return ret; ++} ++ ++uint64_t helper_fcmpge(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float64 fa, fb; ++ uint64_t ret = 0; ++ ++ fa = t_to_float64(a); ++ fb = t_to_float64(b); ++ ++ if (float64_le_quiet(fb, fa, &FP_STATUS)) { ++ ret = 0x4000000000000000ULL; ++ } ++ env->error_code = soft_to_errcode_exc(env); ++ ++ return ret; ++} ++ ++uint64_t helper_fcmpgt(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float64 fa, fb; ++ uint64_t ret = 0; ++ ++ fa = t_to_float64(a); ++ fb = t_to_float64(b); ++ ++ if (float64_lt_quiet(fb, fa, &FP_STATUS)) { ++ ret = 0x4000000000000000ULL; ++ } ++ env->error_code = soft_to_errcode_exc(env); ++ ++ return ret; ++} ++ ++uint64_t helper_fcmpge_s(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float64 fa, fb; ++ uint64_t ret = 0; ++ ++ /* Make sure va and vb is s float. */ ++ fa = float32_to_float64(s_to_float32(a), &FP_STATUS); ++ fb = float32_to_float64(s_to_float32(b), &FP_STATUS); ++ ++ if (float64_le_quiet(fb, fa, &FP_STATUS)) { ++ ret = 0x4000000000000000ULL; ++ } ++ env->error_code = soft_to_errcode_exc(env); ++ ++ return ret; ++} ++ ++uint64_t helper_fcmple_s(CPUSW64State *env, uint64_t a, uint64_t b) ++{ ++ float64 fa, fb; ++ uint64_t ret = 0; ++ ++ /* Make sure va and vb is s float. */ ++ fa = float32_to_float64(s_to_float32(a), &FP_STATUS); ++ fb = float32_to_float64(s_to_float32(b), &FP_STATUS); ++ ++ if (float64_le_quiet(fa, fb, &FP_STATUS)) { ++ ret = 0x4000000000000000ULL; ++ } ++ env->error_code = soft_to_errcode_exc(env); ++ ++ return ret; ++} ++ ++void helper_vfcvtsh(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t vc, ++ uint64_t rd) ++{ ++ uint64_t temp = 0; ++ int i; ++ for (i = 0; i < 4; i++) { ++ temp |= (uint64_t)float32_to_float16(s_to_float32(env->fr[ra + i * 32]), ++ 1, &FP_STATUS) ++ << (i * 16); ++ } ++ for (i = 0; i < 4; i++) { ++ if (i == (vc & 0x3)) { ++ env->fr[rd + i * 32] = temp; ++ } else { ++ env->fr[rd + i * 32] = env->fr[rb + i * 32]; ++ } ++ } ++} ++ ++void helper_vfcvths(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t vc, ++ uint64_t rd) ++{ ++ uint64_t temp; ++ int i; ++ ++ temp = env->fr[ra + 32 * (vc & 0x3)]; ++ for (i = 0; i < 4; i++) { ++ env->fr[rd + i * 32] = float32_to_s( ++ float16_to_float32((temp >> (i * 16)) & 0xffffUL, 1, &FP_STATUS)); ++ } ++} +diff --git a/target/sw64/helper.c b/target/sw64/helper.c +new file mode 100644 +index 0000000000..0cc0af7087 +--- /dev/null ++++ b/target/sw64/helper.c +@@ -0,0 +1,349 @@ ++/* ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library 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 ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see . ++ */ ++ ++#include "qemu/osdep.h" ++#include "qemu/timer.h" ++ ++#include "cpu.h" ++#include "exec/exec-all.h" ++#include "fpu/softfloat.h" ++#include "exec/helper-proto.h" ++#include "hw/core/cpu.h" ++#include "exec/memattrs.h" ++ ++#if defined(CONFIG_USER_ONLY) ++bool sw64_cpu_tlb_fill(CPUState *cs, vaddr address, int size, ++ MMUAccessType access_type, int mmu_idx, ++ bool probe, uintptr_t retaddr) ++{ ++ SW64CPU *cpu = SW64_CPU(cs); ++ ++ cs->exception_index = EXCP_MMFAULT; ++ cpu->env.trap_arg0 = address; ++ cpu_loop_exit_restore(cs, retaddr); ++} ++#else ++static target_ulong ldq_phys_clear(CPUState *cs, target_ulong phys) ++{ ++ return ldq_phys(cs->as, phys & ~(3UL)); ++} ++ ++static int get_sw64_physical_address(CPUSW64State *env, target_ulong addr, ++ int prot_need, int mmu_idx, target_ulong *pphys, ++ int *pprot) ++{ ++ CPUState *cs = CPU(sw64_env_get_cpu(env)); ++ target_ulong phys = 0; ++ int prot = 0; ++ int ret = MM_K_ACV; ++ target_ulong L1pte, L2pte, L3pte, L4pte; ++ target_ulong pt, index, pte_pfn_s; ++ ++ if (((addr >> 28) & 0xffffffff8) == 0xffffffff8) { ++ phys = (~(0xffffffff80000000)) & addr; ++ prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ++ ret = -1; ++ goto exit; ++ } else if (((addr >> 32) & 0xfffff000) == 0xfffff000) { ++ goto do_pgmiss; ++ } else if (((addr >> 52) & 0xfff) == 0xfff) { ++ phys = (~(0xfff0000000000000)) & addr; ++ prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ++ ret = -1; ++ goto exit; ++ } ++do_pgmiss: ++ pte_pfn_s = 28; ++ pt = env->csr[PTBR]; ++ index = (addr >> (TARGET_PAGE_BITS + 3 * TARGET_LEVEL_BITS)) & ((1 << TARGET_LEVEL_BITS)-1); ++ L1pte = ldq_phys_clear(cs, pt + index * 8); ++ if ((L1pte & PTE_VALID) == 0) { ++ ret = MM_K_TNV; ++ goto exit; ++ } ++ if (((L1pte >> 1) & 1) && prot_need == 0) { ++ ret = MM_K_FOR; ++ goto exit; ++ } ++ if (((L1pte >> 2) & 1) && prot_need == 1) { ++ ret = MM_K_FOW; ++ goto exit; ++ } ++ pt = L1pte >> pte_pfn_s << TARGET_PAGE_BITS; ++ ++ index = (addr >> (TARGET_PAGE_BITS + 2 * TARGET_LEVEL_BITS)) & ((1 << TARGET_LEVEL_BITS)-1); ++ L2pte = ldq_phys_clear(cs, pt + index * 8); ++ ++ if ((L2pte & PTE_VALID) == 0) { ++ ret = MM_K_TNV; ++ goto exit; ++ } ++ if (((L2pte >> 1) & 1) && prot_need == 0) { ++ ret = MM_K_FOR; ++ goto exit; ++ } ++ if (((L2pte >> 2) & 1) && prot_need == 1) { ++ ret = MM_K_FOW; ++ goto exit; ++ } ++ ++ pt = L2pte >> pte_pfn_s << TARGET_PAGE_BITS; ++ ++ index = (addr >> (TARGET_PAGE_BITS + 1 * TARGET_LEVEL_BITS)) & ((1 << TARGET_LEVEL_BITS)-1); ++ L3pte = ldq_phys_clear(cs, pt + index * 8); ++ ++ if ((L3pte & PTE_VALID) == 0) { ++ ret = MM_K_TNV; ++ goto exit; ++ } ++ if (((L3pte >> 1) & 1) && prot_need == 0) { ++ ret = MM_K_FOR; ++ goto exit; ++ } ++ if (((L3pte >> 2) & 1) && prot_need == 1) { ++ ret = MM_K_FOW; ++ goto exit; ++ } ++ ++ pt = L3pte >> pte_pfn_s << TARGET_PAGE_BITS; ++ ++ index = (addr >> TARGET_PAGE_BITS) & ((1 << TARGET_LEVEL_BITS)-1); ++ L4pte = ldq_phys_clear(cs, pt + index * 8); ++ if ((L4pte & PTE_VALID) == 0) { ++ ret = MM_K_TNV; ++ goto exit; ++ } ++#if PAGE_READ != 1 || PAGE_WRITE != 2 || PAGE_EXEC != 4 ++#error page bits out of date ++#endif ++ ++ /* Check access violations. */ ++ if ((L4pte & PTE_FOR) == 0) { ++ prot |= PAGE_READ | PAGE_EXEC; ++ } ++ if ((L4pte & PTE_FOW) == 0) { ++ prot |= PAGE_WRITE; ++ } ++ ++ /* Check fault-on-operation violations. */ ++ prot &= ~(L4pte >> 1); ++ ++ phys = (L4pte >> pte_pfn_s << TARGET_PAGE_BITS); ++ ++ if (unlikely((prot & prot_need) == 0)) { ++ ret = (prot_need & PAGE_EXEC ++ ? MM_K_FOE ++ : prot_need & PAGE_WRITE ++ ? MM_K_FOW ++ : prot_need & PAGE_READ ? MM_K_FOR : -1); ++ goto exit; ++ } ++ ++ ret = -1; ++exit: ++ *pphys = phys; ++ *pprot = prot; ++ return ret; ++} ++ ++bool sw64_cpu_tlb_fill(CPUState *cs, vaddr address, int size, ++ MMUAccessType access_type, int mmu_idx, ++ bool probe, uintptr_t retaddr) ++{ ++ SW64CPU *cpu = SW64_CPU(cs); ++ CPUSW64State *env = &cpu->env; ++ target_ulong phys; ++ int prot, fail; ++ ++ if (mmu_idx == MMU_PHYS_IDX) { ++ phys = address; ++ prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ++ fail = 0; ++ if ((address >> 52) & 1) goto do_pgmiss; ++ goto done; ++ } ++ ++do_pgmiss: ++ fail = get_sw64_physical_address(env, address, 1 << access_type, mmu_idx, &phys, &prot); ++ if (unlikely(fail >= 0)) { ++ if (probe) { ++ return false; ++ } ++ cs->exception_index = EXCP_MMFAULT; ++ if (access_type == 2) { ++ env->csr[DS_STAT] = fail; ++ env->csr[DVA] = address & ~(3UL); ++ } else { ++ env->csr[DS_STAT] = fail | (((unsigned long)access_type + 1) << 3); ++ env->csr[DVA] = address; ++ } ++ env->error_code = access_type; ++ cpu_loop_exit_restore(cs, retaddr); ++ } ++done: ++ tlb_set_page(cs, address & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK, prot, ++ mmu_idx, TARGET_PAGE_SIZE); ++ return true; ++} ++ ++hwaddr sw64_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) ++{ ++ SW64CPU *cpu = SW64_CPU(cs); ++ CPUSW64State *env = &cpu->env; ++ target_ulong phys; ++ int prot, fail; ++ int mmu_index = cpu_mmu_index(env, 0); ++ if (mmu_index == MMU_PHYS_IDX) { ++ phys = addr; ++ prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; ++ fail = -1; ++ if ((addr >> 52) & 1) goto do_pgmiss; ++ goto done; ++ } ++do_pgmiss: ++ fail = get_sw64_physical_address(&cpu->env, addr, 1, mmu_index, &phys, &prot); ++done: ++ return (fail >= 0 ? -1 : phys); ++} ++#endif ++ ++static void update_fpcr_status_mask(CPUSW64State* env) { ++ uint64_t t = 0; ++ ++ /* Don't mask the inv excp: ++ * EXC_CTL1 = 1 ++ * EXC_CTL1 = 0, input denormal, DNZ=0 ++ * EXC_CTL1 = 0, no input denormal or DNZ=1, INVD = 0 ++ */ ++ if ((env->fpcr & FPCR_MASK(EXC_CTL) & 0x2)) { ++ if (env->fpcr & FPCR_MASK(EXC_CTL) & 0x1) { ++ t |= (EXC_M_INE | EXC_M_UNF | EXC_M_IOV); ++ } else { ++ t |= EXC_M_INE; ++ } ++ } else { ++ /* INV and DNO mask */ ++ if (env->fpcr & FPCR_MASK(DNZ)) t |= EXC_M_DNO; ++ if (env->fpcr & FPCR_MASK(INVD)) t |= EXC_M_INV; ++ if (env->fpcr & FPCR_MASK(OVFD)) t |= EXC_M_OVF; ++ if (env->fpcr & FPCR_MASK(UNFD)) { ++ t |= EXC_M_UNF; ++ } ++ if (env->fpcr & FPCR_MASK(DZED)) t |= EXC_M_DZE; ++ if (env->fpcr & FPCR_MASK(INED)) t |= EXC_M_INE; ++ } ++ ++ env->fpcr_exc_enable = t; ++} ++ ++void cpu_sw64_store_fpcr(CPUSW64State* env, uint64_t val) { ++ uint64_t fpcr = val; ++ uint8_t ret; ++ ++ switch ((fpcr & FPCR_MASK(DYN)) >> FPCR_DYN_S) { ++ case 0x0: ++ ret = float_round_to_zero; ++ break; ++ case 0x1: ++ ret = float_round_down; ++ break; ++ case 0x2: ++ ret = float_round_nearest_even; ++ break; ++ case 0x3: ++ ret = float_round_up; ++ break; ++ default: ++ ret = float_round_nearest_even; ++ break; ++ } ++ ++ env->fpcr_round_mode = ret; ++ env->fp_status.float_rounding_mode = ret; ++ ++ env->fpcr_flush_to_zero = ++ (fpcr & FPCR_MASK(UNFD)) && (fpcr & FPCR_MASK(UNDZ)); ++ env->fp_status.flush_to_zero = env->fpcr_flush_to_zero; ++ ++ val &= ~0x3UL; ++ val |= env->fpcr & 0x3UL; ++ env->fpcr = val; ++ update_fpcr_status_mask(env); ++} ++ ++uint64_t helper_read_csr(CPUSW64State *env, uint64_t index) ++{ ++ if (index == PRI_BASE) ++ return 0x10000; ++ return env->csr[index]; ++} ++ ++uint64_t helper_rtc(void) ++{ ++#ifndef CONFIG_USER_ONLY ++ return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) * CPUFREQ_SCALE; ++#else ++ return 0; ++#endif ++} ++ ++void helper_write_csr(CPUSW64State *env, uint64_t index, uint64_t va) ++{ ++ env->csr[index] = va; ++#ifndef CONFIG_USER_ONLY ++ CPUState *cs = &(sw64_env_get_cpu(env)->parent_obj); ++ SW64CPU *cpu = SW64_CPU(cs); ++ if ((index == DTB_IA) || (index == DTB_IV) || (index == DTB_IVP) || ++ (index == DTB_IU) || (index == DTB_IS) || (index == ITB_IA) || ++ (index == ITB_IV) || (index == ITB_IVP) || (index == ITB_IU) || ++ (index == ITB_IS) || (index == PTBR)) { ++ tlb_flush(cs); ++ } ++ if (index == INT_CLR || index == INT_PCI_INT) { ++ env->csr[INT_STAT] &= ~va; ++ } ++ ++ if (index == TIMER_CTL && env->csr[index] == 1) { ++ timer_mod(cpu->alarm_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 1000000000 / 250); ++ } ++#endif ++} ++ ++uint64_t cpu_sw64_load_fpcr(CPUSW64State *env) ++{ ++ return (uint64_t)env->fpcr; ++} ++ ++void helper_tb_flush(CPUSW64State *env) ++{ ++ tb_flush(CPU(sw64_env_get_cpu(env))); ++} ++ ++void helper_cpustate_update(CPUSW64State *env, uint64_t pc) ++{ ++ switch (pc & 0x3) { ++ case 0x00: ++ env->flags = ENV_FLAG_HM_MODE; ++ break; ++ case 0x01: ++ env->flags &= ~(ENV_FLAG_PS_USER | ENV_FLAG_HM_MODE); ++ break; ++ case 0x02: ++ env->flags &= ~(ENV_FLAG_PS_USER | ENV_FLAG_HM_MODE); ++ break; ++ case 0x03: ++ env->flags = ENV_FLAG_PS_USER; ++ } ++} +diff --git a/target/sw64/helper.h b/target/sw64/helper.h +new file mode 100644 +index 0000000000..7cafa563c2 +--- /dev/null ++++ b/target/sw64/helper.h +@@ -0,0 +1,127 @@ ++ ++DEF_HELPER_FLAGS_2(zap, TCG_CALL_NO_RWG_SE, i64, i64, i64) ++DEF_HELPER_FLAGS_2(zapnot, TCG_CALL_NO_RWG_SE, i64, i64, i64) ++DEF_HELPER_FLAGS_2(cmpgeb, TCG_CALL_NO_RWG_SE, i64, i64, i64) ++DEF_HELPER_FLAGS_1(s_to_memory, TCG_CALL_NO_RWG_SE, i32, i64) ++DEF_HELPER_FLAGS_1(memory_to_s, TCG_CALL_NO_RWG_SE, i64, i32) ++DEF_HELPER_FLAGS_2(fcvtls, TCG_CALL_NO_RWG, i64, env, i64) ++DEF_HELPER_FLAGS_2(fcvtld, TCG_CALL_NO_RWG, i64, env, i64) ++DEF_HELPER_FLAGS_3(fcvtdl, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_2(fcvtdl_dyn, TCG_CALL_NO_RWG, i64, env, i64) ++DEF_HELPER_FLAGS_3(fris, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(frid, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_2(fcvtsd, TCG_CALL_NO_RWG, i64, env, i64) ++DEF_HELPER_FLAGS_2(fcvtds, TCG_CALL_NO_RWG, i64, env, i64) ++DEF_HELPER_FLAGS_2(fcvtwl, TCG_CALL_NO_RWG, i64, env, i64) ++DEF_HELPER_FLAGS_2(fcvtlw, TCG_CALL_NO_RWG, i64, env, i64) ++DEF_HELPER_FLAGS_5(vfcvtsh, 0, void, env, i64, i64, i64, i64) ++DEF_HELPER_FLAGS_5(vfcvths, 0, void, env, i64, i64, i64, i64) ++DEF_HELPER_FLAGS_3(fadds, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(fsubs, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(fsubd, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(fmuls, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(fmuld, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(fdivs, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(fdivd, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_2(frecs, TCG_CALL_NO_RWG, i64, env, i64) ++DEF_HELPER_FLAGS_2(frecd, TCG_CALL_NO_RWG, i64, env, i64) ++DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_RWG, i64, env, i64) ++DEF_HELPER_FLAGS_2(fsqrt, TCG_CALL_NO_RWG, i64, env, i64) ++DEF_HELPER_FLAGS_4(fmas, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(fmad, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(fmss, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(fmsd, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(fnmas, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(fnmad, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(fnmss, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(fnmsd, TCG_CALL_NO_RWG, i64, env, i64, i64, i64) ++DEF_HELPER_FLAGS_0(rtc, TCG_CALL_NO_RWG, i64) ++DEF_HELPER_FLAGS_1(load_fpcr, 0, i64, env) ++DEF_HELPER_FLAGS_2(store_fpcr, 0, void, env, i64) ++DEF_HELPER_FLAGS_2(setfpcrx, 0, void, env, i64) ++DEF_HELPER_FLAGS_2(ieee_input, 0, void, env, i64) ++DEF_HELPER_FLAGS_2(ieee_input_s, 0, void, env, i64) ++DEF_HELPER_FLAGS_2(read_csr, TCG_CALL_NO_RWG, i64, env, i64) ++DEF_HELPER_FLAGS_3(write_csr, 0, void, env, i64, i64) ++DEF_HELPER_FLAGS_2(cpustate_update, 0, void, env, i64) ++DEF_HELPER_FLAGS_3(trace_mem, 0, void, env, i64, i64) ++DEF_HELPER_FLAGS_3(fcmpun, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(fcmple, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(fcmplt, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(fcmpge, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(fcmpgt, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(fcmpge_s, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(fcmple_s, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_4(srlow, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(sllow, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vlogzz, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vconw, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vcond, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vshfw, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_2(ctlzow, 0, i64, env, i64) ++DEF_HELPER_FLAGS_4(vucaddw, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vucaddwi, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vucsubw, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vucsubwi, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vucaddh, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vucaddhi, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vucsubh, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vucsubhi, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vucaddb, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vucaddbi, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vucsubb, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vucsubbi, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_3(vstw, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(vsts, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_3(vstd, TCG_CALL_NO_RWG, i64, env, i64, i64) ++DEF_HELPER_FLAGS_2(v_print, 0, void, env, i64) ++DEF_HELPER_FLAGS_1(tb_flush, 0, void, env) ++DEF_HELPER_FLAGS_4(vmaxb, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vminb, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vmaxh, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vminh, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vmaxw, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vminw, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(sraow, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vsm4r, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vsm4key, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vsm3msw, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vcmpueqb, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vcmpugtb, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vcmpueqbi, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vcmpugtbi, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vumaxb, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vuminb, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vumaxh, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vuminh, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vumaxw, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vuminw, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_5(vinsb, 0, void, env, i64, i64, i64, i64) ++DEF_HELPER_FLAGS_5(vinsh, 0, void, env, i64, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vinsectlh, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vinsectlw, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vinsectlb, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_5(vshfq, 0, void, env, i64, i64, i64, i64) ++DEF_HELPER_FLAGS_4(vshfqb, 0, void, env, i64, i64, i64) ++DEF_HELPER_FLAGS_5(vsm3r, 0, void, env, i64, i64, i64, i64) ++ ++#ifndef CONFIG_USER_ONLY ++DEF_HELPER_FLAGS_2(fp_exc_raise, 0, void, env, i32) ++DEF_HELPER_FLAGS_2(pri_ldw, 0, i64, env, i64) ++DEF_HELPER_FLAGS_3(pri_stw, 0, void, env, i64, i64) ++DEF_HELPER_FLAGS_2(pri_ldl, 0, i64, env, i64) ++DEF_HELPER_FLAGS_3(pri_stl, 0, void, env, i64, i64) ++#endif ++ ++DEF_HELPER_3(excp, noreturn, env, int, int) ++//DEF_HELPER_FLAGS_3(faddh, TCG_CALL_NO_RWG, i64, env, i64, i64) ++//DEF_HELPER_FLAGS_3(fsubh, TCG_CALL_NO_RWG, i64, env, i64, i64) ++//DEF_HELPER_FLAGS_3(fmulh, TCG_CALL_NO_RWG, i64, env, i64, i64) ++#ifndef CONFIG_USER_ONLY ++/* Scale factor for core3 cpu freq, ie number of ns per tick. */ ++#define CPUFREQ_SCALE 3 ++#endif ++ ++/* SLAVE FLOAT HELPER. */ +diff --git a/target/sw64/int_helper.c b/target/sw64/int_helper.c +new file mode 100644 +index 0000000000..131182585a +--- /dev/null ++++ b/target/sw64/int_helper.c +@@ -0,0 +1,118 @@ ++#include "qemu/osdep.h" ++#include "cpu.h" ++#include "exec/exec-all.h" ++#include "exec/helper-proto.h" ++#include "qemu/host-utils.h" ++#include "exec/memattrs.h" ++ ++uint64_t helper_zapnot(uint64_t val, uint64_t mskb) ++{ ++ uint64_t mask; ++ ++ mask = -(mskb & 0x01) & 0x00000000000000ffull; ++ mask |= -(mskb & 0x02) & 0x000000000000ff00ull; ++ mask |= -(mskb & 0x04) & 0x0000000000ff0000ull; ++ mask |= -(mskb & 0x08) & 0x00000000ff000000ull; ++ mask |= -(mskb & 0x10) & 0x000000ff00000000ull; ++ mask |= -(mskb & 0x20) & 0x0000ff0000000000ull; ++ mask |= -(mskb & 0x40) & 0x00ff000000000000ull; ++ mask |= -(mskb & 0x80) & 0xff00000000000000ull; ++ ++ return val & mask; ++} ++ ++uint64_t helper_zap(uint64_t val, uint64_t mask) ++{ ++ return helper_zapnot(val, ~mask); ++} ++ ++uint64_t helper_cmpgeb(uint64_t va, uint64_t vb) ++{ ++ int i; ++ uint64_t ret = 0; ++ uint64_t tmp; ++ for (i = 0; i < 64; i += 8) { ++ tmp = ((va >> i) & 0xff) + (~(vb >> i) & 0xff) + 1; ++ ret |= (tmp >> 8) << (i / 8); ++ } ++ return ret; ++} ++ ++#ifndef CONFIG_USER_ONLY ++static inline MemTxAttrs cpu_get_mem_attrs(CPUSW64State *env) ++{ ++ return ((MemTxAttrs) { .secure = 1 }); ++} ++ ++static inline AddressSpace *cpu_addressspace(CPUState *cs, MemTxAttrs attrs) ++{ ++ return cpu_get_address_space(cs, cpu_asidx_from_attrs(cs, attrs)); ++} ++ ++uint64_t sw64_ldw_phys(CPUState *cs, hwaddr addr) ++{ ++ SW64CPU *cpu = SW64_CPU(cs); ++ int32_t ret; ++ CPUSW64State *env = &cpu->env; ++ MemTxAttrs attrs = cpu_get_mem_attrs(env); ++ AddressSpace *as = cpu_addressspace(cs, attrs); ++ ++ ret = (int32_t)address_space_ldl(as, addr, attrs, NULL); ++ ++ return (uint64_t)(int64_t)ret; ++} ++ ++void sw64_stw_phys(CPUState *cs, hwaddr addr, uint64_t val) ++{ ++ SW64CPU *cpu = SW64_CPU(cs); ++ CPUSW64State *env = &cpu->env; ++ MemTxAttrs attrs = cpu_get_mem_attrs(env); ++ AddressSpace *as = cpu_addressspace(cs, attrs); ++ ++ address_space_stl(as, addr, (uint32_t)val, attrs, NULL); ++} ++ ++uint64_t sw64_ldl_phys(CPUState *cs, hwaddr addr) ++{ ++ SW64CPU *cpu = SW64_CPU(cs); ++ CPUSW64State *env = &cpu->env; ++ MemTxAttrs attrs = cpu_get_mem_attrs(env); ++ AddressSpace *as = cpu_addressspace(cs, attrs); ++ ++ return address_space_ldq(as, addr, attrs, NULL); ++} ++ ++void sw64_stl_phys(CPUState *cs, hwaddr addr, uint64_t val) ++{ ++ SW64CPU *cpu = SW64_CPU(cs); ++ CPUSW64State *env = &cpu->env; ++ MemTxAttrs attrs = cpu_get_mem_attrs(env); ++ AddressSpace *as = cpu_addressspace(cs, attrs); ++ ++ address_space_stq(as, addr, val, attrs, NULL); ++} ++ ++uint64_t helper_pri_ldw(CPUSW64State *env, uint64_t hwaddr) ++{ ++ CPUState *cs = CPU(sw64_env_get_cpu(env)); ++ return sw64_ldw_phys(cs, hwaddr); ++} ++ ++void helper_pri_stw(CPUSW64State *env, uint64_t val, uint64_t hwaddr) ++{ ++ CPUState *cs = CPU(sw64_env_get_cpu(env)); ++ sw64_stw_phys(cs, hwaddr, val); ++} ++ ++uint64_t helper_pri_ldl(CPUSW64State *env, uint64_t hwaddr) ++{ ++ CPUState *cs = CPU(sw64_env_get_cpu(env)); ++ return sw64_ldl_phys(cs, hwaddr); ++} ++ ++void helper_pri_stl(CPUSW64State *env, uint64_t val, uint64_t hwaddr) ++{ ++ CPUState *cs = CPU(sw64_env_get_cpu(env)); ++ sw64_stl_phys(cs, hwaddr, val); ++} ++#endif +diff --git a/target/sw64/kvm.c b/target/sw64/kvm.c +new file mode 100644 +index 0000000000..fc134c83fb +--- /dev/null ++++ b/target/sw64/kvm.c +@@ -0,0 +1,215 @@ ++/* ++ * SW64 implementation of KVM hooks ++ * ++ * Copyright (c) 2018 Lin Hainan ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ * ++ */ ++ ++#include "qemu/osdep.h" ++#include ++ ++#include ++ ++#include "qemu-common.h" ++#include "qemu/timer.h" ++#include "qemu/error-report.h" ++#include "sysemu/sysemu.h" ++#include "sysemu/kvm.h" ++#include "kvm_sw64.h" ++#include "cpu.h" ++#include "exec/memattrs.h" ++#include "exec/address-spaces.h" ++#include "hw/boards.h" ++#include "qemu/log.h" ++ ++#define init_pc 0xffffffff80011000 ++const KVMCapabilityInfo kvm_arch_required_capabilities[] = { ++ KVM_CAP_LAST_INFO ++}; ++/* 50000 jump to bootlader while 2f00000 jump to bios*/ ++int kvm_sw64_vcpu_init(CPUState *cs) ++{ ++ struct kvm_regs *regs; ++ SW64CPU *cpu = SW64_CPU(cs); ++ regs = (struct kvm_regs *)cpu->k_regs; ++ regs->pc = init_pc; ++ return kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); ++} ++ ++static void kvm_sw64_host_cpu_class_init(ObjectClass *oc, void *data) ++{ ++} ++ ++static void kvm_sw64_host_cpu_initfn(Object *obj) ++{ ++} ++ ++ ++static const TypeInfo host_sw64_cpu_type_info = { ++ .name = TYPE_SW64_HOST_CPU, ++ .parent = TYPE_SW64_CPU, ++ .instance_init = kvm_sw64_host_cpu_initfn, ++ .class_init = kvm_sw64_host_cpu_class_init, ++ .class_size = sizeof(SW64HostCPUClass), ++}; ++ ++int kvm_arch_init(MachineState *ms, KVMState *s) ++{ ++ kvm_async_interrupts_allowed = true; ++ ++ type_register_static(&host_sw64_cpu_type_info); ++ ++ return 0; ++} ++ ++/* 50000 jump to bootlader while 2f00000 jump to bios*/ ++void kvm_sw64_reset_vcpu(SW64CPU *cpu) ++{ ++ CPUState *cs = CPU(cpu); ++ struct kvm_regs *regs; ++ int ret; ++ ++ regs = (struct kvm_regs *)cpu->k_regs; ++ regs->pc = init_pc; ++ ++ ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); ++ ++ if (ret < 0) { ++ fprintf(stderr, "kvm_sw64_vcpu_init failed: %s\n", strerror(-ret)); ++ abort(); ++ } ++ ++ ret = kvm_vcpu_ioctl(cs, KVM_SW64_VCPU_INIT, NULL); ++ ++ if (ret < 0) { ++ fprintf(stderr, "kvm_sw64_vcpu_init failed: %s\n", strerror(-ret)); ++ abort(); ++ } ++} ++ ++unsigned long kvm_arch_vcpu_id(CPUState *cpu) ++{ ++ return cpu->cpu_index; ++} ++ ++#include ++int kvm_arch_init_vcpu(CPUState *cs) ++{ ++ int ret; ++ ret = kvm_sw64_vcpu_init(cs); ++ if (ret) { ++ return ret; ++ } ++ return 0; ++} ++ ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ ++int kvm_arch_get_registers(CPUState *cs) ++{ ++ int ret; ++ SW64CPU *cpu = SW64_CPU(cs); ++ ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, &cpu->k_regs); ++ if (ret < 0) ++ return ret; ++ return kvm_vcpu_ioctl(cs, KVM_SW64_GET_VCB, &cpu->k_vcb); ++} ++ ++int kvm_arch_put_registers(CPUState *cs, int level) ++{ ++ int ret; ++ SW64CPU *cpu = SW64_CPU(cs); ++ struct vcpucb *vcb; ++ ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, &cpu->k_regs); ++ if (ret < 0) ++ return ret; ++ vcb = (struct vcpucb *)cpu->k_vcb; ++ vcb->whami = kvm_arch_vcpu_id(cs); ++ fprintf(stderr,"vcpu %ld init.\n", vcb->whami); ++ return kvm_vcpu_ioctl(cs, KVM_SW64_SET_VCB, &cpu->k_vcb); ++} ++ ++int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, ++ int vector, PCIDevice *dev) ++{ ++ return -1; ++} ++ ++int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, ++ uint64_t address, uint32_t data, PCIDevice *dev) ++{ ++ return 0; ++} ++ ++void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) ++{ ++} ++ ++MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) ++{ ++ return MEMTXATTRS_UNSPECIFIED; ++} ++ ++ ++int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) ++{ ++ return -1; ++} ++ ++bool kvm_arch_stop_on_emulation_error(CPUState *cs) ++{ ++ return true; ++} ++ ++int kvm_arch_process_async_events(CPUState *cs) ++{ ++ return 0; ++} ++ ++void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) ++{ ++} ++ ++void kvm_arch_init_irq_routing(KVMState *s) ++{ ++ /* We know at this point that we're using the in-kernel ++ * irqchip, so we can use irqfds, and on x86 we know ++ * we can use msi via irqfd and GSI routing. ++ */ ++ kvm_msi_via_irqfd_allowed = true; ++ kvm_gsi_routing_allowed = true; ++} ++ ++int kvm_arch_irqchip_create(KVMState *s) ++{ ++ return 0; ++} ++ ++int kvm_arch_release_virq_post(int virq) ++{ ++ return -1; ++} ++ ++int kvm_arch_msi_data_to_gsi(uint32_t data) ++{ ++ return -1; ++} ++ ++ ++void kvm_sw64_register_slave(SW64CPU *cpu) ++{ ++ CPUState *cs = CPU(cpu); ++ ++ kvm_vcpu_ioctl(cs, KVM_SW64_USE_SLAVE, NULL); ++} ++ ++bool kvm_arch_cpu_check_are_resettable(void) ++{ ++ return true; ++} +diff --git a/target/sw64/kvm_sw64.h b/target/sw64/kvm_sw64.h +new file mode 100644 +index 0000000000..5ebd4ec6fd +--- /dev/null ++++ b/target/sw64/kvm_sw64.h +@@ -0,0 +1,47 @@ ++/* ++ * QEMU KVM support -- SW64 specific functions. ++ * ++ * Copyright (c) 2018 Lin Hainan ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ * ++ */ ++ ++#ifndef QEMU_KVM_SW64_H ++#define QEMU_KVM_SW64_H ++ ++#include "sysemu/kvm.h" ++#include "exec/memory.h" ++#include "qemu/error-report.h" ++ ++/** ++ * kvm_sw64_vcpu_init: ++ * @cs: CPUState ++ * ++ * Initialize (or reinitialize) the VCPU by invoking the ++ * KVM_SW64_VCPU_INIT ioctl with the CPU type and feature ++ * bitmask specified in the CPUState. ++ * ++ * Returns: 0 if success else < 0 error code ++ */ ++int kvm_sw64_vcpu_init(CPUState *cs); ++void kvm_sw64_reset_vcpu(SW64CPU *cpu); ++void kvm_sw64_register_slave(SW64CPU *cpu); ++ ++#define TYPE_SW64_HOST_CPU "host-" TYPE_SW64_CPU ++#define SW64_HOST_CPU_CLASS(klass) \ ++ OBJECT_CLASS_CHECK(SW64HostCPUClass, (klass), TYPE_SW64_HOST_CPU) ++#define SW64_HOST_CPU_GET_CLASS(obj) \ ++ OBJECT_GET_CLASS(SW64HostCPUClass, (obj), TYPE_SW64_HOST_CPU) ++ ++typedef struct SW64HostCPUClass { ++ /*< private >*/ ++ SW64CPUClass parent_class; ++ /*< public >*/ ++ ++ uint64_t features; ++ uint32_t target; ++ const char *dtb_compatible; ++} SW64HostCPUClass; ++#endif +diff --git a/target/sw64/machine.c b/target/sw64/machine.c +new file mode 100644 +index 0000000000..df18d3faba +--- /dev/null ++++ b/target/sw64/machine.c +@@ -0,0 +1,18 @@ ++#include "qemu/osdep.h" ++#include "qemu-common.h" ++#include "cpu.h" ++#include "migration/vmstate.h" ++#include "migration/cpu.h" ++ ++VMStateDescription vmstate_sw64_cpu = { ++ .name = "cpu", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++#ifdef CONFIG_KVM ++ VMSTATE_UINTTL_ARRAY(k_regs, SW64CPU, 158), ++ VMSTATE_UINTTL_ARRAY(k_vcb, SW64CPU, 36), ++#endif ++ VMSTATE_END_OF_LIST() ++ } ++}; +diff --git a/target/sw64/meson.build b/target/sw64/meson.build +new file mode 100644 +index 0000000000..ee49e45927 +--- /dev/null ++++ b/target/sw64/meson.build +@@ -0,0 +1,19 @@ ++sw64_ss = ss.source_set() ++sw64_ss.add(files( ++ 'cpu.c', ++ 'exception.c', ++ 'float_helper.c', ++ 'helper.c', ++ 'int_helper.c', ++ 'profile.c', ++ 'simd_helper.c', ++ 'translate.c', ++)) ++ ++sw64_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) ++ ++sw64_softmmu_ss = ss.source_set() ++sw64_softmmu_ss.add(files('machine.c')) ++ ++target_arch += {'sw64': sw64_ss} ++target_softmmu_arch += {'sw64': sw64_softmmu_ss} +diff --git a/target/sw64/profile.c b/target/sw64/profile.c +new file mode 100644 +index 0000000000..73fe077234 +--- /dev/null ++++ b/target/sw64/profile.c +@@ -0,0 +1,2342 @@ ++#include "translate.h" ++ ++const char *insn_opc[535] = { ++ "sys_call", "call", "ret", "jmp", "br", "bsr", "memb", "imemb", ++ "wmemb", "rtc", "rcid", "halt", "rd_f", "wr_f", "rtid", ++ "csrws", "csrwc", "pri_rcsr", "pri_wcsr", "pri_ret", "lldw", "lldl", ++ "ldw_inc", "ldl_inc", "ldw_dec", "ldl_dec", "ldw_set", "ldl_set", "lstw", ++ "lstl", "ldw_nc", "ldl_nc", "ldd_nc", "stw_nc", "stl_nc", "std_nc", ++ "ldwe", "ldse", "ldde", "vlds", "vldd", "vsts", "vstd", ++ "fimovs", "fimovd", "addw", "subw", "s4addw", "s4subw", "s8addw", ++ "s8subw", "addl", "subl", "s4addl", "s4subl", "s8addl", "s8subl", ++ "mulw", "divw", "udivw", "remw", "uremw", "mull", "mulh", ++ "divl", "udivl", "reml", "ureml", "addpi", "addpis", "cmpeq", ++ "cmplt", "cmple", "cmpult", "cmpule", "sbt", "cbt", "and", ++ "bic", "bis", "ornot", "xor", "eqv", "inslb", "inslh", ++ "inslw", "insll", "inshb", "inshh", "inshw", "inshl", "slll", ++ "srll", "sral", "roll", "sllw", "srlw", "sraw", "rolw", ++ "extlb", "extlh", "extlw", "extll", "exthb", "exthh", "exthw", ++ "exthl", "ctpop", "ctlz", "cttz", "revbh", "revbw", "revbl", ++ "casw", "casl", "masklb", "masklh", "masklw", "maskll", "maskhb", ++ "maskhh", "maskhw", "maskhl", "zap", "zapnot", "sextb", "sexth", ++ "seleq", "selge", "selgt", "selle", "sellt", "selne", "sellbc", ++ "sellbs", "addwi", "subwi", "s4addwi", "s4subwi", "s8addwi", "s8subwi", ++ "addli", "subli", "s4addli", "s4subli", "s8addli", "s8subli", "mulwi", ++ "divwi", "udivwi", "remwi", "uremwi", "mulli", "mulhi", "divli", ++ "udivli", "remli", "uremli", "addpii", "addpisi", "cmpeqi", "cmplti", ++ "cmplei", "cmpulti", "cmpulei", "sbti", "cbti", "andi", "bici", ++ "bisi", "ornoti", "xori", "eqvi", "inslbi", "inslhi", "inslwi", ++ "inslli", "inshbi", "inshhi", "inshwi", "inshli", "sllli", "srlli", ++ "srali", "rolli", "sllwi", "srlwi", "srawi", "rolwi", "extlbi", ++ "extlhi", "extlwi", "extlli", "exthbi", "exthhi", "exthwi", "exthli", ++ "ctpopi", "ctlzi", "cttzi", "revbhi", "revbwi", "revbli", "caswi", ++ "casli", "masklbi", "masklhi", "masklwi", "masklli", "maskhbi", "maskhhi", ++ "maskhwi", "maskhli", "zapi", "zapnoti", "sextbi", "sexthi", "cmpgebi", ++ "seleqi", "selgei", "selgti", "sellei", "sellti", "selnei", "sellbci", ++ "sellbsi", "vlogzz", "fadds", "faddd", "fsubs", "fsubd", "fmuls", ++ "fmuld", "fdivs", "fdivd", "fsqrts", "fsqrtd", "fcmpeq", "fcmple", ++ "fcmplt", "fcmpun", "fcvtsd", "fcvtds", "fcvtdl_g", "fcvtdl_p", "fcvtdl_z", ++ "fcvtdl_n", "fcvtdl", "fcvtwl", "fcvtlw", "fcvtls", "fcvtld", "fcpys", ++ "fcpyse", "fcpysn", "ifmovs", "ifmovd", "rfpcr", "wfpcr", "setfpec0", ++ "setfpec1", "setfpec2", "setfpec3", "frecs", "frecd", "fris", "fris_g", ++ "fris_p", "fris_z", "fris_n", "frid", "frid_g", "frid_p", "frid_z", ++ "frid_n", "fmas", "fmad", "fmss", "fmsd", "fnmas", "fnmad", ++ "fnmss", "fnmsd", "fseleq", "fselne", "fsellt", "fselle", "fselgt", ++ "fselge", "vaddw", "vaddwi", "vsubw", "vsubwi", "vcmpgew", "vcmpgewi", ++ "vcmpeqw", "vcmpeqwi", "vcmplew", "vcmplewi", "vcmpltw", "vcmpltwi", "vcmpulew", ++ "vcmpulewi", "vcmpultw", "vcmpultwi", "vsllw", "vsllwi", "vsrlw", "vsrlwi", ++ "vsraw", "vsrawi", "vrolw", "vrolwi", "sllow", "sllowi", "srlow", ++ "srlowi", "vaddl", "vaddli", "vsubl", "vsubli", "vsllb", "vsllbi", ++ "vsrlb", "vsrlbi", "vsrab", "vsrabi", "vrolb", "vrolbi", "vsllh", ++ "vsllhi", "vsrlh", "vsrlhi", "vsrah", "vsrahi", "vrolh", "vrolhi", ++ "ctpopow", "ctlzow", "vslll", "vsllli", "vsrll", "vsrlli", "vsral", ++ "vsrali", "vroll", "vrolli", "vmaxb", "vminb", "vucaddw", "vucaddwi", ++ "vucsubw", "vucsubwi", "vucaddh", "vucaddhi", "vucsubh", "vucsubhi", "vucaddb", ++ "vucaddbi", "vucsubb", "vucsubbi", "sraow", "sraowi", "vsumw", "vsuml", ++ "vsm4r", "vbinvw", "vcmpueqb", "vcmpugtb", "vcmpugtbi", "vsm3msw", "vmaxh", ++ "vminh", "vmaxw", "vminw", "vmaxl", "vminl", "vumaxb", "vuminb", ++ "vumaxh", "vuminh", "vumaxw", "vuminw", "vumaxl", "vuminl", "vsm4key", ++ "vadds", "vaddd", "vsubs", "vsubd", "vmuls", "vmuld", "vdivs", ++ "vdivd", "vsqrts", "vsqrtd", "vfcmpeq", "vfcmple", "vfcmplt", "vfcmpun", ++ "vcpys", "vcpyse", "vcpysn", "vsums", "vsumd", "vfcvtsd", "vfcvtds", ++ "vfcvtls", "vfcvtld", "vfcvtdl", "vfcvtdl_g", "vfcvtdl_p", "vfcvtdl_z", "vfcvtdl_n", ++ "vfris", "vfris_g", "vfris_p", "vfris_z", "vfris_n", "vfrid", "vfrid_g", ++ "vfrid_p", "vfrid_z", "vfrid_n", "vfrecs", "vfrecd", "vmaxs", "vmins", ++ "vmaxd", "vmind", "vmas", "vmad", "vmss", "vmsd", "vnmas", ++ "vnmad", "vnmss", "vnmsd", "vfseleq", "vfsellt", "vfselle", "vseleqw", ++ "vseleqwi", "vsellbcw", "vsellbcwi", "vselltw", "vselltwi", "vsellew", "vsellewi", ++ "vinsw", "vinsf", "vextw", "vextf", "vcpyw", "vcpyf", "vconw", ++ "vshfw", "vcons", "vcond", "vinsb", "vinsh", "vinsectlh", "vinsectlw", ++ "vinsectll", "vinsectlb", "vshfq", "vshfqb", "vcpyb", "vcpyh", "vsm3r", ++ "vfcvtsh", "vfcvths", "vldw_u", "vstw_u", "vlds_u", "vsts_u", "vldd_u", ++ "vstd_u", "vstw_ul", "vstw_uh", "vsts_ul", "vsts_uh", "vstd_ul", "vstd_uh", ++ "vldd_nc", "vstd_nc", "lbr", "ldbu_a", "ldhu_a", "ldw_a", "ldl_a", ++ "flds_a", "fldd_a", "stbu_a", "sthu_a", "stw_a", "stl_a", "fsts_a", ++ "fstd_a", "dpfhr", "dpfhw", "ldbu", "ldhu", "ldw", "ldl", ++ "ldl_u", "pri_ldl", "pri_ldw", "flds", "fldd", "stb", "sth", ++ "stw", "stl", "stl_u", "pri_stl", "pri_stw", "fsts", "fstd", ++ "beq", "bne", "blt", "ble", "bgt", "bge", "blbc", ++ "blbs", "fbeq", "fbne", "fblt", "fble", "fbgt", "fbge", ++ "ldih", "ldi", }; ++ ++void insn_profile(DisasContext *ctx, uint32_t insn) ++{ ++ int32_t disp16, disp26 __attribute__((unused)); ++ uint8_t opc; ++ uint16_t fn3, fn4, fn6, fn8, fn11; ++ TCGv count; ++ int index, offs; ++ ++ opc = extract32(insn, 26, 6); ++ ++ fn3 = extract32(insn, 10, 3); ++ fn6 = extract32(insn, 10, 6); ++ fn4 = extract32(insn, 12, 4); ++ fn8 = extract32(insn, 5, 8); ++ fn11 = extract32(insn, 5, 11); ++ ++ disp16 = sextract32(insn, 0, 16); ++ disp26 = sextract32(insn, 0, 26); ++ ++ index = 0; ++ switch (opc) { ++ case 0x00: ++ /* SYS_CALL */ ++ index = SYS_CALL; ++ break; ++ case 0x01: ++ /* CALL */ ++ index = CALL; ++ break; ++ case 0x02: ++ /* RET */ ++ index = RET; ++ break; ++ case 0x03: ++ /* JMP */ ++ index = JMP; ++ break; ++ case 0x04: ++ /* BR */ ++ index = BR; ++ break; ++ case 0x05: ++ /* BSR */ ++ index = BSR; ++ break; ++ case 0x06: ++ switch (disp16) { ++ case 0x0000: ++ /* MEMB */ ++ index = MEMB; ++ break; ++ case 0x0001: ++ /* IMEMB */ ++ index = IMEMB; ++ break; ++ case 0x0002: ++ /* WMEMB */ ++ index = WMEMB; ++ break; ++ case 0x0020: ++ /* RTC */ ++ index = RTC; ++ break; ++ case 0x0040: ++ /* RCID */ ++ index = RCID; ++ break; ++ case 0x0080: ++ /* HALT */ ++ index = HALT; ++ break; ++ case 0x1000: ++ /* RD_F */ ++ index = RD_F; ++ break; ++ case 0x1020: ++ /* WR_F */ ++ index = WR_F; ++ break; ++ case 0x1040: ++ /* RTID */ ++ index = RTID; ++ break; ++ default: ++ if ((disp16 & 0xFF00) == 0xFC00) { ++ /* CSRWS */ ++ index = CSRWS; ++ break; ++ } ++ if ((disp16 & 0xFF00) == 0xFD00) { ++ /* CSRWC */ ++ index = CSRWC; ++ break; ++ } ++ if ((disp16 & 0xFF00) == 0xFE00) { ++ /* PRI_RCSR */ ++ index = PRI_RCSR; ++ break; ++ } ++ if ((disp16 & 0xFF00) == 0xFF00) { ++ /* PRI_WCSR */ ++ index = PRI_WCSR; ++ break; ++ } ++ goto do_invalid; ++ } ++ break; ++ case 0x07: ++ /* PRI_RET */ ++ index = PRI_RET; ++ break; ++ case 0x08: ++ switch (fn4) { ++ case 0x0: ++ /* LLDW */ ++ index = LLDW; ++ break; ++ case 0x1: ++ /* LLDL */ ++ index = LLDL; ++ break; ++ case 0x2: ++ /* LDW_INC */ ++ index = LDW_INC; ++ break; ++ case 0x3: ++ /* LDL_INC */ ++ index = LDL_INC; ++ break; ++ case 0x4: ++ /* LDW_DEC */ ++ index = LDW_DEC; ++ break; ++ case 0x5: ++ /* LDL_DEC */ ++ index = LDL_DEC; ++ break; ++ case 0x6: ++ /* LDW_SET */ ++ index = LDW_SET; ++ break; ++ case 0x7: ++ /* LDL_SET */ ++ index = LDL_SET; ++ break; ++ case 0x8: ++ /* LSTW */ ++ index = LSTW; ++ break; ++ case 0x9: ++ /* LSTL */ ++ index = LSTL; ++ break; ++ case 0xa: ++ /* LDW_NC */ ++ index = LDW_NC; ++ break; ++ case 0xb: ++ /* LDL_NC */ ++ index = LDL_NC; ++ break; ++ case 0xc: ++ /* LDD_NC */ ++ index = LDD_NC; ++ break; ++ case 0xd: ++ /* STW_NC */ ++ index = STW_NC; ++ break; ++ case 0xe: ++ /* STL_NC */ ++ index = STL_NC; ++ break; ++ case 0xf: ++ /* STD_NC */ ++ index = STD_NC; ++ break; ++ default: ++ goto do_invalid; ++ } ++ break; ++ case 0x9: ++ /* LDWE */ ++ index = LDWE; ++ break; ++ case 0x0a: ++ /* LDSE */ ++ index = LDSE; ++ break; ++ case 0x0b: ++ /* LDDE */ ++ index = LDDE; ++ break; ++ case 0x0c: ++ /* VLDS */ ++ index = VLDS; ++ break; ++ case 0x0d: ++ /* VLDD */ ++ index = VLDD; ++ break; ++ case 0x0e: ++ /* VSTS */ ++ index = VSTS; ++ break; ++ case 0x0f: ++ /* VSTD */ ++ index = VSTD; ++ break; ++ case 0x10: ++ if (fn11 == 0x70) { ++ /* FIMOVS */ ++ index = FIMOVS; ++ } else if (fn11 == 0x78) { ++ /* FIMOVD */ ++ index = FIMOVD; ++ } else { ++ switch (fn11 & 0xff) { ++ case 0x00: ++ /* ADDW */ ++ index = ADDW; ++ break; ++ case 0x01: ++ /* SUBW */ ++ index = SUBW; ++ break; ++ case 0x02: ++ /* S4ADDW */ ++ index = S4ADDW; ++ break; ++ case 0x03: ++ /* S4SUBW */ ++ index = S4SUBW; ++ break; ++ case 0x04: ++ /* S8ADDW */ ++ index = S8ADDW; ++ break; ++ case 0x05: ++ /* S8SUBW */ ++ index = S8SUBW; ++ break; ++ ++ case 0x08: ++ /* ADDL */ ++ index = ADDL; ++ break; ++ case 0x09: ++ /* SUBL */ ++ index = SUBL; ++ break; ++ case 0x0a: ++ /* S4ADDL */ ++ index = S4ADDL; ++ break; ++ case 0x0b: ++ /* S4SUBL */ ++ index = S4SUBL; ++ break; ++ case 0x0c: ++ /* S8ADDL */ ++ index = S8ADDL; ++ break; ++ case 0x0d: ++ /* S8SUBL */ ++ index = S8SUBL; ++ break; ++ case 0x10: ++ /* MULW */ ++ index = MULW; ++ break; ++ case 0x11: ++ /* DIVW */ ++ index = DIVW; ++ break; ++ case 0x12: ++ /* UDIVW */ ++ index = UDIVW; ++ break; ++ case 0x13: ++ /* REMW */ ++ index = REMW; ++ break; ++ case 0x14: ++ /* UREMW */ ++ index = UREMW; ++ break; ++ case 0x18: ++ /* MULL */ ++ index = MULL; ++ break; ++ case 0x19: ++ /* MULH */ ++ index = MULH; ++ break; ++ case 0x1A: ++ /* DIVL */ ++ index = DIVL; ++ break; ++ case 0x1B: ++ /* UDIVL */ ++ index = UDIVL; ++ break; ++ case 0x1C: ++ /* REML */ ++ index = REML; ++ break; ++ case 0x1D: ++ /* UREML */ ++ index = UREML; ++ break; ++ case 0x1E: ++ /* ADDPI */ ++ index = ADDPI; ++ break; ++ case 0x1F: ++ /* ADDPIS */ ++ index = ADDPIS; ++ break; ++ case 0x28: ++ /* CMPEQ */ ++ index = CMPEQ; ++ break; ++ case 0x29: ++ /* CMPLT */ ++ index = CMPLT; ++ break; ++ case 0x2a: ++ /* CMPLE */ ++ index = CMPLE; ++ break; ++ case 0x2b: ++ /* CMPULT */ ++ index = CMPULT; ++ break; ++ case 0x2c: ++ /* CMPULE */ ++ index = CMPULE; ++ break; ++ case 0x2D: ++ /* SBT */ ++ index = SBT; ++ break; ++ case 0x2E: ++ /* CBT */ ++ index = CBT; ++ break; ++ case 0x38: ++ /* AND */ ++ index = AND; ++ break; ++ case 0x39: ++ /* BIC */ ++ index = BIC; ++ break; ++ case 0x3a: ++ /* BIS */ ++ index = BIS; ++ break; ++ case 0x3b: ++ /* ORNOT */ ++ index = ORNOT; ++ break; ++ case 0x3c: ++ /* XOR */ ++ index = XOR; ++ break; ++ case 0x3d: ++ /* EQV */ ++ index = EQV; ++ break; ++ case 0x40: ++ /* INSLB */ ++ index = INSLB; ++ break; ++ case 0x41: ++ /* INSLH */ ++ index = INSLH; ++ break; ++ case 0x42: ++ /* INSLW */ ++ index = INSLW; ++ break; ++ case 0x43: ++ /* INSLL */ ++ index = INSLL; ++ break; ++ case 0x44: ++ /* INSHB */ ++ index = INSHB; ++ break; ++ case 0x45: ++ /* INSHH */ ++ index = INSHH; ++ break; ++ case 0x46: ++ /* INSHW */ ++ index = INSHW; ++ break; ++ case 0x47: ++ /* INSHL */ ++ index = INSHL; ++ break; ++ case 0x48: ++ /* SLLL */ ++ index = SLLL; ++ break; ++ case 0x49: ++ /* SRLL */ ++ index = SRLL; ++ break; ++ case 0x4a: ++ /* SRAL */ ++ index = SRAL; ++ break; ++ case 0x4B: ++ /* ROLL */ ++ index = ROLL; ++ break; ++ case 0x4C: ++ /* SLLW */ ++ index = SLLW; ++ break; ++ case 0x4D: ++ /* SRLW */ ++ index = SRLW; ++ break; ++ case 0x4E: ++ /* SRAW */ ++ index = SRAW; ++ break; ++ case 0x4F: ++ /* ROLW */ ++ index = ROLW; ++ break; ++ case 0x50: ++ /* EXTLB */ ++ index = EXTLB; ++ break; ++ case 0x51: ++ /* EXTLH */ ++ index = EXTLH; ++ break; ++ case 0x52: ++ /* EXTLW */ ++ index = EXTLW; ++ break; ++ case 0x53: ++ /* EXTLL */ ++ index = EXTLL; ++ break; ++ case 0x54: ++ /* EXTHB */ ++ index = EXTHB; ++ break; ++ case 0x55: ++ /* EXTHH */ ++ index = EXTHH; ++ break; ++ case 0x56: ++ /* EXTHW */ ++ index = EXTHW; ++ break; ++ case 0x57: ++ /* EXTHL */ ++ index = EXTHL; ++ break; ++ case 0x58: ++ /* CTPOP */ ++ index = CTPOP; ++ break; ++ case 0x59: ++ /* CTLZ */ ++ index = CTLZ; ++ break; ++ case 0x5a: ++ /* CTTZ */ ++ index = CTTZ; ++ break; ++ case 0x5B: ++ /* REVBH */ ++ index = REVBH; ++ break; ++ case 0x5C: ++ /* REVBW */ ++ index = REVBW; ++ break; ++ case 0x5D: ++ /* REVBL */ ++ index = REVBL; ++ break; ++ case 0x5E: ++ /* CASW */ ++ index = CASW; ++ break; ++ case 0x5F: ++ /* CASL */ ++ index = CASL; ++ break; ++ case 0x60: ++ /* MASKLB */ ++ index = MASKLB; ++ break; ++ case 0x61: ++ /* MASKLH */ ++ index = MASKLH; ++ break; ++ case 0x62: ++ /* MASKLW */ ++ index = MASKLW; ++ break; ++ case 0x63: ++ /* MASKLL */ ++ index = MASKLL; ++ break; ++ case 0x64: ++ /* MASKHB */ ++ index = MASKHB; ++ break; ++ case 0x65: ++ /* MASKHH */ ++ index = MASKHH; ++ break; ++ case 0x66: ++ /* MASKHW */ ++ index = MASKHW; ++ break; ++ case 0x67: ++ /* MASKHL */ ++ index = MASKHL; ++ break; ++ case 0x68: ++ /* ZAP */ ++ index = ZAP; ++ break; ++ case 0x69: ++ /* ZAPNOT */ ++ index = ZAPNOT; ++ break; ++ case 0x6a: ++ /* SEXTB */ ++ index = SEXTB; ++ break; ++ case 0x6b: ++ /* SEXTH */ ++ index = SEXTH; ++ break; ++ case 0x6c: ++ /* CMPGEB*/ ++ break; ++ default: ++ break; ++ } ++ } ++ break; ++ case 0x11: ++ switch (fn3) { ++ case 0x0: ++ /* SELEQ */ ++ index = SELEQ; ++ break; ++ case 0x1: ++ /* SELGE */ ++ index = SELGE; ++ break; ++ case 0x2: ++ /* SELGT */ ++ index = SELGT; ++ break; ++ case 0x3: ++ /* SELLE */ ++ index = SELLE; ++ break; ++ case 0x4: ++ /* SELLT */ ++ index = SELLT; ++ break; ++ case 0x5: ++ /* SELNE */ ++ index = SELNE; ++ break; ++ case 0x6: ++ /* SELLBC */ ++ index = SELLBC; ++ break; ++ case 0x7: ++ /* SELLBS */ ++ index = SELLBS; ++ break; ++ default: ++ break; ++ } ++ break; ++ case 0x12: ++ switch (fn8 & 0xff) { ++ case 0x00: ++ /* ADDWI */ ++ index = ADDWI; ++ break; ++ case 0x01: ++ /* SUBWI */ ++ index = SUBWI; ++ break; ++ case 0x02: ++ /* S4ADDWI */ ++ index = S4ADDWI; ++ break; ++ case 0x03: ++ /* S4SUBWI */ ++ index = S4SUBWI; ++ break; ++ case 0x04: ++ /* S8ADDWI */ ++ index = S8ADDWI; ++ break; ++ case 0x05: ++ /* S8SUBWI */ ++ index = S8SUBWI; ++ break; ++ ++ case 0x08: ++ /* ADDLI */ ++ index = ADDLI; ++ break; ++ case 0x09: ++ /* SUBLI */ ++ index = SUBLI; ++ break; ++ case 0x0a: ++ /* S4ADDLI */ ++ index = S4ADDLI; ++ break; ++ case 0x0b: ++ /* S4SUBLI */ ++ index = S4SUBLI; ++ break; ++ case 0x0c: ++ /* S8ADDLI */ ++ index = S8ADDLI; ++ break; ++ case 0x0d: ++ /* S8SUBLI */ ++ index = S8SUBLI; ++ break; ++ case 0x10: ++ /* MULWI */ ++ index = MULWI; ++ break; ++ case 0x11: ++ /* DIVWI */ ++ index = DIVWI; ++ break; ++ case 0x12: ++ /* UDIVWI */ ++ index = UDIVWI; ++ break; ++ case 0x13: ++ /* REMWI */ ++ index = REMWI; ++ break; ++ case 0x14: ++ /* UREMWI */ ++ index = UREMWI; ++ break; ++ case 0x18: ++ /* MULLI */ ++ index = MULLI; ++ break; ++ case 0x19: ++ /* MULHI */ ++ index = MULHI; ++ break; ++ case 0x1A: ++ /* DIVLI */ ++ index = DIVLI; ++ break; ++ case 0x1B: ++ /* UDIVLI */ ++ index = UDIVLI; ++ break; ++ case 0x1C: ++ /* REMLI */ ++ index = REMLI; ++ break; ++ case 0x1D: ++ /* UREMLI */ ++ index = UREMLI; ++ break; ++ case 0x1E: ++ /* ADDPII */ ++ index = ADDPII; ++ break; ++ case 0x1F: ++ /* ADDPISI */ ++ index = ADDPISI; ++ break; ++ case 0x28: ++ /* CMPEQI */ ++ index = CMPEQI; ++ break; ++ case 0x29: ++ /* CMPLTI */ ++ index = CMPLTI; ++ break; ++ case 0x2a: ++ /* CMPLEI */ ++ index = CMPLEI; ++ break; ++ case 0x2b: ++ /* CMPULTI */ ++ index = CMPULTI; ++ break; ++ case 0x2c: ++ /* CMPULEI */ ++ index = CMPULEI; ++ break; ++ case 0x2D: ++ /* SBTI */ ++ index = SBTI; ++ break; ++ case 0x2E: ++ /* CBTI */ ++ index = CBTI; ++ break; ++ case 0x38: ++ /* ANDI */ ++ index = ANDI; ++ break; ++ case 0x39: ++ /* BICI */ ++ index = BICI; ++ break; ++ case 0x3a: ++ /* BISI */ ++ index = BISI; ++ break; ++ case 0x3b: ++ /* ORNOTI */ ++ index = ORNOTI; ++ break; ++ case 0x3c: ++ /* XORI */ ++ index = XORI; ++ break; ++ case 0x3d: ++ /* EQVI */ ++ index = EQVI; ++ break; ++ case 0x40: ++ /* INSLBI */ ++ index = INSLBI; ++ break; ++ case 0x41: ++ /* INSLHI */ ++ index = INSLHI; ++ break; ++ case 0x42: ++ /* INSLWI */ ++ index = INSLWI; ++ break; ++ case 0x43: ++ /* INSLLI */ ++ index = INSLLI; ++ break; ++ case 0x44: ++ /* INSHBI */ ++ index = INSHBI; ++ break; ++ case 0x45: ++ /* INSHHI */ ++ index = INSHHI; ++ break; ++ case 0x46: ++ /* INSHWI */ ++ index = INSHWI; ++ break; ++ case 0x47: ++ /* INSHLI */ ++ index = INSHLI; ++ break; ++ case 0x48: ++ /* SLLLI */ ++ index = SLLLI; ++ break; ++ case 0x49: ++ /* SRLLI */ ++ index = SRLLI; ++ break; ++ case 0x4a: ++ /* SRALI */ ++ index = SRALI; ++ break; ++ case 0x4B: ++ /* ROLLI */ ++ index = ROLLI; ++ break; ++ case 0x4C: ++ /* SLLWI */ ++ index = SLLWI; ++ break; ++ case 0x4D: ++ /* SRLWI */ ++ index = SRLWI; ++ break; ++ case 0x4E: ++ /* SRAWI */ ++ index = SRAWI; ++ break; ++ case 0x4F: ++ /* ROLWI */ ++ index = ROLWI; ++ break; ++ case 0x50: ++ /* EXTLBI */ ++ index = EXTLBI; ++ break; ++ case 0x51: ++ /* EXTLHI */ ++ index = EXTLHI; ++ break; ++ case 0x52: ++ /* EXTLWI */ ++ index = EXTLWI; ++ break; ++ case 0x53: ++ /* EXTLLI */ ++ index = EXTLLI; ++ break; ++ case 0x54: ++ /* EXTHBI */ ++ index = EXTHBI; ++ break; ++ case 0x55: ++ /* EXTHHI */ ++ index = EXTHHI; ++ break; ++ case 0x56: ++ /* EXTHWI */ ++ index = EXTHWI; ++ break; ++ case 0x57: ++ /* EXTHLI */ ++ index = EXTHLI; ++ break; ++ case 0x58: ++ /* CTPOPI */ ++ index = CTPOPI; ++ break; ++ case 0x59: ++ /* CTLZI */ ++ index = CTLZI; ++ break; ++ case 0x5a: ++ /* CTTZI */ ++ index = CTTZI; ++ break; ++ case 0x5B: ++ /* REVBHI */ ++ index = REVBHI; ++ break; ++ case 0x5C: ++ /* REVBWI */ ++ index = REVBWI; ++ break; ++ case 0x5D: ++ /* REVBLI */ ++ index = REVBLI; ++ break; ++ case 0x5E: ++ /* CASWI */ ++ index = CASWI; ++ break; ++ case 0x5F: ++ /* CASLI */ ++ index = CASLI; ++ break; ++ case 0x60: ++ /* MASKLBI */ ++ index = MASKLBI; ++ break; ++ case 0x61: ++ /* MASKLHI */ ++ index = MASKLHI; ++ break; ++ case 0x62: ++ /* MASKLWI */ ++ index = MASKLWI; ++ break; ++ case 0x63: ++ /* MASKLLI */ ++ index = MASKLLI; ++ break; ++ case 0x64: ++ /* MASKHBI */ ++ index = MASKHBI; ++ break; ++ case 0x65: ++ /* MASKHHI */ ++ index = MASKHHI; ++ break; ++ case 0x66: ++ /* MASKHWI */ ++ index = MASKHWI; ++ break; ++ case 0x67: ++ /* MASKHLI */ ++ index = MASKHLI; ++ break; ++ case 0x68: ++ /* ZAPI */ ++ index = ZAPI; ++ break; ++ case 0x69: ++ /* ZAPNOTI */ ++ index = ZAPNOTI; ++ break; ++ case 0x6a: ++ /* SEXTBI */ ++ index = SEXTBI; ++ break; ++ case 0x6b: ++ /* SEXTHI */ ++ index = SEXTHI; ++ break; ++ case 0x6c: ++ /* CMPGEBI */ ++ index = CMPGEBI; ++ break; ++ default: ++ break; ++ } ++ break; ++ case 0x13: ++ switch (fn3) { ++ case 0x0: ++ /* SELEQI */ ++ index = SELEQI; ++ break; ++ case 0x1: ++ /* SELGEI */ ++ index = SELGEI; ++ break; ++ case 0x2: ++ /* SELGTI */ ++ index = SELGTI; ++ break; ++ case 0x3: ++ /* SELLEI */ ++ index = SELLEI; ++ break; ++ case 0x4: ++ /* SELLTI */ ++ index = SELLTI; ++ break; ++ case 0x5: ++ /* SELNEI */ ++ index = SELNEI; ++ break; ++ case 0x6: ++ /* SELLBCI */ ++ index = SELLBCI; ++ break; ++ case 0x7: ++ /* SELLBSI */ ++ index = SELLBSI; ++ break; ++ default: ++ break; ++ } ++ break; ++ case 0x14: ++ case 0x15: ++ case 0x16: ++ case 0x17: ++ /* VLOGZZ */ ++ index = VLOGZZ; ++ break; ++ case 0x18: ++ switch (fn8) { ++ case 0x00: ++ /* FADDS */ ++ index = FADDS; ++ break; ++ case 0x01: ++ /* FADDD */ ++ index = FADDD; ++ break; ++ case 0x02: ++ /* FSUBS */ ++ index = FSUBS; ++ break; ++ case 0x03: ++ /* FSUBD */ ++ index = FSUBD; ++ break; ++ case 0x4: ++ /* FMULS */ ++ index = FMULS; ++ break; ++ case 0x05: ++ /* FMULD */ ++ index = FMULD; ++ break; ++ case 0x06: ++ /* FDIVS */ ++ index = FDIVS; ++ break; ++ case 0x07: ++ /* FDIVD */ ++ index = FDIVD; ++ break; ++ case 0x08: ++ /* FSQRTS */ ++ index = FSQRTS; ++ break; ++ case 0x09: ++ /* FSQRTD */ ++ index = FSQRTD; ++ break; ++ case 0x10: ++ /* FCMPEQ */ ++ index = FCMPEQ; ++ break; ++ case 0x11: ++ /* FCMPLE */ ++ index = FCMPLE; ++ break; ++ case 0x12: ++ /* FCMPLT */ ++ index = FCMPLT; ++ break; ++ case 0x13: ++ /* FCMPUN */ ++ index = FCMPUN; ++ break; ++ case 0x20: ++ /* FCVTSD */ ++ index = FCVTSD; ++ break; ++ case 0x21: ++ /* FCVTDS */ ++ index = FCVTDS; ++ break; ++ case 0x22: ++ /* FCVTDL_G */ ++ index = FCVTDL_G; ++ break; ++ case 0x23: ++ /* FCVTDL_P */ ++ index = FCVTDL_P; ++ break; ++ case 0x24: ++ /* FCVTDL_Z */ ++ index = FCVTDL_Z; ++ break; ++ case 0x25: ++ /* FCVTDL_N */ ++ index = FCVTDL_N; ++ break; ++ case 0x27: ++ /* FCVTDL */ ++ index = FCVTDL; ++ break; ++ case 0x28: ++ /* FCVTWL */ ++ index = FCVTWL; ++ break; ++ case 0x29: ++ /* FCVTLW */ ++ index = FCVTLW; ++ break; ++ case 0x2d: ++ /* FCVTLS */ ++ index = FCVTLS; ++ break; ++ case 0x2f: ++ /* FCVTLD */ ++ index = FCVTLD; ++ break; ++ case 0x30: ++ /* FCPYS */ ++ index = FCPYS; ++ break; ++ case 0x31: ++ /* FCPYSE */ ++ index = FCPYSE; ++ break; ++ case 0x32: ++ /* FCPYSN */ ++ index = FCPYSN; ++ break; ++ case 0x40: ++ /* IFMOVS */ ++ index = IFMOVS; ++ break; ++ case 0x41: ++ /* IFMOVD */ ++ index = IFMOVD; ++ break; ++ case 0x50: ++ /* RFPCR */ ++ index = RFPCR; ++ break; ++ case 0x51: ++ /* WFPCR */ ++ index = WFPCR; ++ break; ++ case 0x54: ++ /* SETFPEC0 */ ++ index = SETFPEC0; ++ break; ++ case 0x55: ++ /* SETFPEC1 */ ++ index = SETFPEC1; ++ break; ++ case 0x56: ++ /* SETFPEC2 */ ++ index = SETFPEC2; ++ break; ++ case 0x57: ++ /* SETFPEC3 */ ++ index = SETFPEC3; ++ break; ++ case 0x58: ++ /* FRECS */ ++ index = FRECS; ++ break; ++ case 0x59: ++ /* FRECD */ ++ index = FRECD; ++ break; ++ case 0x5A: ++ /* FRIS */ ++ index = FRIS; ++ break; ++ case 0x5B: ++ /* FRIS_G */ ++ index = FRIS_G; ++ break; ++ case 0x5C: ++ /* FRIS_P */ ++ index = FRIS_P; ++ break; ++ case 0x5D: ++ /* FRIS_Z */ ++ index = FRIS_Z; ++ break; ++ case 0x5F: ++ /* FRIS_N */ ++ index = FRIS_N; ++ break; ++ case 0x60: ++ /* FRID */ ++ index = FRID; ++ break; ++ case 0x61: ++ /* FRID_G */ ++ index = FRID_G; ++ break; ++ case 0x62: ++ /* FRID_P */ ++ index = FRID_P; ++ break; ++ case 0x63: ++ /* FRID_Z */ ++ index = FRID_Z; ++ break; ++ case 0x64: ++ /* FRID_N */ ++ index = FRID_N; ++ break; ++ default: ++ break; ++ } ++ break; ++ case 0x19: ++ switch (fn6) { ++ case 0x00: ++ /* FMAS */ ++ index = FMAS; ++ break; ++ case 0x01: ++ /* FMAD */ ++ index = FMAD; ++ break; ++ case 0x02: ++ /* FMSS */ ++ index = FMSS; ++ break; ++ case 0x03: ++ /* FMSD */ ++ index = FMSD; ++ break; ++ case 0x04: ++ /* FNMAS */ ++ index = FNMAS; ++ break; ++ case 0x05: ++ /* FNMAD */ ++ index = FNMAD; ++ break; ++ case 0x06: ++ /* FNMSS */ ++ index = FNMSS; ++ break; ++ case 0x07: ++ /* FNMSD */ ++ index = FNMSD; ++ break; ++ case 0x10: ++ /* FSELEQ */ ++ index = FSELEQ; ++ break; ++ case 0x11: ++ /* FSELNE */ ++ index = FSELNE; ++ break; ++ case 0x12: ++ /* FSELLT */ ++ index = FSELLT; ++ break; ++ case 0x13: ++ /* FSELLE */ ++ index = FSELLE; ++ break; ++ case 0x14: ++ /* FSELGT */ ++ index = FSELGT; ++ break; ++ case 0x15: ++ /* FSELGE */ ++ index = FSELGE; ++ break; ++ default: ++ break; ++ } ++ break; ++ case 0x1A: ++ switch (fn8) { ++ case 0x00: ++ /* VADDW */ ++ index = VADDW; ++ break; ++ case 0x20: ++ /* VADDWI */ ++ index = VADDWI; ++ break; ++ case 0x01: ++ /* VSUBW */ ++ index = VSUBW; ++ break; ++ case 0x21: ++ /* VSUBWI */ ++ index = VSUBWI; ++ break; ++ case 0x02: ++ /* VCMPGEW */ ++ index = VCMPGEW; ++ break; ++ case 0x22: ++ /* VCMPGEWI */ ++ index = VCMPGEWI; ++ break; ++ case 0x03: ++ /* VCMPEQW */ ++ index = VCMPEQW; ++ break; ++ case 0x23: ++ /* VCMPEQWI */ ++ index = VCMPEQWI; ++ break; ++ case 0x04: ++ /* VCMPLEW */ ++ index = VCMPLEW; ++ break; ++ case 0x24: ++ /* VCMPLEWI */ ++ index = VCMPLEWI; ++ break; ++ case 0x05: ++ /* VCMPLTW */ ++ index = VCMPLTW; ++ break; ++ case 0x25: ++ /* VCMPLTWI */ ++ index = VCMPLTWI; ++ break; ++ case 0x06: ++ /* VCMPULEW */ ++ index = VCMPULEW; ++ break; ++ case 0x26: ++ /* VCMPULEWI */ ++ index = VCMPULEWI; ++ break; ++ case 0x07: ++ /* VCMPULTW */ ++ index = VCMPULTW; ++ break; ++ case 0x27: ++ /* VCMPULTWI */ ++ index = VCMPULTWI; ++ break; ++ case 0x08: ++ /* VSLLW */ ++ index = VSLLW; ++ break; ++ case 0x28: ++ /* VSLLWI */ ++ index = VSLLWI; ++ break; ++ case 0x09: ++ /* VSRLW */ ++ index = VSRLW; ++ break; ++ case 0x29: ++ /* VSRLWI */ ++ index = VSRLWI; ++ break; ++ case 0x0A: ++ /* VSRAW */ ++ index = VSRAW; ++ break; ++ case 0x2A: ++ /* VSRAWI */ ++ index = VSRAWI; ++ break; ++ case 0x0B: ++ /* VROLW */ ++ index = VROLW; ++ break; ++ case 0x2B: ++ /* VROLWI */ ++ index = VROLWI; ++ break; ++ case 0x0C: ++ /* SLLOW */ ++ index = SLLOW; ++ break; ++ case 0x2C: ++ /* SLLOWI */ ++ index = SLLOWI; ++ break; ++ case 0x0D: ++ /* SRLOW */ ++ index = SRLOW; ++ break; ++ case 0x2D: ++ /* SRLOWI */ ++ index = SRLOWI; ++ break; ++ case 0x0E: ++ /* VADDL */ ++ index = VADDL; ++ break; ++ case 0x2E: ++ /* VADDLI */ ++ index = VADDLI; ++ break; ++ case 0x0F: ++ /* VSUBL */ ++ index = VSUBL; ++ break; ++ case 0x2F: ++ /* VSUBLI */ ++ index = VSUBLI; ++ break; ++ case 0x10: ++ /* VSLLB */ ++ index = VSLLB; ++ break; ++ case 0x30: ++ /* VSLLBI */ ++ index = VSLLBI; ++ break; ++ case 0x11: ++ /* VSRLB */ ++ index = VSRLB; ++ break; ++ case 0x31: ++ /* VSRLBI */ ++ index = VSRLBI; ++ break; ++ case 0x12: ++ /* VSRAB */ ++ index = VSRAB; ++ break; ++ case 0x32: ++ /* VSRABI */ ++ index = VSRABI; ++ break; ++ case 0x13: ++ /* VROLB */ ++ index = VROLB; ++ break; ++ case 0x33: ++ /* VROLBI */ ++ index = VROLBI; ++ break; ++ case 0x14: ++ /* VSLLH */ ++ index = VSLLH; ++ break; ++ case 0x34: ++ /* VSLLHI */ ++ index = VSLLHI; ++ break; ++ case 0x15: ++ /* VSRLH */ ++ index = VSRLH; ++ break; ++ case 0x35: ++ /* VSRLHI */ ++ index = VSRLHI; ++ break; ++ case 0x16: ++ /* VSRAH */ ++ index = VSRAH; ++ break; ++ case 0x36: ++ /* VSRAHI */ ++ index = VSRAHI; ++ break; ++ case 0x17: ++ /* VROLH */ ++ index = VROLH; ++ break; ++ case 0x37: ++ /* VROLHI */ ++ index = VROLHI; ++ break; ++ case 0x18: ++ /* CTPOPOW */ ++ index = CTPOPOW; ++ break; ++ case 0x19: ++ /* CTLZOW */ ++ index = CTLZOW; ++ break; ++ case 0x1A: ++ /* VSLLL */ ++ index = VSLLL; ++ break; ++ case 0x3A: ++ /* VSLLLI */ ++ index = VSLLLI; ++ break; ++ case 0x1B: ++ /* VSRLL */ ++ index = VSRLL; ++ break; ++ case 0x3B: ++ /* VSRLLI */ ++ index = VSRLLI; ++ break; ++ case 0x1C: ++ /* VSRAL */ ++ index = VSRAL; ++ break; ++ case 0x3C: ++ /* VSRALI */ ++ index = VSRALI; ++ break; ++ case 0x1D: ++ /* VROLL */ ++ index = VROLL; ++ break; ++ case 0x3D: ++ /* VROLLI */ ++ index = VROLLI; ++ break; ++ case 0x1E: ++ /* VMAXB */ ++ index = VMAXB; ++ break; ++ case 0x1F: ++ /* VMINB */ ++ index = VMINB; ++ break; ++ case 0x40: ++ /* VUCADDW */ ++ index = VUCADDW; ++ break; ++ case 0x60: ++ /* VUCADDWI */ ++ index = VUCADDWI; ++ break; ++ case 0x41: ++ /* VUCSUBW */ ++ index = VUCSUBW; ++ break; ++ case 0x61: ++ /* VUCSUBWI */ ++ index = VUCSUBWI; ++ break; ++ case 0x42: ++ /* VUCADDH */ ++ index = VUCADDH; ++ break; ++ case 0x62: ++ /* VUCADDHI */ ++ index = VUCADDHI; ++ break; ++ case 0x43: ++ /* VUCSUBH */ ++ index = VUCSUBH; ++ break; ++ case 0x63: ++ /* VUCSUBHI */ ++ index = VUCSUBHI; ++ break; ++ case 0x44: ++ /* VUCADDB */ ++ index = VUCADDB; ++ break; ++ case 0x64: ++ /* VUCADDBI */ ++ index = VUCADDBI; ++ break; ++ case 0x45: ++ /* VUCSUBB */ ++ index = VUCSUBB; ++ break; ++ case 0x65: ++ /* VUCSUBBI */ ++ index = VUCSUBBI; ++ break; ++ case 0x46: ++ /* SRAOW */ ++ index = SRAOW; ++ break; ++ case 0x66: ++ /* SRAOWI */ ++ index = SRAOWI; ++ break; ++ case 0x47: ++ /* VSUMW */ ++ index = VSUMW; ++ break; ++ case 0x48: ++ /* VSUML */ ++ index = VSUML; ++ break; ++ case 0x49: ++ /* VSM4R */ ++ index = VSM4R; ++ break; ++ case 0x4A: ++ /* VBINVW */ ++ index = VBINVW; ++ break; ++ case 0x4B: ++ /* VCMPUEQB */ ++ index = VCMPUEQB; ++ break; ++ case 0x6B: ++ /* VCMPUEQBI*/ ++ break; ++ case 0x4C: ++ /* VCMPUGTB */ ++ index = VCMPUGTB; ++ break; ++ case 0x6C: ++ /* VCMPUGTBI */ ++ index = VCMPUGTBI; ++ break; ++ case 0x4D: ++ /* VSM3MSW */ ++ index = VSM3MSW; ++ break; ++ case 0x50: ++ /* VMAXH */ ++ index = VMAXH; ++ break; ++ case 0x51: ++ /* VMINH */ ++ index = VMINH; ++ break; ++ case 0x52: ++ /* VMAXW */ ++ index = VMAXW; ++ break; ++ case 0x53: ++ /* VMINW */ ++ index = VMINW; ++ break; ++ case 0x54: ++ /* VMAXL */ ++ index = VMAXL; ++ break; ++ case 0x55: ++ /* VMINL */ ++ index = VMINL; ++ break; ++ case 0x56: ++ /* VUMAXB */ ++ index = VUMAXB; ++ break; ++ case 0x57: ++ /* VUMINB */ ++ index = VUMINB; ++ break; ++ case 0x58: ++ /* VUMAXH */ ++ index = VUMAXH; ++ break; ++ case 0x59: ++ /* VUMINH */ ++ index = VUMINH; ++ break; ++ case 0x5A: ++ /* VUMAXW */ ++ index = VUMAXW; ++ break; ++ case 0x5B: ++ /* VUMINW */ ++ index = VUMINW; ++ break; ++ case 0x5C: ++ /* VUMAXL */ ++ index = VUMAXL; ++ break; ++ case 0x5D: ++ /* VUMINL */ ++ index = VUMINL; ++ break; ++ case 0x68: ++ /* VSM4KEY */ ++ index = VSM4KEY; ++ break; ++ case 0x80: ++ /* VADDS */ ++ index = VADDS; ++ break; ++ case 0x81: ++ /* VADDD */ ++ index = VADDD; ++ break; ++ case 0x82: ++ /* VSUBS */ ++ index = VSUBS; ++ break; ++ case 0x83: ++ /* VSUBD */ ++ index = VSUBD; ++ break; ++ case 0x84: ++ /* VMULS */ ++ index = VMULS; ++ break; ++ case 0x85: ++ /* VMULD */ ++ index = VMULD; ++ break; ++ case 0x86: ++ /* VDIVS */ ++ index = VDIVS; ++ break; ++ case 0x87: ++ /* VDIVD */ ++ index = VDIVD; ++ break; ++ case 0x88: ++ /* VSQRTS */ ++ index = VSQRTS; ++ break; ++ case 0x89: ++ /* VSQRTD */ ++ index = VSQRTD; ++ break; ++ case 0x8C: ++ /* VFCMPEQ */ ++ index = VFCMPEQ; ++ break; ++ case 0x8D: ++ /* VFCMPLE */ ++ index = VFCMPLE; ++ break; ++ case 0x8E: ++ /* VFCMPLT */ ++ index = VFCMPLT; ++ break; ++ case 0x8F: ++ /* VFCMPUN */ ++ index = VFCMPUN; ++ break; ++ case 0x90: ++ /* VCPYS */ ++ index = VCPYS; ++ break; ++ case 0x91: ++ /* VCPYSE */ ++ index = VCPYSE; ++ break; ++ case 0x92: ++ /* VCPYSN */ ++ index = VCPYSN; ++ break; ++ case 0x93: ++ /* VSUMS */ ++ index = VSUMS; ++ break; ++ case 0x94: ++ /* VSUMD */ ++ index = VSUMD; ++ break; ++ case 0x95: ++ /* VFCVTSD */ ++ index = VFCVTSD; ++ break; ++ case 0x96: ++ /* VFCVTDS */ ++ index = VFCVTDS; ++ break; ++ case 0x99: ++ /* VFCVTLS */ ++ index = VFCVTLS; ++ break; ++ case 0x9A: ++ /* VFCVTLD */ ++ index = VFCVTLD; ++ break; ++ case 0x9B: ++ /* VFCVTDL */ ++ index = VFCVTDL; ++ break; ++ case 0x9C: ++ /* VFCVTDL_G */ ++ index = VFCVTDL_G; ++ break; ++ case 0x9D: ++ /* VFCVTDL_P */ ++ index = VFCVTDL_P; ++ break; ++ case 0x9E: ++ /* VFCVTDL_Z */ ++ index = VFCVTDL_Z; ++ break; ++ case 0x9F: ++ /* VFCVTDL_N */ ++ index = VFCVTDL_N; ++ break; ++ case 0xA0: ++ /* VFRIS */ ++ index = VFRIS; ++ break; ++ case 0xA1: ++ /* VFRIS_G */ ++ index = VFRIS_G; ++ break; ++ case 0xA2: ++ /* VFRIS_P */ ++ index = VFRIS_P; ++ break; ++ case 0xA3: ++ /* VFRIS_Z */ ++ index = VFRIS_Z; ++ break; ++ case 0xA4: ++ /* VFRIS_N */ ++ index = VFRIS_N; ++ break; ++ case 0xA5: ++ /* VFRID */ ++ index = VFRID; ++ break; ++ case 0xA6: ++ /* VFRID_G */ ++ index = VFRID_G; ++ break; ++ case 0xA7: ++ /* VFRID_P */ ++ index = VFRID_P; ++ break; ++ case 0xA8: ++ /* VFRID_Z */ ++ index = VFRID_Z; ++ break; ++ case 0xA9: ++ /* VFRID_N */ ++ index = VFRID_N; ++ break; ++ case 0xAA: ++ /* VFRECS */ ++ index = VFRECS; ++ break; ++ case 0xAB: ++ /* VFRECD */ ++ index = VFRECD; ++ break; ++ case 0xAC: ++ /* VMAXS */ ++ index = VMAXS; ++ break; ++ case 0xAD: ++ /* VMINS */ ++ index = VMINS; ++ break; ++ case 0xAE: ++ /* VMAXD */ ++ index = VMAXD; ++ break; ++ case 0xAF: ++ /* VMIND */ ++ index = VMIND; ++ break; ++ default: ++ break; ++ } ++ break; ++ case 0x1B: ++ switch (fn6) { ++ case 0x00: ++ /* VMAS */ ++ index = VMAS; ++ break; ++ case 0x01: ++ /* VMAD */ ++ index = VMAD; ++ break; ++ case 0x02: ++ /* VMSS */ ++ index = VMSS; ++ break; ++ case 0x03: ++ /* VMSD */ ++ index = VMSD; ++ break; ++ case 0x04: ++ /* VNMAS */ ++ index = VNMAS; ++ break; ++ case 0x05: ++ /* VNMAD */ ++ index = VNMAD; ++ break; ++ case 0x06: ++ /* VNMSS */ ++ index = VNMSS; ++ break; ++ case 0x07: ++ /* VNMSD */ ++ index = VNMSD; ++ break; ++ case 0x10: ++ /* VFSELEQ */ ++ index = VFSELEQ; ++ break; ++ case 0x12: ++ /* VFSELLT */ ++ index = VFSELLT; ++ break; ++ case 0x13: ++ /* VFSELLE */ ++ index = VFSELLE; ++ break; ++ case 0x18: ++ /* VSELEQW */ ++ index = VSELEQW; ++ break; ++ case 0x38: ++ /* VSELEQWI */ ++ index = VSELEQWI; ++ break; ++ case 0x19: ++ /* VSELLBCW */ ++ index = VSELLBCW; ++ break; ++ case 0x39: ++ /* VSELLBCWI */ ++ index = VSELLBCWI; ++ break; ++ case 0x1A: ++ /* VSELLTW */ ++ index = VSELLTW; ++ break; ++ case 0x3A: ++ /* VSELLTWI */ ++ index = VSELLTWI; ++ break; ++ case 0x1B: ++ /* VSELLEW */ ++ index = VSELLEW; ++ break; ++ case 0x3B: ++ /* VSELLEWI */ ++ index = VSELLEWI; ++ break; ++ case 0x20: ++ /* VINSW */ ++ index = VINSW; ++ break; ++ case 0x21: ++ /* VINSF */ ++ index = VINSF; ++ break; ++ case 0x22: ++ /* VEXTW */ ++ index = VEXTW; ++ break; ++ case 0x23: ++ /* VEXTF */ ++ index = VEXTF; ++ break; ++ case 0x24: ++ /* VCPYW */ ++ index = VCPYW; ++ break; ++ case 0x25: ++ /* VCPYF */ ++ index = VCPYF; ++ break; ++ case 0x26: ++ /* VCONW */ ++ index = VCONW; ++ break; ++ case 0x27: ++ /* VSHFW */ ++ index = VSHFW; ++ break; ++ case 0x28: ++ /* VCONS */ ++ index = VCONS; ++ break; ++ case 0x29: ++ /* VCOND */ ++ index = VCOND; ++ break; ++ case 0x2A: ++ /* VINSB */ ++ index = VINSB; ++ break; ++ case 0x2B: ++ /* VINSH */ ++ index = VINSH; ++ break; ++ case 0x2C: ++ /* VINSECTLH */ ++ index = VINSECTLH; ++ break; ++ case 0x2D: ++ /* VINSECTLW */ ++ index = VINSECTLW; ++ break; ++ case 0x2E: ++ /* VINSECTLL */ ++ index = VINSECTLL; ++ break; ++ case 0x2F: ++ /* VINSECTLB */ ++ index = VINSECTLB; ++ break; ++ case 0x30: ++ /* VSHFQ */ ++ index = VSHFQ; ++ break; ++ case 0x31: ++ /* VSHFQB */ ++ index = VSHFQB; ++ break; ++ case 0x32: ++ /* VCPYB */ ++ index = VCPYB; ++ break; ++ case 0x33: ++ /* VCPYH */ ++ index = VCPYH; ++ break; ++ case 0x34: ++ /* VSM3R */ ++ index = VSM3R; ++ break; ++ case 0x35: ++ /* VFCVTSH */ ++ index = VFCVTSH; ++ break; ++ case 0x36: ++ /* VFCVTHS */ ++ index = VFCVTHS; ++ break; ++ default: ++ break; ++ } ++ break; ++ case 0x1C: ++ switch (fn4) { ++ case 0x0: ++ /* VLDW_U */ ++ index = VLDW_U; ++ break; ++ case 0x1: ++ /* VSTW_U */ ++ index = VSTW_U; ++ break; ++ case 0x2: ++ /* VLDS_U */ ++ index = VLDS_U; ++ break; ++ case 0x3: ++ /* VSTS_U */ ++ index = VSTS_U; ++ break; ++ case 0x4: ++ /* VLDD_U */ ++ index = VLDD_U; ++ break; ++ case 0x5: ++ /* VSTD_U */ ++ index = VSTD_U; ++ break; ++ case 0x8: ++ /* VSTW_UL */ ++ index = VSTW_UL; ++ break; ++ case 0x9: ++ /* VSTW_UH */ ++ index = VSTW_UH; ++ break; ++ case 0xa: ++ /* VSTS_UL */ ++ index = VSTS_UL; ++ break; ++ case 0xb: ++ /* VSTS_UH */ ++ index = VSTS_UH; ++ break; ++ case 0xc: ++ /* VSTD_UL */ ++ index = VSTD_UL; ++ break; ++ case 0xd: ++ /* VSTD_UH */ ++ index = VSTD_UH; ++ break; ++ case 0xe: ++ /* VLDD_NC */ ++ index = VLDD_NC; ++ break; ++ case 0xf: ++ /* VSTD_NC */ ++ index = VSTD_NC; ++ break; ++ default: ++ break; ++ } ++ break; ++ case 0x1D: ++ /* LBR */ ++ index = LBR; ++ break; ++ case 0x1E: ++ switch (fn4) { ++ case 0x0: ++ /* LDBU_A */ ++ index = LDBU_A; ++ break; ++ case 0x1: ++ /* LDHU_A */ ++ index = LDHU_A; ++ break; ++ case 0x2: ++ /* LDW_A */ ++ index = LDW_A; ++ break; ++ case 0x3: ++ /* LDL_A */ ++ index = LDL_A; ++ break; ++ case 0x4: ++ /* FLDS_A */ ++ index = FLDS_A; ++ break; ++ case 0x5: ++ /* FLDD_A */ ++ index = FLDD_A; ++ break; ++ case 0x6: ++ /* STBU_A */ ++ index = STBU_A; ++ break; ++ case 0x7: ++ /* STHU_A */ ++ index = STHU_A; ++ break; ++ case 0x8: ++ /* STW_A */ ++ index = STW_A; ++ break; ++ case 0x9: ++ /* STL_A */ ++ index = STL_A; ++ break; ++ case 0xA: ++ /* FSTS_A */ ++ index = FSTS_A; ++ break; ++ case 0xB: ++ /* FSTD_A */ ++ index = FSTD_A; ++ break; ++ case 0xE: ++ /* DPFHR */ ++ index = DPFHR; ++ break; ++ case 0xF: ++ /* DPFHW */ ++ index = DPFHW; ++ break; ++ default: ++ break; ++ } ++ break; ++ case 0x20: ++ /* LDBU */ ++ index = LDBU; ++ break; ++ case 0x21: ++ /* LDHU */ ++ index = LDHU; ++ break; ++ case 0x22: ++ /* LDW */ ++ index = LDW; ++ break; ++ case 0x23: ++ /* LDL */ ++ index = LDL; ++ break; ++ case 0x24: ++ /* LDL_U */ ++ index = LDL_U; ++ break; ++ case 0x25: ++ if ((insn >> 12) & 1) { ++ /* PRI_LDL */ ++ index = PRI_LDL; ++ } else { ++ /* PRI_LDW */ ++ index = PRI_LDW; ++ } ++ break; ++ case 0x26: ++ /* FLDS */ ++ index = FLDS; ++ break; ++ case 0x27: ++ /* FLDD */ ++ index = FLDD; ++ break; ++ case 0x28: ++ /* STB */ ++ index = STB; ++ break; ++ case 0x29: ++ /* STH */ ++ index = STH; ++ break; ++ case 0x2a: ++ /* STW */ ++ index = STW; ++ break; ++ case 0x2b: ++ /* STL */ ++ index = STL; ++ break; ++ case 0x2c: ++ /* STL_U */ ++ index = STL_U; ++ break; ++ case 0x2d: ++ if ((insn >> 12) & 1) { ++ /* PRI_STL */ ++ index = PRI_STL; ++ } else { ++ /* PRI_STW */ ++ index = PRI_STW; ++ } ++ break; ++ case 0x2e: ++ /* FSTS */ ++ index = FSTS; ++ break; ++ case 0x2f: ++ /* FSTD */ ++ index = FSTD; ++ break; ++ case 0x30: ++ /* BEQ */ ++ index = BEQ; ++ break; ++ case 0x31: ++ /* BNE */ ++ index = BNE; ++ break; ++ case 0x32: ++ /* BLT */ ++ index = BLT; ++ break; ++ case 0x33: ++ /* BLE */ ++ index = BLE; ++ break; ++ case 0x34: ++ /* BGT */ ++ index = BGT; ++ break; ++ case 0x35: ++ /* BGE */ ++ index = BGE; ++ break; ++ case 0x36: ++ /* BLBC */ ++ index = BLBC; ++ break; ++ case 0x37: ++ /* BLBS */ ++ index = BLBS; ++ break; ++ case 0x38: ++ /* FBEQ */ ++ index = FBEQ; ++ break; ++ case 0x39: ++ /* FBNE */ ++ index = FBNE; ++ break; ++ case 0x3a: ++ /* FBLT */ ++ index = FBLT; ++ break; ++ case 0x3b: ++ /* FBLE */ ++ index = FBLE; ++ break; ++ case 0x3c: ++ /* FBGT */ ++ index = FBGT; ++ break; ++ case 0x3d: ++ /* FBGE */ ++ index = FBGE; ++ break; ++ case 0x3f: ++ /* LDIH */ ++ index = LDIH; ++ break; ++ case 0x3e: ++ /* LDI */ ++ index = LDI; ++ break; ++ default: ++do_invalid: ++ break; ++ } ++ count = tcg_temp_new(); ++ offs = offsetof(CPUSW64State, insn_count[index]); ++ tcg_gen_ld_i64(count, cpu_env, offs); ++ tcg_gen_addi_i64(count, count, 1); ++ tcg_gen_st_i64(count, cpu_env, offs); ++ tcg_temp_free(count); ++} +diff --git a/target/sw64/profile.h b/target/sw64/profile.h +new file mode 100644 +index 0000000000..5aca541ea7 +--- /dev/null ++++ b/target/sw64/profile.h +@@ -0,0 +1,541 @@ ++#ifndef PROFILE_H ++#define PROFILE_H ++#define SYS_CALL 0 ++#define CALL 1 ++#define RET 2 ++#define JMP 3 ++#define BR 4 ++#define BSR 5 ++#define MEMB 6 ++#define IMEMB 7 ++#define WMEMB 8 ++#define RTC 9 ++#define RCID 10 ++#define HALT 11 ++#define RD_F 12 ++#define WR_F 13 ++#define RTID 14 ++#define CSRWS 15 ++#define CSRWC 16 ++#define PRI_RCSR 17 ++#define PRI_WCSR 18 ++#define PRI_RET 19 ++#define LLDW 20 ++#define LLDL 21 ++#define LDW_INC 22 ++#define LDL_INC 23 ++#define LDW_DEC 24 ++#define LDL_DEC 25 ++#define LDW_SET 26 ++#define LDL_SET 27 ++#define LSTW 28 ++#define LSTL 29 ++#define LDW_NC 30 ++#define LDL_NC 31 ++#define LDD_NC 32 ++#define STW_NC 33 ++#define STL_NC 34 ++#define STD_NC 35 ++#define LDWE 36 ++#define LDSE 37 ++#define LDDE 38 ++#define VLDS 39 ++#define VLDD 40 ++#define VSTS 41 ++#define VSTD 42 ++#define FIMOVS 43 ++#define FIMOVD 44 ++#define ADDW 45 ++#define SUBW 46 ++#define S4ADDW 47 ++#define S4SUBW 48 ++#define S8ADDW 49 ++#define S8SUBW 50 ++#define ADDL 51 ++#define SUBL 52 ++#define S4ADDL 53 ++#define S4SUBL 54 ++#define S8ADDL 55 ++#define S8SUBL 56 ++#define MULW 57 ++#define DIVW 58 ++#define UDIVW 59 ++#define REMW 60 ++#define UREMW 61 ++#define MULL 62 ++#define MULH 63 ++#define DIVL 64 ++#define UDIVL 65 ++#define REML 66 ++#define UREML 67 ++#define ADDPI 68 ++#define ADDPIS 69 ++#define CMPEQ 70 ++#define CMPLT 71 ++#define CMPLE 72 ++#define CMPULT 73 ++#define CMPULE 74 ++#define SBT 75 ++#define CBT 76 ++#define AND 77 ++#define BIC 78 ++#define BIS 79 ++#define ORNOT 80 ++#define XOR 81 ++#define EQV 82 ++#define INSLB 83 ++#define INSLH 84 ++#define INSLW 85 ++#define INSLL 86 ++#define INSHB 87 ++#define INSHH 88 ++#define INSHW 89 ++#define INSHL 90 ++#define SLLL 91 ++#define SRLL 92 ++#define SRAL 93 ++#define ROLL 94 ++#define SLLW 95 ++#define SRLW 96 ++#define SRAW 97 ++#define ROLW 98 ++#define EXTLB 99 ++#define EXTLH 100 ++#define EXTLW 101 ++#define EXTLL 102 ++#define EXTHB 103 ++#define EXTHH 104 ++#define EXTHW 105 ++#define EXTHL 106 ++#define CTPOP 107 ++#define CTLZ 108 ++#define CTTZ 109 ++#define REVBH 110 ++#define REVBW 111 ++#define REVBL 112 ++#define CASW 113 ++#define CASL 114 ++#define MASKLB 115 ++#define MASKLH 116 ++#define MASKLW 117 ++#define MASKLL 118 ++#define MASKHB 119 ++#define MASKHH 120 ++#define MASKHW 121 ++#define MASKHL 122 ++#define ZAP 123 ++#define ZAPNOT 124 ++#define SEXTB 125 ++#define SEXTH 126 ++#define SELEQ 127 ++#define SELGE 128 ++#define SELGT 129 ++#define SELLE 130 ++#define SELLT 131 ++#define SELNE 132 ++#define SELLBC 133 ++#define SELLBS 134 ++#define ADDWI 135 ++#define SUBWI 136 ++#define S4ADDWI 137 ++#define S4SUBWI 138 ++#define S8ADDWI 139 ++#define S8SUBWI 140 ++#define ADDLI 141 ++#define SUBLI 142 ++#define S4ADDLI 143 ++#define S4SUBLI 144 ++#define S8ADDLI 145 ++#define S8SUBLI 146 ++#define MULWI 147 ++#define DIVWI 148 ++#define UDIVWI 149 ++#define REMWI 150 ++#define UREMWI 151 ++#define MULLI 152 ++#define MULHI 153 ++#define DIVLI 154 ++#define UDIVLI 155 ++#define REMLI 156 ++#define UREMLI 157 ++#define ADDPII 158 ++#define ADDPISI 159 ++#define CMPEQI 160 ++#define CMPLTI 161 ++#define CMPLEI 162 ++#define CMPULTI 163 ++#define CMPULEI 164 ++#define SBTI 165 ++#define CBTI 166 ++#define ANDI 167 ++#define BICI 168 ++#define BISI 169 ++#define ORNOTI 170 ++#define XORI 171 ++#define EQVI 172 ++#define INSLBI 173 ++#define INSLHI 174 ++#define INSLWI 175 ++#define INSLLI 176 ++#define INSHBI 177 ++#define INSHHI 178 ++#define INSHWI 179 ++#define INSHLI 180 ++#define SLLLI 181 ++#define SRLLI 182 ++#define SRALI 183 ++#define ROLLI 184 ++#define SLLWI 185 ++#define SRLWI 186 ++#define SRAWI 187 ++#define ROLWI 188 ++#define EXTLBI 189 ++#define EXTLHI 190 ++#define EXTLWI 191 ++#define EXTLLI 192 ++#define EXTHBI 193 ++#define EXTHHI 194 ++#define EXTHWI 195 ++#define EXTHLI 196 ++#define CTPOPI 197 ++#define CTLZI 198 ++#define CTTZI 199 ++#define REVBHI 200 ++#define REVBWI 201 ++#define REVBLI 202 ++#define CASWI 203 ++#define CASLI 204 ++#define MASKLBI 205 ++#define MASKLHI 206 ++#define MASKLWI 207 ++#define MASKLLI 208 ++#define MASKHBI 209 ++#define MASKHHI 210 ++#define MASKHWI 211 ++#define MASKHLI 212 ++#define ZAPI 213 ++#define ZAPNOTI 214 ++#define SEXTBI 215 ++#define SEXTHI 216 ++#define CMPGEBI 217 ++#define SELEQI 218 ++#define SELGEI 219 ++#define SELGTI 220 ++#define SELLEI 221 ++#define SELLTI 222 ++#define SELNEI 223 ++#define SELLBCI 224 ++#define SELLBSI 225 ++#define VLOGZZ 226 ++#define FADDS 227 ++#define FADDD 228 ++#define FSUBS 229 ++#define FSUBD 230 ++#define FMULS 231 ++#define FMULD 232 ++#define FDIVS 233 ++#define FDIVD 234 ++#define FSQRTS 235 ++#define FSQRTD 236 ++#define FCMPEQ 237 ++#define FCMPLE 238 ++#define FCMPLT 239 ++#define FCMPUN 240 ++#define FCVTSD 241 ++#define FCVTDS 242 ++#define FCVTDL_G 243 ++#define FCVTDL_P 244 ++#define FCVTDL_Z 245 ++#define FCVTDL_N 246 ++#define FCVTDL 247 ++#define FCVTWL 248 ++#define FCVTLW 249 ++#define FCVTLS 250 ++#define FCVTLD 251 ++#define FCPYS 252 ++#define FCPYSE 253 ++#define FCPYSN 254 ++#define IFMOVS 255 ++#define IFMOVD 256 ++#define RFPCR 257 ++#define WFPCR 258 ++#define SETFPEC0 259 ++#define SETFPEC1 260 ++#define SETFPEC2 261 ++#define SETFPEC3 262 ++#define FRECS 263 ++#define FRECD 264 ++#define FRIS 265 ++#define FRIS_G 266 ++#define FRIS_P 267 ++#define FRIS_Z 268 ++#define FRIS_N 269 ++#define FRID 270 ++#define FRID_G 271 ++#define FRID_P 272 ++#define FRID_Z 273 ++#define FRID_N 274 ++#define FMAS 275 ++#define FMAD 276 ++#define FMSS 277 ++#define FMSD 278 ++#define FNMAS 279 ++#define FNMAD 280 ++#define FNMSS 281 ++#define FNMSD 282 ++#define FSELEQ 283 ++#define FSELNE 284 ++#define FSELLT 285 ++#define FSELLE 286 ++#define FSELGT 287 ++#define FSELGE 288 ++#define VADDW 289 ++#define VADDWI 290 ++#define VSUBW 291 ++#define VSUBWI 292 ++#define VCMPGEW 293 ++#define VCMPGEWI 294 ++#define VCMPEQW 295 ++#define VCMPEQWI 296 ++#define VCMPLEW 297 ++#define VCMPLEWI 298 ++#define VCMPLTW 299 ++#define VCMPLTWI 300 ++#define VCMPULEW 301 ++#define VCMPULEWI 302 ++#define VCMPULTW 303 ++#define VCMPULTWI 304 ++#define VSLLW 305 ++#define VSLLWI 306 ++#define VSRLW 307 ++#define VSRLWI 308 ++#define VSRAW 309 ++#define VSRAWI 310 ++#define VROLW 311 ++#define VROLWI 312 ++#define SLLOW 313 ++#define SLLOWI 314 ++#define SRLOW 315 ++#define SRLOWI 316 ++#define VADDL 317 ++#define VADDLI 318 ++#define VSUBL 319 ++#define VSUBLI 320 ++#define VSLLB 321 ++#define VSLLBI 322 ++#define VSRLB 323 ++#define VSRLBI 324 ++#define VSRAB 325 ++#define VSRABI 326 ++#define VROLB 327 ++#define VROLBI 328 ++#define VSLLH 329 ++#define VSLLHI 330 ++#define VSRLH 331 ++#define VSRLHI 332 ++#define VSRAH 333 ++#define VSRAHI 334 ++#define VROLH 335 ++#define VROLHI 336 ++#define CTPOPOW 337 ++#define CTLZOW 338 ++#define VSLLL 339 ++#define VSLLLI 340 ++#define VSRLL 341 ++#define VSRLLI 342 ++#define VSRAL 343 ++#define VSRALI 344 ++#define VROLL 345 ++#define VROLLI 346 ++#define VMAXB 347 ++#define VMINB 348 ++#define VUCADDW 349 ++#define VUCADDWI 350 ++#define VUCSUBW 351 ++#define VUCSUBWI 352 ++#define VUCADDH 353 ++#define VUCADDHI 354 ++#define VUCSUBH 355 ++#define VUCSUBHI 356 ++#define VUCADDB 357 ++#define VUCADDBI 358 ++#define VUCSUBB 359 ++#define VUCSUBBI 360 ++#define SRAOW 361 ++#define SRAOWI 362 ++#define VSUMW 363 ++#define VSUML 364 ++#define VSM4R 365 ++#define VBINVW 366 ++#define VCMPUEQB 367 ++#define VCMPUGTB 368 ++#define VCMPUGTBI 369 ++#define VSM3MSW 370 ++#define VMAXH 371 ++#define VMINH 372 ++#define VMAXW 373 ++#define VMINW 374 ++#define VMAXL 375 ++#define VMINL 376 ++#define VUMAXB 377 ++#define VUMINB 378 ++#define VUMAXH 379 ++#define VUMINH 380 ++#define VUMAXW 381 ++#define VUMINW 382 ++#define VUMAXL 383 ++#define VUMINL 384 ++#define VSM4KEY 385 ++#define VADDS 386 ++#define VADDD 387 ++#define VSUBS 388 ++#define VSUBD 389 ++#define VMULS 390 ++#define VMULD 391 ++#define VDIVS 392 ++#define VDIVD 393 ++#define VSQRTS 394 ++#define VSQRTD 395 ++#define VFCMPEQ 396 ++#define VFCMPLE 397 ++#define VFCMPLT 398 ++#define VFCMPUN 399 ++#define VCPYS 400 ++#define VCPYSE 401 ++#define VCPYSN 402 ++#define VSUMS 403 ++#define VSUMD 404 ++#define VFCVTSD 405 ++#define VFCVTDS 406 ++#define VFCVTLS 407 ++#define VFCVTLD 408 ++#define VFCVTDL 409 ++#define VFCVTDL_G 410 ++#define VFCVTDL_P 411 ++#define VFCVTDL_Z 412 ++#define VFCVTDL_N 413 ++#define VFRIS 414 ++#define VFRIS_G 415 ++#define VFRIS_P 416 ++#define VFRIS_Z 417 ++#define VFRIS_N 418 ++#define VFRID 419 ++#define VFRID_G 420 ++#define VFRID_P 421 ++#define VFRID_Z 422 ++#define VFRID_N 423 ++#define VFRECS 424 ++#define VFRECD 425 ++#define VMAXS 426 ++#define VMINS 427 ++#define VMAXD 428 ++#define VMIND 429 ++#define VMAS 430 ++#define VMAD 431 ++#define VMSS 432 ++#define VMSD 433 ++#define VNMAS 434 ++#define VNMAD 435 ++#define VNMSS 436 ++#define VNMSD 437 ++#define VFSELEQ 438 ++#define VFSELLT 439 ++#define VFSELLE 440 ++#define VSELEQW 441 ++#define VSELEQWI 442 ++#define VSELLBCW 443 ++#define VSELLBCWI 444 ++#define VSELLTW 445 ++#define VSELLTWI 446 ++#define VSELLEW 447 ++#define VSELLEWI 448 ++#define VINSW 449 ++#define VINSF 450 ++#define VEXTW 451 ++#define VEXTF 452 ++#define VCPYW 453 ++#define VCPYF 454 ++#define VCONW 455 ++#define VSHFW 456 ++#define VCONS 457 ++#define VCOND 458 ++#define VINSB 459 ++#define VINSH 460 ++#define VINSECTLH 461 ++#define VINSECTLW 462 ++#define VINSECTLL 463 ++#define VINSECTLB 464 ++#define VSHFQ 465 ++#define VSHFQB 466 ++#define VCPYB 467 ++#define VCPYH 468 ++#define VSM3R 469 ++#define VFCVTSH 470 ++#define VFCVTHS 471 ++#define VLDW_U 472 ++#define VSTW_U 473 ++#define VLDS_U 474 ++#define VSTS_U 475 ++#define VLDD_U 476 ++#define VSTD_U 477 ++#define VSTW_UL 478 ++#define VSTW_UH 479 ++#define VSTS_UL 480 ++#define VSTS_UH 481 ++#define VSTD_UL 482 ++#define VSTD_UH 483 ++#define VLDD_NC 484 ++#define VSTD_NC 485 ++#define LBR 486 ++#define LDBU_A 487 ++#define LDHU_A 488 ++#define LDW_A 489 ++#define LDL_A 490 ++#define FLDS_A 491 ++#define FLDD_A 492 ++#define STBU_A 493 ++#define STHU_A 494 ++#define STW_A 495 ++#define STL_A 496 ++#define FSTS_A 497 ++#define FSTD_A 498 ++#define DPFHR 499 ++#define DPFHW 500 ++#define LDBU 501 ++#define LDHU 502 ++#define LDW 503 ++#define LDL 504 ++#define LDL_U 505 ++#define PRI_LDL 506 ++#define PRI_LDW 507 ++#define FLDS 508 ++#define FLDD 509 ++#define STB 510 ++#define STH 511 ++#define STW 512 ++#define STL 513 ++#define STL_U 514 ++#define PRI_STL 515 ++#define PRI_STW 516 ++#define FSTS 517 ++#define FSTD 518 ++#define BEQ 519 ++#define BNE 520 ++#define BLT 521 ++#define BLE 522 ++#define BGT 523 ++#define BGE 524 ++#define BLBC 525 ++#define BLBS 526 ++#define FBEQ 527 ++#define FBNE 528 ++#define FBLT 529 ++#define FBLE 530 ++#define FBGT 531 ++#define FBGE 532 ++#define LDIH 533 ++#define LDI 534 ++ ++extern const char *insn_opc[535]; ++ ++#endif +diff --git a/target/sw64/simd_helper.c b/target/sw64/simd_helper.c +new file mode 100644 +index 0000000000..13bd52de3d +--- /dev/null ++++ b/target/sw64/simd_helper.c +@@ -0,0 +1,1058 @@ ++#include "qemu/osdep.h" ++#include "cpu.h" ++#include "exec/exec-all.h" ++#include "exec/helper-proto.h" ++ ++#undef DEBUG_SIMD ++ ++static inline uint8_t *get_element_b(CPUSW64State *env, uint64_t ra, ++ int index) ++{ ++ return (uint8_t*)&env->fr[ra + (index / 8) * 32] + (index % 8); ++} ++ ++static inline uint16_t *get_element_h(CPUSW64State *env, uint64_t ra, ++ int index) ++{ ++ return (uint16_t*)&env->fr[ra + (index / 4) * 32] + (index % 4); ++} ++ ++static inline uint32_t *get_element_w(CPUSW64State *env, uint64_t ra, ++ int index) ++{ ++ return (uint32_t*)&env->fr[ra + (index / 2) * 32] + (index % 2); ++} ++ ++static inline uint64_t *get_element_l(CPUSW64State *env, uint64_t ra, ++ int index) ++{ ++ return &env->fr[ra + index * 32]; ++} ++ ++void helper_srlow(CPUSW64State *env, uint64_t ra, uint64_t rc, uint64_t shift) ++{ ++ int i; ++ int adden; ++ int dest, src; ++ adden = shift >> 6; ++ shift &= 0x3f; ++#ifdef DEBUG_SIMD ++ printf("right shift = %ld adden = %d\n", shift, adden); ++ printf("in_fr[%ld]:", ra); ++ for (i = 3 ; i >= 0; i--) { ++ printf("%016lx ", env->fr[ra + 32 * i]); ++ } ++ printf("\n"); ++#endif ++ ++ for (i = 0; (i + adden) < 4; i++) { ++ dest = i * 32 + rc; ++ src = (i + adden) * 32 + ra; ++ env->fr[dest] = env->fr[src] >> shift; ++ if (((i + adden) < 3) && (shift != 0)) ++ env->fr[dest] |= (env->fr[src + 32] << (64 - shift)); ++ } ++ ++ for (; i < 4; i++) { ++ env->fr[rc + i * 32] = 0; ++ } ++#ifdef DEBUG_SIMD ++ printf("out_fr[%ld]:", rc); ++ for (i = 3 ; i >= 0; i--) { ++ printf("%016lx ", env->fr[rc + 32 * i]); ++ } ++ printf("\n"); ++#endif ++} ++ ++void helper_sllow(CPUSW64State *env, uint64_t ra, uint64_t rc, uint64_t shift) ++{ ++ int i; ++ int adden; ++ int dest, src; ++ adden = shift >> 6; ++ shift &= 0x3f; ++#ifdef DEBUG_SIMD ++ printf("left shift = %ld adden = %d\n", shift, adden); ++ printf("in_fr[%ld]:", ra); ++ for (i = 3 ; i >= 0; i--) { ++ printf("%016lx ", env->fr[ra + 32 * i]); ++ } ++ printf("\n"); ++#endif ++ ++ for (i = 3; (i - adden) >= 0; i--) { ++ dest = i * 32 + rc; ++ src = (i - adden) * 32 + ra; ++ env->fr[dest] = env->fr[src] << shift; ++ if (((i - adden) > 0) && (shift != 0)) ++ env->fr[dest] |= (env->fr[src - 32] >> (64 - shift)); ++ } ++ for (; i >= 0; i--) { ++ env->fr[rc + i * 32] = 0; ++ } ++#ifdef DEBUG_SIMD ++ printf("out_fr[%ld]:", rc); ++ for (i = 3 ; i >= 0; i--) { ++ printf("%016lx ", env->fr[rc + 32 * i]); ++ } ++ printf("\n"); ++#endif ++} ++ ++static uint64_t do_logzz(uint64_t va, uint64_t vb, uint64_t vc, uint64_t zz) ++{ ++ int i; ++ uint64_t ret = 0; ++ int index; ++ ++ for (i = 0; i < 64; i++) { ++ index = (((va >> i) & 1) << 2) | (((vb >> i) & 1) << 1) | ((vc >> i) & 1); ++ ret |= ((zz >> index) & 1) << i; ++ } ++ ++ return ret; ++} ++ ++void helper_vlogzz(CPUSW64State *env, uint64_t args, uint64_t rd, uint64_t zz) ++{ ++ int i; ++ int ra, rb, rc; ++ ra = args >> 16; ++ rb = (args >> 8) & 0xff; ++ rc = args & 0xff; ++#ifdef DEBUG_SIMD ++ printf("zz = %lx\n", zz); ++ printf("in_fr[%d]:", ra); ++ for (i = 3 ; i >= 0; i--) { ++ printf("%016lx ", env->fr[ra + 32 * i]); ++ } ++ printf("\n"); ++ printf("in_fr[%d]:", rb); ++ for (i = 3 ; i >= 0; i--) { ++ printf("%016lx ", env->fr[rb + 32 * i]); ++ } ++ printf("\n"); ++ printf("in_fr[%d]:", rc); ++ for (i = 3 ; i >= 0; i--) { ++ printf("%016lx ", env->fr[rc + 32 * i]); ++ } ++ printf("\n"); ++#endif ++ for (i = 0; i < 4; i++) { ++ env->fr[rd + i * 32] = do_logzz(env->fr[ra + i * 32], env->fr[rb + i * 32], ++ env->fr[rc + i * 32], zz); ++ } ++#ifdef DEBUG_SIMD ++ printf("out_fr[%ld]:", rd); ++ for (i = 3 ; i >= 0; i--) { ++ printf("%016lx ", env->fr[rd + 32 * i]); ++ } ++ printf("\n"); ++#endif ++} ++ ++void helper_v_print(CPUSW64State *env, uint64_t v) ++{ ++ printf("PC[%lx]: fr[%lx]:\n", GETPC(), v); ++} ++ ++void helper_vconw(CPUSW64State *env, uint64_t args, uint64_t rd, ++ uint64_t byte4_len) ++{ ++ int ra, rb; ++ int count; ++ int i; ++ uint32_t *ptr_dst, *ptr_src; ++ uint32_t tmp[8]; ++ ++ ra = (args >> 8) & 0xff; ++ rb = args & 0xff; ++ count = 8 - byte4_len; ++ ++ for (i = 0; i < 8; i++) { ++ ptr_dst = get_element_w(env, rd, i); ++ if (i < count) { ++ ptr_src = get_element_w(env, ra, i + byte4_len); ++ } else { ++ ptr_src = get_element_w(env, rb, i - count); ++ } ++ tmp[i] = *ptr_src; ++ } ++ for (i = 0; i < 8; i++) { ++ ptr_dst = get_element_w(env, rd, i); ++ *ptr_dst = tmp[i]; ++ } ++} ++ ++void helper_vcond(CPUSW64State *env, uint64_t args, uint64_t rd, ++ uint64_t byte8_len) ++{ ++ int ra, rb; ++ int count; ++ int i; ++ uint64_t *ptr_dst, *ptr_src; ++ uint64_t tmp[8]; ++ ++ ra = (args >> 8) & 0xff; ++ rb = args & 0xff; ++ count = 4 - byte8_len; ++ ++ for (i = 0; i < 4; i++) { ++ if (i < count) { ++ ptr_src = get_element_l(env, ra, i + byte8_len); ++ } else { ++ ptr_src = get_element_l(env, rb, i - count); ++ } ++ tmp[i] = *ptr_src; ++ } ++ for (i = 0; i < 4; i++) { ++ ptr_dst = get_element_l(env, rd, i + byte8_len); ++ *ptr_dst = tmp[i]; ++ } ++} ++ ++void helper_vshfw(CPUSW64State *env, uint64_t args, uint64_t rd, uint64_t vc) ++{ ++ int ra, rb; ++ int i; ++ uint32_t *ptr_dst, *ptr_src; ++ uint32_t tmp[8]; ++ int flag, idx; ++ ++ ra = (args >> 8) & 0xff; ++ rb = args & 0xff; ++ ++ for (i = 0; i < 8; i++) { ++ flag = (vc >> (i * 4)) & 0x8; ++ idx = (vc >> (i * 4)) & 0x7; ++ if (flag == 0) { ++ ptr_src = get_element_w(env, ra, idx); ++ } else { ++ ptr_src = get_element_w(env, rb, idx); ++ } ++ tmp[i] = *ptr_src; ++ } ++ for (i = 0; i < 8; i++) { ++ ptr_dst = get_element_w(env, rd, i); ++ *ptr_dst = tmp[i]; ++ } ++} ++ ++uint64_t helper_ctlzow(CPUSW64State *env, uint64_t ra) ++{ ++ int i, j; ++ uint64_t val; ++ uint64_t ctlz = 0; ++ ++ for (j = 3; j >= 0; j--) { ++ val = env->fr[ra + 32 * j]; ++ for (i = 63; i >= 0; i--) { ++ if ((val >> i) & 1) ++ return ctlz << 29; ++ else ++ ctlz++; ++ } ++ } ++ return ctlz << 29; ++} ++ ++void helper_vucaddw(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t rc) ++{ ++ int a, b, c; ++ int ret; ++ int i; ++ ++ for (i = 0; i < 4; i++) { ++ a = (int)(env->fr[ra + i * 32] & 0xffffffff); ++ b = (int)(env->fr[rb + i * 32] & 0xffffffff); ++ c = a + b; ++ if ((c ^ a) < 0 && (c ^ b) < 0) { ++ if (a < 0) ++ c = 0x80000000; ++ else ++ c = 0x7fffffff; ++ } ++ ret = c; ++ ++ a = (int)(env->fr[ra + i * 32] >> 32); ++ b = (int)(env->fr[rb + i * 32] >> 32); ++ c = a + b; ++ if ((c ^ a) < 0 && (c ^ b) < 0) { ++ if (a < 0) ++ c = 0x80000000; ++ else ++ c = 0x7fffffff; ++ } ++ env->fr[rc + i * 32] = ((uint64_t)(uint32_t)c << 32) | ++ (uint64_t)(uint32_t)ret; ++ } ++} ++ ++void helper_vucaddwi(CPUSW64State *env, uint64_t ra, uint64_t vb, uint64_t rc) ++{ ++ int a, b, c; ++ int ret; ++ int i; ++ ++ b = (int)vb; ++ for (i = 0; i < 4; i++) { ++ a = (int)(env->fr[ra + i * 32] & 0xffffffff); ++ c = a + b; ++ if ((c ^ a) < 0 && (c ^ b) < 0) { ++ if (a < 0) ++ c = 0x80000000; ++ else ++ c = 0x7fffffff; ++ } ++ ret = c; ++ ++ a = (int)(env->fr[ra + i * 32] >> 32); ++ c = a + b; ++ if ((c ^ a) < 0 && (c ^ b) < 0) { ++ if (a < 0) ++ c = 0x80000000; ++ else ++ c = 0x7fffffff; ++ } ++ env->fr[rc + i * 32] = ((uint64_t)(uint32_t)c << 32) | ++ (uint64_t)(uint32_t)ret; ++ } ++} ++ ++void helper_vucsubw(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t rc) ++{ ++ int a, b, c; ++ int ret; ++ int i; ++ ++ for (i = 0; i < 4; i++) { ++ a = (int)(env->fr[ra + i * 32] & 0xffffffff); ++ b = (int)(env->fr[rb + i * 32] & 0xffffffff); ++ c = a - b; ++ if ((b ^ a) < 0 && (c ^ a) < 0) { ++ if (a < 0) ++ c = 0x80000000; ++ else ++ c = 0x7fffffff; ++ } ++ ret = c; ++ ++ a = (int)(env->fr[ra + i * 32] >> 32); ++ b = (int)(env->fr[rb + i * 32] >> 32); ++ c = a - b; ++ if ((b ^ a) < 0 && (c ^ a) < 0) { ++ if (a < 0) ++ c = 0x80000000; ++ else ++ c = 0x7fffffff; ++ } ++ env->fr[rc + i * 32] = ((uint64_t)(uint32_t)c << 32) | ++ (uint64_t)(uint32_t)ret; ++ } ++} ++ ++void helper_vucsubwi(CPUSW64State *env, uint64_t ra, uint64_t vb, uint64_t rc) ++{ ++ int a, b, c; ++ int ret; ++ int i; ++ ++ b = (int)vb; ++ for (i = 0; i < 4; i++) { ++ a = (int)(env->fr[ra + i * 32] & 0xffffffff); ++ c = a - b; ++ if ((b ^ a) < 0 && (c ^ a) < 0) { ++ if (a < 0) ++ c = 0x80000000; ++ else ++ c = 0x7fffffff; ++ } ++ ret = c; ++ ++ a = (int)(env->fr[ra + i * 32] >> 32); ++ c = a - b; ++ if ((b ^ a) < 0 && (c ^ a) < 0) { ++ if (a < 0) ++ c = 0x80000000; ++ else ++ c = 0x7fffffff; ++ } ++ env->fr[rc + i * 32] = ((uint64_t)(uint32_t)c << 32) | ++ (uint64_t)(uint32_t)ret; ++ } ++} ++ ++void helper_vucaddh(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t rc) ++{ ++ short a, b, c; ++ uint64_t ret; ++ int i, j; ++ ++ for (i = 0; i < 4; i++) { ++ ret = 0; ++ for (j = 0; j < 4; j++) { ++ a = (short)((env->fr[ra + i * 32] >> (j * 16)) & 0xffff); ++ b = (short)((env->fr[rb + i * 32] >> (j * 16)) & 0xffff); ++ c = a + b; ++ if ((c ^ a) < 0 && (c ^ b) < 0) { ++ if (a < 0) ++ c = 0x8000; ++ else ++ c = 0x7fff; ++ } ++ ret |= ((uint64_t)(uint16_t)c) << (j * 16); ++ } ++ env->fr[rc + i * 32] = ret; ++ } ++} ++ ++void helper_vucaddhi(CPUSW64State *env, uint64_t ra, uint64_t vb, uint64_t rc) ++{ ++ short a, b, c; ++ uint64_t ret; ++ int i, j; ++ ++ b = (short)vb; ++ for (i = 0; i < 4; i++) { ++ ret = 0; ++ for (j = 0; j < 4; j++) { ++ a = (short)((env->fr[ra + i * 32] >> (j * 16)) & 0xffff); ++ c = a + b; ++ if ((c ^ a) < 0 && (c ^ b) < 0) { ++ if (a < 0) ++ c = 0x8000; ++ else ++ c = 0x7fff; ++ } ++ ret |= ((uint64_t)(uint16_t)c) << (j * 16); ++ } ++ env->fr[rc + i * 32] = ret; ++ } ++} ++ ++void helper_vucsubh(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t rc) ++{ ++ short a, b, c; ++ uint64_t ret; ++ int i, j; ++ ++ for (i = 0; i < 4; i++) { ++ ret = 0; ++ for (j = 0; j < 4; j++) { ++ a = (short)((env->fr[ra + i * 32] >> (j * 16)) & 0xffff); ++ b = (short)((env->fr[rb + i * 32] >> (j * 16)) & 0xffff); ++ c = a - b; ++ if ((b ^ a) < 0 && (c ^ a) < 0) { ++ if (a < 0) ++ c = 0x8000; ++ else ++ c = 0x7fff; ++ } ++ ret |= ((uint64_t)(uint16_t)c) << (j * 16); ++ } ++ env->fr[rc + i * 32] = ret; ++ } ++} ++ ++void helper_vucsubhi(CPUSW64State *env, uint64_t ra, uint64_t vb, uint64_t rc) ++{ ++ short a, b, c; ++ uint64_t ret; ++ int i, j; ++ ++ b = (short)vb; ++ for (i = 0; i < 4; i++) { ++ ret = 0; ++ for (j = 0; j < 4; j++) { ++ a = (short)((env->fr[ra + i * 32] >> (j * 16)) & 0xffff); ++ c = a - b; ++ if ((b ^ a) < 0 && (c ^ a) < 0) { ++ if (a < 0) ++ c = 0x8000; ++ else ++ c = 0x7fff; ++ } ++ ret |= ((uint64_t)(uint16_t)c) << (j * 16); ++ } ++ env->fr[rc + i * 32] = ret; ++ } ++} ++ ++void helper_vucaddb(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t rc) ++{ ++ int8_t a, b, c; ++ uint64_t ret; ++ int i, j; ++ ++ for (i = 0; i < 4; i++) { ++ ret = 0; ++ for (j = 0; j < 8; j++) { ++ a = (int8_t)((env->fr[ra + i * 32] >> (j * 8)) & 0xff); ++ b = (int8_t)((env->fr[rb + i * 32] >> (j * 8)) & 0xff); ++ c = a + b; ++ if ((c ^ a) < 0 && (c ^ b) < 0) { ++ if (a < 0) ++ c = 0x80; ++ else ++ c = 0x7f; ++ } ++ ret |= ((uint64_t)(uint8_t)c) << (j * 8); ++ } ++ env->fr[rc + i * 32] = ret; ++ } ++} ++ ++void helper_vucaddbi(CPUSW64State *env, uint64_t ra, uint64_t vb, uint64_t rc) ++{ ++ int8_t a, b, c; ++ uint64_t ret; ++ int i, j; ++ ++ b = (int8_t)(vb & 0xff); ++ for (i = 0; i < 4; i++) { ++ ret = 0; ++ for (j = 0; j < 8; j++) { ++ a = (int8_t)((env->fr[ra + i * 32] >> (j * 8)) & 0xff); ++ c = a + b; ++ if ((c ^ a) < 0 && (c ^ b) < 0) { ++ if (a < 0) ++ c = 0x80; ++ else ++ c = 0x7f; ++ } ++ ret |= ((uint64_t)(uint8_t)c) << (j * 8); ++ } ++ env->fr[rc + i * 32] = ret; ++ } ++} ++ ++void helper_vucsubb(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t rc) ++{ ++ int8_t a, b, c; ++ uint64_t ret; ++ int i, j; ++ ++ for (i = 0; i < 4; i++) { ++ ret = 0; ++ for (j = 0; j < 8; j++) { ++ a = (int8_t)((env->fr[ra + i * 32] >> (j * 8)) & 0xff); ++ b = (int8_t)((env->fr[rb + i * 32] >> (j * 8)) & 0xff); ++ c = a - b; ++ if ((b ^ a) < 0 && (c ^ a) < 0) { ++ if (a < 0) ++ c = 0x80; ++ else ++ c = 0x7f; ++ } ++ ret |= ((uint64_t)(uint8_t)c) << (j * 8); ++ } ++ env->fr[rc + i * 32] = ret; ++ } ++} ++ ++void helper_vucsubbi(CPUSW64State *env, uint64_t ra, uint64_t vb, uint64_t rc) ++{ ++ int8_t a, b, c; ++ uint64_t ret; ++ int i, j; ++ ++ b = (int8_t)(vb & 0xff); ++ for (i = 0; i < 4; i++) { ++ ret = 0; ++ for (j = 0; j < 8; j++) { ++ a = (int8_t)((env->fr[ra + i * 32] >> (j * 8)) & 0xffff); ++ c = a - b; ++ if ((b ^ a) < 0 && (c ^ a) < 0) { ++ if (a < 0) ++ c = 0x80; ++ else ++ c = 0x7f; ++ } ++ ret |= ((uint64_t)(uint8_t)c) << (j * 8); ++ } ++ env->fr[rc + i * 32] = ret; ++ } ++} ++ ++uint64_t helper_vstw(CPUSW64State *env, uint64_t t0, uint64_t t1) ++{ ++ uint64_t idx, shift; ++ ++ idx = t0 + (t1 / 2) * 32; ++ shift = (t1 % 2) * 32; ++ ++ return (env->fr[idx] >> shift) & 0xffffffffUL; ++} ++ ++uint64_t helper_vsts(CPUSW64State *env, uint64_t t0, uint64_t t1) ++{ ++ uint64_t idx, val; ++ ++ idx = t0 + t1 * 32; ++ val = env->fr[idx]; ++ ++ return ((val >> 32) & 0xc0000000) | ((val >> 29) & 0x3fffffff); ++} ++ ++uint64_t helper_vstd(CPUSW64State *env, uint64_t t0, uint64_t t1) ++{ ++ uint64_t idx; ++ ++ idx = t0 + t1 * 32; ++ return env->fr[idx]; ++} ++ ++#define HELPER_VMAX(name, _suffix, type, loop) \ ++ void glue(glue(helper_, name), _suffix)(CPUSW64State *env, uint64_t ra, \ ++ uint64_t rb, uint64_t rc) \ ++ { \ ++ int i; \ ++ type *ptr_dst, *ptr_src_a, *ptr_src_b; \ ++ \ ++ for (i = 0; i < loop; i++) { \ ++ ptr_dst = (type*)glue(get_element_, _suffix)(env, rc, i); \ ++ ptr_src_a = (type*)glue(get_element_, _suffix)(env, ra, i); \ ++ ptr_src_b = (type*)glue(get_element_, _suffix)(env, rb, i); \ ++ \ ++ if (*ptr_src_a >= *ptr_src_b) { \ ++ *ptr_dst = *ptr_src_a; \ ++ } else { \ ++ *ptr_dst = *ptr_src_b; \ ++ } \ ++ } \ ++ } ++ ++#define HELPER_VMIN(name, _suffix, type, loop) \ ++ void glue(glue(helper_, name), _suffix)(CPUSW64State *env, uint64_t ra, \ ++ uint64_t rb, uint64_t rc) \ ++ { \ ++ int i; \ ++ type *ptr_dst, *ptr_src_a, *ptr_src_b; \ ++ \ ++ for (i = 0; i < loop; i++) { \ ++ ptr_dst = (type*)glue(get_element_, _suffix)(env, rc, i); \ ++ ptr_src_a = (type*)glue(get_element_, _suffix)(env, ra, i); \ ++ ptr_src_b = (type*)glue(get_element_, _suffix)(env, rb, i); \ ++ \ ++ if (*ptr_src_a <= *ptr_src_b) { \ ++ *ptr_dst = *ptr_src_a; \ ++ } else { \ ++ *ptr_dst = *ptr_src_b; \ ++ } \ ++ } \ ++ } ++ ++HELPER_VMAX(vmax, b, int8_t, 32) ++HELPER_VMIN(vmin, b, int8_t, 32) ++HELPER_VMAX(vmax, h, int16_t, 16) ++HELPER_VMIN(vmin, h, int16_t, 16) ++HELPER_VMAX(vmax, w, int32_t, 8) ++HELPER_VMIN(vmin, w, int32_t, 8) ++HELPER_VMAX(vumax, b, uint8_t, 32) ++HELPER_VMIN(vumin, b, uint8_t, 32) ++HELPER_VMAX(vumax, h, uint16_t, 16) ++HELPER_VMIN(vumin, h, uint16_t, 16) ++HELPER_VMAX(vumax, w, uint32_t, 8) ++HELPER_VMIN(vumin, w, uint32_t, 8) ++ ++void helper_sraow(CPUSW64State *env, uint64_t ra, uint64_t rc, uint64_t shift) ++{ ++ int i; ++ int adden; ++ int dest, src; ++ uint64_t sign; ++ adden = shift >> 6; ++ shift &= 0x3f; ++ sign = (uint64_t)((int64_t)env->fr[ra + 96] >> 63); ++#ifdef DEBUG_SIMD ++ printf("right shift = %ld adden = %d\n", shift, adden); ++ printf("in_fr[%ld]:", ra); ++ for (i = 3 ; i >= 0; i--) { ++ printf("%016lx ", env->fr[ra + 32 * i]); ++ } ++ printf("\n"); ++#endif ++ ++ for (i = 0; (i + adden) < 4; i++) { ++ dest = i * 32 + rc; ++ src = (i + adden) * 32 + ra; ++ env->fr[dest] = env->fr[src] >> shift; ++ if (shift != 0) { ++ if (((i + adden) < 3)) ++ env->fr[dest] |= (env->fr[src + 32] << (64 - shift)); ++ else ++ env->fr[dest] |= (sign << (64 - shift)); ++ } ++ } ++ ++ for (; i < 4; i++) { ++ env->fr[rc + i * 32] = sign; ++ } ++#ifdef DEBUG_SIMD ++ printf("out_fr[%ld]:", rc); ++ for (i = 3 ; i >= 0; i--) { ++ printf("%016lx ", env->fr[rc + 32 * i]); ++ } ++ printf("\n"); ++#endif ++} ++ ++static uint16_t sm4_sbox[16][16] = { ++ { 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05 }, ++ { 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99 }, ++ { 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62 }, ++ { 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6 }, ++ { 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8 }, ++ { 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35 }, ++ { 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87 }, ++ { 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e }, ++ { 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1 }, ++ { 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3 }, ++ { 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f }, ++ { 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51 }, ++ { 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8 }, ++ { 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0 }, ++ { 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84 }, ++ { 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48 } ++}; ++ ++static uint32_t SBOX(uint32_t val) ++{ ++ int ret = 0; ++ int i; ++ int idx_x, idx_y; ++ for (i = 0; i < 4; i++) { ++ idx_x = (val >> (i * 8)) & 0xff; ++ idx_y = idx_x & 0xf; ++ idx_x = idx_x >> 4; ++ ++ ret |= (sm4_sbox[idx_x][idx_y] << (i * 8)); ++ } ++ return ret; ++} ++ ++static uint32_t rotl(uint32_t val, int shift) ++{ ++ uint64_t ret = (uint64_t)val; ++ ret = (ret << (shift & 0x1f)); ++ return (uint32_t)((ret & 0xffffffff) | (ret >> 32)); ++} ++ ++void helper_vsm4r(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t rc) ++{ ++ uint32_t W[12], rk[8]; ++ uint32_t temp1, temp2; ++ int i, j; ++ ++ for (i = 0; i < 8; i++) { ++ rk[i] = *get_element_w(env, rb, i); ++ } ++ for (i = 0; i < 2; i++) { ++ for (j = 0; j < 4; j++) { ++ W[j] = *get_element_w(env, ra, i * 4 + j); ++ } ++ for (j = 0; j < 8; j++) { ++ temp1 = W[j + 1] ^ W[j + 2] ^ W[j + 3] ^ rk[j]; ++ temp2 = SBOX(temp1); ++ W[j + 4] = W[j] ^ temp2 ^ rotl(temp2, 2) ^ rotl(temp2, 10) ^ rotl(temp2, 18) ^ rotl(temp2, 24); ++ } ++ ++ for (j = 0; j < 4; j++) { ++ *get_element_w(env, rc, i * 4 + j) = W[8 + j]; ++ } ++ } ++} ++ ++void helper_vcmpueqb(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t rc) ++{ ++ uint8_t *ptr_a, *ptr_b, *ptr_c; ++ int i; ++ ++ for (i = 0; i < 32; i++) { ++ ptr_a = get_element_b(env, ra, i); ++ ptr_b = get_element_b(env, rb, i); ++ ptr_c = get_element_b(env, rc, i); ++ ++ *ptr_c = (*ptr_a == *ptr_b) ? 1 : 0; ++ ; ++ } ++} ++ ++void helper_vcmpugtb(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t rc) ++{ ++ uint8_t *ptr_a, *ptr_b, *ptr_c; ++ int i; ++ ++ for (i = 0; i < 32; i++) { ++ ptr_a = get_element_b(env, ra, i); ++ ptr_b = get_element_b(env, rb, i); ++ ptr_c = get_element_b(env, rc, i); ++ ++ *ptr_c = (*ptr_a > *ptr_b) ? 1 : 0; ++ ; ++ } ++} ++ ++void helper_vcmpueqbi(CPUSW64State *env, uint64_t ra, uint64_t vb, ++ uint64_t rc) ++{ ++ uint8_t *ptr_a, *ptr_c; ++ int i; ++ ++ for (i = 0; i < 32; i++) { ++ ptr_a = get_element_b(env, ra, i); ++ ptr_c = get_element_b(env, rc, i); ++ ++ *ptr_c = (*ptr_a == vb) ? 1 : 0; ++ ; ++ } ++} ++ ++void helper_vcmpugtbi(CPUSW64State *env, uint64_t ra, uint64_t vb, ++ uint64_t rc) ++{ ++ uint8_t *ptr_a, *ptr_c; ++ int i; ++ ++ for (i = 0; i < 32; i++) { ++ ptr_a = get_element_b(env, ra, i); ++ ptr_c = get_element_b(env, rc, i); ++ ++ *ptr_c = (*ptr_a > vb) ? 1 : 0; ++ ; ++ } ++} ++ ++void helper_vsm3msw(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t rc) ++{ ++ uint32_t W[24]; ++ uint32_t temp; ++ int i; ++ ++ for (i = 0; i < 8; i++) { ++ W[i + 0] = *get_element_w(env, ra, i); ++ W[i + 8] = *get_element_w(env, rb, i); ++ } ++ for (i = 16; i < 24; i++) { ++ temp = W[i - 16] ^ W[i - 9] ^ rotl(W[i - 3], 15); ++ temp = temp ^ rotl(temp, 15) ^ rotl(temp, 23) ^ rotl(W[i - 13], 7) ^ W[i - 6]; ++ W[i] = temp; ++ } ++ for (i = 0; i < 8; i++) { ++ *get_element_w(env, rc, i) = W[16 + i]; ++ } ++} ++ ++static uint32_t selck[4][8] = { ++ {0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9}, ++ {0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9}, ++ {0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299}, ++ {0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279} ++}; ++ ++void helper_vsm4key(CPUSW64State *env, uint64_t ra, uint64_t vb, uint64_t rc) ++{ ++ uint32_t K[12], *CK; ++ int i; ++ uint32_t temp1, temp2; ++ ++ for (i = 4; i < 8; i++) { ++ K[i - 4] = *get_element_w(env, ra, i); ++ } ++ CK = selck[vb]; ++ ++ for (i = 0; i < 8; i++) { ++ temp1 = K[i + 1] ^ K[i + 2] ^ K[i + 3] ^ CK[i]; ++ temp2 = SBOX(temp1); ++ K[i + 4] = K[i] ^ temp2 ^ rotl(temp2, 13) ^ rotl(temp2, 23); ++ } ++ for (i = 0; i < 8; i++) { ++ *get_element_w(env, rc, i) = K[i + 4]; ++ } ++} ++ ++void helper_vinsb(CPUSW64State *env, uint64_t va, uint64_t rb, uint64_t vc, ++ uint64_t rd) ++{ ++ int i; ++ ++ for (i = 0; i < 128; i += 32) { ++ env->fr[rd + i] = env->fr[rb + i]; ++ } ++ ++ *get_element_b(env, rd, vc) = (uint8_t)(va & 0xff); ++} ++ ++void helper_vinsh(CPUSW64State *env, uint64_t va, uint64_t rb, uint64_t vc, ++ uint64_t rd) ++{ ++ int i; ++ ++ if (vc >= 16) ++ return; ++ ++ for (i = 0; i < 128; i += 32) { ++ env->fr[rd + i] = env->fr[rb + i]; ++ } ++ ++ *get_element_h(env, rd, vc) = (uint16_t)(va & 0xffff); ++} ++ ++void helper_vinsectlh(CPUSW64State *env, uint64_t ra, uint64_t rb, ++ uint64_t rd) ++{ ++ int i; ++ uint32_t temp[8]; ++ for (i = 0; i < 8; i++) { ++ temp[i] = *get_element_h(env, ra, i) | ((uint32_t)*get_element_h(env, rb, i) << 16); ++ } ++ for (i = 0; i < 8; i++) { ++ *get_element_w(env, rd, i) = temp[i]; ++ } ++} ++void helper_vinsectlw(CPUSW64State *env, uint64_t ra, uint64_t rb, ++ uint64_t rd) ++{ ++ int i; ++ uint64_t temp[4]; ++ for (i = 0; i < 4; i++) { ++ temp[i] = *get_element_w(env, ra, i) | ((uint64_t)*get_element_w(env, rb, i) << 32); ++ } ++ for (i = 0; i < 4; i++) { ++ *get_element_l(env, rd, i) = temp[i]; ++ } ++} ++ ++void helper_vinsectlb(CPUSW64State *env, uint64_t ra, uint64_t rb, ++ uint64_t rd) ++{ ++ int i; ++ uint16_t temp[16]; ++ for (i = 0; i < 16; i++) { ++ temp[i] = *get_element_b(env, ra, i) | ((uint16_t)*get_element_b(env, rb, i) << 8); ++ } ++ for (i = 0; i < 16; i++) { ++ *get_element_h(env, rd, i) = temp[i]; ++ } ++} ++ ++void helper_vshfq(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t vc, ++ uint64_t rd) ++{ ++ int i; ++ int idx; ++ uint64_t temp[4]; ++ for (i = 0; i < 2; i++) { ++ idx = ((vc >> (i * 2)) & 1) * 64; ++ if ((vc >> (i * 2 + 1)) & 1) { ++ temp[i * 2] = env->fr[rb + idx]; ++ temp[i * 2 + 1] = env->fr[rb + idx + 32]; ++ } else { ++ temp[i * 2] = env->fr[ra + idx]; ++ temp[i * 2 + 1] = env->fr[ra + idx + 32]; ++ } ++ } ++ for (i = 0; i < 4; i++) { ++ env->fr[rd + i * 32] = temp[i]; ++ } ++} ++ ++void helper_vshfqb(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t rd) ++{ ++ int i; ++ int idx; ++ int vb; ++ uint8_t temp[32]; ++ ++ for (i = 0; i < 16; i++) { ++ vb = *get_element_b(env, rb, i); ++ if (vb >> 7) { ++ temp[i] = 0; ++ } else { ++ idx = vb & 0xf; ++ temp[i] = *get_element_b(env, ra, idx); ++ } ++ vb = *get_element_b(env, rb, i + 16); ++ if (vb >> 7) { ++ temp[i + 16] = 0; ++ } else { ++ idx = vb & 0xf; ++ temp[i + 16] = *get_element_b(env, ra, idx + 16); ++ } ++ } ++ for (i = 0; i < 4; i++) { ++ env->fr[rd + i * 32] = *((uint64_t*)temp + i); ++ } ++} ++ ++void helper_vsm3r(CPUSW64State *env, uint64_t ra, uint64_t rb, uint64_t vc, ++ uint64_t rd) ++{ ++ uint32_t W[8]; ++ uint32_t A, B, C, D, E, F, G, H, T; ++ int i; ++ uint32_t SS1, SS2, TT1, TT2, P0; ++ ++ if (vc >= 16) ++ return; ++ for (i = 0; i < 8; i++) { ++ W[i] = *get_element_w(env, ra, i); ++ } ++ A = *get_element_w(env, rb, 0); ++ B = *get_element_w(env, rb, 1); ++ C = *get_element_w(env, rb, 2); ++ D = *get_element_w(env, rb, 3); ++ E = *get_element_w(env, rb, 4); ++ F = *get_element_w(env, rb, 5); ++ G = *get_element_w(env, rb, 6); ++ H = *get_element_w(env, rb, 7); ++ ++ if (vc < 4) { ++ T = 0x79cc4519; ++ for (i = 0; i < 4; i++) { ++ SS1 = rotl(rotl(A, 12) + E + rotl(T, 4 * vc + i), 7); ++ SS2 = SS1 ^ rotl(A, 12); ++ TT1 = (A ^ B ^ C) + D + SS2 + (W[i] ^ W[i + 4]); ++ TT2 = (E ^ F ^ G) + H + SS1 + W[i]; ++ ++ P0 = TT2 ^ rotl(TT2, 9) ^ rotl(TT2, 17); ++ ++ H = G; ++ G = rotl(F, 19); ++ F = E; ++ E = P0; ++ D = C; ++ C = rotl(B, 9); ++ B = A; ++ A = TT1; ++ } ++ } else { ++ T = 0x7a879d8a; ++ for (i = 0; i < 4; i++) { ++ SS1 = rotl(rotl(A, 12) + E + rotl(T, 4 * vc + i), 7); ++ SS2 = SS1 ^ rotl(A, 12); ++ TT1 = ((A & B) | (A & C) | (B & C)) + D + SS2 + (W[i] ^ W[i + 4]); ++ TT2 = ((E & F) | ((~E) & G)) + H + SS1 + W[i]; ++ ++ P0 = TT2 ^ rotl(TT2, 9) ^ rotl(TT2, 17); ++ ++ H = G; ++ G = rotl(F, 19); ++ F = E; ++ E = P0; ++ D = C; ++ C = rotl(B, 9); ++ B = A; ++ A = TT1; ++ } ++ } ++ *get_element_w(env, rd, 0) = A; ++ *get_element_w(env, rd, 1) = B; ++ *get_element_w(env, rd, 2) = C; ++ *get_element_w(env, rd, 3) = D; ++ *get_element_w(env, rd, 4) = E; ++ *get_element_w(env, rd, 5) = F; ++ *get_element_w(env, rd, 6) = G; ++ *get_element_w(env, rd, 7) = H; ++} +diff --git a/target/sw64/translate.c b/target/sw64/translate.c +new file mode 100644 +index 0000000000..37b7e89077 +--- /dev/null ++++ b/target/sw64/translate.c +@@ -0,0 +1,3798 @@ ++#include "translate.h" ++#include "tcg/tcg.h" ++#define DEVELOP_SW64 1 ++#ifdef DEVELOP_SW64 ++ ++#define ILLEGAL(x) \ ++ do { \ ++ printf("Illegal SW64 0x%x at line %d!\n", x, __LINE__); \ ++ exit(-1); \ ++ } while (0) ++#endif ++ ++TCGv cpu_pc; ++TCGv cpu_std_ir[31]; ++TCGv cpu_fr[128]; ++TCGv cpu_lock_addr; ++TCGv cpu_lock_flag; ++TCGv cpu_lock_success; ++#ifdef SW64_FIXLOCK ++TCGv cpu_lock_value; ++#endif ++ ++#ifndef CONFIG_USER_ONLY ++TCGv cpu_hm_ir[31]; ++#endif ++ ++#include "exec/gen-icount.h" ++ ++void sw64_translate_init(void) ++{ ++#define DEF_VAR(V) \ ++ { &cpu_##V, #V, offsetof(CPUSW64State, V) } ++ ++ typedef struct { ++ TCGv* var; ++ const char* name; ++ int ofs; ++ } GlobalVar; ++ ++ static const GlobalVar vars[] = { ++ DEF_VAR(pc), DEF_VAR(lock_addr), ++ DEF_VAR(lock_flag), DEF_VAR(lock_success), ++#ifdef SW64_FIXLOCK ++ DEF_VAR(lock_value), ++#endif ++ }; ++ cpu_pc = tcg_global_mem_new_i64(cpu_env, ++ offsetof(CPUSW64State, pc), "PC"); ++ ++#undef DEF_VAR ++ ++ /* Use the symbolic register names that match the disassembler. */ ++ static const char ireg_names[31][4] = { ++ "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "s0", "s1", ++ "s2", "s3", "s4", "s5", "fp", "a0", "a1", "a2", "a3", "a4", "a5", ++ "t8", "t9", "t10", "t11", "ra", "t12", "at", "gp", "sp"}; ++ ++ static const char freg_names[128][4] = { ++ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", ++ "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", ++ "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", ++ "f30", "f31", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", ++ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", ++ "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", ++ "f28", "f29", "f30", "f31", "f0", "f1", "f2", "f3", "f4", "f5", ++ "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", ++ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", ++ "f26", "f27", "f28", "f29", "f30", "f31", "f0", "f1", "f2", "f3", ++ "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", ++ "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", ++ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"}; ++ ++#ifndef CONFIG_USER_ONLY ++ static const char shadow_names[10][8] = { ++ "hm_p1", "hm_p2", "hm_p4", "hm_p5", "hm_p6", ++ "hm_p7", "hm_p20", "hm_p21", "hm_p22", "hm_p23"}; ++ static const int shadow_index[10] = {1, 2, 4, 5, 6, 7, 20, 21, 22, 23}; ++#endif ++ ++ int i; ++ ++ for (i = 0; i < 31; i++) { ++ cpu_std_ir[i] = tcg_global_mem_new_i64( ++ cpu_env, offsetof(CPUSW64State, ir[i]), ireg_names[i]); ++ } ++ ++ for (i = 0; i < 128; i++) { ++ cpu_fr[i] = tcg_global_mem_new_i64( ++ cpu_env, offsetof(CPUSW64State, fr[i]), freg_names[i]); ++ } ++ for (i = 0; i < ARRAY_SIZE(vars); ++i) { ++ const GlobalVar* v = &vars[i]; ++ *v->var = tcg_global_mem_new_i64(cpu_env, v->ofs, v->name); ++ } ++#ifndef CONFIG_USER_ONLY ++ memcpy(cpu_hm_ir, cpu_std_ir, sizeof(cpu_hm_ir)); ++ for (i = 0; i < 10; i++) { ++ int r = shadow_index[i]; ++ cpu_hm_ir[r] = tcg_global_mem_new_i64( ++ cpu_env, offsetof(CPUSW64State, sr[i]), shadow_names[i]); ++ } ++#endif ++} ++ ++static bool in_superpage(DisasContext* ctx, int64_t addr) ++{ ++ return false; ++} ++ ++bool use_exit_tb(DisasContext* ctx) ++{ ++ return ((tb_cflags(ctx->base.tb) & CF_LAST_IO) || ++ ctx->base.singlestep_enabled || singlestep); ++} ++ ++bool use_goto_tb(DisasContext* ctx, uint64_t dest) ++{ ++ /* Suppress goto_tb in the case of single-steping and IO. */ ++ if (unlikely(use_exit_tb(ctx))) { ++ return false; ++ } ++ /* If the destination is in the superpage, the page perms can't change. */ ++ if (in_superpage(ctx, dest)) { ++ return true; ++ } ++/* Check for the dest on the same page as the start of the TB. */ ++#ifndef CONFIG_USER_ONLY ++ return ((ctx->base.tb->pc ^ dest) & TARGET_PAGE_MASK) == 0; ++#else ++ return true; ++#endif ++} ++ ++void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src) ++{ ++ uint64_t mzero = 1ull << 63; ++ ++ switch (cond) { ++ case TCG_COND_LE: ++ case TCG_COND_GT: ++ /* For <= or >, the -0.0 value directly compares the way we want. */ ++ tcg_gen_mov_i64(dest, src); ++ break; ++ ++ case TCG_COND_EQ: ++ case TCG_COND_NE: ++ /* For == or !=, we can simply mask off the sign bit and compare. */ ++ tcg_gen_andi_i64(dest, src, mzero - 1); ++ break; ++ ++ case TCG_COND_GE: ++ case TCG_COND_LT: ++ /* For >= or <, map -0.0 to +0.0 via comparison and mask. */ ++ tcg_gen_setcondi_i64(TCG_COND_NE, dest, src, mzero); ++ tcg_gen_neg_i64(dest, dest); ++ tcg_gen_and_i64(dest, dest, src); ++ break; ++ ++ default: ++ abort(); ++ } ++} ++ ++static TCGv load_zero(DisasContext *ctx) ++{ ++ if (!ctx->zero) { ++ ctx->zero = tcg_const_i64(0); ++ } ++ return ctx->zero; ++} ++ ++static void free_context_temps(DisasContext *ctx) ++{ ++ if (ctx->zero) { ++ tcg_temp_free(ctx->zero); ++ ctx->zero = NULL; ++ } ++} ++ ++static TCGv load_gir(DisasContext *ctx, unsigned reg) ++{ ++ if (likely(reg < 31)) { ++ return ctx->ir[reg]; ++ } else { ++ return load_zero(ctx); ++ } ++} ++ ++static void gen_excp_1(int exception, int error_code) ++{ ++ TCGv_i32 tmp1, tmp2; ++ ++ tmp1 = tcg_const_i32(exception); ++ tmp2 = tcg_const_i32(error_code); ++ gen_helper_excp(cpu_env, tmp1, tmp2); ++ tcg_temp_free_i32(tmp2); ++ tcg_temp_free_i32(tmp1); ++} ++ ++static DisasJumpType gen_excp(DisasContext* ctx, int exception, ++ int error_code) ++{ ++ tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next); ++ gen_excp_1(exception, error_code); ++ return DISAS_NORETURN; ++} ++ ++static int i_count = 1; ++ ++static inline DisasJumpType gen_invalid(DisasContext *ctx) ++{ ++ if (i_count == 0) { ++ i_count++; ++ return DISAS_NEXT; ++ } ++ fprintf(stderr, "here %lx\n", ctx->base.pc_next); ++ return gen_excp(ctx, EXCP_OPCDEC, 0); ++} ++ ++static uint64_t zapnot_mask(uint8_t byte_mask) ++{ ++ uint64_t mask = 0; ++ int i; ++ ++ for (i = 0; i < 8; ++i) { ++ if ((byte_mask >> i) & 1) { ++ mask |= 0xffull << (i * 8); ++ } ++ } ++ return mask; ++} ++ ++static void gen_ins_l(DisasContext* ctx, TCGv vc, TCGv va, TCGv vb, ++ uint8_t byte_mask) ++{ ++ TCGv tmp = tcg_temp_new(); ++ TCGv shift = tcg_temp_new(); ++ ++ tcg_gen_andi_i64(tmp, va, zapnot_mask(byte_mask)); ++ ++ tcg_gen_andi_i64(shift, vb, 7); ++ tcg_gen_shli_i64(shift, shift, 3); ++ tcg_gen_shl_i64(vc, tmp, shift); ++ ++ tcg_temp_free(shift); ++ tcg_temp_free(tmp); ++} ++ ++static void gen_ins_h(DisasContext* ctx, TCGv vc, TCGv va, TCGv vb, ++ uint8_t byte_mask) ++{ ++ TCGv tmp = tcg_temp_new(); ++ TCGv shift = tcg_temp_new(); ++ ++ tcg_gen_andi_i64(tmp, va, zapnot_mask(byte_mask)); ++ ++ tcg_gen_shli_i64(shift, vb, 3); ++ tcg_gen_not_i64(shift, shift); ++ tcg_gen_andi_i64(shift, shift, 0x3f); ++ ++ tcg_gen_shr_i64(vc, tmp, shift); ++ tcg_gen_shri_i64(vc, vc, 1); ++ tcg_temp_free(shift); ++ tcg_temp_free(tmp); ++} ++ ++static void gen_ext_l(DisasContext* ctx, TCGv vc, TCGv va, TCGv vb, ++ uint8_t byte_mask) ++{ ++ TCGv tmp = tcg_temp_new(); ++ TCGv shift = tcg_temp_new(); ++ ++ tcg_gen_andi_i64(shift, vb, 7); ++ tcg_gen_shli_i64(shift, shift, 3); ++ tcg_gen_shr_i64(tmp, va, shift); ++ ++ tcg_gen_andi_i64(vc, tmp, zapnot_mask(byte_mask)); ++ ++ tcg_temp_free(shift); ++ tcg_temp_free(tmp); ++} ++ ++static void gen_ext_h(DisasContext* ctx, TCGv vc, TCGv va, TCGv vb, ++ uint8_t byte_mask) ++{ ++ TCGv tmp = tcg_temp_new(); ++ TCGv shift = tcg_temp_new(); ++ ++ tcg_gen_andi_i64(shift, vb, 7); ++ tcg_gen_shli_i64(shift, shift, 3); ++ tcg_gen_movi_i64(tmp, 64); ++ tcg_gen_sub_i64(shift, tmp, shift); ++ tcg_gen_shl_i64(tmp, va, shift); ++ ++ tcg_gen_andi_i64(vc, tmp, zapnot_mask(byte_mask)); ++ ++ tcg_temp_free(shift); ++ tcg_temp_free(tmp); ++} ++ ++static void gen_mask_l(DisasContext* ctx, TCGv vc, TCGv va, TCGv vb, ++ uint8_t byte_mask) ++{ ++ TCGv shift = tcg_temp_new(); ++ TCGv mask = tcg_temp_new(); ++ ++ tcg_gen_andi_i64(shift, vb, 7); ++ tcg_gen_shli_i64(shift, shift, 3); ++ tcg_gen_movi_i64(mask, zapnot_mask(byte_mask)); ++ tcg_gen_shl_i64(mask, mask, shift); ++ ++ tcg_gen_andc_i64(vc, va, mask); ++ ++ tcg_temp_free(mask); ++ tcg_temp_free(shift); ++} ++ ++static void gen_mask_h(DisasContext *ctx, TCGv vc, TCGv va, TCGv vb, ++ uint8_t byte_mask) ++{ ++ TCGv shift = tcg_temp_new(); ++ TCGv mask = tcg_temp_new(); ++ ++ /* The instruction description is as above, where the byte_mask ++ is shifted left, and then we extract bits <15:8>. This can be ++ emulated with a right-shift on the expanded byte mask. This ++ requires extra care because for an input <2:0> == 0 we need a ++ shift of 64 bits in order to generate a zero. This is done by ++ splitting the shift into two parts, the variable shift - 1 ++ followed by a constant 1 shift. The code we expand below is ++ equivalent to ~(B * 8) & 63. */ ++ ++ tcg_gen_shli_i64(shift, vb, 3); ++ tcg_gen_not_i64(shift, shift); ++ tcg_gen_andi_i64(shift, shift, 0x3f); ++ tcg_gen_movi_i64(mask, zapnot_mask(byte_mask)); ++ tcg_gen_shr_i64(mask, mask, shift); ++ tcg_gen_shri_i64(mask, mask, 1); ++ ++ tcg_gen_andc_i64(vc, va, mask); ++ ++ tcg_temp_free(mask); ++ tcg_temp_free(shift); ++} ++ ++static inline void gen_load_mem( ++ DisasContext *ctx, void (*tcg_gen_qemu_load)(TCGv t0, TCGv t1, int flags), ++ int ra, int rb, int32_t disp16, bool fp, bool clear) ++{ ++ TCGv tmp, addr, va; ++ ++ /* LDQ_U with ra $31 is UNOP. Other various loads are forms of ++ prefetches, which we can treat as nops. No worries about ++ missed exceptions here. */ ++ if (unlikely(ra == 31)) { ++ return; ++ } ++ ++ tmp = tcg_temp_new(); ++ addr = load_gir(ctx, rb); ++ ++ if (disp16) { ++ tcg_gen_addi_i64(tmp, addr, (int64_t)disp16); ++ addr = tmp; ++ } else { ++ tcg_gen_mov_i64(tmp, addr); ++ addr = tmp; ++ } ++ if (clear) { ++ tcg_gen_andi_i64(tmp, addr, ~0x7UL); ++ addr = tmp; ++ } ++ ++ va = (fp ? cpu_fr[ra] : load_gir(ctx, ra)); ++ tcg_gen_qemu_load(va, addr, ctx->mem_idx); ++ ++ tcg_temp_free(tmp); ++} ++ ++static inline void gen_store_mem( ++ DisasContext *ctx, void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1, int flags), ++ int ra, int rb, int32_t disp16, bool fp, bool clear) ++{ ++ TCGv tmp, addr, va; ++ ++ tmp = tcg_temp_new(); ++ addr = load_gir(ctx, rb); ++ if (disp16) { ++ tcg_gen_addi_i64(tmp, addr, disp16); ++ addr = tmp; ++ } else { ++ tcg_gen_mov_i64(tmp, addr); ++ addr = tmp; ++ } ++ if (clear) { ++ tcg_gen_andi_i64(tmp, addr, ~0x7); ++ addr = tmp; ++ } ++ va = (fp ? cpu_fr[ra] : load_gir(ctx, ra)); ++ ++ tcg_gen_qemu_store(va, addr, ctx->mem_idx); ++ gen_helper_trace_mem(cpu_env, addr, va); ++ tcg_temp_free(tmp); ++} ++ ++static void cal_with_iregs_2(DisasContext *ctx, TCGv vc, TCGv va, TCGv vb, ++ int32_t disp13, uint16_t fn) ++{ ++ TCGv tmp; ++ ++ switch (fn & 0xff) { ++ case 0x00: ++ /* ADDW */ ++ tcg_gen_add_i64(vc, va, vb); ++ tcg_gen_ext32s_i64(vc, vc); ++ break; ++ case 0x01: ++ /* SUBW */ ++ tcg_gen_sub_i64(vc, va, vb); ++ tcg_gen_ext32s_i64(vc, vc); ++ break; ++ case 0x02: ++ /* S4ADDW */ ++ tmp = tcg_temp_new(); ++ tcg_gen_shli_i64(tmp, va, 2); ++ tcg_gen_add_i64(tmp, tmp, vb); ++ tcg_gen_ext32s_i64(vc, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x03: ++ /* S4SUBW */ ++ tmp = tcg_temp_new(); ++ tcg_gen_shli_i64(tmp, va, 2); ++ tcg_gen_sub_i64(tmp, tmp, vb); ++ tcg_gen_ext32s_i64(vc, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x04: ++ /* S8ADDW */ ++ tmp = tcg_temp_new(); ++ tcg_gen_shli_i64(tmp, va, 3); ++ tcg_gen_add_i64(tmp, tmp, vb); ++ tcg_gen_ext32s_i64(vc, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x05: ++ /* S8SUBW */ ++ tmp = tcg_temp_new(); ++ tcg_gen_shli_i64(tmp, va, 3); ++ tcg_gen_sub_i64(tmp, tmp, vb); ++ tcg_gen_ext32s_i64(vc, tmp); ++ tcg_temp_free(tmp); ++ break; ++ ++ case 0x08: ++ /* ADDL */ ++ tcg_gen_add_i64(vc, va, vb); ++ break; ++ case 0x09: ++ /* SUBL */ ++ tcg_gen_sub_i64(vc, va, vb); ++ break; ++ case 0x0a: ++ /* S4ADDL */ ++ tmp = tcg_temp_new(); ++ tcg_gen_shli_i64(tmp, va, 2); ++ tcg_gen_add_i64(vc, tmp, vb); ++ tcg_temp_free(tmp); ++ break; ++ case 0x0b: ++ /* S4SUBL */ ++ tmp = tcg_temp_new(); ++ tcg_gen_shli_i64(tmp, va, 2); ++ tcg_gen_sub_i64(vc, tmp, vb); ++ tcg_temp_free(tmp); ++ break; ++ case 0x0c: ++ /* S8ADDL */ ++ tmp = tcg_temp_new(); ++ tcg_gen_shli_i64(tmp, va, 3); ++ tcg_gen_add_i64(vc, tmp, vb); ++ tcg_temp_free(tmp); ++ break; ++ case 0x0d: ++ /* S8SUBL */ ++ tmp = tcg_temp_new(); ++ tcg_gen_shli_i64(tmp, va, 3); ++ tcg_gen_sub_i64(vc, tmp, vb); ++ tcg_temp_free(tmp); ++ break; ++ case 0x10: ++ /* MULW */ ++ tcg_gen_mul_i64(vc, va, vb); ++ tcg_gen_ext32s_i64(vc, vc); ++ break; ++ case 0x18: ++ /* MULL */ ++ tcg_gen_mul_i64(vc, va, vb); ++ break; ++ case 0x19: ++ /* MULH */ ++ tmp = tcg_temp_new(); ++ tcg_gen_mulu2_i64(tmp, vc, va, vb); ++ tcg_temp_free(tmp); ++ break; ++ case 0x28: ++ /* CMPEQ */ ++ tcg_gen_setcond_i64(TCG_COND_EQ, vc, va, vb); ++ break; ++ case 0x29: ++ /* CMPLT */ ++ tcg_gen_setcond_i64(TCG_COND_LT, vc, va, vb); ++ break; ++ case 0x2a: ++ /* CMPLE */ ++ tcg_gen_setcond_i64(TCG_COND_LE, vc, va, vb); ++ break; ++ case 0x2b: ++ /* CMPULT */ ++ tcg_gen_setcond_i64(TCG_COND_LTU, vc, va, vb); ++ break; ++ case 0x2c: ++ /* CMPULE */ ++ tcg_gen_setcond_i64(TCG_COND_LEU, vc, va, vb); ++ break; ++ case 0x38: ++ /* AND */ ++ tcg_gen_and_i64(vc, va, vb); ++ break; ++ case 0x39: ++ /* BIC */ ++ tcg_gen_andc_i64(vc, va, vb); ++ break; ++ case 0x3a: ++ /* BIS */ ++ tcg_gen_or_i64(vc, va, vb); ++ break; ++ case 0x3b: ++ /* ORNOT */ ++ tcg_gen_orc_i64(vc, va, vb); ++ break; ++ case 0x3c: ++ /* XOR */ ++ tcg_gen_xor_i64(vc, va, vb); ++ break; ++ case 0x3d: ++ /* EQV */ ++ tcg_gen_eqv_i64(vc, va, vb); ++ break; ++ case 0x40: ++ /* INSLB */ ++ gen_ins_l(ctx, vc, va, vb, 0x1); ++ break; ++ case 0x41: ++ /* INSLH */ ++ gen_ins_l(ctx, vc, va, vb, 0x3); ++ break; ++ case 0x42: ++ /* INSLW */ ++ gen_ins_l(ctx, vc, va, vb, 0xf); ++ break; ++ case 0x43: ++ /* INSLL */ ++ gen_ins_l(ctx, vc, va, vb, 0xff); ++ break; ++ case 0x44: ++ /* INSHB */ ++ gen_ins_h(ctx, vc, va, vb, 0x1); ++ break; ++ case 0x45: ++ /* INSHH */ ++ gen_ins_h(ctx, vc, va, vb, 0x3); ++ break; ++ case 0x46: ++ /* INSHW */ ++ gen_ins_h(ctx, vc, va, vb, 0xf); ++ break; ++ case 0x47: ++ /* INSHL */ ++ gen_ins_h(ctx, vc, va, vb, 0xff); ++ break; ++ case 0x48: ++ /* SLL/SLLL */ ++ tmp = tcg_temp_new(); ++ tcg_gen_andi_i64(tmp, vb, 0x3f); ++ tcg_gen_shl_i64(vc, va, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x49: ++ /* SRL/SRLL */ ++ tmp = tcg_temp_new(); ++ tcg_gen_andi_i64(tmp, vb, 0x3f); ++ tcg_gen_shr_i64(vc, va, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x4a: ++ /* SRA/SRAL */ ++ tmp = tcg_temp_new(); ++ tcg_gen_andi_i64(tmp, vb, 0x3f); ++ tcg_gen_sar_i64(vc, va, tmp); ++ tcg_temp_free(tmp); ++ break; ++ case 0x50: ++ /* EXTLB */ ++ gen_ext_l(ctx, vc, va, vb, 0x1); ++ break; ++ case 0x51: ++ /* EXTLH */ ++ gen_ext_l(ctx, vc, va, vb, 0x3); ++ break; ++ case 0x52: ++ /* EXTLW */ ++ gen_ext_l(ctx, vc, va, vb, 0xf); ++ break; ++ case 0x53: ++ /* EXTLL */ ++ gen_ext_l(ctx, vc, va, vb, 0xff); ++ break; ++ case 0x54: ++ /* EXTHB */ ++ gen_ext_h(ctx, vc, va, vb, 0x1); ++ break; ++ case 0x55: ++ /* EXTHH */ ++ gen_ext_h(ctx, vc, va, vb, 0x3); ++ break; ++ case 0x56: ++ /* EXTHW */ ++ gen_ext_h(ctx, vc, va, vb, 0xf); ++ break; ++ case 0x57: ++ /* EXTHL */ ++ gen_ext_h(ctx, vc, va, vb, 0xff); ++ break; ++ case 0x58: ++ /* CTPOP */ ++ tcg_gen_ctpop_i64(vc, vb); ++ break; ++ case 0x59: ++ /* CTLZ */ ++ tcg_gen_clzi_i64(vc, vb, 64); ++ break; ++ case 0x5a: ++ /* CTTZ */ ++ tcg_gen_ctzi_i64(vc, vb, 64); ++ break; ++ case 0x60: ++ /* MASKLB */ ++ gen_mask_l(ctx, vc, va, vb, 0x1); ++ break; ++ case 0x61: ++ /* MASKLH */ ++ gen_mask_l(ctx, vc, va, vb, 0x3); ++ break; ++ case 0x62: ++ /* MASKLW */ ++ gen_mask_l(ctx, vc, va, vb, 0xf); ++ break; ++ case 0x63: ++ /* MASKLL */ ++ gen_mask_l(ctx, vc, va, vb, 0xff); ++ break; ++ case 0x64: ++ /* MASKHB */ ++ gen_mask_h(ctx, vc, va, vb, 0x1); ++ break; ++ case 0x65: ++ /* MASKHH */ ++ gen_mask_h(ctx, vc, va, vb, 0x3); ++ break; ++ case 0x66: ++ /* MASKHW */ ++ gen_mask_h(ctx, vc, va, vb, 0xf); ++ break; ++ case 0x67: ++ /* MASKHL */ ++ gen_mask_h(ctx, vc, va, vb, 0xff); ++ break; ++ case 0x68: ++ /* ZAP */ ++ gen_helper_zap(vc, va, vb); ++ break; ++ case 0x69: ++ /* ZAPNOT */ ++ gen_helper_zapnot(vc, va, vb); ++ break; ++ case 0x6a: ++ /* SEXTB */ ++ tcg_gen_ext8s_i64(vc, vb); ++ break; ++ case 0x6b: ++ /* SEXTH */ ++ tcg_gen_ext16s_i64(vc, vb); ++ break; ++ case 0x6c: ++ /* CMPGEB*/ ++ gen_helper_cmpgeb(vc, va, vb); ++ break; ++ default: ++ ILLEGAL(fn); ++ } ++} ++ ++static void cal_with_imm_2(DisasContext *ctx, TCGv vc, TCGv va, int64_t disp, ++ uint8_t fn) ++{ ++ TCGv_i64 t0 = tcg_const_i64(disp); ++ cal_with_iregs_2(ctx, vc, va, t0, 0, fn); ++ tcg_temp_free_i64(t0); ++} ++ ++static void cal_with_iregs_3(DisasContext *ctx, TCGv vd, TCGv va, TCGv vb, ++ TCGv vc, uint8_t fn) ++{ ++ TCGv_i64 t0 = tcg_const_i64(0); ++ TCGv_i64 tmp; ++ switch (fn) { ++ case 0x0: ++ /* SELEQ */ ++ tcg_gen_movcond_i64(TCG_COND_EQ, vd, va, t0, vb, vc); ++ break; ++ case 0x1: ++ /* SELGE */ ++ tcg_gen_movcond_i64(TCG_COND_GE, vd, va, t0, vb, vc); ++ break; ++ case 0x2: ++ /* SELGT */ ++ tcg_gen_movcond_i64(TCG_COND_GT, vd, va, t0, vb, vc); ++ break; ++ case 0x3: ++ /* SELLE */ ++ tcg_gen_movcond_i64(TCG_COND_LE, vd, va, t0, vb, vc); ++ break; ++ case 0x4: ++ /* SELLT */ ++ tcg_gen_movcond_i64(TCG_COND_LT, vd, va, t0, vb, vc); ++ break; ++ case 0x5: ++ /* SELNE */ ++ tcg_gen_movcond_i64(TCG_COND_NE, vd, va, t0, vb, vc); ++ break; ++ case 0x6: ++ /* SELLBC */ ++ tmp = tcg_temp_new_i64(); ++ tcg_gen_andi_i64(tmp, va, 1); ++ tcg_gen_movcond_i64(TCG_COND_EQ, vd, tmp, t0, vb, vc); ++ tcg_temp_free_i64(tmp); ++ break; ++ case 0x7: ++ /* SELLBS */ ++ tmp = tcg_temp_new_i64(); ++ tcg_gen_andi_i64(tmp, va, 1); ++ tcg_gen_movcond_i64(TCG_COND_NE, vd, tmp, t0, vb, vc); ++ tcg_temp_free_i64(tmp); ++ break; ++ default: ++ ILLEGAL(fn); ++ break; ++ } ++ tcg_temp_free_i64(t0); ++} ++ ++static void cal_with_imm_3(DisasContext *ctx, TCGv vd, TCGv va, int32_t disp, ++ TCGv vc, uint8_t fn) ++{ ++ TCGv_i64 vb = tcg_const_i64(disp); ++ cal_with_iregs_3(ctx, vd, va, vb, vc, fn); ++ tcg_temp_free_i64(vb); ++} ++ ++static DisasJumpType gen_bdirect(DisasContext *ctx, int ra, int32_t disp) ++{ ++ uint64_t dest = ctx->base.pc_next + ((int64_t)disp << 2); ++ if (ra != 31) { ++ tcg_gen_movi_i64(load_gir(ctx, ra), ctx->base.pc_next & (~0x3UL)); ++ } ++ if (disp == 0) { ++ return 0; ++ } else if (use_goto_tb(ctx, dest)) { ++ tcg_gen_goto_tb(0); ++ tcg_gen_movi_i64(cpu_pc, dest); ++ tcg_gen_exit_tb(ctx->base.tb, 0); ++ return DISAS_NORETURN; ++ } else { ++ tcg_gen_movi_i64(cpu_pc, dest); ++ return DISAS_PC_UPDATED; ++ } ++} ++ ++static DisasJumpType gen_bcond_internal(DisasContext *ctx, TCGCond cond, ++ TCGv cmp, int disp) ++{ ++ uint64_t dest = ctx->base.pc_next + (disp << 2); ++ TCGLabel* lab_true = gen_new_label(); ++ ++ if (use_goto_tb(ctx, dest)) { ++ tcg_gen_brcondi_i64(cond, cmp, 0, lab_true); ++ ++ tcg_gen_goto_tb(0); ++ tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next); ++ tcg_gen_exit_tb(ctx->base.tb, 0); ++ ++ gen_set_label(lab_true); ++ tcg_gen_goto_tb(1); ++ tcg_gen_movi_i64(cpu_pc, dest); ++ tcg_gen_exit_tb(ctx->base.tb, 1); ++ ++ return DISAS_NORETURN; ++ } else { ++ TCGv_i64 t = tcg_const_i64(0); ++ TCGv_i64 d = tcg_const_i64(dest); ++ TCGv_i64 p = tcg_const_i64(ctx->base.pc_next); ++ ++ tcg_gen_movcond_i64(cond, cpu_pc, cmp, t, d, p); ++ ++ tcg_temp_free_i64(t); ++ tcg_temp_free_i64(d); ++ tcg_temp_free_i64(p); ++ return DISAS_PC_UPDATED; ++ } ++} ++ ++static DisasJumpType gen_bcond(DisasContext *ctx, TCGCond cond, uint32_t ra, ++ int32_t disp, uint64_t mask) ++{ ++ TCGv tmp = tcg_temp_new(); ++ DisasJumpType ret; ++ ++ tcg_gen_andi_i64(tmp, load_gir(ctx, ra), mask); ++ ret = gen_bcond_internal(ctx, cond, tmp, disp); ++ tcg_temp_free(tmp); ++ return ret; ++} ++ ++static DisasJumpType gen_fbcond(DisasContext *ctx, TCGCond cond, int ra, ++ int32_t disp) ++{ ++ TCGv cmp_tmp = tcg_temp_new(); ++ DisasJumpType ret; ++ ++ gen_fold_mzero(cond, cmp_tmp, cpu_fr[ra]); ++ ret = gen_bcond_internal(ctx, cond, cmp_tmp, disp); ++ tcg_temp_free(cmp_tmp); ++ return ret; ++} ++ ++#ifndef CONFIG_USER_ONLY ++static void gen_qemu_pri_ldw(TCGv t0, TCGv t1, int memidx) ++{ ++ gen_helper_pri_ldw(t0, cpu_env, t1); ++} ++ ++static void gen_qemu_pri_stw(TCGv t0, TCGv t1, int memidx) ++{ ++ gen_helper_pri_stw(cpu_env, t0, t1); ++} ++ ++static void gen_qemu_pri_ldl(TCGv t0, TCGv t1, int memidx) ++{ ++ gen_helper_pri_ldl(t0, cpu_env, t1); ++} ++ ++static void gen_qemu_pri_stl(TCGv t0, TCGv t1, int memidx) ++{ ++ gen_helper_pri_stl(cpu_env, t0, t1); ++} ++#endif ++ ++static inline void gen_load_mem_simd( ++ DisasContext *ctx, void (*tcg_gen_qemu_load)(int t0, TCGv t1, int flags), ++ int ra, int rb, int32_t disp16, uint64_t mask) ++{ ++ TCGv tmp, addr; ++ ++ /* LDQ_U with ra $31 is UNOP. Other various loads are forms of ++ prefetches, which we can treat as nops. No worries about ++ missed exceptions here. */ ++ if (unlikely(ra == 31)) ++ return; ++ ++ tmp = tcg_temp_new(); ++ addr = load_gir(ctx, rb); ++ ++ if (disp16) { ++ tcg_gen_addi_i64(tmp, addr, (int64_t)disp16); ++ addr = tmp; ++ } else { ++ tcg_gen_mov_i64(tmp, addr); ++ addr = tmp; ++ } ++ ++ if (mask) { ++ tcg_gen_andi_i64(addr, addr, mask); ++ } ++ ++ tcg_gen_qemu_load(ra, addr, ctx->mem_idx); ++ // FIXME: for debug ++ ++ tcg_temp_free(tmp); ++} ++ ++static inline void gen_store_mem_simd( ++ DisasContext *ctx, void (*tcg_gen_qemu_store)(int t0, TCGv t1, int flags), ++ int ra, int rb, int32_t disp16, uint64_t mask) ++{ ++ TCGv tmp, addr; ++ ++ tmp = tcg_temp_new(); ++ addr = load_gir(ctx, rb); ++ if (disp16) { ++ tcg_gen_addi_i64(tmp, addr, (int64_t)disp16); ++ addr = tmp; ++ } else { ++ tcg_gen_mov_i64(tmp, addr); ++ addr = tmp; ++ } ++ if (mask) { ++ tcg_gen_andi_i64(addr, addr, mask); ++ } ++ // FIXME: for debug ++ tcg_gen_qemu_store(ra, addr, ctx->mem_idx); ++ ++ tcg_temp_free(tmp); ++} ++ ++static void gen_qemu_ldwe(int t0, TCGv t1, int memidx) ++{ ++ TCGv tmp = tcg_temp_new(); ++ ++ tcg_gen_qemu_ld_i64(tmp, t1, memidx, MO_ALIGN_4 | MO_LEUL); ++ tcg_gen_shli_i64(cpu_fr[t0], tmp, 32); ++ tcg_gen_or_i64(cpu_fr[t0], cpu_fr[t0], tmp); ++ tcg_gen_mov_i64(cpu_fr[t0 + 32], cpu_fr[t0]); ++ tcg_gen_mov_i64(cpu_fr[t0 + 64], cpu_fr[t0]); ++ tcg_gen_mov_i64(cpu_fr[t0 + 96], cpu_fr[t0]); ++ ++ tcg_temp_free(tmp); ++} ++ ++static void gen_qemu_vlds(int t0, TCGv t1, int memidx) ++{ ++ int i; ++ TCGv_i32 tmp32 = tcg_temp_new_i32(); ++ ++ tcg_gen_qemu_ld_i32(tmp32, t1, memidx, MO_ALIGN_4 | MO_LEUL); ++ gen_helper_memory_to_s(cpu_fr[t0], tmp32); ++ tcg_gen_addi_i64(t1, t1, 4); ++ ++ for (i = 1; i < 4; i++) { ++ tcg_gen_qemu_ld_i32(tmp32, t1, memidx, MO_LEUL); ++ gen_helper_memory_to_s(cpu_fr[t0 + i * 32], tmp32); ++ tcg_gen_addi_i64(t1, t1, 4); ++ } ++ ++ tcg_temp_free_i32(tmp32); ++} ++ ++static void gen_qemu_ldse(int t0, TCGv t1, int memidx) ++{ ++ TCGv_i32 tmp32 = tcg_temp_new_i32(); ++ TCGv tmp64 = tcg_temp_new(); ++ ++ tcg_gen_qemu_ld_i32(tmp32, t1, memidx, MO_ALIGN_4 | MO_LEUL); ++ gen_helper_memory_to_s(cpu_fr[t0], tmp32); ++ tcg_gen_mov_i64(cpu_fr[t0 + 32], cpu_fr[t0]); ++ tcg_gen_mov_i64(cpu_fr[t0 + 64], cpu_fr[t0]); ++ tcg_gen_mov_i64(cpu_fr[t0 + 96], cpu_fr[t0]); ++ ++ tcg_temp_free(tmp64); ++ tcg_temp_free_i32(tmp32); ++} ++ ++static void gen_qemu_ldde(int t0, TCGv t1, int memidx) ++{ ++ tcg_gen_qemu_ld_i64(cpu_fr[t0], t1, memidx, MO_ALIGN_4 | MO_TEQ); ++ tcg_gen_mov_i64(cpu_fr[t0 + 32], cpu_fr[t0]); ++ tcg_gen_mov_i64(cpu_fr[t0 + 64], cpu_fr[t0]); ++ tcg_gen_mov_i64(cpu_fr[t0 + 96], cpu_fr[t0]); ++} ++ ++static void gen_qemu_vldd(int t0, TCGv t1, int memidx) ++{ ++ tcg_gen_qemu_ld_i64(cpu_fr[t0], t1, memidx, MO_ALIGN_4 | MO_TEQ); ++ tcg_gen_addi_i64(t1, t1, 8); ++ tcg_gen_qemu_ld_i64(cpu_fr[t0 + 32], t1, memidx, MO_TEQ); ++ tcg_gen_addi_i64(t1, t1, 8); ++ tcg_gen_qemu_ld_i64(cpu_fr[t0 + 64], t1, memidx, MO_TEQ); ++ tcg_gen_addi_i64(t1, t1, 8); ++ tcg_gen_qemu_ld_i64(cpu_fr[t0 + 96], t1, memidx, MO_TEQ); ++} ++ ++static void gen_qemu_vsts(int t0, TCGv t1, int memidx) ++{ ++ int i; ++ TCGv_i32 tmp = tcg_temp_new_i32(); ++ ++ gen_helper_s_to_memory(tmp, cpu_fr[t0]); ++ tcg_gen_qemu_st_i32(tmp, t1, memidx, MO_ALIGN_4 | MO_LEUL); ++ tcg_gen_addi_i64(t1, t1, 4); ++ for (i = 1; i < 4; i++) { ++ gen_helper_s_to_memory(tmp, cpu_fr[t0 + 32 * i]); ++ tcg_gen_qemu_st_i32(tmp, t1, memidx, MO_LEUL); ++ tcg_gen_addi_i64(t1, t1, 4); ++ } ++ tcg_temp_free_i32(tmp); ++} ++ ++static void gen_qemu_vstd(int t0, TCGv t1, int memidx) ++{ ++ tcg_gen_qemu_st_i64(cpu_fr[t0], t1, memidx, MO_ALIGN_4 | MO_TEQ); ++ tcg_gen_addi_i64(t1, t1, 8); ++ tcg_gen_qemu_st_i64(cpu_fr[t0 + 32], t1, memidx, MO_TEQ); ++ tcg_gen_addi_i64(t1, t1, 8); ++ tcg_gen_qemu_st_i64(cpu_fr[t0 + 64], t1, memidx, MO_TEQ); ++ tcg_gen_addi_i64(t1, t1, 8); ++ tcg_gen_qemu_st_i64(cpu_fr[t0 + 96], t1, memidx, MO_TEQ); ++} ++ ++static inline void gen_qemu_fsts(TCGv t0, TCGv t1, int flags) ++{ ++ TCGv_i32 tmp = tcg_temp_new_i32(); ++ gen_helper_s_to_memory(tmp, t0); ++ tcg_gen_qemu_st_i32(tmp, t1, flags, MO_LEUL); ++ tcg_temp_free_i32(tmp); ++} ++ ++static inline void gen_qemu_flds(TCGv t0, TCGv t1, int flags) ++{ ++ TCGv_i32 tmp = tcg_temp_new_i32(); ++ tcg_gen_qemu_ld_i32(tmp, t1, flags, MO_LEUL); ++ gen_helper_memory_to_s(t0, tmp); ++ tcg_temp_free_i32(tmp); ++} ++ ++static TCGv gen_ieee_input(DisasContext *ctx, int reg, int is_cmp) ++{ ++ TCGv val; ++ ++ if (unlikely(reg == 31)) { ++ val = load_zero(ctx); ++ } else { ++ val = cpu_fr[reg]; ++#ifndef CONFIG_USER_ONLY ++ /* In system mode, raise exceptions for denormals like real ++ hardware. In user mode, proceed as if the OS completion ++ handler is handling the denormal as per spec. */ ++ gen_helper_ieee_input(cpu_env, val); ++#endif ++ } ++ return val; ++} ++ ++static void gen_fp_exc_raise(int rc) ++{ ++#ifndef CONFIG_USER_ONLY ++ TCGv_i32 reg = tcg_const_i32(rc + 32); ++ gen_helper_fp_exc_raise(cpu_env, reg); ++ tcg_temp_free_i32(reg); ++#endif ++} ++ ++static void gen_ieee_arith2(DisasContext *ctx, ++ void (*helper)(TCGv, TCGv_ptr, TCGv), int ra, ++ int rc) ++{ ++ TCGv va, vc; ++ ++ va = gen_ieee_input(ctx, ra, 0); ++ vc = cpu_fr[rc]; ++ helper(vc, cpu_env, va); ++ ++ gen_fp_exc_raise(rc); ++} ++ ++static void gen_ieee_arith3(DisasContext *ctx, ++ void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv), int ra, ++ int rb, int rc) ++{ ++ TCGv va, vb, vc; ++ ++ va = gen_ieee_input(ctx, ra, 0); ++ vb = gen_ieee_input(ctx, rb, 0); ++ vc = cpu_fr[rc]; ++ helper(vc, cpu_env, va, vb); ++ ++ gen_fp_exc_raise(rc); ++} ++ ++#define IEEE_ARITH2(name) \ ++ static inline void glue(gen_, name)(DisasContext * ctx, int ra, int rc) { \ ++ gen_ieee_arith2(ctx, gen_helper_##name, ra, rc); \ ++ } ++ ++#define IEEE_ARITH3(name) \ ++ static inline void glue(gen_, name)(DisasContext * ctx, int ra, int rb, \ ++ int rc) { \ ++ gen_ieee_arith3(ctx, gen_helper_##name, ra, rb, rc); \ ++ } ++IEEE_ARITH3(fadds) ++IEEE_ARITH3(faddd) ++IEEE_ARITH3(fsubs) ++IEEE_ARITH3(fsubd) ++IEEE_ARITH3(fmuls) ++IEEE_ARITH3(fmuld) ++IEEE_ARITH3(fdivs) ++IEEE_ARITH3(fdivd) ++IEEE_ARITH2(frecs) ++IEEE_ARITH2(frecd) ++ ++static void gen_ieee_compare(DisasContext *ctx, ++ void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv), int ra, ++ int rb, int rc) ++{ ++ TCGv va, vb, vc; ++ ++ va = gen_ieee_input(ctx, ra, 1); ++ vb = gen_ieee_input(ctx, rb, 1); ++ vc = cpu_fr[rc]; ++ helper(vc, cpu_env, va, vb); ++ ++ gen_fp_exc_raise(rc); ++} ++ ++#define IEEE_CMP2(name) \ ++ static inline void glue(gen_, name)(DisasContext *ctx, int ra, int rb, \ ++ int rc) { \ ++ gen_ieee_compare(ctx, gen_helper_##name, ra, rb, rc); \ ++ } ++ ++IEEE_CMP2(fcmpun) ++IEEE_CMP2(fcmpeq) ++IEEE_CMP2(fcmplt) ++IEEE_CMP2(fcmple) ++ ++static void gen_fcvtdl(int rb, int rc, uint64_t round_mode) ++{ ++ TCGv tmp64; ++ tmp64 = tcg_temp_new_i64(); ++ tcg_gen_movi_i64(tmp64, round_mode); ++ gen_helper_fcvtdl(cpu_fr[rc], cpu_env, cpu_fr[rb], tmp64); ++ tcg_temp_free(tmp64); ++ gen_fp_exc_raise(rc); ++} ++ ++static void cal_with_fregs_2(DisasContext *ctx, uint8_t rc, uint8_t ra, ++ uint8_t rb, uint8_t fn) ++{ ++ TCGv tmp64; ++ TCGv_i32 tmp32; ++ switch (fn) { ++ case 0x00: ++ /* FADDS */ ++ gen_fadds(ctx, ra, rb, rc); ++ break; ++ case 0x01: ++ /* FADDD */ ++ gen_faddd(ctx, ra, rb, rc); ++ break; ++ case 0x02: ++ /* FSUBS */ ++ gen_fsubs(ctx, ra, rb, rc); ++ break; ++ case 0x03: ++ /* FSUBD */ ++ gen_fsubd(ctx, ra, rb, rc); ++ break; ++ case 0x4: ++ /* FMULS */ ++ gen_fmuls(ctx, ra, rb, rc); ++ break; ++ case 0x05: ++ /* FMULD */ ++ gen_fmuld(ctx, ra, rb, rc); ++ break; ++ case 0x06: ++ /* FDIVS */ ++ gen_fdivs(ctx, ra, rb, rc); ++ break; ++ case 0x07: ++ /* FDIVD */ ++ gen_fdivd(ctx, ra, rb, rc); ++ break; ++ case 0x08: ++ /* FSQRTS */ ++ gen_helper_fsqrts(cpu_fr[rc], cpu_env, cpu_fr[rb]); ++ break; ++ case 0x09: ++ /* FSQRTD */ ++ gen_helper_fsqrt(cpu_fr[rc], cpu_env, cpu_fr[rb]); ++ break; ++ case 0x10: ++ /* FCMPEQ */ ++ gen_fcmpeq(ctx, ra, rb, rc); ++ break; ++ case 0x11: ++ /* FCMPLE */ ++ gen_fcmple(ctx, ra, rb, rc); ++ break; ++ case 0x12: ++ /* FCMPLT */ ++ gen_fcmplt(ctx, ra, rb, rc); ++ break; ++ case 0x13: ++ /* FCMPUN */ ++ gen_fcmpun(ctx, ra, rb, rc); ++ break; ++ case 0x20: ++ /* FCVTSD */ ++ gen_helper_fcvtsd(cpu_fr[rc], cpu_env, cpu_fr[rb]); ++ break; ++ case 0x21: ++ /* FCVTDS */ ++ gen_helper_fcvtds(cpu_fr[rc], cpu_env, cpu_fr[rb]); ++ break; ++ case 0x22: ++ /* FCVTDL_G */ ++ gen_fcvtdl(rb, rc, 0); ++ break; ++ case 0x23: ++ /* FCVTDL_P */ ++ gen_fcvtdl(rb, rc, 2); ++ break; ++ case 0x24: ++ /* FCVTDL_Z */ ++ gen_fcvtdl(rb, rc, 3); ++ break; ++ case 0x25: ++ /* FCVTDL_N */ ++ gen_fcvtdl(rb, rc, 1); ++ break; ++ case 0x27: ++ /* FCVTDL */ ++ gen_helper_fcvtdl_dyn(cpu_fr[rc], cpu_env, cpu_fr[rb]); ++ break; ++ case 0x28: ++ /* FCVTWL */ ++ gen_helper_fcvtwl(cpu_fr[rc], cpu_env, cpu_fr[rb]); ++ tcg_gen_ext32s_i64(cpu_fr[rc], cpu_fr[rc]); ++ break; ++ case 0x29: ++ /* FCVTLW */ ++ gen_helper_fcvtlw(cpu_fr[rc], cpu_env, cpu_fr[rb]); ++ break; ++ case 0x2d: ++ /* FCVTLS */ ++ gen_helper_fcvtls(cpu_fr[rc], cpu_env, cpu_fr[rb]); ++ break; ++ case 0x2f: ++ /* FCVTLD */ ++ gen_helper_fcvtld(cpu_fr[rc], cpu_env, cpu_fr[rb]); ++ break; ++ case 0x30: ++ /* FCPYS */ ++ tmp64 = tcg_temp_new(); ++ tcg_gen_shri_i64(tmp64, cpu_fr[ra], 63); ++ tcg_gen_shli_i64(tmp64, tmp64, 63); ++ tcg_gen_andi_i64(cpu_fr[rc], cpu_fr[rb], 0x7fffffffffffffffUL); ++ tcg_gen_or_i64(cpu_fr[rc], tmp64, cpu_fr[rc]); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x31: ++ /* FCPYSE */ ++ tmp64 = tcg_temp_new(); ++ tcg_gen_shri_i64(tmp64, cpu_fr[ra], 52); ++ tcg_gen_shli_i64(tmp64, tmp64, 52); ++ tcg_gen_andi_i64(cpu_fr[rc], cpu_fr[rb], 0x000fffffffffffffUL); ++ tcg_gen_or_i64(cpu_fr[rc], tmp64, cpu_fr[rc]); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x32: ++ /* FCPYSN */ ++ tmp64 = tcg_temp_new(); ++ tcg_gen_shri_i64(tmp64, cpu_fr[ra], 63); ++ tcg_gen_not_i64(tmp64, tmp64); ++ tcg_gen_shli_i64(tmp64, tmp64, 63); ++ tcg_gen_andi_i64(cpu_fr[rc], cpu_fr[rb], 0x7fffffffffffffffUL); ++ tcg_gen_or_i64(cpu_fr[rc], tmp64, cpu_fr[rc]); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x40: ++ /* IFMOVS */ ++ tmp64 = tcg_temp_new(); ++ tmp32 = tcg_temp_new_i32(); ++ tcg_gen_movi_i64(tmp64, ra); ++ tcg_gen_extrl_i64_i32(tmp32, load_gir(ctx, ra)); ++ gen_helper_memory_to_s(tmp64, tmp32); ++ tcg_gen_mov_i64(cpu_fr[rc], tmp64); ++ tcg_gen_movi_i64(tmp64, rc); ++ tcg_temp_free(tmp64); ++ tcg_temp_free_i32(tmp32); ++ break; ++ case 0x41: ++ /* IFMOVD */ ++ tcg_gen_mov_i64(cpu_fr[rc], load_gir(ctx, ra)); ++ break; ++ case 0x50: ++ /* RFPCR */ ++ gen_helper_load_fpcr(cpu_fr[ra], cpu_env); ++ break; ++ case 0x51: ++ /* WFPCR */ ++ gen_helper_store_fpcr(cpu_env, cpu_fr[ra]); ++ break; ++ case 0x54: ++ /* SETFPEC0 */ ++ tmp64 = tcg_const_i64(0); ++ gen_helper_setfpcrx(cpu_env, tmp64); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x55: ++ /* SETFPEC1 */ ++ tmp64 = tcg_const_i64(1); ++ gen_helper_setfpcrx(cpu_env, tmp64); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x56: ++ /* SETFPEC2 */ ++ tmp64 = tcg_const_i64(2); ++ gen_helper_setfpcrx(cpu_env, tmp64); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x57: ++ /* SETFPEC3 */ ++ tmp64 = tcg_const_i64(3); ++ gen_helper_setfpcrx(cpu_env, tmp64); ++ tcg_temp_free(tmp64); ++ break; ++ default: ++ fprintf(stderr, "Illegal insn func[%x]\n", fn); ++ gen_invalid(ctx); ++ break; ++ } ++} ++ ++static void cal_with_fregs_4(DisasContext *ctx, uint8_t rd, uint8_t ra, ++ uint8_t rb, uint8_t rc, uint8_t fn) ++{ ++ TCGv zero = tcg_const_i64(0); ++ TCGv va, vb, vc, vd, tmp64; ++ ++ va = cpu_fr[ra]; ++ vb = cpu_fr[rb]; ++ vc = cpu_fr[rc]; ++ vd = cpu_fr[rd]; ++ ++ switch (fn) { ++ case 0x00: ++ /* FMAS */ ++ gen_helper_fmas(vd, cpu_env, va, vb, vc); ++ break; ++ case 0x01: ++ /* FMAD */ ++ gen_helper_fmad(vd, cpu_env, va, vb, vc); ++ break; ++ case 0x02: ++ /* FMSS */ ++ gen_helper_fmss(vd, cpu_env, va, vb, vc); ++ break; ++ case 0x03: ++ /* FMSD */ ++ gen_helper_fmsd(vd, cpu_env, va, vb, vc); ++ break; ++ case 0x04: ++ /* FNMAS */ ++ gen_helper_fnmas(vd, cpu_env, va, vb, vc); ++ break; ++ case 0x05: ++ /* FNMAD */ ++ gen_helper_fnmad(vd, cpu_env, va, vb, vc); ++ break; ++ case 0x06: ++ /* FNMSS */ ++ gen_helper_fnmss(vd, cpu_env, va, vb, vc); ++ break; ++ case 0x07: ++ /* FNMSD */ ++ gen_helper_fnmsd(vd, cpu_env, va, vb, vc); ++ break; ++ case 0x10: ++ /* FSELEQ */ ++ // Maybe wrong translation. ++ tmp64 = tcg_temp_new(); ++ gen_helper_fcmpeq(tmp64, cpu_env, va, zero); ++ tcg_gen_movcond_i64(TCG_COND_EQ, vd, tmp64, zero, vc, vb); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x11: ++ /* FSELNE */ ++ tmp64 = tcg_temp_new(); ++ gen_helper_fcmpeq(tmp64, cpu_env, va, zero); ++ tcg_gen_movcond_i64(TCG_COND_EQ, vd, tmp64, zero, vb, vc); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x12: ++ /* FSELLT */ ++ tmp64 = tcg_temp_new(); ++ gen_helper_fcmplt(tmp64, cpu_env, va, zero); ++ tcg_gen_movcond_i64(TCG_COND_EQ, vd, tmp64, zero, vc, vb); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x13: ++ /* FSELLE */ ++ tmp64 = tcg_temp_new(); ++ gen_helper_fcmple(tmp64, cpu_env, va, zero); ++ tcg_gen_movcond_i64(TCG_COND_EQ, vd, tmp64, zero, vc, vb); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x14: ++ /* FSELGT */ ++ tmp64 = tcg_temp_new(); ++ gen_helper_fcmpgt(tmp64, cpu_env, va, zero); ++ tcg_gen_movcond_i64(TCG_COND_NE, vd, tmp64, zero, vb, vc); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x15: ++ /* FSELGE */ ++ tmp64 = tcg_temp_new(); ++ gen_helper_fcmpge(tmp64, cpu_env, va, zero); ++ tcg_gen_movcond_i64(TCG_COND_NE, vd, tmp64, zero, vb, vc); ++ tcg_temp_free(tmp64); ++ break; ++ default: ++ fprintf(stderr, "Illegal insn func[%x]\n", fn); ++ gen_invalid(ctx); ++ break; ++ } ++ tcg_temp_free(zero); ++} ++static inline void gen_qemu_lldw(TCGv t0, TCGv t1, int flags) ++{ ++ tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LESL); ++ tcg_gen_mov_i64(cpu_lock_addr, t1); ++#ifdef SW64_FIXLOCK ++ tcg_gen_ext32u_i64(cpu_lock_value, t0); ++#endif ++} ++ ++static inline void gen_qemu_lldl(TCGv t0, TCGv t1, int flags) ++{ ++ tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LEQ); ++ tcg_gen_mov_i64(cpu_lock_addr, t1); ++#ifdef SW64_FIXLOCK ++ tcg_gen_mov_i64(cpu_lock_value, t0); ++#endif ++} ++ ++static DisasJumpType gen_store_conditional(DisasContext *ctx, int ra, int rb, ++ int32_t disp16, int mem_idx, ++ MemOp op) ++{ ++ TCGLabel *lab_fail, *lab_done; ++ TCGv addr; ++ ++ addr = tcg_temp_new_i64(); ++ tcg_gen_addi_i64(addr, load_gir(ctx, rb), disp16); ++ free_context_temps(ctx); ++ ++ lab_fail = gen_new_label(); ++ lab_done = gen_new_label(); ++ tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail); ++ tcg_temp_free_i64(addr); ++ tcg_gen_brcondi_i64(TCG_COND_NE, cpu_lock_flag, 0x1, lab_fail); ++#ifdef SW64_FIXLOCK ++ TCGv val = tcg_temp_new_i64(); ++ tcg_gen_atomic_cmpxchg_i64(val, cpu_lock_addr, cpu_lock_value, ++ load_gir(ctx, ra), mem_idx, op); ++ tcg_gen_setcond_i64(TCG_COND_EQ, cpu_lock_success, val, cpu_lock_value); ++ tcg_temp_free_i64(val); ++#else ++ tcg_gen_qemu_st_i64(load_gir(ctx, ra), addr, mem_idx, op); ++#endif ++ ++ tcg_gen_br(lab_done); ++ ++ gen_set_label(lab_fail); ++ tcg_gen_movi_i64(cpu_lock_success, 0); ++ gen_set_label(lab_done); ++ ++ tcg_gen_movi_i64(cpu_lock_flag, 0); ++ tcg_gen_movi_i64(cpu_lock_addr, -1); ++ return DISAS_NEXT; ++} ++ ++static DisasJumpType gen_sys_call(DisasContext *ctx, int syscode) ++{ ++ if (syscode >= 0x80 && syscode <= 0xbf) { ++ switch (syscode) { ++ case 0x86: ++ /* IMB */ ++ /* No-op inside QEMU */ ++ break; ++#ifdef CONFIG_USER_ONLY ++ case 0x9E: ++ /* RDUNIQUE */ ++ tcg_gen_ld_i64(ctx->ir[IDX_V0], cpu_env, ++ offsetof(CPUSW64State, unique)); ++ break; ++ case 0x9F: ++ /* WRUNIQUE */ ++ tcg_gen_st_i64(ctx->ir[IDX_A0], cpu_env, ++ offsetof(CPUSW64State, unique)); ++ break; ++#endif ++ default: ++ goto do_sys_call; ++ } ++ return DISAS_NEXT; ++ } ++do_sys_call: ++#ifdef CONFIG_USER_ONLY ++ return gen_excp(ctx, EXCP_CALL_SYS, syscode); ++#else ++ tcg_gen_movi_i64(cpu_hm_ir[23], ctx->base.pc_next); ++ return gen_excp(ctx, EXCP_CALL_SYS, syscode); ++#endif ++} ++ ++static void read_csr(int idx, TCGv va) ++{ ++ TCGv_i64 tmp = tcg_const_i64(idx); ++ gen_helper_read_csr(va, cpu_env, tmp); ++ tcg_temp_free_i64(tmp); ++} ++ ++static void write_csr(int idx, TCGv va, CPUSW64State *env) ++{ ++ TCGv_i64 tmp = tcg_const_i64(idx); ++ gen_helper_write_csr(cpu_env, tmp, va); ++ tcg_temp_free_i64(tmp); ++} ++ ++static inline void ldx_set(DisasContext *ctx, int ra, int rb, int32_t disp12, ++ bool bype) ++{ ++ TCGv tmp, addr, va, t1; ++ ++ /* LDQ_U with ra $31 is UNOP. Other various loads are forms of ++ prefetches, which we can treat as nops. No worries about ++ missed exceptions here. */ ++ if (unlikely(ra == 31)) { ++ return; ++ } ++ ++ tmp = tcg_temp_new(); ++ t1 = tcg_const_i64(1); ++ addr = load_gir(ctx, rb); ++ ++ tcg_gen_addi_i64(tmp, addr, disp12); ++ addr = tmp; ++ ++ va = load_gir(ctx, ra); ++ if (bype == 0) { ++ tcg_gen_atomic_xchg_i64(va, addr, t1, ctx->mem_idx, MO_TESL); ++ } else { ++ tcg_gen_atomic_xchg_i64(va, addr, t1, ctx->mem_idx, MO_TEQ); ++ } ++ ++ tcg_temp_free(tmp); ++ tcg_temp_free(t1); ++} ++ ++static inline void ldx_xxx(DisasContext *ctx, int ra, int rb, int32_t disp12, ++ bool bype, int64_t val) ++{ ++ TCGv tmp, addr, va, t; ++ ++ /* LDQ_U with ra $31 is UNOP. Other various loads are forms of ++ prefetches, which we can treat as nops. No worries about ++ missed exceptions here. */ ++ if (unlikely(ra == 31)) { ++ return; ++ } ++ ++ tmp = tcg_temp_new(); ++ t = tcg_const_i64(val); ++ addr = load_gir(ctx, rb); ++ ++ tcg_gen_addi_i64(tmp, addr, disp12); ++ addr = tmp; ++ ++ va = load_gir(ctx, ra); ++ if (bype == 0) { ++ tcg_gen_atomic_fetch_add_i64(va, addr, t, ctx->mem_idx, MO_TESL); ++ } else { ++ tcg_gen_atomic_fetch_add_i64(va, addr, t, ctx->mem_idx, MO_TEQ); ++ } ++ ++ tcg_temp_free(tmp); ++ tcg_temp_free(t); ++} ++ ++static void tcg_gen_srlow_i64(int ra, int rc, int rb) ++{ ++ TCGv va, vb, vc; ++ TCGv shift; ++ ++ va = tcg_const_i64(ra); ++ vc = tcg_const_i64(rc); ++ shift = tcg_temp_new(); ++ vb = cpu_fr[rb]; ++ tcg_gen_shri_i64(shift, vb, 29); ++ tcg_gen_andi_i64(shift, shift, 0xff); ++ ++ gen_helper_srlow(cpu_env, va, vc, shift); ++ ++ tcg_temp_free(vc); ++ tcg_temp_free(va); ++ tcg_temp_free(shift); ++} ++ ++static void tcg_gen_srlowi_i64(int ra, int rc, int disp8) ++{ ++ TCGv va, vc; ++ TCGv shift; ++ ++ va = tcg_const_i64(ra); ++ vc = tcg_const_i64(rc); ++ shift = tcg_temp_new(); ++ tcg_gen_movi_i64(shift, disp8); ++ tcg_gen_andi_i64(shift, shift, 0xff); ++ ++ gen_helper_srlow(cpu_env, va, vc, shift); ++ ++ tcg_temp_free(vc); ++ tcg_temp_free(va); ++ tcg_temp_free(shift); ++} ++ ++static void tcg_gen_sllow_i64(int ra, int rc, int rb) ++{ ++ TCGv va, vb, vc; ++ TCGv shift; ++ ++ va = tcg_const_i64(ra); ++ vc = tcg_const_i64(rc); ++ shift = tcg_temp_new(); ++ vb = cpu_fr[rb]; ++ tcg_gen_shri_i64(shift, vb, 29); ++ tcg_gen_andi_i64(shift, shift, 0xff); ++ ++ gen_helper_sllow(cpu_env, va, vc, shift); ++ ++ tcg_temp_free(vc); ++ tcg_temp_free(va); ++ tcg_temp_free(shift); ++} ++ ++static void tcg_gen_sllowi_i64(int ra, int rc, int disp8) ++{ ++ TCGv va, vc; ++ TCGv shift; ++ ++ va = tcg_const_i64(ra); ++ vc = tcg_const_i64(rc); ++ shift = tcg_temp_new(); ++ tcg_gen_movi_i64(shift, disp8); ++ tcg_gen_andi_i64(shift, shift, 0xff); ++ ++ gen_helper_sllow(cpu_env, va, vc, shift); ++ ++ tcg_temp_free(vc); ++ tcg_temp_free(va); ++ tcg_temp_free(shift); ++} ++ ++static void gen_qemu_vstw_uh(int t0, TCGv t1, int memidx) ++{ ++ TCGv byte4_len; ++ TCGv addr_start, addr_end; ++ TCGv tmp[8]; ++ TCGv ti; ++ int i; ++ ++ tmp[0] = tcg_temp_new(); ++ tmp[1] = tcg_temp_new(); ++ tmp[2] = tcg_temp_new(); ++ tmp[3] = tcg_temp_new(); ++ tmp[4] = tcg_temp_new(); ++ tmp[5] = tcg_temp_new(); ++ tmp[6] = tcg_temp_new(); ++ tmp[7] = tcg_temp_new(); ++ ti = tcg_temp_new(); ++ addr_start = tcg_temp_new(); ++ addr_end = tcg_temp_new(); ++ byte4_len = tcg_temp_new(); ++ ++ tcg_gen_shri_i64(byte4_len, t1, 2); ++ tcg_gen_andi_i64(byte4_len, byte4_len, 0x7UL); ++ tcg_gen_andi_i64(t1, t1, ~0x3UL); /* t1 = addr + byte4_len * 4 */ ++ tcg_gen_andi_i64(addr_start, t1, ~0x1fUL); ++ tcg_gen_mov_i64(addr_end, t1); ++ for (i = 7; i >= 0; i--) { ++ tcg_gen_movcond_i64(TCG_COND_GEU, t1, t1, addr_start, t1, addr_start); ++ tcg_gen_qemu_ld_i64(tmp[i], t1, memidx, MO_TEUL); ++ tcg_gen_subi_i64(t1, t1, 4); ++ tcg_gen_movi_i64(ti, i); ++ if (i % 2) ++ tcg_gen_shli_i64(tmp[i], tmp[i], 32); ++ } ++ tcg_gen_subfi_i64(byte4_len, 8, byte4_len); ++ ++ for (i = 0; i < 8; i++) { ++ tcg_gen_movi_i64(ti, i); ++ tcg_gen_movcond_i64(TCG_COND_GEU, tmp[i], ti, byte4_len, cpu_fr[t0 + (i / 2)*32], tmp[i]); ++ if (i % 2) ++ tcg_gen_shri_i64(tmp[i], tmp[i], 32); ++ else ++ tcg_gen_andi_i64(tmp[i], tmp[i], 0xffffffffUL); ++ } ++ ++ tcg_gen_subi_i64(addr_end, addr_end, 32); ++ for (i = 0; i < 8; i++) { ++ tcg_gen_movcond_i64(TCG_COND_GEU, t1, addr_end, addr_start, addr_end, addr_start); ++ tcg_gen_qemu_st_i64(tmp[i], t1, memidx, MO_TEUL); ++ tcg_gen_addi_i64(addr_end, addr_end, 4); ++ } ++ ++ tcg_temp_free(ti); ++ tcg_temp_free(addr_start); ++ tcg_temp_free(addr_end); ++ tcg_temp_free(byte4_len); ++ tcg_temp_free(tmp[0]); ++ tcg_temp_free(tmp[1]); ++ tcg_temp_free(tmp[2]); ++ tcg_temp_free(tmp[3]); ++ tcg_temp_free(tmp[4]); ++ tcg_temp_free(tmp[5]); ++ tcg_temp_free(tmp[6]); ++ tcg_temp_free(tmp[7]); ++} ++ ++static void gen_qemu_vstw_ul(int t0, TCGv t1, int memidx) ++{ ++ TCGv byte4_len; ++ TCGv addr_start, addr_end; ++ TCGv tmp[8]; ++ TCGv ti; ++ int i; ++ ++ tmp[0] = tcg_temp_new(); ++ tmp[1] = tcg_temp_new(); ++ tmp[2] = tcg_temp_new(); ++ tmp[3] = tcg_temp_new(); ++ tmp[4] = tcg_temp_new(); ++ tmp[5] = tcg_temp_new(); ++ tmp[6] = tcg_temp_new(); ++ tmp[7] = tcg_temp_new(); ++ ti = tcg_temp_new(); ++ addr_start = tcg_temp_new(); ++ addr_end = tcg_temp_new(); ++ byte4_len = tcg_temp_new(); ++ ++ tcg_gen_shri_i64(byte4_len, t1, 2); ++ tcg_gen_andi_i64(byte4_len, byte4_len, 0x7UL); ++ tcg_gen_andi_i64(t1, t1, ~0x3UL); /* t1 = addr + byte4_len * 4 */ ++ tcg_gen_mov_i64(addr_start, t1); /* t1 = addr + byte4_len * 4 */ ++ tcg_gen_addi_i64(addr_end, addr_start, 24); ++ for (i = 0; i < 8; i++) { ++ tcg_gen_movcond_i64(TCG_COND_LEU, t1, t1, addr_end, t1, addr_end); ++ tcg_gen_qemu_ld_i64(tmp[i], t1, memidx, MO_TEUL); ++ tcg_gen_addi_i64(t1, t1, 4); ++ if (i % 2) ++ tcg_gen_shli_i64(tmp[i], tmp[i], 32); ++ } ++ tcg_gen_subfi_i64(byte4_len, 8, byte4_len); ++ ++ for (i = 0; i < 8; i++) { ++ tcg_gen_movi_i64(ti, i); ++ tcg_gen_movcond_i64(TCG_COND_LTU, tmp[i], ti, byte4_len, cpu_fr[t0 + (i/2)*32], tmp[i]); ++ if (i % 2) ++ tcg_gen_shri_i64(tmp[i], tmp[i], 32); ++ else ++ tcg_gen_andi_i64(tmp[i], tmp[i], 0xffffffffUL); ++ } ++ ++ tcg_gen_addi_i64(addr_start, addr_start, 32); ++ for (i = 7; i >= 0; i--) { ++ tcg_gen_subi_i64(addr_start, addr_start, 4); ++ tcg_gen_movcond_i64(TCG_COND_LEU, t1, addr_start, addr_end, addr_start, addr_end); ++ tcg_gen_qemu_st_i64(tmp[i], t1, memidx, MO_TEUL); ++ } ++ ++ tcg_temp_free(ti); ++ tcg_temp_free(addr_start); ++ tcg_temp_free(addr_end); ++ tcg_temp_free(byte4_len); ++ tcg_temp_free(tmp[0]); ++ tcg_temp_free(tmp[1]); ++ tcg_temp_free(tmp[2]); ++ tcg_temp_free(tmp[3]); ++ tcg_temp_free(tmp[4]); ++ tcg_temp_free(tmp[5]); ++ tcg_temp_free(tmp[6]); ++ tcg_temp_free(tmp[7]); ++} ++ ++static void gen_qemu_vsts_uh(int t0, TCGv t1, int memidx) ++{ ++ TCGv byte4_len; ++ TCGv addr_start, addr_end; ++ TCGv tmp[4]; ++ TCGv ftmp; ++ TCGv ti; ++ int i; ++ ++ tmp[0] = tcg_temp_new(); ++ tmp[1] = tcg_temp_new(); ++ tmp[2] = tcg_temp_new(); ++ tmp[3] = tcg_temp_new(); ++ ti = tcg_temp_new(); ++ ftmp = tcg_temp_new(); ++ addr_start = tcg_temp_new(); ++ addr_end = tcg_temp_new(); ++ byte4_len = tcg_temp_new(); ++ ++ tcg_gen_shri_i64(byte4_len, t1, 2); ++ tcg_gen_andi_i64(byte4_len, byte4_len, 0x3UL); ++ tcg_gen_andi_i64(t1, t1, ~0x3UL); /* t1 = addr + byte4_len * 4 */ ++ tcg_gen_andi_i64(addr_start, t1, ~0xfUL); ++ tcg_gen_mov_i64(addr_end, t1); ++ for (i = 3; i >= 0; i--) { ++ tcg_gen_movcond_i64(TCG_COND_GEU, t1, t1, addr_start, t1, addr_start); ++ tcg_gen_qemu_ld_i64(tmp[i], t1, memidx, MO_TEUL); ++ tcg_gen_subi_i64(t1, t1, 4); ++ } ++ tcg_gen_subfi_i64(byte4_len, 4, byte4_len); ++ ++ for (i = 0; i < 4; i++) { ++ tcg_gen_shri_i64(ti, cpu_fr[t0 + i * 32], 62); ++ tcg_gen_shli_i64(ti, ti, 30); ++ tcg_gen_shri_i64(ftmp, cpu_fr[t0 + i * 32], 29); ++ tcg_gen_andi_i64(ftmp, ftmp, 0x3fffffffUL); ++ tcg_gen_or_i64(ftmp, ftmp, ti); ++ tcg_gen_movi_i64(ti, i); ++ tcg_gen_movcond_i64(TCG_COND_GEU, tmp[i], ti, byte4_len, ftmp, tmp[i]); ++ } ++ ++ tcg_gen_subi_i64(addr_end, addr_end, 16); ++ for (i = 0; i < 4; i++) { ++ tcg_gen_movcond_i64(TCG_COND_GEU, t1, addr_end, addr_start, addr_end, addr_start); ++ tcg_gen_qemu_st_i64(tmp[i], t1, memidx, MO_TEUL); ++ tcg_gen_addi_i64(addr_end, addr_end, 4); ++ } ++ ++ tcg_temp_free(ti); ++ tcg_temp_free(ftmp); ++ tcg_temp_free(addr_start); ++ tcg_temp_free(addr_end); ++ tcg_temp_free(byte4_len); ++ tcg_temp_free(tmp[0]); ++ tcg_temp_free(tmp[1]); ++ tcg_temp_free(tmp[2]); ++ tcg_temp_free(tmp[3]); ++} ++ ++static void gen_qemu_vsts_ul(int t0, TCGv t1, int memidx) ++{ ++ TCGv byte4_len; ++ TCGv addr_start, addr_end; ++ TCGv tmp[4]; ++ TCGv ftmp; ++ TCGv ti; ++ int i; ++ ++ tmp[0] = tcg_temp_new(); ++ tmp[1] = tcg_temp_new(); ++ tmp[2] = tcg_temp_new(); ++ tmp[3] = tcg_temp_new(); ++ ftmp = tcg_temp_new(); ++ ti = tcg_temp_new(); ++ addr_start = tcg_temp_new(); ++ addr_end = tcg_temp_new(); ++ byte4_len = tcg_temp_new(); ++ ++ tcg_gen_shri_i64(byte4_len, t1, 2); ++ tcg_gen_andi_i64(byte4_len, byte4_len, 0x3UL); ++ tcg_gen_andi_i64(t1, t1, ~0x3UL); /* t1 = addr + byte4_len * 4 */ ++ tcg_gen_mov_i64(addr_start, t1); /* t1 = addr + byte4_len * 4 */ ++ tcg_gen_addi_i64(addr_end, addr_start, 12); ++ for (i = 0; i < 4; i++) { ++ tcg_gen_movcond_i64(TCG_COND_LEU, t1, t1, addr_end, t1, addr_end); ++ tcg_gen_qemu_ld_i64(tmp[i], t1, memidx, MO_TEUL); ++ tcg_gen_addi_i64(t1, t1, 4); ++ } ++ tcg_gen_subfi_i64(byte4_len, 4, byte4_len); ++ ++ for (i = 0; i < 4; i++) { ++ tcg_gen_shri_i64(ti, cpu_fr[t0 + i * 32], 62); ++ tcg_gen_shli_i64(ti, ti, 30); ++ tcg_gen_shri_i64(ftmp, cpu_fr[t0 + i * 32], 29); ++ tcg_gen_andi_i64(ftmp, ftmp, 0x3fffffffUL); ++ tcg_gen_or_i64(ftmp, ftmp, ti); ++ tcg_gen_movi_i64(ti, i); ++ tcg_gen_movcond_i64(TCG_COND_LTU, tmp[i], ti, byte4_len, ftmp, tmp[i]); ++ } ++ ++ tcg_gen_addi_i64(addr_start, addr_start, 16); ++ for (i = 3; i >= 0; i--) { ++ tcg_gen_subi_i64(addr_start, addr_start, 4); ++ tcg_gen_movcond_i64(TCG_COND_LEU, t1, addr_start, addr_end, addr_start, addr_end); ++ tcg_gen_qemu_st_i64(tmp[i], t1, memidx, MO_TEUL); ++ } ++ ++ tcg_temp_free(ti); ++ tcg_temp_free(addr_start); ++ tcg_temp_free(addr_end); ++ tcg_temp_free(byte4_len); ++ tcg_temp_free(ftmp); ++ tcg_temp_free(tmp[0]); ++ tcg_temp_free(tmp[1]); ++ tcg_temp_free(tmp[2]); ++ tcg_temp_free(tmp[3]); ++} ++ ++static void gen_qemu_vstd_uh(int t0, TCGv t1, int memidx) ++{ ++ TCGv byte8_len; ++ TCGv addr_start, addr_end; ++ TCGv tmp[4]; ++ TCGv ti; ++ int i; ++ ++ tmp[0] = tcg_temp_new(); ++ tmp[1] = tcg_temp_new(); ++ tmp[2] = tcg_temp_new(); ++ tmp[3] = tcg_temp_new(); ++ ti = tcg_temp_new(); ++ addr_start = tcg_temp_new(); ++ addr_end = tcg_temp_new(); ++ byte8_len = tcg_temp_new(); ++ ++ tcg_gen_shri_i64(byte8_len, t1, 3); ++ tcg_gen_andi_i64(byte8_len, byte8_len, 0x3UL); ++ tcg_gen_andi_i64(t1, t1, ~0x7UL); /* t1 = addr + byte4_len * 4 */ ++ tcg_gen_andi_i64(addr_start, t1, ~0x1fUL); ++ tcg_gen_mov_i64(addr_end, t1); ++ for (i = 3; i >= 0; i--) { ++ tcg_gen_movcond_i64(TCG_COND_GEU, t1, t1, addr_start, t1, addr_start); ++ tcg_gen_qemu_ld_i64(tmp[i], t1, memidx, MO_TEQ); ++ tcg_gen_subi_i64(t1, t1, 8); ++ } ++ tcg_gen_subfi_i64(byte8_len, 4, byte8_len); ++ ++ for (i = 0; i < 4; i++) { ++ tcg_gen_movi_i64(ti, i); ++ tcg_gen_movcond_i64(TCG_COND_GEU, tmp[i], ti, byte8_len, cpu_fr[t0 + i*32], tmp[i]); ++ } ++ ++ tcg_gen_subi_i64(addr_end, addr_end, 32); ++ for (i = 0; i < 4; i++) { ++ tcg_gen_movcond_i64(TCG_COND_GEU, t1, addr_end, addr_start, addr_end, addr_start); ++ tcg_gen_qemu_st_i64(tmp[i], t1, memidx, MO_TEQ); ++ tcg_gen_addi_i64(addr_end, addr_end, 8); ++ } ++ ++ tcg_temp_free(ti); ++ tcg_temp_free(addr_start); ++ tcg_temp_free(addr_end); ++ tcg_temp_free(byte8_len); ++ tcg_temp_free(tmp[0]); ++ tcg_temp_free(tmp[1]); ++ tcg_temp_free(tmp[2]); ++ tcg_temp_free(tmp[3]); ++} ++ ++static void gen_qemu_vstd_ul(int t0, TCGv t1, int memidx) ++{ ++ TCGv byte8_len; ++ TCGv addr_start, addr_end; ++ TCGv tmp[4]; ++ TCGv ti; ++ int i; ++ ++ tmp[0] = tcg_temp_new(); ++ tmp[1] = tcg_temp_new(); ++ tmp[2] = tcg_temp_new(); ++ tmp[3] = tcg_temp_new(); ++ ti = tcg_temp_new(); ++ addr_start = tcg_temp_new(); ++ addr_end = tcg_temp_new(); ++ byte8_len = tcg_temp_new(); ++ ++ tcg_gen_shri_i64(byte8_len, t1, 3); ++ tcg_gen_andi_i64(byte8_len, byte8_len, 0x3UL); ++ tcg_gen_andi_i64(t1, t1, ~0x7UL); /* t1 = addr + byte4_len * 4 */ ++ tcg_gen_mov_i64(addr_start, t1); /* t1 = addr + byte4_len * 4 */ ++ tcg_gen_addi_i64(addr_end, addr_start, 24); ++ for (i = 0; i < 4; i++) { ++ tcg_gen_movcond_i64(TCG_COND_LEU, t1, t1, addr_end, t1, addr_end); ++ tcg_gen_qemu_ld_i64(tmp[i], t1, memidx, MO_TEQ); ++ tcg_gen_addi_i64(t1, t1, 8); ++ } ++ tcg_gen_subfi_i64(byte8_len, 4, byte8_len); ++ ++ for (i = 0; i < 4; i++) { ++ tcg_gen_movi_i64(ti, i); ++ tcg_gen_movcond_i64(TCG_COND_LTU, tmp[i], ti, byte8_len, cpu_fr[t0 + i*32], tmp[i]); ++ } ++ ++ tcg_gen_addi_i64(addr_start, addr_start, 32); ++ for (i = 3; i >= 0; i--) { ++ tcg_gen_subi_i64(addr_start, addr_start, 8); ++ tcg_gen_movcond_i64(TCG_COND_LEU, t1, addr_start, addr_end, addr_start, addr_end); ++ tcg_gen_qemu_st_i64(tmp[i], t1, memidx, MO_TEQ); ++ } ++ ++ tcg_temp_free(ti); ++ tcg_temp_free(addr_start); ++ tcg_temp_free(addr_end); ++ tcg_temp_free(byte8_len); ++ tcg_temp_free(tmp[0]); ++ tcg_temp_free(tmp[1]); ++ tcg_temp_free(tmp[2]); ++ tcg_temp_free(tmp[3]); ++} ++ ++static void tcg_gen_vcpys_i64(int ra, int rb, int rc) ++{ ++ int i; ++ TCGv tmp64 = tcg_temp_new(); ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_shri_i64(tmp64, cpu_fr[ra + i], 63); ++ tcg_gen_shli_i64(tmp64, tmp64, 63); ++ tcg_gen_andi_i64(cpu_fr[rc + i], cpu_fr[rb + i], 0x7fffffffffffffffUL); ++ tcg_gen_or_i64(cpu_fr[rc + i], tmp64, cpu_fr[rc + i]); ++ } ++ tcg_temp_free(tmp64); ++} ++ ++static void tcg_gen_vcpyse_i64(int ra, int rb, int rc) ++{ ++ int i; ++ ++ TCGv tmp64 = tcg_temp_new(); ++ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_shri_i64(tmp64, cpu_fr[ra + i], 52); ++ tcg_gen_shli_i64(tmp64, tmp64, 52); ++ tcg_gen_andi_i64(cpu_fr[rc + i], cpu_fr[rb + i], 0x000fffffffffffffUL); ++ tcg_gen_or_i64(cpu_fr[rc + i], tmp64, cpu_fr[rc + i]); ++ } ++ tcg_temp_free(tmp64); ++} ++ ++static void tcg_gen_vcpysn_i64(int ra, int rb, int rc) ++{ ++ int i; ++ TCGv tmp64 = tcg_temp_new(); ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_shri_i64(tmp64, cpu_fr[ra + i], 63); ++ tcg_gen_not_i64(tmp64, tmp64); ++ tcg_gen_shli_i64(tmp64, tmp64, 63); ++ tcg_gen_andi_i64(cpu_fr[rc + i], cpu_fr[rb + i], 0x7fffffffffffffffUL); ++ tcg_gen_or_i64(cpu_fr[rc + i], tmp64, cpu_fr[rc + i]); ++ } ++ tcg_temp_free(tmp64); ++} ++ ++static void tcg_gen_vlogzz_i64(DisasContext *ctx, int opc, int ra, int rb, ++ int rc, int rd, int fn6) ++{ ++ TCGv zz; ++ TCGv args, vd; ++ zz = tcg_const_i64(((opc & 0x3) << 6) | fn6); ++ args = tcg_const_i64((ra << 16) | (rb << 8) | rc); ++ vd = tcg_const_i64(rd); ++ ++ gen_helper_vlogzz(cpu_env, args, vd, zz); ++ ++ tcg_temp_free(vd); ++ tcg_temp_free(args); ++ tcg_temp_free(zz); ++} ++ ++static void gen_qemu_vcmpxxw_i64(TCGCond cond, int ra, int rb, int rc) ++{ ++ TCGv va, vb, vc, tmp64; ++ int i; ++ ++ va = tcg_temp_new(); ++ vb = tcg_temp_new(); ++ vc = tcg_temp_new(); ++ tmp64 = tcg_temp_new(); ++ ++ for (i = 0; i < 128; i += 32) { ++ if ((cond >> 1) & 1) { ++ tcg_gen_ext32s_i64(va, cpu_fr[ra + i]); ++ tcg_gen_ext32s_i64(vb, cpu_fr[rb + i]); ++ } else { ++ tcg_gen_ext32u_i64(va, cpu_fr[ra + i]); ++ tcg_gen_ext32u_i64(vb, cpu_fr[rb + i]); ++ } ++ tcg_gen_setcond_i64(cond, vc, va, vb); ++ tcg_gen_mov_i64(tmp64, vc); ++ ++ tcg_gen_shri_i64(va, cpu_fr[ra + i], 32); ++ tcg_gen_shri_i64(vb, cpu_fr[rb + i], 32); ++ if ((cond >> 1) & 1) { ++ tcg_gen_ext32s_i64(va, va); ++ tcg_gen_ext32s_i64(vb, vb); ++ } else { ++ tcg_gen_ext32u_i64(va, va); ++ tcg_gen_ext32u_i64(vb, vb); ++ } ++ tcg_gen_setcond_i64(cond, vc, va, vb); ++ tcg_gen_shli_i64(vc, vc, 32); ++ tcg_gen_or_i64(cpu_fr[rc + i], tmp64, vc); ++ } ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ tcg_temp_free(tmp64); ++} ++ ++static void gen_qemu_vcmpxxwi_i64(TCGCond cond, int ra, int rb, int rc) ++{ ++ TCGv va, vb, vc, tmp64; ++ int i; ++ ++ va = tcg_temp_new(); ++ vb = tcg_const_i64(rb); ++ vc = tcg_temp_new(); ++ tmp64 = tcg_temp_new(); ++ ++ for (i = 0; i < 128; i += 32) { ++ if ((cond >> 1) & 1) { ++ tcg_gen_ext32s_i64(va, cpu_fr[ra + i]); ++ } else { ++ tcg_gen_ext32u_i64(va, cpu_fr[ra + i]); ++ } ++ tcg_gen_setcond_i64(cond, vc, va, vb); ++ tcg_gen_mov_i64(tmp64, vc); ++ ++ tcg_gen_shri_i64(va, cpu_fr[ra + i], 32); ++ if ((cond >> 1) & 1) { ++ tcg_gen_ext32s_i64(va, va); ++ } else { ++ tcg_gen_ext32u_i64(va, va); ++ } ++ tcg_gen_setcond_i64(cond, vc, va, vb); ++ tcg_gen_shli_i64(vc, vc, 32); ++ tcg_gen_or_i64(cpu_fr[rc + i], tmp64, vc); ++ } ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ tcg_temp_free(tmp64); ++} ++ ++static void gen_qemu_vselxxw(TCGCond cond, int ra, int rb, int rc, int rd, ++ int mask) ++{ ++ int i; ++ ++ TCGv t0 = tcg_const_i64(0); ++ TCGv tmpa = tcg_temp_new(); ++ TCGv tmpb = tcg_temp_new(); ++ TCGv tmpc = tcg_temp_new(); ++ TCGv tmpd = tcg_temp_new(); ++ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_ext32s_i64(tmpa, cpu_fr[ra + i]); ++ tcg_gen_ext32u_i64(tmpb, cpu_fr[rb + i]); ++ tcg_gen_ext32u_i64(tmpc, cpu_fr[rc + i]); ++ if (mask) tcg_gen_andi_i64(tmpa, tmpa, mask); ++ tcg_gen_movcond_i64(cond, tmpd, tmpa, t0, tmpb, tmpc); ++ ++ tcg_gen_andi_i64(tmpa, cpu_fr[ra + i], 0xffffffff00000000UL); ++ tcg_gen_andi_i64(tmpb, cpu_fr[rb + i], 0xffffffff00000000UL); ++ tcg_gen_andi_i64(tmpc, cpu_fr[rc + i], 0xffffffff00000000UL); ++ if (mask) tcg_gen_andi_i64(tmpa, tmpa, (uint64_t)mask << 32); ++ tcg_gen_movcond_i64(cond, cpu_fr[rd + i], tmpa, t0, tmpb, tmpc); ++ ++ tcg_gen_or_i64(cpu_fr[rd + i], cpu_fr[rd + i], tmpd); ++ } ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(tmpa); ++ tcg_temp_free(tmpb); ++ tcg_temp_free(tmpc); ++ tcg_temp_free(tmpd); ++} ++ ++static void gen_qemu_vselxxwi(TCGCond cond, int ra, int rb, int disp8, int rd, ++ int mask) ++{ ++ int i; ++ ++ TCGv t0 = tcg_const_i64(0); ++ TCGv tmpa = tcg_temp_new(); ++ TCGv tmpb = tcg_temp_new(); ++ TCGv tmpc_0 = tcg_temp_new(); ++ TCGv tmpc_1 = tcg_temp_new(); ++ TCGv tmpd = tcg_temp_new(); ++ ++ tcg_gen_movi_i64(tmpc_0, (uint64_t)(((uint64_t)disp8))); ++ tcg_gen_movi_i64(tmpc_1, (uint64_t)(((uint64_t)disp8 << 32))); ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_ext32s_i64(tmpa, cpu_fr[ra + i]); ++ tcg_gen_ext32u_i64(tmpb, cpu_fr[rb + i]); ++ if (mask) tcg_gen_andi_i64(tmpa, tmpa, mask); ++ tcg_gen_movcond_i64(cond, tmpd, tmpa, t0, tmpb, tmpc_0); ++ ++ tcg_gen_andi_i64(tmpa, cpu_fr[ra + i], 0xffffffff00000000UL); ++ tcg_gen_andi_i64(tmpb, cpu_fr[rb + i], 0xffffffff00000000UL); ++ if (mask) tcg_gen_andi_i64(tmpa, tmpa, (uint64_t)mask << 32); ++ tcg_gen_movcond_i64(cond, cpu_fr[rd + i], tmpa, t0, tmpb, tmpc_1); ++ ++ tcg_gen_or_i64(cpu_fr[rd + i], cpu_fr[rd + i], tmpd); ++ } ++ ++ tcg_temp_free(t0); ++ tcg_temp_free(tmpa); ++ tcg_temp_free(tmpb); ++ tcg_temp_free(tmpc_0); ++ tcg_temp_free(tmpc_1); ++ tcg_temp_free(tmpd); ++} ++ ++DisasJumpType translate_one(DisasContextBase *dcbase, uint32_t insn, ++ CPUState *cpu) ++{ ++ int32_t disp5, disp8, disp12, disp13, disp16, disp21, disp26 __attribute__((unused)); ++ uint8_t opc, ra, rb, rc, rd; ++ uint16_t fn3, fn4, fn6, fn8, fn11; ++ int32_t i; ++ TCGv va, vb, vc, vd; ++ TCGv_i32 tmp32; ++ TCGv_i64 tmp64, tmp64_0, tmp64_1, shift; ++ TCGv_i32 tmpa, tmpb, tmpc; ++ DisasJumpType ret; ++ DisasContext* ctx = container_of(dcbase, DisasContext, base); ++ ++ opc = extract32(insn, 26, 6); ++ ra = extract32(insn, 21, 5); ++ rb = extract32(insn, 16, 5); ++ rc = extract32(insn, 0, 5); ++ rd = extract32(insn, 5, 5); ++ ++ fn3 = extract32(insn, 10, 3); ++ fn6 = extract32(insn, 10, 6); ++ fn4 = extract32(insn, 12, 4); ++ fn8 = extract32(insn, 5, 8); ++ fn11 = extract32(insn, 5, 11); ++ ++ disp5 = extract32(insn, 5, 5); ++ disp8 = extract32(insn, 13, 8); ++ disp12 = sextract32(insn, 0, 12); ++ disp13 = sextract32(insn, 13, 13); ++ disp16 = sextract32(insn, 0, 16); ++ disp21 = sextract32(insn, 0, 21); ++ disp26 = sextract32(insn, 0, 26); ++ ++ ret = DISAS_NEXT; ++ insn_profile(ctx, insn); ++ ++ switch (opc) { ++ case 0x00: ++ /* SYS_CALL */ ++ ret = gen_sys_call(ctx, insn & 0x1ffffff); ++ break; ++ case 0x01: ++ /* CALL */ ++ case 0x02: ++ /* RET */ ++ case 0x03: ++ /* JMP */ ++ vb = load_gir(ctx, rb); ++ tcg_gen_addi_i64(cpu_pc, vb, ctx->base.pc_next & 0x3); ++ if (ra != 31) { ++ tcg_gen_movi_i64(load_gir(ctx, ra), ctx->base.pc_next & (~3UL)); ++ } ++ ret = DISAS_PC_UPDATED; ++ break; ++ case 0x04: ++ /* BR */ ++ case 0x05: ++ /* BSR */ ++ ret = gen_bdirect(ctx, ra, disp21); ++ break; ++ case 0x06: ++ switch (disp16) { ++ case 0x0000: ++ /* MEMB */ ++ tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); ++ break; ++ case 0x0001: ++ /* IMEMB */ ++ /* No achievement in Qemu*/ ++ break; ++ case 0x0020: ++ /* RTC */ ++ if (disp16 && unlikely(ra == 31)) break; ++ va = load_gir(ctx, ra); ++ gen_helper_rtc(va); ++ break; ++ case 0x0040: ++ /* RCID */ ++ if (disp16 && unlikely(ra == 31)) break; ++ va = load_gir(ctx, ra); ++ read_csr(0xc4, va); ++ break; ++ case 0x0080: ++ /* HALT */ ++#ifndef CONFIG_USER_ONLY ++ { ++ tmp32 = tcg_const_i32(1); ++ tcg_gen_st_i32( ++ tmp32, cpu_env, ++ -offsetof(SW64CPU, env) + offsetof(CPUState, halted)); ++ tcg_temp_free_i32(tmp32); ++ } ++ ret = gen_excp(ctx, EXCP_HALTED, 0); ++#endif ++ break; ++ case 0x1000: ++ /* RD_F */ ++ if (disp16 && unlikely(ra == 31)) break; ++ va = load_gir(ctx, ra); ++ tcg_gen_mov_i64(va, cpu_lock_success); ++ break; ++ case 0x1020: ++ /* WR_F */ ++ if (disp16 && unlikely(ra == 31)) break; ++ va = load_gir(ctx, ra); ++ tcg_gen_andi_i64(cpu_lock_flag, va, 0x1); ++ break; ++ case 0x1040: ++ /* RTID */ ++ if (unlikely(ra == 31)) break; ++ va = load_gir(ctx, ra); ++ read_csr(0xc7, va); ++ break; ++ default: ++ if ((disp16 & 0xFF00) == 0xFE00) { ++ /* PRI_RCSR */ ++ if (disp16 && unlikely(ra == 31)) break; ++ va = load_gir(ctx, ra); ++ read_csr(disp16 & 0xff, va); ++ break; ++ } ++ if ((disp16 & 0xFF00) == 0xFF00) { ++ /* PRI_WCSR */ ++ va = load_gir(ctx, ra); ++ write_csr(disp16 & 0xff, va, ctx->env); ++ break; ++ } ++ goto do_invalid; ++ } ++ break; ++ case 0x07: ++ /* PRI_RET */ ++ va = load_gir(ctx, ra); ++ tcg_gen_mov_i64(cpu_pc, va); ++ gen_helper_cpustate_update(cpu_env, va); ++ ret = DISAS_PC_UPDATED_NOCHAIN; ++ break; ++ case 0x08: ++ switch (fn4) { ++ case 0x0: ++ /* LLDW */ ++ gen_load_mem(ctx, &gen_qemu_lldw, ra, rb, disp12, 0, 0); ++ break; ++ case 0x1: ++ /* LLDL */ ++ gen_load_mem(ctx, &gen_qemu_lldl, ra, rb, disp12, 0, 0); ++ break; ++ case 0x2: ++ /* LDW_INC */ ++ ldx_xxx(ctx, ra, rb, disp12, 0, 1); ++ break; ++ case 0x3: ++ /* LDL_INC */ ++ ldx_xxx(ctx, ra, rb, disp12, 1, 1); ++ break; ++ case 0x4: ++ /* LDW_DEC */ ++ ldx_xxx(ctx, ra, rb, disp12, 0, -1); ++ break; ++ case 0x5: ++ /* LDL_DEC */ ++ ldx_xxx(ctx, ra, rb, disp12, 1, -1); ++ break; ++ case 0x6: ++ /* LDW_SET */ ++ ldx_set(ctx, ra, rb, disp12, 0); ++ break; ++ case 0x7: ++ /* LDL_SET */ ++ ldx_set(ctx, ra, rb, disp12, 1); ++ break; ++ case 0x8: ++ /* LSTW */ ++ ret = gen_store_conditional(ctx, ra, rb, disp12, ++ ctx->mem_idx, MO_LEUL); ++ break; ++ case 0x9: ++ /* LSTL */ ++ ret = gen_store_conditional(ctx, ra, rb, disp12, ++ ctx->mem_idx, MO_LEQ); ++ break; ++ case 0xa: ++ /* LDW_NC */ ++ gen_load_mem(ctx, &tcg_gen_qemu_ld32s, ra, rb, disp12, 0, ++ 0); ++ break; ++ case 0xb: ++ /* LDL_NC */ ++ gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp12, 0, 0); ++ break; ++ case 0xc: ++ /* LDD_NC */ ++ gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp12, 1, 0); ++ break; ++ case 0xd: ++ /* STW_NC */ ++ gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp12, 0, ++ 0); ++ break; ++ case 0xe: ++ /* STL_NC */ ++ gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp12, 0, ++ 0); ++ break; ++ case 0xf: ++ /* STD_NC */ ++ gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp12, 1, ++ 0); ++ break; ++ default: ++ goto do_invalid; ++ } ++ break; ++ case 0x9: ++ /* LDWE */ ++ gen_load_mem_simd(ctx, &gen_qemu_ldwe, ra, rb, disp16, 0); ++ break; ++ case 0x0a: ++ /* LDSE */ ++ gen_load_mem_simd(ctx, &gen_qemu_ldse, ra, rb, disp16, 0); ++ break; ++ case 0x0b: ++ /* LDDE */ ++ gen_load_mem_simd(ctx, &gen_qemu_ldde, ra, rb, disp16, 0); ++ break; ++ case 0x0c: ++ /* VLDS */ ++ gen_load_mem_simd(ctx, &gen_qemu_vlds, ra, rb, disp16, 0); ++ break; ++ case 0x0d: ++ /* VLDD */ ++ if (unlikely(ra == 31)) break; ++ gen_load_mem_simd(ctx, &gen_qemu_vldd, ra, rb, disp16, 0); ++ break; ++ case 0x0e: ++ /* VSTS */ ++ gen_store_mem_simd(ctx, &gen_qemu_vsts, ra, rb, disp16, 0); ++ break; ++ case 0x0f: ++ /* VSTD */ ++ gen_store_mem_simd(ctx, &gen_qemu_vstd, ra, rb, disp16, 0); ++ break; ++ case 0x10: ++ if (unlikely(rc == 31)) break; ++ if (fn11 == 0x70) { ++ /* FIMOVS */ ++ va = cpu_fr[ra]; ++ vc = load_gir(ctx, rc); ++ tmp32 = tcg_temp_new_i32(); ++ gen_helper_s_to_memory(tmp32, va); ++ tcg_gen_ext_i32_i64(vc, tmp32); ++ tcg_temp_free_i32(tmp32); ++ } else if (fn11 == 0x78) { ++ /* FIMOVD */ ++ va = cpu_fr[ra]; ++ vc = load_gir(ctx, rc); ++ tcg_gen_mov_i64(vc, va); ++ } else { ++ va = load_gir(ctx, ra); ++ vb = load_gir(ctx, rb); ++ vc = load_gir(ctx, rc); ++ cal_with_iregs_2(ctx, vc, va, vb, disp13, fn11); ++ } ++ break; ++ case 0x11: ++ if (unlikely(rc == 31)) break; ++ va = load_gir(ctx, ra); ++ vb = load_gir(ctx, rb); ++ vc = load_gir(ctx, rc); ++ vd = load_gir(ctx, rd); ++ cal_with_iregs_3(ctx, vc, va, vb, vd, fn3); ++ break; ++ case 0x12: ++ if (unlikely(rc == 31)) break; ++ va = load_gir(ctx, ra); ++ vc = load_gir(ctx, rc); ++ cal_with_imm_2(ctx, vc, va, disp8, fn8); ++ break; ++ case 0x13: ++ if (rc == 31) /* Special deal */ ++ break; ++ va = load_gir(ctx, ra); ++ vc = load_gir(ctx, rc); ++ vd = load_gir(ctx, rd); ++ cal_with_imm_3(ctx, vc, va, disp8, vd, fn3); ++ break; ++ case 0x14: ++ case 0x15: ++ case 0x16: ++ case 0x17: ++ /* VLOGZZ */ ++ tcg_gen_vlogzz_i64(ctx, opc, ra, rb, rd, rc, fn6); ++ break; ++ case 0x18: ++ if (unlikely(rc == 31)) break; ++ cal_with_fregs_2(ctx, rc, ra, rb, fn8); ++ break; ++ case 0x19: ++ if (unlikely(rc == 31)) break; ++ cal_with_fregs_4(ctx, rc, ra, rb, rd, fn6); ++ break; ++ case 0x1A: ++ /* SIMD */ ++ if (unlikely(rc == 31)) break; ++ switch (fn8) { ++ case 0x00: ++ /* VADDW */ ++ tmp64 = tcg_temp_new(); ++ va = tcg_temp_new(); ++ vb = tcg_temp_new(); ++ vc = tcg_temp_new(); ++ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_andi_i64(va, cpu_fr[ra + i], 0xffffffffUL); ++ tcg_gen_andi_i64(vb, cpu_fr[rb + i], 0xffffffffUL); ++ tcg_gen_add_i64(tmp64, va, vb); ++ tcg_gen_ext32u_i64(tmp64, tmp64); ++ tcg_gen_andi_i64(va, cpu_fr[ra + i], ++ 0xffffffff00000000UL); ++ tcg_gen_andi_i64(vb, cpu_fr[rb + i], ++ 0xffffffff00000000UL); ++ tcg_gen_add_i64(vc, va, vb); ++ tcg_gen_or_i64(tmp64, tmp64, vc); ++ tcg_gen_mov_i64(cpu_fr[rc + i], tmp64); ++ } ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x20: ++ /* VADDW */ ++ tmp64 = tcg_temp_new(); ++ va = tcg_temp_new(); ++ vc = tcg_temp_new(); ++ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_andi_i64(va, cpu_fr[ra + i], 0xffffffffUL); ++ tcg_gen_addi_i64(tmp64, va, disp8); ++ tcg_gen_ext32u_i64(tmp64, tmp64); ++ tcg_gen_andi_i64(va, cpu_fr[ra + i], ++ 0xffffffff00000000UL); ++ tcg_gen_addi_i64(vc, va, ((uint64_t)disp8 << 32)); ++ tcg_gen_or_i64(tmp64, tmp64, vc); ++ tcg_gen_mov_i64(cpu_fr[rc + i], tmp64); ++ } ++ tcg_temp_free(va); ++ tcg_temp_free(vc); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x01: ++ /* VSUBW */ ++ tmp64 = tcg_temp_new(); ++ va = tcg_temp_new(); ++ vb = tcg_temp_new(); ++ vc = tcg_temp_new(); ++ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_andi_i64(va, cpu_fr[ra + i], 0xffffffffUL); ++ tcg_gen_andi_i64(vb, cpu_fr[rb + i], 0xffffffffUL); ++ tcg_gen_sub_i64(tmp64, va, vb); ++ tcg_gen_ext32u_i64(tmp64, tmp64); ++ tcg_gen_andi_i64(va, cpu_fr[ra + i], ++ 0xffffffff00000000UL); ++ tcg_gen_andi_i64(vb, cpu_fr[rb + i], ++ 0xffffffff00000000UL); ++ tcg_gen_sub_i64(vc, va, vb); ++ tcg_gen_or_i64(tmp64, tmp64, vc); ++ tcg_gen_mov_i64(cpu_fr[rc + i], tmp64); ++ } ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x21: ++ /* VSUBW */ ++ tmp64 = tcg_temp_new(); ++ va = tcg_temp_new(); ++ vc = tcg_temp_new(); ++ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_andi_i64(va, cpu_fr[ra + i], 0xffffffffUL); ++ tcg_gen_subi_i64(tmp64, va, disp8); ++ tcg_gen_ext32u_i64(tmp64, tmp64); ++ tcg_gen_andi_i64(va, cpu_fr[ra + i], ++ 0xffffffff00000000UL); ++ tcg_gen_subi_i64(vc, va, ((uint64_t)disp8 << 32)); ++ tcg_gen_or_i64(tmp64, tmp64, vc); ++ tcg_gen_mov_i64(cpu_fr[rc + i], tmp64); ++ } ++ tcg_temp_free(va); ++ tcg_temp_free(vc); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x02: ++ /* VCMPGEW */ ++ tmp64 = tcg_const_i64(0); ++ va = tcg_temp_new(); ++ vb = tcg_temp_new(); ++ vc = tcg_temp_new(); ++ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_ext32s_i64(va, cpu_fr[ra + i]); ++ tcg_gen_ext32s_i64(vb, cpu_fr[rb + i]); ++ tcg_gen_setcond_i64(TCG_COND_GE, vc, va, vb); ++ tcg_gen_or_i64(tmp64, tmp64, vc); ++ tcg_gen_shri_i64(va, cpu_fr[ra + i], 32); ++ tcg_gen_shri_i64(vb, cpu_fr[rb + i], 32); ++ tcg_gen_ext32s_i64(va, va); ++ tcg_gen_ext32s_i64(vb, vb); ++ tcg_gen_setcond_i64(TCG_COND_GE, vc, va, vb); ++ tcg_gen_or_i64(tmp64, tmp64, vc); ++ } ++ tcg_gen_shli_i64(cpu_fr[rc], tmp64, 29); ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x22: ++ /* VCMPGEW */ ++ tmp64 = tcg_const_i64(0); ++ va = tcg_temp_new(); ++ vb = tcg_const_i64(disp8); ++ vc = tcg_temp_new(); ++ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_ext32s_i64(va, cpu_fr[ra + i]); ++ tcg_gen_setcond_i64(TCG_COND_GE, vc, va, vb); ++ tcg_gen_or_i64(tmp64, tmp64, vc); ++ tcg_gen_shri_i64(va, cpu_fr[ra + i], 32); ++ tcg_gen_ext32s_i64(va, va); ++ tcg_gen_setcond_i64(TCG_COND_GE, vc, va, vb); ++ tcg_gen_or_i64(tmp64, tmp64, vc); ++ } ++ tcg_gen_shli_i64(cpu_fr[rc], tmp64, 29); ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x03: ++ /* VCMPEQW */ ++ gen_qemu_vcmpxxw_i64(TCG_COND_EQ, ra, rb, rc); ++ break; ++ case 0x23: ++ /* VCMPEQW */ ++ gen_qemu_vcmpxxwi_i64(TCG_COND_EQ, ra, disp8, rc); ++ break; ++ case 0x04: ++ /* VCMPLEW */ ++ gen_qemu_vcmpxxw_i64(TCG_COND_LE, ra, rb, rc); ++ break; ++ case 0x24: ++ /* VCMPLEW */ ++ gen_qemu_vcmpxxwi_i64(TCG_COND_LE, ra, disp8, rc); ++ break; ++ case 0x05: ++ /* VCMPLTW */ ++ gen_qemu_vcmpxxw_i64(TCG_COND_LT, ra, rb, rc); ++ break; ++ case 0x25: ++ /* VCMPLTW */ ++ gen_qemu_vcmpxxwi_i64(TCG_COND_LT, ra, disp8, rc); ++ break; ++ case 0x06: ++ /* VCMPULEW */ ++ gen_qemu_vcmpxxw_i64(TCG_COND_LEU, ra, rb, rc); ++ break; ++ case 0x26: ++ /* VCMPULEW */ ++ gen_qemu_vcmpxxwi_i64(TCG_COND_LEU, ra, disp8, rc); ++ break; ++ case 0x07: ++ /* VCMPULTW */ ++ gen_qemu_vcmpxxw_i64(TCG_COND_LTU, ra, rb, rc); ++ break; ++ case 0x27: ++ /* VCMPULTW */ ++ gen_qemu_vcmpxxwi_i64(TCG_COND_LTU, ra, disp8, rc); ++ break; ++ case 0x08: ++ /* VSLLW */ ++ tmp64 = tcg_temp_new(); ++ shift = tcg_temp_new(); ++ vc = tcg_temp_new(); ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_shri_i64(shift, cpu_fr[rb], 29); ++ tcg_gen_andi_i64(shift, shift, 0x1fUL); ++ ++ tcg_gen_shl_i64(vc, cpu_fr[ra + i], shift); ++ tcg_gen_ext32u_i64(tmp64, vc); ++ ++ tcg_gen_andi_i64(vc, cpu_fr[ra + i], ++ 0xffffffff00000000UL); ++ tcg_gen_shl_i64(vc, vc, shift); ++ tcg_gen_or_i64(cpu_fr[rc + i], tmp64, vc); ++ } ++ tcg_temp_free(tmp64); ++ tcg_temp_free(shift); ++ tcg_temp_free(vc); ++ break; ++ case 0x28: ++ /* VSLLW */ ++ tmp64 = tcg_temp_new(); ++ shift = tcg_temp_new(); ++ vc = tcg_temp_new(); ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_movi_i64(shift, disp8 & 0x1fUL); ++ ++ tcg_gen_shl_i64(vc, cpu_fr[ra + i], shift); ++ tcg_gen_ext32u_i64(tmp64, vc); ++ ++ tcg_gen_andi_i64(vc, cpu_fr[ra + i], ++ 0xffffffff00000000UL); ++ tcg_gen_shl_i64(vc, vc, shift); ++ tcg_gen_or_i64(cpu_fr[rc + i], tmp64, vc); ++ } ++ tcg_temp_free(tmp64); ++ tcg_temp_free(shift); ++ tcg_temp_free(vc); ++ break; ++ case 0x09: ++ /* VSRLW */ ++ tmp64 = tcg_temp_new(); ++ shift = tcg_temp_new(); ++ vc = tcg_temp_new(); ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_shri_i64(shift, cpu_fr[rb], 29); ++ tcg_gen_andi_i64(shift, shift, 0x1fUL); ++ ++ tcg_gen_ext32u_i64(vc, cpu_fr[ra + i]); ++ tcg_gen_shr_i64(tmp64, vc, shift); ++ ++ tcg_gen_shr_i64(vc, cpu_fr[ra + i], shift); ++ tcg_gen_andi_i64(vc, vc, 0xffffffff00000000UL); ++ tcg_gen_or_i64(cpu_fr[rc + i], tmp64, vc); ++ } ++ tcg_temp_free(tmp64); ++ tcg_temp_free(shift); ++ tcg_temp_free(vc); ++ break; ++ case 0x29: ++ /* VSRLW */ ++ tmp64 = tcg_temp_new(); ++ shift = tcg_temp_new(); ++ vc = tcg_temp_new(); ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_movi_i64(shift, disp8 & 0x1fUL); ++ ++ tcg_gen_ext32u_i64(vc, cpu_fr[ra + i]); ++ tcg_gen_shr_i64(tmp64, vc, shift); ++ ++ tcg_gen_shr_i64(vc, cpu_fr[ra + i], shift); ++ tcg_gen_andi_i64(vc, vc, 0xffffffff00000000UL); ++ tcg_gen_or_i64(cpu_fr[rc + i], tmp64, vc); ++ } ++ tcg_temp_free(tmp64); ++ tcg_temp_free(shift); ++ tcg_temp_free(vc); ++ break; ++ case 0x0A: ++ /* VSRAW */ ++ tmp64 = tcg_temp_new(); ++ shift = tcg_temp_new(); ++ vc = tcg_temp_new(); ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_shri_i64(shift, cpu_fr[rb], 29); ++ tcg_gen_andi_i64(shift, shift, 0x1fUL); ++ ++ tcg_gen_ext32s_i64(vc, cpu_fr[ra + i]); ++ tcg_gen_sar_i64(tmp64, vc, shift); ++ ++ tcg_gen_sar_i64(vc, cpu_fr[ra + i], shift); ++ tcg_gen_andi_i64(vc, vc, 0xffffffff00000000UL); ++ tcg_gen_or_i64(cpu_fr[rc + i], tmp64, vc); ++ } ++ tcg_temp_free(tmp64); ++ tcg_temp_free(shift); ++ tcg_temp_free(vc); ++ break; ++ case 0x2A: ++ /* VSRAWI */ ++ tmp64 = tcg_temp_new(); ++ shift = tcg_temp_new(); ++ vc = tcg_temp_new(); ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_movi_i64(shift, disp8 & 0x1fUL); ++ ++ tcg_gen_ext32s_i64(vc, cpu_fr[ra + i]); ++ tcg_gen_sar_i64(tmp64, vc, shift); ++ ++ tcg_gen_sar_i64(vc, cpu_fr[ra + i], shift); ++ tcg_gen_andi_i64(vc, vc, 0xffffffff00000000UL); ++ tcg_gen_or_i64(cpu_fr[rc + i], tmp64, vc); ++ } ++ tcg_temp_free(tmp64); ++ tcg_temp_free(shift); ++ tcg_temp_free(vc); ++ break; ++ case 0x0B: ++ /* VROLW */ ++ tmpa = tcg_temp_new_i32(); ++ tmpb = tcg_temp_new_i32(); ++ tmpc = tcg_temp_new_i32(); ++ tmp64 = tcg_temp_new(); ++ shift = tcg_temp_new(); ++ vc = tcg_temp_new(); ++ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_shri_i64(shift, cpu_fr[rb], 29); ++ tcg_gen_andi_i64(shift, shift, 0x1fUL); ++ ++ tcg_gen_extrl_i64_i32(tmpa, cpu_fr[ra + i]); ++ tcg_gen_extrl_i64_i32(tmpb, shift); ++ ++ tcg_gen_rotl_i32(tmpc, tmpa, tmpb); ++ tcg_gen_extu_i32_i64(tmp64, tmpc); ++ ++ tcg_gen_extrh_i64_i32(tmpa, cpu_fr[ra + i]); ++ tcg_gen_rotl_i32(tmpc, tmpa, tmpb); ++ tcg_gen_extu_i32_i64(vc, tmpc); ++ tcg_gen_shli_i64(vc, vc, 32); ++ ++ tcg_gen_or_i64(cpu_fr[rc + i], vc, tmp64); ++ } ++ tcg_temp_free_i32(tmpa); ++ tcg_temp_free_i32(tmpb); ++ tcg_temp_free_i32(tmpc); ++ tcg_temp_free(tmp64); ++ tcg_temp_free(shift); ++ tcg_temp_free(vc); ++ break; ++ case 0x2B: ++ /* VROLW */ ++ tmpa = tcg_temp_new_i32(); ++ tmpb = tcg_temp_new_i32(); ++ tmpc = tcg_temp_new_i32(); ++ tmp64 = tcg_temp_new(); ++ shift = tcg_temp_new(); ++ vc = tcg_temp_new(); ++ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_movi_i64(shift, disp8 & 0x1fUL); ++ ++ tcg_gen_extrl_i64_i32(tmpa, cpu_fr[ra + i]); ++ tcg_gen_extrl_i64_i32(tmpb, shift); ++ ++ tcg_gen_rotl_i32(tmpc, tmpa, tmpb); ++ tcg_gen_extu_i32_i64(tmp64, tmpc); ++ ++ tcg_gen_extrh_i64_i32(tmpa, cpu_fr[ra + i]); ++ tcg_gen_rotl_i32(tmpc, tmpa, tmpb); ++ tcg_gen_extu_i32_i64(vc, tmpc); ++ tcg_gen_shli_i64(vc, vc, 32); ++ ++ tcg_gen_or_i64(cpu_fr[rc + i], vc, tmp64); ++ } ++ tcg_temp_free_i32(tmpa); ++ tcg_temp_free_i32(tmpb); ++ tcg_temp_free_i32(tmpc); ++ tcg_temp_free(tmp64); ++ tcg_temp_free(shift); ++ tcg_temp_free(vc); ++ break; ++ case 0x0C: ++ /* SLLOW */ ++ tcg_gen_sllow_i64(ra, rc, rb); ++ break; ++ case 0x2C: ++ /* SLLOW */ ++ tcg_gen_sllowi_i64(ra, rc, disp8); ++ break; ++ case 0x0D: ++ /* SRLOW */ ++ tcg_gen_srlow_i64(ra, rc, rb); ++ break; ++ case 0x2D: ++ /* SRLOW */ ++ tcg_gen_srlowi_i64(ra, rc, disp8); ++ break; ++ case 0x0E: ++ /* VADDL */ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_add_i64(cpu_fr[rc + i], cpu_fr[ra + i], ++ cpu_fr[rb + i]); ++ } ++ break; ++ case 0x2E: ++ /* VADDL */ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_addi_i64(cpu_fr[rc + i], cpu_fr[ra + i], disp8); ++ } ++ break; ++ case 0x0F: ++ /* VSUBL */ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_sub_i64(cpu_fr[rc + i], cpu_fr[ra + i], ++ cpu_fr[rb + i]); ++ } ++ break; ++ case 0x2F: ++ /* VSUBL */ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_subi_i64(cpu_fr[rc + i], cpu_fr[ra + i], disp8); ++ } ++ break; ++ case 0x18: ++ /* CTPOPOW */ ++ tmp64 = tcg_const_i64(0); ++ tmp64_0 = tcg_temp_new(); ++ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_ctpop_i64(tmp64_0, cpu_fr[ra + i]); ++ tcg_gen_add_i64(tmp64, tmp64, tmp64_0); ++ } ++ tcg_gen_shli_i64(cpu_fr[rc], tmp64, 29); ++ tcg_temp_free(tmp64); ++ tcg_temp_free(tmp64_0); ++ break; ++ case 0x19: ++ /* CTLZOW */ ++ va = tcg_const_i64(ra); ++ gen_helper_ctlzow(cpu_fr[rc], cpu_env, va); ++ tcg_temp_free(va); ++ break; ++ case 0x40: ++ /* VUCADDW */ ++ va = tcg_const_i64(ra); ++ vb = tcg_const_i64(rb); ++ vc = tcg_const_i64(rc); ++ gen_helper_vucaddw(cpu_env, va, vb, vc); ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ break; ++ case 0x60: ++ /* VUCADDW */ ++ va = tcg_const_i64(ra); ++ vb = tcg_const_i64(disp8); ++ vc = tcg_const_i64(rc); ++ gen_helper_vucaddwi(cpu_env, va, vb, vc); ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ break; ++ case 0x41: ++ /* VUCSUBW */ ++ va = tcg_const_i64(ra); ++ vb = tcg_const_i64(rb); ++ vc = tcg_const_i64(rc); ++ gen_helper_vucsubw(cpu_env, va, vb, vc); ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ break; ++ case 0x61: ++ /* VUCSUBW */ ++ va = tcg_const_i64(ra); ++ vb = tcg_const_i64(disp8); ++ vc = tcg_const_i64(rc); ++ gen_helper_vucsubwi(cpu_env, va, vb, vc); ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ break; ++ case 0x42: ++ /* VUCADDH */ ++ va = tcg_const_i64(ra); ++ vb = tcg_const_i64(rb); ++ vc = tcg_const_i64(rc); ++ gen_helper_vucaddh(cpu_env, va, vb, vc); ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ break; ++ case 0x62: ++ /* VUCADDH */ ++ va = tcg_const_i64(ra); ++ vb = tcg_const_i64(disp8); ++ vc = tcg_const_i64(rc); ++ gen_helper_vucaddhi(cpu_env, va, vb, vc); ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ break; ++ case 0x43: ++ /* VUCSUBH */ ++ va = tcg_const_i64(ra); ++ vb = tcg_const_i64(rb); ++ vc = tcg_const_i64(rc); ++ gen_helper_vucsubh(cpu_env, va, vb, vc); ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ break; ++ case 0x63: ++ /* VUCSUBH */ ++ va = tcg_const_i64(ra); ++ vb = tcg_const_i64(disp8); ++ vc = tcg_const_i64(rc); ++ gen_helper_vucsubhi(cpu_env, va, vb, vc); ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ break; ++ case 0x44: ++ /* VUCADDB */ ++ va = tcg_const_i64(ra); ++ vb = tcg_const_i64(rb); ++ vc = tcg_const_i64(rc); ++ gen_helper_vucaddb(cpu_env, va, vb, vc); ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ break; ++ case 0x64: ++ /* VUCADDB */ ++ va = tcg_const_i64(ra); ++ vb = tcg_const_i64(disp8); ++ vc = tcg_const_i64(rc); ++ gen_helper_vucaddbi(cpu_env, va, vb, vc); ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ break; ++ case 0x45: ++ /* VUCSUBB */ ++ va = tcg_const_i64(ra); ++ vb = tcg_const_i64(rb); ++ vc = tcg_const_i64(rc); ++ gen_helper_vucsubb(cpu_env, va, vb, vc); ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ break; ++ case 0x65: ++ /* VUCSUBB */ ++ va = tcg_const_i64(ra); ++ vb = tcg_const_i64(disp8); ++ vc = tcg_const_i64(rc); ++ gen_helper_vucsubbi(cpu_env, va, vb, vc); ++ tcg_temp_free(va); ++ tcg_temp_free(vb); ++ tcg_temp_free(vc); ++ break; ++ case 0x80: ++ /* VADDS */ ++ for (i = 0; i < 128; i += 32) ++ gen_fadds(ctx, ra + i, rb + i, rc + i); ++ break; ++ case 0x81: ++ /* VADDD */ ++ for (i = 0; i < 128; i += 32) ++ gen_faddd(ctx, ra + i, rb + i, rc + i); ++ break; ++ case 0x82: ++ /* VSUBS */ ++ for (i = 0; i < 128; i += 32) ++ gen_fsubs(ctx, ra + i, rb + i, rc + i); ++ break; ++ case 0x83: ++ /* VSUBD */ ++ for (i = 0; i < 128; i += 32) ++ gen_fsubd(ctx, ra + i, rb + i, rc + i); ++ break; ++ case 0x84: ++ /* VMULS */ ++ for (i = 0; i < 128; i += 32) ++ gen_fmuls(ctx, ra + i, rb + i, rc + i); ++ break; ++ case 0x85: ++ /* VMULD */ ++ for (i = 0; i < 128; i += 32) ++ gen_fmuld(ctx, ra + i, rb + i, rc + i); ++ break; ++ case 0x86: ++ /* VDIVS */ ++ for (i = 0; i < 128; i += 32) ++ gen_fdivs(ctx, ra + i, rb + i, rc + i); ++ break; ++ case 0x87: ++ /* VDIVD */ ++ for (i = 0; i < 128; i += 32) ++ gen_fdivd(ctx, ra + i, rb + i, rc + i); ++ break; ++ case 0x88: ++ /* VSQRTS */ ++ for (i = 0; i < 128; i += 32) ++ gen_helper_fsqrts(cpu_fr[rc + i], cpu_env, ++ cpu_fr[rb + i]); ++ break; ++ case 0x89: ++ /* VSQRTD */ ++ for (i = 0; i < 128; i += 32) ++ gen_helper_fsqrt(cpu_fr[rc + i], cpu_env, ++ cpu_fr[rb + i]); ++ break; ++ case 0x8C: ++ /* VFCMPEQ */ ++ for (i = 0; i < 128; i += 32) ++ gen_fcmpeq(ctx, ra + i, rb + i, rc + i); ++ break; ++ case 0x8D: ++ /* VFCMPLE */ ++ for (i = 0; i < 128; i += 32) ++ gen_fcmple(ctx, ra + i, rb + i, rc + i); ++ break; ++ case 0x8E: ++ /* VFCMPLT */ ++ for (i = 0; i < 128; i += 32) ++ gen_fcmplt(ctx, ra + i, rb + i, rc + i); ++ break; ++ case 0x8F: ++ /* VFCMPUN */ ++ for (i = 0; i < 128; i += 32) ++ gen_fcmpun(ctx, ra + i, rb + i, rc + i); ++ break; ++ case 0x90: ++ /* VCPYS */ ++ tcg_gen_vcpys_i64(ra, rb, rc); ++ break; ++ case 0x91: ++ /* VCPYSE */ ++ tcg_gen_vcpyse_i64(ra, rb, rc); ++ break; ++ case 0x92: ++ /* VCPYSN */ ++ tcg_gen_vcpysn_i64(ra, rb, rc); ++ break; ++ case 0x93: ++ /* VSUMS */ ++ gen_fadds(ctx, ra, ra + 32, rc); ++ gen_fadds(ctx, rc, ra + 64, rc); ++ gen_fadds(ctx, rc, ra + 96, rc); ++ break; ++ case 0x94: ++ /* VSUMD */ ++ gen_faddd(ctx, ra, ra + 32, rc); ++ gen_faddd(ctx, rc, ra + 64, rc); ++ gen_faddd(ctx, rc, ra + 96, rc); ++ break; ++ default: ++ printf("ILLEGAL BELOW OPC[%x] func[%08x]\n", opc, fn8); ++ ret = gen_invalid(ctx); ++ break; ++ } ++ break; ++ case 0x1B: ++ /* SIMD */ ++ if (unlikely(rc == 31)) break; ++ switch (fn6) { ++ case 0x00: ++ /* VMAS */ ++ for (i = 0; i < 128; i += 32) ++ gen_helper_fmas(cpu_fr[rc + i], cpu_env, cpu_fr[ra + i], ++ cpu_fr[rb + i], cpu_fr[rd + i]); ++ break; ++ case 0x01: ++ /* VMAD */ ++ for (i = 0; i < 128; i += 32) ++ gen_helper_fmad(cpu_fr[rc + i], cpu_env, cpu_fr[ra + i], ++ cpu_fr[rb + i], cpu_fr[rd + i]); ++ break; ++ case 0x02: ++ /* VMSS */ ++ for (i = 0; i < 128; i += 32) ++ gen_helper_fmss(cpu_fr[rc + i], cpu_env, cpu_fr[ra + i], ++ cpu_fr[rb + i], cpu_fr[rd + i]); ++ break; ++ case 0x03: ++ /* VMSD */ ++ for (i = 0; i < 128; i += 32) ++ gen_helper_fmsd(cpu_fr[rc + i], cpu_env, cpu_fr[ra + i], ++ cpu_fr[rb + i], cpu_fr[rd + i]); ++ break; ++ case 0x04: ++ /* VNMAS */ ++ for (i = 0; i < 128; i += 32) ++ gen_helper_fnmas(cpu_fr[rc + i], cpu_env, ++ cpu_fr[ra + i], cpu_fr[rb + i], ++ cpu_fr[rd + i]); ++ break; ++ case 0x05: ++ /* VNMAD */ ++ for (i = 0; i < 128; i += 32) ++ gen_helper_fnmad(cpu_fr[rc + i], cpu_env, ++ cpu_fr[ra + i], cpu_fr[rb + i], ++ cpu_fr[rd + i]); ++ break; ++ case 0x06: ++ /* VNMSS */ ++ for (i = 0; i < 128; i += 32) ++ gen_helper_fnmss(cpu_fr[rc + i], cpu_env, ++ cpu_fr[ra + i], cpu_fr[rb + i], ++ cpu_fr[rd + i]); ++ break; ++ case 0x07: ++ /* VNMSD */ ++ for (i = 0; i < 128; i += 32) ++ gen_helper_fnmsd(cpu_fr[rc + i], cpu_env, ++ cpu_fr[ra + i], cpu_fr[rb + i], ++ cpu_fr[rd + i]); ++ break; ++ case 0x10: ++ /* VFSELEQ */ ++ tmp64 = tcg_temp_new(); ++ tmp64_0 = tcg_const_i64(0); ++ for (i = 0; i < 128; i += 32) { ++ gen_helper_fcmpeq(tmp64, cpu_env, cpu_fr[ra + i], ++ tmp64_0); ++ tcg_gen_movcond_i64(TCG_COND_EQ, cpu_fr[rc + i], tmp64, ++ tmp64_0, cpu_fr[rd + i], ++ cpu_fr[rb + i]); ++ } ++ tcg_temp_free(tmp64); ++ tcg_temp_free(tmp64_0); ++ break; ++ case 0x12: ++ /* VFSELLT */ ++ tmp64 = tcg_temp_new(); ++ tmp64_0 = tcg_const_i64(0); ++ tmp64_1 = tcg_temp_new(); ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_andi_i64(tmp64, cpu_fr[ra + i], ++ 0x7fffffffffffffffUL); ++ tcg_gen_setcond_i64(TCG_COND_NE, tmp64, tmp64, ++ tmp64_0); ++ tcg_gen_shri_i64(tmp64_1, cpu_fr[ra +i], 63); ++ tcg_gen_and_i64(tmp64, tmp64_1, tmp64); ++ tcg_gen_movcond_i64(TCG_COND_EQ, cpu_fr[rc + i], tmp64, ++ tmp64_0, cpu_fr[rd + i], ++ cpu_fr[rb + i]); ++ } ++ tcg_temp_free(tmp64); ++ tcg_temp_free(tmp64_0); ++ tcg_temp_free(tmp64_1); ++ break; ++ case 0x13: ++ /* VFSELLE */ ++ tmp64 = tcg_temp_new(); ++ tmp64_0 = tcg_const_i64(0); ++ tmp64_1 = tcg_temp_new(); ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_andi_i64(tmp64, cpu_fr[ra + i], ++ 0x7fffffffffffffffUL); ++ tcg_gen_setcond_i64(TCG_COND_EQ, tmp64, tmp64, ++ tmp64_0); ++ tcg_gen_shri_i64(tmp64_1, cpu_fr[ra + i], 63); ++ tcg_gen_or_i64(tmp64, tmp64_1, tmp64); ++ tcg_gen_movcond_i64(TCG_COND_EQ, cpu_fr[rc + i], tmp64, ++ tmp64_0, cpu_fr[rd + i], ++ cpu_fr[rb + i]); ++ } ++ tcg_temp_free(tmp64); ++ tcg_temp_free(tmp64_0); ++ tcg_temp_free(tmp64_1); ++ break; ++ case 0x18: ++ /* VSELEQW */ ++ gen_qemu_vselxxw(TCG_COND_EQ, ra, rb, rd, rc, 0); ++ break; ++ case 0x38: ++ /* VSELEQW */ ++ gen_qemu_vselxxwi(TCG_COND_EQ, ra, rb, disp5, rc, 0); ++ break; ++ case 0x19: ++ /* VSELLBCW */ ++ gen_qemu_vselxxw(TCG_COND_EQ, ra, rb, rd, rc, 1); ++ break; ++ case 0x39: ++ /* VSELLBCW */ ++ gen_qemu_vselxxwi(TCG_COND_EQ, ra, rb, disp5, rc, 1); ++ break; ++ case 0x1A: ++ /* VSELLTW */ ++ gen_qemu_vselxxw(TCG_COND_LT, ra, rb, rd, rc, 0); ++ break; ++ case 0x3A: ++ /* VSELLTW */ ++ gen_qemu_vselxxwi(TCG_COND_LT, ra, rb, disp5, rc, 0); ++ break; ++ case 0x1B: ++ /* VSELLEW */ ++ gen_qemu_vselxxw(TCG_COND_LE, ra, rb, rd, rc, 0); ++ break; ++ case 0x3B: ++ /* VSELLEW */ ++ gen_qemu_vselxxwi(TCG_COND_LE, ra, rb, disp5, rc, 0); ++ break; ++ case 0x20: ++ /* VINSW */ ++ if (disp5 > 7) break; ++ tmp64 = tcg_temp_new(); ++ tmp32 = tcg_temp_new_i32(); ++ gen_helper_s_to_memory(tmp32, cpu_fr[ra]); ++ tcg_gen_extu_i32_i64(tmp64, tmp32); ++ tcg_gen_shli_i64(tmp64, tmp64, (disp5 % 2) * 32); ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_mov_i64(cpu_fr[rc + i], cpu_fr[rb + i]); ++ } ++ if (disp5 % 2) { ++ tcg_gen_andi_i64(cpu_fr[rc + (disp5 / 2) * 32], ++ cpu_fr[rc + (disp5 / 2) * 32], ++ 0xffffffffUL); ++ } else { ++ tcg_gen_andi_i64(cpu_fr[rc + (disp5 / 2) * 32], ++ cpu_fr[rc + (disp5 / 2) * 32], ++ 0xffffffff00000000UL); ++ } ++ tcg_gen_or_i64(cpu_fr[rc + (disp5 / 2) * 32], ++ cpu_fr[rc + (disp5 / 2) * 32], tmp64); ++ tcg_temp_free(tmp64); ++ tcg_temp_free_i32(tmp32); ++ break; ++ case 0x21: ++ /* VINSF */ ++ if (disp5 > 3) break; ++ tmp64 = tcg_temp_new(); ++ tcg_gen_mov_i64(tmp64, cpu_fr[ra]); ++ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_mov_i64(cpu_fr[rc + i], cpu_fr[rb + i]); ++ } ++ tcg_gen_mov_i64(cpu_fr[rc + disp5 * 32], tmp64); ++ tcg_temp_free(tmp64); ++ break; ++ case 0x22: ++ /* VEXTW */ ++ if (disp5 > 7) break; ++ tmp64 = tcg_temp_new(); ++ tmp32 = tcg_temp_new_i32(); ++ tcg_gen_shri_i64(tmp64, cpu_fr[ra + (disp5 / 2) * 32], ++ (disp5 % 2) * 32); ++ tcg_gen_extrl_i64_i32(tmp32, tmp64); ++ gen_helper_memory_to_s(tmp64, tmp32); ++ tcg_gen_mov_i64(cpu_fr[rc], tmp64); ++ tcg_temp_free(tmp64); ++ tcg_temp_free_i32(tmp32); ++ break; ++ case 0x23: ++ /* VEXTF */ ++ if (disp5 > 3) break; ++ tcg_gen_mov_i64(cpu_fr[rc], cpu_fr[ra + disp5 * 32]); ++ break; ++ case 0x24: ++ /* VCPYW */ ++ tmp64 = tcg_temp_new(); ++ tmp64_0 = tcg_temp_new(); ++ /* FIXME: for debug ++ tcg_gen_movi_i64(tmp64, ra); ++ gen_helper_v_print(cpu_env, tmp64); ++ */ ++ tcg_gen_shri_i64(tmp64, cpu_fr[ra], 29); ++ tcg_gen_andi_i64(tmp64_0, tmp64, 0x3fffffffUL); ++ tcg_gen_shri_i64(tmp64, cpu_fr[ra], 62); ++ tcg_gen_shli_i64(tmp64, tmp64, 30); ++ tcg_gen_or_i64(tmp64_0, tmp64, tmp64_0); ++ tcg_gen_mov_i64(tmp64, tmp64_0); ++ tcg_gen_shli_i64(tmp64, tmp64, 32); ++ tcg_gen_or_i64(tmp64_0, tmp64_0, tmp64); ++ tcg_gen_mov_i64(cpu_fr[rc], tmp64_0); ++ tcg_gen_mov_i64(cpu_fr[rc + 32], cpu_fr[rc]); ++ tcg_gen_mov_i64(cpu_fr[rc + 64], cpu_fr[rc]); ++ tcg_gen_mov_i64(cpu_fr[rc + 96], cpu_fr[rc]); ++ /* FIXME: for debug ++ tcg_gen_movi_i64(tmp64, rb); ++ gen_helper_v_print(cpu_env, tmp64); ++ tcg_gen_movi_i64(tmp64, rc); ++ gen_helper_v_print(cpu_env, tmp64); ++ */ ++ tcg_temp_free(tmp64); ++ tcg_temp_free(tmp64_0); ++ break; ++ case 0x25: ++ /* VCPYF */ ++ for (i = 0; i < 128; i += 32) { ++ tcg_gen_mov_i64(cpu_fr[rc + i], cpu_fr[ra]); ++ } ++ break; ++ case 0x26: ++ /* VCONW */ ++ tmp64 = tcg_const_i64(ra << 8 | rb); ++ tmp64_0 = tcg_temp_new(); ++ vd = tcg_const_i64(rc); ++ tcg_gen_shri_i64(tmp64_0, cpu_fr[rd], 2); ++ tcg_gen_andi_i64(tmp64_0, tmp64_0, 0x7ul); ++ gen_helper_vconw(cpu_env, tmp64, vd, tmp64_0); ++ tcg_temp_free(tmp64_0); ++ tcg_temp_free(tmp64); ++ tcg_temp_free(vd); ++ break; ++ case 0x27: ++ /* VSHFW */ ++ tmp64 = tcg_const_i64(ra << 8 | rb); ++ vd = tcg_const_i64(rc); ++ gen_helper_vshfw(cpu_env, tmp64, vd, cpu_fr[rd]); ++ tcg_temp_free(tmp64); ++ tcg_temp_free(vd); ++ break; ++ case 0x28: ++ /* VCONS */ ++ tmp64 = tcg_const_i64(ra << 8 | rb); ++ tmp64_0 = tcg_temp_new(); ++ vd = tcg_const_i64(rc); ++ tcg_gen_shri_i64(tmp64_0, cpu_fr[rd], 2); ++ tcg_gen_andi_i64(tmp64_0, tmp64_0, 0x3ul); ++ gen_helper_vcond(cpu_env, tmp64, vd, tmp64_0); ++ tcg_temp_free(tmp64_0); ++ tcg_temp_free(tmp64); ++ tcg_temp_free(vd); ++ break; ++ case 0x29: ++ /* FIXME: VCOND maybe it's wrong in the instruction book ++ * that there are no temp. */ ++ tmp64 = tcg_const_i64(ra << 8 | rb); ++ tmp64_0 = tcg_temp_new(); ++ vd = tcg_const_i64(rc); ++ tcg_gen_shri_i64(tmp64_0, cpu_fr[rd], 3); ++ tcg_gen_andi_i64(tmp64_0, tmp64_0, 0x3ul); ++ gen_helper_vcond(cpu_env, tmp64, vd, tmp64_0); ++ tcg_temp_free(tmp64_0); ++ tcg_temp_free(tmp64); ++ tcg_temp_free(vd); ++ break; ++ default: ++ printf("ILLEGAL BELOW OPC[%x] func[%08x]\n", opc, fn6); ++ ret = gen_invalid(ctx); ++ break; ++ } ++ break; ++ case 0x1C: ++ switch (fn4) { ++ case 0x0: ++ /* VLDW_U */ ++ if (unlikely(ra == 31)) break; ++ gen_load_mem_simd(ctx, &gen_qemu_vldd, ra, rb, disp12, ++ ~0x1fUL); ++ break; ++ case 0x1: ++ /* VSTW_U */ ++ gen_store_mem_simd(ctx, &gen_qemu_vstd, ra, rb, disp12, ++ ~0x1fUL); ++ break; ++ case 0x2: ++ /* VLDS_U */ ++ if (unlikely(ra == 31)) break; ++ gen_load_mem_simd(ctx, &gen_qemu_vlds, ra, rb, disp12, ++ ~0xfUL); ++ break; ++ case 0x3: ++ /* VSTS_U */ ++ gen_store_mem_simd(ctx, &gen_qemu_vsts, ra, rb, disp12, ++ ~0xfUL); ++ break; ++ case 0x4: ++ /* VLDD_U */ ++ if (unlikely(ra == 31)) break; ++ gen_load_mem_simd(ctx, &gen_qemu_vldd, ra, rb, disp12, ++ ~0x1fUL); ++ break; ++ case 0x5: ++ /* VSTD_U */ ++ gen_store_mem_simd(ctx, &gen_qemu_vstd, ra, rb, disp12, ++ ~0x1fUL); ++ break; ++ case 0x8: ++ /* VSTW_UL */ ++ gen_store_mem_simd(ctx, &gen_qemu_vstw_ul, ra, rb, disp12, ++ 0); ++ break; ++ case 0x9: ++ /* VSTW_UH */ ++ gen_store_mem_simd(ctx, &gen_qemu_vstw_uh, ra, rb, disp12, ++ 0); ++ break; ++ case 0xa: ++ /* VSTS_UL */ ++ gen_store_mem_simd(ctx, &gen_qemu_vsts_ul, ra, rb, disp12, ++ 0); ++ break; ++ case 0xb: ++ /* VSTS_UH */ ++ gen_store_mem_simd(ctx, &gen_qemu_vsts_uh, ra, rb, disp12, ++ 0); ++ break; ++ case 0xc: ++ /* VSTD_UL */ ++ gen_store_mem_simd(ctx, &gen_qemu_vstd_ul, ra, rb, disp12, ++ 0); ++ break; ++ case 0xd: ++ /* VSTD_UH */ ++ gen_store_mem_simd(ctx, &gen_qemu_vstd_uh, ra, rb, disp12, ++ 0); ++ break; ++ case 0xe: ++ /* VLDD_NC */ ++ gen_load_mem_simd(ctx, &gen_qemu_vldd, ra, rb, disp12, 0); ++ break; ++ case 0xf: ++ /* VSTD_NC */ ++ gen_store_mem_simd(ctx, &gen_qemu_vstd, ra, rb, disp12, 0); ++ break; ++ default: ++ printf("ILLEGAL BELOW OPC[%x] func[%08x]\n", opc, fn4); ++ ret = gen_invalid(ctx); ++ break; ++ } ++ break; ++ case 0x20: ++ /* LDBU */ ++ gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0); ++ break; ++ case 0x21: ++ /* LDHU */ ++ gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0); ++ break; ++ case 0x22: ++ /* LDW */ ++ gen_load_mem(ctx, &tcg_gen_qemu_ld32s, ra, rb, disp16, 0, 0); ++ break; ++ case 0x23: ++ /* LDL */ ++ gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 0); ++ break; ++ case 0x24: ++ /* LDL_U */ ++ gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 1); ++ break; ++ case 0x25: ++ /* PRI_LD */ ++#ifndef CONFIG_USER_ONLY ++ if ((insn >> 12) & 1) { ++ gen_load_mem(ctx, &gen_qemu_pri_ldl, ra, rb, disp12, 0, 1); ++ } else { ++ gen_load_mem(ctx, &gen_qemu_pri_ldw, ra, rb, disp12, 0, 1); ++ } ++#endif ++ break; ++ case 0x26: ++ /* FLDS */ ++ gen_load_mem(ctx, &gen_qemu_flds, ra, rb, disp16, 1, 0); ++ break; ++ case 0x27: ++ /* FLDD */ ++ gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 1, 0); ++ break; ++ case 0x28: ++ /* STB */ ++ gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0); ++ break; ++ case 0x29: ++ /* STH */ ++ gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0); ++ break; ++ case 0x2a: ++ /* STW */ ++ gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0); ++ break; ++ case 0x2b: ++ /* STL */ ++ gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0); ++ break; ++ case 0x2c: ++ /* STL_U */ ++ gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1); ++ break; ++ case 0x2d: ++ /* PRI_ST */ ++#ifndef CONFIG_USER_ONLY ++ if ((insn >> 12) & 1) { ++ gen_store_mem(ctx, &gen_qemu_pri_stl, ra, rb, disp12, 0, 1); ++ } else { ++ gen_store_mem(ctx, &gen_qemu_pri_stw, ra, rb, disp12, 0, 1); ++ } ++#endif ++ break; ++ case 0x2e: ++ /* FSTS */ ++ gen_store_mem(ctx, &gen_qemu_fsts, ra, rb, disp16, 1, 0); ++ break; ++ case 0x2f: ++ /* FSTD */ ++ gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0); ++ break; ++ case 0x30: ++ /* BEQ */ ++ ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, (uint64_t)-1); ++ break; ++ case 0x31: ++ /* BNE */ ++ ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, (uint64_t)-1); ++ break; ++ case 0x32: ++ /* BLT */ ++ ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21, (uint64_t)-1); ++ break; ++ case 0x33: ++ /* BLE */ ++ ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21, (uint64_t)-1); ++ break; ++ case 0x34: ++ /* BGT */ ++ ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21, (uint64_t)-1); ++ break; ++ case 0x35: ++ /* BGE */ ++ ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21, (uint64_t)-1); ++ break; ++ case 0x36: ++ /* BLBC */ ++ ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21, 1); ++ break; ++ case 0x37: ++ /* BLBS */ ++ ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21, 1); ++ break; ++ case 0x38: ++ /* FBEQ */ ++ ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21); ++ break; ++ case 0x39: ++ /* FBNE */ ++ ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21); ++ break; ++ case 0x3a: ++ /* FBLT */ ++ ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21); ++ break; ++ case 0x3b: ++ /* FBLE */ ++ ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21); ++ break; ++ case 0x3c: ++ /* FBGT */ ++ ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21); ++ break; ++ case 0x3d: ++ /* FBGE */ ++ ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21); ++ break; ++ case 0x3f: ++ /* LDIH */ ++ disp16 = ((uint32_t)disp16) << 16; ++ if (ra == 31) break; ++ va = load_gir(ctx, ra); ++ if (rb == 31) { ++ tcg_gen_movi_i64(va, disp16); ++ } else { ++ tcg_gen_addi_i64(va, load_gir(ctx, rb), (int64_t)disp16); ++ } ++ break; ++ case 0x3e: ++ /* LDI */ ++ if (ra == 31) break; ++ va = load_gir(ctx, ra); ++ if (rb == 31) { ++ tcg_gen_movi_i64(va, disp16); ++ } else { ++ tcg_gen_addi_i64(va, load_gir(ctx, rb), (int64_t)disp16); ++ } ++ break; ++ do_invalid: ++ default: ++ printf("ILLEGAL BELOW OPC[%x] insn[%08x]\n", opc, insn); ++ ret = gen_invalid(ctx); ++ } ++ return ret; ++} ++static void sw64_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) ++{ ++ DisasContext* ctx = container_of(dcbase, DisasContext, base); ++ CPUSW64State* env = cpu->env_ptr; /*init by instance_initfn*/ ++ ++ ctx->tbflags = ctx->base.tb->flags; ++ ctx->mem_idx = cpu_mmu_index(env, false); ++#ifdef CONFIG_USER_ONLY ++ ctx->ir = cpu_std_ir; ++#else ++ ctx->ir = (ctx->tbflags & ENV_FLAG_HM_MODE ? cpu_hm_ir : cpu_std_ir); ++#endif ++ ctx->zero = NULL; ++} ++ ++static void sw64_tr_tb_start(DisasContextBase *db, CPUState *cpu) ++{ ++} ++ ++static void sw64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) ++{ ++ tcg_gen_insn_start(dcbase->pc_next); ++} ++ ++static void sw64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) ++{ ++ DisasContext *ctx = container_of(dcbase, DisasContext, base); ++ CPUSW64State *env = cpu->env_ptr; ++ uint32_t insn; ++ ++ insn = cpu_ldl_code(env, ctx->base.pc_next & (~3UL)); ++ ctx->env = env; ++ ctx->base.pc_next += 4; ++ ctx->base.is_jmp = ctx->translate_one(dcbase, insn, cpu); ++ ++ free_context_temps(ctx); ++ translator_loop_temp_check(&ctx->base); ++} ++ ++/* FIXME:Linhainan */ ++static void sw64_tr_tb_stop(DisasContextBase* dcbase, CPUState* cpu) { ++ DisasContext* ctx = container_of(dcbase, DisasContext, base); ++ ++ switch (ctx->base.is_jmp) { ++ case DISAS_NORETURN: ++ break; ++ case DISAS_TOO_MANY: ++ if (use_goto_tb(ctx, ctx->base.pc_next)) { ++ tcg_gen_goto_tb(0); ++ tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next); ++ tcg_gen_exit_tb(ctx->base.tb, 0); ++ } ++ /* FALLTHRU */ ++ case DISAS_PC_STALE: ++ tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next); ++ /* FALLTHRU */ ++ case DISAS_PC_UPDATED: ++ if (!use_exit_tb(ctx)) { ++ tcg_gen_lookup_and_goto_ptr(); ++ break; ++ } ++ /* FALLTHRU */ ++ case DISAS_PC_UPDATED_NOCHAIN: ++ if (ctx->base.singlestep_enabled) { ++ /* FIXME: for gdb*/ ++ cpu_loop_exit(cpu); ++ } else { ++ tcg_gen_exit_tb(NULL, 0); ++ } ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++} ++ ++static void sw64_tr_disas_log(const DisasContextBase* dcbase, CPUState* cpu) { ++ SW64CPU* sc = SW64_CPU(cpu); ++ qemu_log("IN(%d): %s\n", sc->cid, ++ lookup_symbol(dcbase->pc_first)); ++ log_target_disas(cpu, dcbase->pc_first & (~0x3UL), dcbase->tb->size); ++} ++ ++static void init_transops(CPUState *cpu, DisasContext *dc) ++{ ++ dc->translate_one = translate_one; ++} ++ ++void restore_state_to_opc(CPUSW64State* env, TranslationBlock* tb, ++ target_ulong* data) { ++ env->pc = data[0]; ++} ++ ++static const TranslatorOps sw64_trans_ops = { ++ .init_disas_context = sw64_tr_init_disas_context, ++ .tb_start = sw64_tr_tb_start, ++ .insn_start = sw64_tr_insn_start, ++ .translate_insn = sw64_tr_translate_insn, ++ .tb_stop = sw64_tr_tb_stop, ++ .disas_log = sw64_tr_disas_log, ++}; ++ ++void gen_intermediate_code(CPUState* cpu, TranslationBlock* tb, int max_insns) ++{ ++ DisasContext dc; ++ init_transops(cpu, &dc); ++ translator_loop(&sw64_trans_ops, &dc.base, cpu, tb, max_insns); ++} +diff --git a/target/sw64/translate.h b/target/sw64/translate.h +new file mode 100644 +index 0000000000..e93df0815e +--- /dev/null ++++ b/target/sw64/translate.h +@@ -0,0 +1,60 @@ ++#ifndef SW64_TRANSLATE_H ++#define SW64_TRANSLATE_H ++#include "qemu/osdep.h" ++#include "cpu.h" ++#include "sysemu/cpus.h" ++#include "disas/disas.h" ++#include "qemu/host-utils.h" ++#include "exec/exec-all.h" ++#include "exec/cpu_ldst.h" ++#include "tcg/tcg-op.h" ++#include "exec/helper-proto.h" ++#include "exec/helper-gen.h" ++#include "trace-tcg.h" ++#include "exec/translator.h" ++#include "exec/log.h" ++ ++#define DISAS_PC_UPDATED_NOCHAIN DISAS_TARGET_0 ++#define DISAS_PC_UPDATED DISAS_TARGET_1 ++#define DISAS_PC_STALE DISAS_TARGET_2 ++#define DISAS_PC_UPDATED_T DISAS_TOO_MANY ++ ++typedef struct DisasContext DisasContext; ++struct DisasContext { ++ DisasContextBase base; ++ ++ uint32_t tbflags; ++ ++ /* The set of registers active in the current context. */ ++ TCGv *ir; ++ ++ /* Accel: Temporaries for $31 and $f31 as source and destination. */ ++ TCGv zero; ++ int mem_idx; ++ CPUSW64State *env; ++ DisasJumpType (*translate_one)(DisasContextBase *dcbase, uint32_t insn, ++ CPUState *cpu); ++}; ++ ++extern TCGv cpu_pc; ++extern TCGv cpu_std_ir[31]; ++extern TCGv cpu_fr[128]; ++extern TCGv cpu_lock_addr; ++extern TCGv cpu_lock_flag; ++extern TCGv cpu_lock_success; ++#ifdef SW64_FIXLOCK ++extern TCGv cpu_lock_value; ++#endif ++#ifndef CONFIG_USER_ONLY ++extern TCGv cpu_hm_ir[31]; ++#endif ++ ++DisasJumpType translate_one(DisasContextBase *dcbase, uint32_t insn, ++ CPUState *cpu); ++DisasJumpType th1_translate_one(DisasContextBase *dcbase, uint32_t insn, ++ CPUState *cpu); ++bool use_exit_tb(DisasContext *ctx); ++bool use_goto_tb(DisasContext *ctx, uint64_t dest); ++void insn_profile(DisasContext *ctx, uint32_t insn); ++extern void gen_fold_mzero(TCGCond cond, TCGv dest, TCGv src); ++#endif +diff --git a/tcg/sw64/tcg-target-con-set.h b/tcg/sw64/tcg-target-con-set.h +new file mode 100755 +index 0000000000..71fdfdcbef +--- /dev/null ++++ b/tcg/sw64/tcg-target-con-set.h +@@ -0,0 +1,39 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * Define SW_64 target-specific constraint sets. ++ * Copyright (c) 2021 Linaro ++ */ ++ ++/* ++ * C_On_Im(...) defines a constraint set with outputs and inputs. ++ * Each operand should be a sequence of constraint letters as defined by ++ * tcg-target-con-str.h; the constraint combination is inclusive or. ++ */ ++C_O0_I1(r) ++C_O0_I2(lZ, l) ++C_O0_I2(r, rA) ++C_O0_I2(rZ, r) ++C_O0_I2(w, r) ++C_O1_I1(r, l) ++C_O1_I1(r, r) ++C_O1_I1(w, r) ++C_O1_I1(w, w) ++C_O1_I1(w, wr) ++C_O1_I2(r, 0, rZ) ++C_O1_I2(r, r, r) ++C_O1_I2(r, r, rA) ++C_O1_I2(r, r, rAL) ++C_O1_I2(r, r, ri) ++C_O1_I2(r, r, rL) ++C_O1_I2(r, rZ, rZ) ++C_O1_I2(w, 0, w) ++C_O1_I2(w, w, w) ++C_O1_I2(w, w, wN) ++C_O1_I2(w, w, wO) ++C_O1_I2(w, w, wZ) ++C_O1_I3(w, w, w, w) ++C_O1_I4(r, r, rA, rZ, rZ) ++C_O2_I4(r, r, rZ, rZ, rA, rMZ) ++C_O1_I4(r, r, rU, rZ, rZ) ++C_O0_I2(r, rU) ++C_O1_I2(r, r, rU) +diff --git a/tcg/sw64/tcg-target-con-str.h b/tcg/sw64/tcg-target-con-str.h +new file mode 100755 +index 0000000000..47edb3837b +--- /dev/null ++++ b/tcg/sw64/tcg-target-con-str.h +@@ -0,0 +1,28 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * Define sw_64 target-specific operand constraints. ++ * Copyright (c) 2021 Linaro ++ */ ++ ++/* ++ * Define constraint letters for register sets: ++ * REGS(letter, register_mask) ++ */ ++REGS('r', ALL_GENERAL_REGS) ++REGS('l', ALL_QLDST_REGS) ++REGS('w', ALL_VECTOR_REGS) ++ ++/* ++ * Define constraint letters for constants: ++ * CONST(letter, TCG_CT_CONST_* bit set) ++ */ ++ ++CONST('Z', TCG_CT_CONST_ZERO) ++CONST('A', TCG_CT_CONST_LONG) ++CONST('M', TCG_CT_CONST_MONE) ++CONST('O', TCG_CT_CONST_ORRI) ++CONST('W', TCG_CT_CONST_WORD) ++CONST('L', TCG_CT_CONST_LONG) ++CONST('U', TCG_CT_CONST_U8) ++CONST('S', TCG_CT_CONST_S8) ++ +diff --git a/tcg/sw64/tcg-target.c.inc b/tcg/sw64/tcg-target.c.inc +new file mode 100755 +index 0000000000..982f159e23 +--- /dev/null ++++ b/tcg/sw64/tcg-target.c.inc +@@ -0,0 +1,2109 @@ ++/* ++ * Initial TCG Implementation for sw_64 ++ * ++ */ ++ ++#include "../tcg-pool.c.inc" ++#include "qemu/bitops.h" ++ ++/* We're going to re-use TCGType in setting of the SF bit, which controls ++ the size of the operation performed. If we know the values match, it ++ makes things much cleaner. */ ++QEMU_BUILD_BUG_ON(TCG_TYPE_I32 != 0 || TCG_TYPE_I64 != 1); ++static const tcg_insn_unit *tb_ret_addr; ++ ++#ifdef CONFIG_DEBUG_TCG ++static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { ++ "X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", ++ "X8", "X9", "X10", "X11", "X12", "X13", "X14", "fp", ++ "X16", "X17", "X18", "X19", "X20", "X21", "X22", "X23", ++ "X24", "X25", "X26", "X27", "X28", "X29", "Xsp", "X31", ++ ++ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", ++ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", ++ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", ++ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", ++}; ++#endif /* CONFIG_DEBUG_TCG */ ++ ++static const int tcg_target_reg_alloc_order[] = { ++ /* TCG_REG_X9 qemu saved for AREG0*/ ++ TCG_REG_X10, TCG_REG_X11, TCG_REG_X12, TCG_REG_X13, TCG_REG_X14, ++ ++ TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3, TCG_REG_X4, ++ TCG_REG_X5, TCG_REG_X6, TCG_REG_X7, TCG_REG_X8, ++ ++ TCG_REG_X22, TCG_REG_X23, TCG_REG_X24, /*TCG_REG_X25, TCG_REG_X26, TCG_REG_X27, */ ++ ++ /* TCG_REG_SP=TCG_REG_X15 saved for system*/ ++ TCG_REG_X16, TCG_REG_X17, TCG_REG_X18, TCG_REG_X19, TCG_REG_X20, TCG_REG_X21, TCG_REG_X28, /* TCG_REG_X29, TCG_REG_X30, TCG_REG_X31 */ ++ ++ /* TCG_REG_TMP=TCG_REG_X27 reserved as temporary register */ ++ /* TCG_REG_TMP2=TCG_REG_X25 reserved as temporary register */ ++ /* TCG_REG_RA=TCG_REG_X26 reserved as temporary */ ++ /* TCG_REG_GP=TCG_REG_X29 gp saved for system*/ ++ /* TCG_REG_SP=TCG_REG_X30 sp saved for system*/ ++ /* TCG_REG_ZERO=TCG_REG_X31 zero saved for system*/ ++ ++ TCG_REG_F2, TCG_REG_F3, TCG_REG_F4, TCG_REG_F5, TCG_REG_F6, TCG_REG_F7, TCG_REG_F8, TCG_REG_F9, /* f2-f9 saved registers */ ++ /* TCG_VEC_TMP=TCG_REG_F10, TCG_VEC_TMP2=TCG_REG_F11, are saved as temporary */ ++ TCG_REG_F12, TCG_REG_F13, TCG_REG_F14, TCG_REG_F15, /* f10-f15 temporary registers */ ++ ++ TCG_REG_F22, TCG_REG_F23, TCG_REG_F24, TCG_REG_F25, TCG_REG_F26, TCG_REG_F27, TCG_REG_F28, TCG_REG_F29, TCG_REG_F30, /* f22-f30 temporary registers */ ++ /* TCG_REG_F31, zero saved for system */ ++ ++ TCG_REG_F16, TCG_REG_F17, TCG_REG_F18, TCG_REG_F19, TCG_REG_F20, TCG_REG_F21, /* input args */ ++ ++ TCG_REG_F0, TCG_REG_F1, /*output args */ ++}; ++ ++static const int tcg_target_call_iarg_regs[6] = { ++ TCG_REG_X16, TCG_REG_X17, TCG_REG_X18, TCG_REG_X19, TCG_REG_X20, TCG_REG_X21, ++}; ++static const int tcg_target_call_oarg_regs[1] = { ++ TCG_REG_X0, ++}; ++ ++#define TCG_REG_TMP TCG_REG_X27 ++#define TCG_REG_TMP2 TCG_REG_X25 ++#define TCG_FLOAT_TMP TCG_REG_F10 ++#define TCG_FLOAT_TMP2 TCG_REG_F11 ++ ++#define ALL_GENERAL_REGS 0xffffffffu ++#define ALL_QLDST_REGS ALL_GENERAL_REGS ++#define PUSH_SIZE ((15-9+1+1) * 8) ++#define FRAME_SIZE \ ++ ((PUSH_SIZE \ ++ + TCG_STATIC_CALL_ARGS_SIZE \ ++ + CPU_TEMP_BUF_NLONGS * sizeof(long) \ ++ + TCG_TARGET_STACK_ALIGN - 1) \ ++ & ~(TCG_TARGET_STACK_ALIGN - 1)) ++ ++/* We encode the format of the insn into the beginning of the name, so that ++ we can have the preprocessor help "typecheck" the insn vs the output ++ function. We don't have nice names for the formats, so we use the section ++ number of the architecture reference manual in which the instruction ++ group is described. */ ++#define OPC_OP(x) ((x & 0x3f) << 26) ++#define OPC_FUNC(x) ((x & 0xff) << 5) ++#define OPC_FUNC_COMPLEX(x) ((x & 0xff) << 10) ++typedef enum { ++ OPC_NOP =0X43ff075f, ++ OPC_SYS_CALL =OPC_OP(0x00), ++ OPC_CALL =OPC_OP(0x01), ++ OPC_RET =OPC_OP(0x02), ++ OPC_JMP =OPC_OP(0x03), ++ OPC_BR =OPC_OP(0x04), ++ OPC_BSR =OPC_OP(0x05), ++ OPC_PRI_RET =OPC_OP(0x07), ++ OPC_LDWE =OPC_OP(0x09), ++ OPC_LDSE =OPC_OP(0x0A), ++ OPC_LDDE =OPC_OP(0x0B), ++ OPC_VLDS =OPC_OP(0x0C), ++ OPC_VLDD =OPC_OP(0x0D), ++ OPC_VSTS =OPC_OP(0x0E), ++ OPC_VSTD =OPC_OP(0x0F), ++ ++ OPC_LDBU =OPC_OP(0x20), ++ OPC_LDHU =OPC_OP(0x21), ++ OPC_LDW =OPC_OP(0x22), ++ OPC_LDL =OPC_OP(0x23), ++ OPC_LDL_U =OPC_OP(0x24), ++ OPC_FLDS =OPC_OP(0X26), ++ OPC_PRI_LD =OPC_OP(0x25), ++ OPC_FLDD =OPC_OP(0X27), ++ OPC_STB =OPC_OP(0X28), ++ OPC_STH =OPC_OP(0x29), ++ OPC_STW =OPC_OP(0x2a), ++ OPC_STL =OPC_OP(0x2B), ++ OPC_STL_U =OPC_OP(0x2C), ++ OPC_PRI_ST =OPC_OP(0x2D), ++ OPC_FSTS =OPC_OP(0x2E), ++ OPC_FSTD =OPC_OP(0x2F), ++ ++ OPC_BEQ =OPC_OP(0x30), ++ OPC_BNE =OPC_OP(0x31), ++ OPC_BLT =OPC_OP(0x32), ++ OPC_BLE =OPC_OP(0x33), ++ OPC_BGT =OPC_OP(0x34), ++ OPC_BGE =OPC_OP(0x35), ++ OPC_BLBC =OPC_OP(0x36), ++ OPC_BLBS =OPC_OP(0x37), ++ ++ OPC_FBEQ =OPC_OP(0x38), ++ OPC_FBNE =OPC_OP(0x39), ++ OPC_FBLT =OPC_OP(0x3A), ++ OPC_FBLE =OPC_OP(0x3B), ++ OPC_FBGT =OPC_OP(0x3C), ++ OPC_FBGE =OPC_OP(0x3D), ++ OPC_LDI =OPC_OP(0x3E), ++ OPC_LDIH =OPC_OP(0x3F), ++ ++ OPC_ADDW =(OPC_OP(0x10) | OPC_FUNC(0x0)), ++ OPC_ADDW_I =(OPC_OP(0x12) | OPC_FUNC(0x0)), ++ OPC_SUBW =(OPC_OP(0x10) | OPC_FUNC(0x1)), ++ OPC_SUBW_I =(OPC_OP(0x12) | OPC_FUNC(0x1)), ++ OPC_S4ADDW =(OPC_OP(0x10) | OPC_FUNC(0x02)), ++ OPC_S4ADDW_I =(OPC_OP(0x12) | OPC_FUNC(0x02)), ++ OPC_S4SUBW =(OPC_OP(0x10) | OPC_FUNC(0x03)), ++ OPC_S4SUBW_I =(OPC_OP(0x12) | OPC_FUNC(0x03)), ++ ++ OPC_S8ADDW =(OPC_OP(0x10) | OPC_FUNC(0x04)), ++ OPC_S8ADDW_I =(OPC_OP(0x12) | OPC_FUNC(0x04)), ++ OPC_S8SUBW =(OPC_OP(0x10) | OPC_FUNC(0x05)), ++ OPC_S8SUBW_I =(OPC_OP(0x12) | OPC_FUNC(0x05)), ++ ++ OPC_ADDL =(OPC_OP(0x10) | OPC_FUNC(0x8)), ++ OPC_ADDL_I =(OPC_OP(0x12) | OPC_FUNC(0x8)), ++ OPC_SUBL =(OPC_OP(0x10) | OPC_FUNC(0x9)), ++ OPC_SUBL_I =(OPC_OP(0x12) | OPC_FUNC(0x9)), ++ ++ OPC_S4ADDL =(OPC_OP(0x10) | OPC_FUNC(0xA)), ++ OPC_S4ADDL_I =(OPC_OP(0x12) | OPC_FUNC(0xA)), ++ OPC_S4SUBL =(OPC_OP(0x10) | OPC_FUNC(0xB)), ++ OPC_S4SUBL_I =(OPC_OP(0x12) | OPC_FUNC(0xB)), ++ ++ OPC_S8ADDL =(OPC_OP(0x10) | OPC_FUNC(0xC)), ++ OPC_S8ADDL_I =(OPC_OP(0x12) | OPC_FUNC(0xC)), ++ OPC_S8SUBL =(OPC_OP(0x10) | OPC_FUNC(0xD)), ++ OPC_S8SUBL_I =(OPC_OP(0x12) | OPC_FUNC(0xD)), ++ ++ OPC_MULW =(OPC_OP(0x10) | OPC_FUNC(0x10)), ++ OPC_MULW_I =(OPC_OP(0x12) | OPC_FUNC(0x10)), ++ OPC_MULL =(OPC_OP(0x10) | OPC_FUNC(0x18)), ++ OPC_MULL_I =(OPC_OP(0x12) | OPC_FUNC(0x18)), ++ ++ OPC_UMULH =(OPC_OP(0x10) | OPC_FUNC(0x19)), ++ OPC_UMULH_I =(OPC_OP(0x12) | OPC_FUNC(0x19)), ++ ++ OPC_CTPOP =(OPC_OP(0x10) | OPC_FUNC(0x58)), ++ OPC_CTLZ =(OPC_OP(0x10) | OPC_FUNC(0x59)), ++ OPC_CTTZ =(OPC_OP(0x10) | OPC_FUNC(0x5A)), ++ ++ OPC_ZAP =(OPC_OP(0x10) | OPC_FUNC(0x68)), ++ OPC_ZAP_I =(OPC_OP(0x12) | OPC_FUNC(0x68)), ++ OPC_ZAPNOT =(OPC_OP(0x10) | OPC_FUNC(0x69)), ++ OPC_ZAPNOT_I =(OPC_OP(0x12) | OPC_FUNC(0x69)), ++ ++ OPC_SEXTB =(OPC_OP(0x10) | OPC_FUNC(0x6A)), ++ OPC_SEXTB_I =(OPC_OP(0x12) | OPC_FUNC(0x6A)), ++ OPC_SEXTH =(OPC_OP(0x10) | OPC_FUNC(0x6B)), ++ OPC_SEXTH_I =(OPC_OP(0x12) | OPC_FUNC(0x6B)), ++ ++ OPC_CMPEQ =(OPC_OP(0x10) | OPC_FUNC(0x28)), ++ OPC_CMPEQ_I =(OPC_OP(0x12) | OPC_FUNC(0x28)), ++ ++ OPC_CMPLT =(OPC_OP(0x10) | OPC_FUNC(0x29)), ++ OPC_CMPLT_I =(OPC_OP(0x12) | OPC_FUNC(0x29)), ++ OPC_CMPLE =(OPC_OP(0x10) | OPC_FUNC(0x2A)), ++ OPC_CMPLE_I =(OPC_OP(0x12) | OPC_FUNC(0x2A)), ++ ++ OPC_CMPULT =(OPC_OP(0x10) | OPC_FUNC(0x2B)), ++ OPC_CMPULT_I =(OPC_OP(0x12) | OPC_FUNC(0x2B)), ++ OPC_CMPULE =(OPC_OP(0x10) | OPC_FUNC(0x2C)), ++ OPC_CMPULE_I =(OPC_OP(0x12) | OPC_FUNC(0x2C)), ++ ++ OPC_AND =(OPC_OP(0x10) | OPC_FUNC(0x38)), ++ OPC_BIC =(OPC_OP(0x10) | OPC_FUNC(0x39)), ++ OPC_BIS =(OPC_OP(0x10) | OPC_FUNC(0x3A)), ++ OPC_ORNOT =(OPC_OP(0x10) | OPC_FUNC(0x3B)), ++ OPC_XOR =(OPC_OP(0x10) | OPC_FUNC(0x3C)), ++ OPC_EQV =(OPC_OP(0x10) | OPC_FUNC(0x3D)), ++ ++ OPC_AND_I =(OPC_OP(0x12) | OPC_FUNC(0x38)), ++ OPC_BIC_I =(OPC_OP(0x12) | OPC_FUNC(0x39)), ++ OPC_BIS_I =(OPC_OP(0x12) | OPC_FUNC(0x3A)), ++ OPC_ORNOT_I =(OPC_OP(0x12) | OPC_FUNC(0x3B)), ++ OPC_XOR_I =(OPC_OP(0x12) | OPC_FUNC(0x3C)), ++ OPC_EQV_I =(OPC_OP(0x12) | OPC_FUNC(0x3D)), ++ ++ OPC_SLL =(OPC_OP(0x10) | OPC_FUNC(0x48)), ++ OPC_SRL =(OPC_OP(0x10) | OPC_FUNC(0x49)), ++ OPC_SRA =(OPC_OP(0x10) | OPC_FUNC(0x4A)), ++ OPC_SLL_I =(OPC_OP(0x12) | OPC_FUNC(0x48)), ++ OPC_SRL_I =(OPC_OP(0x12) | OPC_FUNC(0x49)), ++ OPC_SRA_I =(OPC_OP(0x12) | OPC_FUNC(0x4A)), ++ ++ OPC_SELEQ =(OPC_OP(0x11) | OPC_FUNC_COMPLEX(0x00)), ++ OPC_SELGE =(OPC_OP(0x11) | OPC_FUNC_COMPLEX(0x01)), ++ OPC_SELGT =(OPC_OP(0x11) | OPC_FUNC_COMPLEX(0x02)), ++ OPC_SELLE =(OPC_OP(0x11) | OPC_FUNC_COMPLEX(0x03)), ++ OPC_SELLT =(OPC_OP(0x11) | OPC_FUNC_COMPLEX(0x04)), ++ OPC_SELNE =(OPC_OP(0x11) | OPC_FUNC_COMPLEX(0x05)), ++ OPC_SELLBC =(OPC_OP(0x11) | OPC_FUNC_COMPLEX(0x06)), ++ OPC_SELLBS =(OPC_OP(0x11) | OPC_FUNC_COMPLEX(0x07)), ++ OPC_SELEQ_I =(OPC_OP(0x13) | OPC_FUNC_COMPLEX(0x00)), ++ OPC_SELGE_I =(OPC_OP(0x13) | OPC_FUNC_COMPLEX(0x01)), ++ OPC_SELGT_I =(OPC_OP(0x13) | OPC_FUNC_COMPLEX(0x02)), ++ OPC_SELLE_I =(OPC_OP(0x13) | OPC_FUNC_COMPLEX(0x03)), ++ OPC_SELLT_I =(OPC_OP(0x13) | OPC_FUNC_COMPLEX(0x04)), ++ OPC_SELNE_I =(OPC_OP(0x13) | OPC_FUNC_COMPLEX(0x05)), ++ OPC_SELLBC_I =(OPC_OP(0x13) | OPC_FUNC_COMPLEX(0x06)), ++ OPC_SELLBS_I =(OPC_OP(0x13) | OPC_FUNC_COMPLEX(0x07)), ++ ++ OPC_INS0B =(OPC_OP(0x10) | OPC_FUNC(0x40)), ++ OPC_INS1B =(OPC_OP(0x10) | OPC_FUNC(0x41)), ++ OPC_INS2B =(OPC_OP(0x10) | OPC_FUNC(0x42)), ++ OPC_INS3B =(OPC_OP(0x10) | OPC_FUNC(0x43)), ++ OPC_INS4B =(OPC_OP(0x10) | OPC_FUNC(0x44)), ++ OPC_INS5B =(OPC_OP(0x10) | OPC_FUNC(0x45)), ++ OPC_INS6B =(OPC_OP(0x10) | OPC_FUNC(0x46)), ++ OPC_INS7B =(OPC_OP(0x10) | OPC_FUNC(0x47)), ++ OPC_INS0B_I =(OPC_OP(0x12) | OPC_FUNC(0x40)), ++ OPC_INS1B_I =(OPC_OP(0x12) | OPC_FUNC(0x41)), ++ OPC_INS2B_I =(OPC_OP(0x12) | OPC_FUNC(0x42)), ++ OPC_INS3B_I =(OPC_OP(0x12) | OPC_FUNC(0x43)), ++ OPC_INS4B_I =(OPC_OP(0x12) | OPC_FUNC(0x44)), ++ OPC_INS5B_I =(OPC_OP(0x12) | OPC_FUNC(0x45)), ++ OPC_INS6B_I =(OPC_OP(0x12) | OPC_FUNC(0x46)), ++ OPC_INS7B_I =(OPC_OP(0x12) | OPC_FUNC(0x47)), ++ ++ OPC_EXT0B =(OPC_OP(0x10) | OPC_FUNC(0x50)), ++ OPC_EXT1B =(OPC_OP(0x10) | OPC_FUNC(0x51)), ++ OPC_EXT2B =(OPC_OP(0x10) | OPC_FUNC(0x52)), ++ OPC_EXT3B =(OPC_OP(0x10) | OPC_FUNC(0x53)), ++ OPC_EXT4B =(OPC_OP(0x10) | OPC_FUNC(0x54)), ++ OPC_EXT5B =(OPC_OP(0x10) | OPC_FUNC(0x55)), ++ OPC_EXT6B =(OPC_OP(0x10) | OPC_FUNC(0x56)), ++ OPC_EXT7B =(OPC_OP(0x10) | OPC_FUNC(0x57)), ++ OPC_EXT0B_I =(OPC_OP(0x12) | OPC_FUNC(0x50)), ++ OPC_EXT1B_I =(OPC_OP(0x12) | OPC_FUNC(0x51)), ++ OPC_EXT2B_I =(OPC_OP(0x12) | OPC_FUNC(0x52)), ++ OPC_EXT3B_I =(OPC_OP(0x12) | OPC_FUNC(0x53)), ++ OPC_EXT4B_I =(OPC_OP(0x12) | OPC_FUNC(0x54)), ++ OPC_EXT5B_I =(OPC_OP(0x12) | OPC_FUNC(0x55)), ++ OPC_EXT6B_I =(OPC_OP(0x12) | OPC_FUNC(0x56)), ++ OPC_EXT7B_I =(OPC_OP(0x12) | OPC_FUNC(0x57)), ++ ++ OPC_MASK0B =(OPC_OP(0x10) | OPC_FUNC(0x60)), ++ OPC_MASK1B =(OPC_OP(0x10) | OPC_FUNC(0x61)), ++ OPC_MASK2B =(OPC_OP(0x10) | OPC_FUNC(0x62)), ++ OPC_MASK3B =(OPC_OP(0x10) | OPC_FUNC(0x63)), ++ OPC_MASK4B =(OPC_OP(0x10) | OPC_FUNC(0x64)), ++ OPC_MASK5B =(OPC_OP(0x10) | OPC_FUNC(0x65)), ++ OPC_MASK6B =(OPC_OP(0x10) | OPC_FUNC(0x66)), ++ OPC_MASK7B =(OPC_OP(0x10) | OPC_FUNC(0x67)), ++ OPC_MASK0B_I =(OPC_OP(0x12) | OPC_FUNC(0x60)), ++ OPC_MASK1B_I =(OPC_OP(0x12) | OPC_FUNC(0x61)), ++ OPC_MASK2B_I =(OPC_OP(0x12) | OPC_FUNC(0x62)), ++ OPC_MASK3B_I =(OPC_OP(0x12) | OPC_FUNC(0x63)), ++ OPC_MASK4B_I =(OPC_OP(0x12) | OPC_FUNC(0x64)), ++ OPC_MASK5B_I =(OPC_OP(0x12) | OPC_FUNC(0x65)), ++ OPC_MASK6B_I =(OPC_OP(0x12) | OPC_FUNC(0x66)), ++ OPC_MASK7B_I =(OPC_OP(0x12) | OPC_FUNC(0x67)), ++ ++ OPC_CNPGEB =(OPC_OP(0x10) | OPC_FUNC(0x6C)), ++ OPC_CNPGEB_I =(OPC_OP(0x12) | OPC_FUNC(0x6C)), ++ ++ OPC_MEMB =(OPC_OP(0x06) | OPC_FUNC(0x0)), ++ OPC_RTC =(OPC_OP(0x06) | OPC_FUNC(0x20)), ++ ++ /*float insn*/ ++ OPC_RFPCR = (OPC_OP(0x18) | OPC_FUNC(0x50)), ++ OPC_WFPCR = (OPC_OP(0x18) | OPC_FUNC(0x51)), ++ OPC_SETFPEC0 = (OPC_OP(0x18) | OPC_FUNC(0x54)), ++ OPC_SETFPEC1 = (OPC_OP(0x18) | OPC_FUNC(0x55)), ++ OPC_SETFPEC2 = (OPC_OP(0x18) | OPC_FUNC(0x56)), ++ OPC_SETFPEC3 = (OPC_OP(0x18) | OPC_FUNC(0x57)), ++ ++ ++ OPC_IFMOVS = (OPC_OP(0x18) | OPC_FUNC(0x40)), ++ OPC_IFMOVD = (OPC_OP(0x18) | OPC_FUNC(0x41)), ++ OPC_FIMOVS = (OPC_OP(0x10) | OPC_FUNC(0x70)), ++ OPC_FIMOVD = (OPC_OP(0x10) | OPC_FUNC(0x78)), ++ ++ /*translate S--D*/ ++ /*translate S/D--Long*/ ++ OPC_FCVTSD = (OPC_OP(0x18) | OPC_FUNC(0x20)), ++ OPC_FCVTDS = (OPC_OP(0x18) | OPC_FUNC(0x21)), ++ OPC_FCVTDL_G = (OPC_OP(0x18) | OPC_FUNC(0x22)), ++ OPC_FCVTDL_P = (OPC_OP(0x18) | OPC_FUNC(0x23)), ++ OPC_FCVTDL_Z = (OPC_OP(0x18) | OPC_FUNC(0x24)), ++ OPC_FCVTDL_N = (OPC_OP(0x18) | OPC_FUNC(0x25)), ++ OPC_FCVTDL = (OPC_OP(0x18) | OPC_FUNC(0x27)), ++ OPC_FCVTLS = (OPC_OP(0x18) | OPC_FUNC(0x2D)), ++ OPC_FCVTLD = (OPC_OP(0x18) | OPC_FUNC(0x2F)), ++ ++ ++ OPC_FADDS = (OPC_OP(0x18) | OPC_FUNC(0x00)), ++ OPC_FADDD = (OPC_OP(0x18) | OPC_FUNC(0x01)), ++ OPC_FSUBS = (OPC_OP(0x18) | OPC_FUNC(0x02)), ++ OPC_FSUBD = (OPC_OP(0x18) | OPC_FUNC(0x03)), ++ OPC_FMULS = (OPC_OP(0x18) | OPC_FUNC(0x04)), ++ OPC_FMULD = (OPC_OP(0x18) | OPC_FUNC(0x05)), ++ OPC_FDIVS = (OPC_OP(0x18) | OPC_FUNC(0x06)), ++ OPC_FDIVD = (OPC_OP(0x18) | OPC_FUNC(0x07)), ++ OPC_FSQRTS = (OPC_OP(0x18) | OPC_FUNC(0x08)), ++ OPC_FSQRTD = (OPC_OP(0x18) | OPC_FUNC(0x09)), ++}SW_64Insn; ++ ++static void tcg_out_insn_br(TCGContext *s, SW_64Insn insn, TCGReg rd, intptr_t imm64); ++static void tcg_out_insn_ldst(TCGContext *s, SW_64Insn insn, TCGReg rd, TCGReg rn, intptr_t imm16); ++static void tcg_out_insn_simpleReg(TCGContext *s, SW_64Insn insn, TCGReg rd, TCGReg rn, TCGReg rm); ++static void tcg_out_insn_simple(TCGContext *s, SW_64Insn insn_Imm, SW_64Insn insn_Reg, TCGReg rd, TCGReg rn, intptr_t imm64); ++static void tcg_out_insn_simpleImm(TCGContext *s, SW_64Insn insn_Imm, TCGReg rd, TCGReg rn, intptr_t imm64); ++static void tcg_out_insn_bitImm(TCGContext *s, SW_64Insn insn_Imm, TCGReg rd, TCGReg rn, unsigned long imm64); ++static void tcg_out_insn_bit(TCGContext *s, SW_64Insn insn_Imm, SW_64Insn insn_Reg, TCGReg rd, TCGReg rn, unsigned long imm64); ++static void tcg_out_insn_complexReg(TCGContext *s, SW_64Insn insn, TCGReg cond, TCGReg rd, TCGReg rn, TCGReg rm); ++static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,TCGReg a1,TCGReg a2, bool const_b, TCGReg v1, TCGReg v2); ++static bool reloc_pc21(tcg_insn_unit *src_rw, const tcg_insn_unit *target); ++static inline uint32_t tcg_in32(TCGContext *s); ++static void tcg_out_movr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn); ++static void tcg_out_ldst(TCGContext *s, SW_64Insn insn, TCGReg rd, TCGReg rn, intptr_t offset, bool sign); ++static void tcg_out_cond_cmp(TCGContext *s, TCGCond cond, TCGReg ret, TCGArg a, TCGArg b, bool const_b); ++static void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd, TCGReg rn, int64_t aimm); ++static inline void tcg_out_extr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm, unsigned int m); ++static inline void tcg_out_rotl_Reg(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm); ++static inline void tcg_out_rotr_Reg(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm); ++static inline void tcg_out_rotl_Imm(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int m); ++static inline void tcg_out_rotr_Imm(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int m); ++static void tcg_out_cltz(TCGContext *s, SW_64Insn opc_clz, TCGType ext, TCGReg rd, TCGReg rn, TCGArg b, bool const_b); ++static inline void tcg_out_bswap16u(TCGContext *s, TCGReg rd, TCGReg rn); ++static inline void tcg_out_bswap16s(TCGContext *s, TCGReg rd, TCGReg rn); ++static inline void tcg_out_bswap32u(TCGContext *s, TCGReg rd, TCGReg rn); ++static inline void tcg_out_bswap32s(TCGContext *s, TCGReg rd, TCGReg rn); ++static inline void tcg_out_bswap64(TCGContext *s, TCGReg rd, TCGReg rn); ++static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, MemOpIdx oi); ++static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, MemOpIdx oi, TCGType ext); ++static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, TCGReg arg1, TCGReg arg2); ++static void tcg_out_extract(TCGContext *s, TCGReg rd, TCGReg rn, int pos, int len); ++static void tcg_out_dep(TCGContext *s, TCGReg rd, TCGReg rn, int pos, int len); ++static void tcg_out_mulsh64(TCGContext *s, TCGReg rd, TCGReg rn, TCGReg rm); ++ ++#define tcg_out_insn_jump tcg_out_insn_ldst ++#define tcg_out_insn_bitReg tcg_out_insn_simpleReg ++ ++static void tcg_target_init(TCGContext *s) ++{ ++ tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffffu; ++ tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffffu; ++ tcg_target_available_regs[TCG_TYPE_V64] = 0xffffffff00000000ull; ++ tcg_target_available_regs[TCG_TYPE_V128] = 0xffffffff00000000ull; ++ tcg_target_call_clobber_regs = -1ull; ++ ++ //sw_64 callee saved x9-x15 ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X9); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X10); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X11); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X12); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X13); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X14); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X15); ++ ++ //sw_64 callee saved f2~f9 ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F2); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F3); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F4); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F5); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F6); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F7); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F8); ++ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F9); ++ ++ s->reserved_regs = 0; ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP); ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP); //TCG_REG_X27 ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2); //TCG_REG_X25 ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); //TCG_REG_X26 ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_X29); /*sw_64 platform register */ ++ tcg_regset_set_reg(s->reserved_regs, TCG_FLOAT_TMP); /*sw_64 platform register */ ++ tcg_regset_set_reg(s->reserved_regs, TCG_FLOAT_TMP2); /*sw_64 platform register */ ++} ++ ++ ++#ifndef CONFIG_SOFTMMU ++ #define USE_GUEST_BASE guest_base != 0 ++ #define TCG_REG_GUEST_BASE TCG_REG_X14 ++#endif ++ ++ ++#define zeroExt 0 ++#define sigExt 1 ++ ++ ++static void tcg_target_qemu_prologue(TCGContext *s) ++{ ++ TCGReg r; ++ int ofs; ++ ++ /* allocate space for all saved registers */ ++ /* subl $sp,PUSH_SIZE,$sp */ ++ tcg_out_insn_simple(s, OPC_SUBL_I, OPC_SUBL, TCG_REG_SP, TCG_REG_SP, PUSH_SIZE); ++ ++ /* Push (FP, LR) */ ++ /* stl $fp,0($sp) */ ++ tcg_out_insn_ldst(s, OPC_STL, TCG_REG_FP, TCG_REG_SP, 0); ++ /* stl $26,8($sp) */ ++ tcg_out_insn_ldst(s, OPC_STL, TCG_REG_RA, TCG_REG_SP, 8); ++ ++ ++ /* Set up frame pointer for canonical unwinding. */ ++ /* TCG_REG_FP=TCG_REG_SP */ ++ tcg_out_movr(s, TCG_TYPE_I64, TCG_REG_FP, TCG_REG_SP); ++ ++ /* Store callee-preserved regs x9..x14. */ ++ for (r = TCG_REG_X9; r <= TCG_REG_X14; r += 1){ ++ ofs = (r - TCG_REG_X9 + 2) * 8; ++ tcg_out_insn_ldst(s, OPC_STL, r, TCG_REG_SP, ofs); ++ } ++ ++ /* Make stack space for TCG locals. */ ++ /* subl $sp,FRAME_SIZE-PUSH_SIZE,$sp */ ++ tcg_out_insn_simple(s, OPC_SUBL_I, OPC_SUBL, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE - PUSH_SIZE); ++ ++ /* Inform TCG about how to find TCG locals with register, offset, size. */ ++ tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, ++ CPU_TEMP_BUF_NLONGS * sizeof(long)); ++ ++#if !defined(CONFIG_SOFTMMU) ++ if (USE_GUEST_BASE) { ++ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, guest_base); ++ tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE); ++ } ++#endif ++ ++ /* TCG_AREG0=tcg_target_call_iarg_regs[0], on sw, we mov $16 to $9 */ ++ tcg_out_mov(s, TCG_TYPE_I64, TCG_AREG0, tcg_target_call_iarg_regs[0]); ++ tcg_out_insn_jump(s, OPC_JMP, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0); ++ ++ /* ++ * Return path for goto_ptr. Set return value to 0, a-la exit_tb, ++ * and fall through to the rest of the epilogue. ++ */ ++ tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr); ++ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, 0); ++ ++ /* TB epilogue */ ++ tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr); ++ ++ /* Remove TCG locals stack space. */ ++ /* addl $sp,FRAME_SIZE-PUSH_SIZE,$sp */ ++ tcg_out_insn_simple(s, OPC_ADDL_I, OPC_ADDL, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE - PUSH_SIZE); ++ ++ /* Restore registers x9..x14. */ ++ for (r = TCG_REG_X9; r <= TCG_REG_X14; r += 1) { ++ int ofs = (r - TCG_REG_X9 + 2) * 8; ++ tcg_out_insn_ldst(s, OPC_LDL, r, TCG_REG_SP, ofs); ++ } ++ ++ ++ /* Pop (FP, LR) */ ++ /* ldl $fp,0($sp) */ ++ tcg_out_insn_ldst(s, OPC_LDL, TCG_REG_FP, TCG_REG_SP, 0); ++ /* ldl $26,8($sp) */ ++ tcg_out_insn_ldst(s, OPC_LDL, TCG_REG_RA, TCG_REG_SP, 8); ++ ++ /* restore SP to previous frame. */ ++ /* addl $sp,PUSH_SIZE,$sp */ ++ tcg_out_insn_simple(s, OPC_ADDL_I, OPC_ADDL, TCG_REG_SP, TCG_REG_SP, PUSH_SIZE); ++ ++ tcg_out_insn_jump(s, OPC_RET, TCG_REG_ZERO, TCG_REG_RA, 0); ++} ++ ++static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) ++{ ++ if (ret == arg) { ++ return true; ++ } ++ switch (type) { ++ case TCG_TYPE_I32: ++ case TCG_TYPE_I64: ++ if (ret < 32 && arg < 32) { ++ tcg_out_movr(s, type, ret, arg); ++ break; ++ } else if (ret < 32) { ++ break; ++ } else if (arg < 32) { ++ break; ++ } ++ /* FALLTHRU */ ++ default: ++ g_assert_not_reached(); ++ } ++ return true; ++} ++ ++ ++static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) ++{ ++ switch (op) { ++ case INDEX_op_goto_ptr: ++ return C_O0_I1(r); ++ ++ case INDEX_op_ld8u_i32: ++ case INDEX_op_ld8s_i32: ++ case INDEX_op_ld16u_i32: ++ case INDEX_op_ld16s_i32: ++ case INDEX_op_ld_i32: ++ case INDEX_op_ld8u_i64: ++ case INDEX_op_ld8s_i64: ++ case INDEX_op_ld16u_i64: ++ case INDEX_op_ld16s_i64: ++ case INDEX_op_ld32u_i64: ++ case INDEX_op_ld32s_i64: ++ case INDEX_op_ld_i64: ++ case INDEX_op_neg_i32: ++ case INDEX_op_neg_i64: ++ case INDEX_op_not_i32: ++ case INDEX_op_not_i64: ++ case INDEX_op_bswap16_i32: ++ case INDEX_op_bswap32_i32: ++ case INDEX_op_bswap16_i64: ++ case INDEX_op_bswap32_i64: ++ case INDEX_op_bswap64_i64: ++ case INDEX_op_ext8s_i32: ++ case INDEX_op_ext16s_i32: ++ case INDEX_op_ext8u_i32: ++ case INDEX_op_ext16u_i32: ++ case INDEX_op_ext8s_i64: ++ case INDEX_op_ext16s_i64: ++ case INDEX_op_ext32s_i64: ++ case INDEX_op_ext8u_i64: ++ case INDEX_op_ext16u_i64: ++ case INDEX_op_ext32u_i64: ++ case INDEX_op_ext_i32_i64: ++ case INDEX_op_extu_i32_i64: ++ case INDEX_op_extract_i32: ++ case INDEX_op_extract_i64: ++ case INDEX_op_sextract_i32: ++ case INDEX_op_sextract_i64: ++ return C_O1_I1(r, r); ++ ++ case INDEX_op_st8_i32: ++ case INDEX_op_st16_i32: ++ case INDEX_op_st_i32: ++ case INDEX_op_st8_i64: ++ case INDEX_op_st16_i64: ++ case INDEX_op_st32_i64: ++ case INDEX_op_st_i64: ++ return C_O0_I2(rZ, r); ++ ++ case INDEX_op_add_i32: ++ case INDEX_op_add_i64: ++ case INDEX_op_sub_i32: ++ case INDEX_op_sub_i64: ++ return C_O1_I2(r, r, rU);//rA ++ ++ case INDEX_op_setcond_i32: ++ case INDEX_op_setcond_i64: ++ return C_O1_I2(r, r, rU);//compare,rA ++ ++ case INDEX_op_mul_i32: ++ case INDEX_op_mul_i64: ++ case INDEX_op_div_i32: ++ case INDEX_op_div_i64: ++ case INDEX_op_divu_i32: ++ case INDEX_op_divu_i64: ++ case INDEX_op_rem_i32: ++ case INDEX_op_rem_i64: ++ case INDEX_op_remu_i32: ++ case INDEX_op_remu_i64: ++ case INDEX_op_muluh_i64: ++ case INDEX_op_mulsh_i64: ++ return C_O1_I2(r, r, r); ++ ++ case INDEX_op_and_i32: ++ case INDEX_op_and_i64: ++ case INDEX_op_or_i32: ++ case INDEX_op_or_i64: ++ case INDEX_op_xor_i32: ++ case INDEX_op_xor_i64: ++ case INDEX_op_andc_i32: ++ case INDEX_op_andc_i64: ++ case INDEX_op_orc_i32: ++ case INDEX_op_orc_i64: ++ case INDEX_op_eqv_i32: ++ case INDEX_op_eqv_i64: ++ return C_O1_I2(r, r, rU);//rL ++ ++ case INDEX_op_shl_i32: ++ case INDEX_op_shr_i32: ++ case INDEX_op_sar_i32: ++ case INDEX_op_rotl_i32: ++ case INDEX_op_rotr_i32: ++ case INDEX_op_shl_i64: ++ case INDEX_op_shr_i64: ++ case INDEX_op_sar_i64: ++ case INDEX_op_rotl_i64: ++ case INDEX_op_rotr_i64: ++ return C_O1_I2(r, r, ri); ++ ++ case INDEX_op_clz_i32: ++ case INDEX_op_clz_i64: ++ return C_O1_I2(r, r, r); //rAL ++ ++ case INDEX_op_ctz_i32: ++ case INDEX_op_ctz_i64: ++ return C_O1_I2(r, r, r);//rAL ++ ++ case INDEX_op_brcond_i32: ++ case INDEX_op_brcond_i64: ++ return C_O0_I2(r, rU);//rA ++ ++ case INDEX_op_movcond_i32: ++ case INDEX_op_movcond_i64: ++ return C_O1_I4(r, r, rU, rZ, rZ);//rA->rU ++ ++ case INDEX_op_qemu_ld_i32: ++ case INDEX_op_qemu_ld_i64: ++ return C_O1_I1(r, l); ++ ++ case INDEX_op_qemu_st_i32: ++ case INDEX_op_qemu_st_i64: ++ return C_O0_I2(lZ, l); ++ ++ case INDEX_op_deposit_i32: ++ case INDEX_op_deposit_i64: ++ return C_O1_I2(r, 0, rZ); ++ ++ case INDEX_op_extract2_i32: ++ case INDEX_op_extract2_i64: ++ return C_O1_I2(r, rZ, rZ); ++ ++ case INDEX_op_add2_i32: ++ case INDEX_op_add2_i64: ++ case INDEX_op_sub2_i32: ++ case INDEX_op_sub2_i64: ++ return C_O2_I4(r, r, rZ, rZ, rA, rMZ); ++ ++ case INDEX_op_add_vec: ++ case INDEX_op_sub_vec: ++ case INDEX_op_mul_vec: ++ case INDEX_op_xor_vec: ++ case INDEX_op_ssadd_vec: ++ case INDEX_op_sssub_vec: ++ case INDEX_op_usadd_vec: ++ case INDEX_op_ussub_vec: ++ case INDEX_op_smax_vec: ++ case INDEX_op_smin_vec: ++ case INDEX_op_umax_vec: ++ case INDEX_op_umin_vec: ++ case INDEX_op_shlv_vec: ++ case INDEX_op_shrv_vec: ++ case INDEX_op_sarv_vec: ++ return C_O1_I2(w, w, w); ++ case INDEX_op_not_vec: ++ case INDEX_op_neg_vec: ++ case INDEX_op_abs_vec: ++ case INDEX_op_shli_vec: ++ case INDEX_op_shri_vec: ++ case INDEX_op_sari_vec: ++ return C_O1_I1(w, w); ++ case INDEX_op_ld_vec: ++ case INDEX_op_dupm_vec: ++ return C_O1_I1(w, r); ++ case INDEX_op_st_vec: ++ return C_O0_I2(w, r); ++ case INDEX_op_dup_vec: ++ return C_O1_I1(w, wr); ++ case INDEX_op_or_vec: ++ case INDEX_op_andc_vec: ++ return C_O1_I2(w, w, wO); ++ case INDEX_op_and_vec: ++ case INDEX_op_orc_vec: ++ return C_O1_I2(w, w, wN); ++ case INDEX_op_cmp_vec: ++ return C_O1_I2(w, w, wZ); ++ case INDEX_op_bitsel_vec: ++ return C_O1_I3(w, w, w, w); ++ ++ default: ++ g_assert_not_reached(); ++ } ++} ++ ++ ++static void tcg_out_nop_fill(tcg_insn_unit *p, int count) ++{ ++ int i; ++ for (i = 0; i < count; ++i) { ++ p[i] = OPC_NOP; ++ } ++} ++ ++/* SW instruction format of syscall ++ * insn = opcode[31,26]:Function[25,0], ++ */ ++ ++/* SW instruction format of br(alias jump) ++ * insn = opcode[31,26]:Rd[25,21]:disp[20,0], ++ */ ++static void tcg_out_insn_br(TCGContext *s, SW_64Insn insn, TCGReg rd, intptr_t imm64) ++{ ++ tcg_debug_assert(imm64 <= 0xfffff && imm64 >= -0x100000); ++ tcg_out32(s, insn | (rd & 0x1f) << 21 | (imm64 & 0x1fffff)); ++} ++ ++ ++/* SW instruction format of (load and store) ++ * insn = opcode[31,26]:rd[25,21]:rn[20,16]:disp[15,0] ++ */ ++static void tcg_out_insn_ldst(TCGContext *s, SW_64Insn insn, TCGReg rd, TCGReg rn, intptr_t imm16) ++{ ++ tcg_debug_assert(imm16 <= 0x7fff && imm16 >= -0x8000); ++ tcg_out32(s, insn | (rd & 0x1f) << 21 | (rn & 0x1f) << 16 | (imm16 & 0xffff)); ++} ++ ++ ++/* SW instruction format of simple operator for Register ++ * insn = opcode[31,26]:rn(ra)[25,21]:rn(rb)[20,16]:Zeors[15,13]:function[12,5]:rd(rc)[4,0] ++ */ ++static void tcg_out_insn_simpleReg(TCGContext *s, SW_64Insn insn, TCGReg rd, TCGReg rn, TCGReg rm) ++{ ++ tcg_out32(s, insn | (rn & 0x1f) << 21 | (rm & 0x1f) << 16 | (rd & 0x1f)); ++} ++ ++/* SW instruction format of simple operator for imm ++ * insn = opcode[31,26]:rn(ra)[25,21]:disp[20,13]:function[12,5]:rd(rc)[4,0] ++ */ ++static void tcg_out_insn_simple(TCGContext *s, SW_64Insn insn_Imm, SW_64Insn insn_Reg, TCGReg rd, TCGReg rn, intptr_t imm64) ++{ ++ if(imm64 <= 0x7f && imm64 >= -0x80) { ++ tcg_out32(s, insn_Imm | (rn & 0x1f) << 21 | (imm64 & 0xff) << 13 | (rd & 0x1f)); ++ } ++ else { ++ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, imm64); ++ tcg_out_insn_simpleReg(s, insn_Reg, rd, rn, TCG_REG_TMP); ++ } ++} ++ ++ ++static void tcg_out_insn_simpleImm(TCGContext *s, SW_64Insn insn_Imm, TCGReg rd, TCGReg rn, intptr_t imm64) ++{ ++ tcg_debug_assert(imm64 <= 0x7f && imm64 >= -0x80); ++ tcg_out32(s, insn_Imm | (rn & 0x1f) << 21 | (imm64 & 0xff) << 13 | (rd & 0x1f)); ++ ++} ++ ++static void tcg_out_insn_bitImm(TCGContext *s, SW_64Insn insn_Imm, TCGReg rd, TCGReg rn, unsigned long imm64) ++{ ++ tcg_debug_assert(imm64 <= 255); ++ tcg_out32(s, insn_Imm | (rn & 0x1f) << 21 | (imm64 & 0xff) << 13 | (rd & 0x1f)); ++} ++/* sw bit operation: and bis etc */ ++static void tcg_out_insn_bit(TCGContext *s, SW_64Insn insn_Imm, SW_64Insn insn_Reg, TCGReg rd, TCGReg rn, unsigned long imm64) ++{ ++ if (imm64 <= 255) { ++ tcg_out32(s, insn_Imm | (rn & 0x1f) << 21 | (imm64 & 0xff) << 13 | (rd & 0x1f)); ++ } ++ else { ++ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, imm64); ++ tcg_out_insn_bitReg(s, insn_Reg, rd, rn, TCG_REG_TMP); ++ } ++} ++ ++/* SW instruction format of complex operator ++ * insn = opcode[31,26]:rd[25,21]:rn[20,16],function[15,10]:rm[9,5]:rx[4,0] ++ */ ++static void tcg_out_insn_complexReg(TCGContext *s, SW_64Insn insn, TCGReg cond, TCGReg rd, TCGReg rn, TCGReg rm) ++{ ++ tcg_out32(s, insn | (cond & 0x1f) << 21 | (rn & 0x1f) << 16 | (rm & 0x1f) << 5 | (rd & 0x1f)); ++} ++ ++static bool reloc_pc21(tcg_insn_unit *src_rw, const tcg_insn_unit *target) ++{ ++ const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); ++ ptrdiff_t offset = target - (src_rx + 1) ; ++ ++ if (offset == sextract64(offset, 0, 21)) { ++ /* read instruction, mask away previous PC_REL21 parameter contents, ++ set the proper offset, then write back the instruction. */ ++ *src_rw = deposit32(*src_rw, 0, 21, offset); ++ return true; ++ } ++ return false; ++} ++ ++/* sw*/ ++static bool patch_reloc(tcg_insn_unit *code_ptr, int type, intptr_t value, intptr_t addend) ++{ ++ tcg_debug_assert(addend == 0); ++ switch (type) { ++ case R_SW_64_BRADDR: ++ return reloc_pc21(code_ptr, (const tcg_insn_unit *)value); ++ default: ++ g_assert_not_reached(); ++ } ++} ++ ++static inline uint32_t tcg_in32(TCGContext *s) ++{ ++ uint32_t v = *(uint32_t *)s->code_ptr; ++ return v; ++} ++ ++/*SW Register to register move using ADDL*/ ++static void tcg_out_movr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn) ++{ ++ tcg_out_insn_simpleReg(s, OPC_BIS, rd, rn, TCG_REG_ZERO); ++ if (ext == TCG_TYPE_I32){ ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf); ++ } ++} ++ ++/*sw ++ *put imm into rd ++ */ ++static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, tcg_target_long orig) ++{ ++ long l0, l1, l2=0, l3=0, extra=0; ++ tcg_target_long val = orig; ++ TCGReg rs = TCG_REG_ZERO; ++ ++ if (type == TCG_TYPE_I32) ++ val = (int32_t)val; ++ ++ l0 = (int16_t)val; ++ val = (val - l0) >> 16; ++ l1 = (int16_t)val; ++ ++ if (orig >> 31 == -1 || orig >> 31 == 0) { ++ if (l1 < 0 && orig >= 0) { ++ extra = 0x4000; ++ l1 = (int16_t)(val - 0x4000); ++ } ++ } else { ++ val = (val - l1) >> 16; ++ l2 = (int16_t)val; ++ val = (val - l2) >> 16; ++ l3 = (int16_t)val; ++ ++ if (l3) { ++ tcg_out_insn_ldst(s, OPC_LDIH, rd, rs, l3); ++ rs = rd; ++ } ++ if (l2) { ++ tcg_out_insn_ldst(s, OPC_LDI, rd, rs, l2); ++ rs = rd; ++ } ++ if (l3 || l2) ++ tcg_out_insn_simpleImm(s, OPC_SLL_I, rd, rd, 32); ++ } ++ ++ if (l1) { ++ tcg_out_insn_ldst(s, OPC_LDIH, rd, rs, l1); ++ rs = rd; ++ } ++ ++ if (extra) { ++ tcg_out_insn_ldst(s, OPC_LDIH, rd, rs, extra); ++ rs = rd; ++ } ++ ++ tcg_out_insn_ldst(s, OPC_LDI, rd, rs, l0); ++} ++ ++ ++/*sw ++* memory <=> Reg in (B H W L) bytes ++*/ ++static void tcg_out_ldst(TCGContext *s, SW_64Insn insn, TCGReg rd, TCGReg rn, intptr_t offset, bool sign) ++{ ++ int16_t lo = offset; ++ if (offset != lo) { ++ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, offset - lo); ++ if (rn != TCG_REG_ZERO) { ++ tcg_out_insn_simpleReg(s, OPC_ADDL, TCG_REG_TMP, TCG_REG_TMP, rn); ++ } ++ tcg_out_insn_ldst(s, insn, rd, TCG_REG_TMP, lo); ++ } ++ else { ++ tcg_out_insn_ldst(s, insn, rd, rn, lo); ++ } ++ ++ switch (insn) { ++ case OPC_LDBU: ++ if (sign) ++ tcg_out_insn_simpleReg(s, OPC_SEXTB, rd, TCG_REG_ZERO, rd); //for micro-op:INDEX_op_ld8s_i32/64,set rd[63,8]=1 ++ break; ++ case OPC_LDHU: ++ if (sign) ++ tcg_out_insn_simpleReg(s, OPC_SEXTH, rd, TCG_REG_ZERO, rd); //for micro-op:INDEX_op_ld16s_i32/64,set rd[63,16]=1 ++ break; ++ case OPC_LDW: ++ if (!sign) ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf); //for micro-op:INDEX_op_ld32u_i32/64,set rd[63,32]=0 ++ break; ++ default: ++ break; ++ } ++} ++ ++/* TCG_REG_TMP stores result_of_condition_compare */ ++static void tcg_out_cond_cmp(TCGContext *s, TCGCond cond, TCGReg ret, TCGArg a, TCGArg b, bool const_b) ++{ ++ if (const_b) { ++ switch(cond) { ++ case TCG_COND_ALWAYS: ++ case TCG_COND_NEVER: ++ break; ++ case TCG_COND_EQ: ++ case TCG_COND_NE: ++ tcg_out_insn_simple(s, OPC_CMPEQ_I, OPC_CMPEQ, ret, a, b); ++ break; ++ case TCG_COND_LT: ++ case TCG_COND_GE: ++ tcg_out_insn_simple(s, OPC_CMPLT_I, OPC_CMPLT, ret, a, b); ++ break; ++ case TCG_COND_LE: ++ case TCG_COND_GT: ++ tcg_out_insn_simple(s, OPC_CMPLE_I, OPC_CMPLE, ret, a, b); ++ break; ++ case TCG_COND_LTU: ++ case TCG_COND_GEU: ++ tcg_out_insn_simple(s, OPC_CMPULT_I, OPC_CMPULT, ret, a, b); ++ break; ++ case TCG_COND_LEU: ++ case TCG_COND_GTU: ++ tcg_out_insn_simple(s, OPC_CMPULE_I, OPC_CMPULE, ret, a, b); ++ break; ++ }//cond ++ }//if (const_b) ++ else { ++ switch(cond) { ++ case TCG_COND_ALWAYS: ++ case TCG_COND_NEVER: ++ break; ++ case TCG_COND_EQ: ++ case TCG_COND_NE: ++ tcg_out_insn_simpleReg(s, OPC_CMPEQ, ret, a, b); ++ break; ++ case TCG_COND_LT: ++ case TCG_COND_GE: ++ tcg_out_insn_simpleReg(s, OPC_CMPLT, ret, a, b); ++ break; ++ case TCG_COND_LE: ++ case TCG_COND_GT: ++ tcg_out_insn_simpleReg(s, OPC_CMPLE, ret, a, b); ++ break; ++ case TCG_COND_LTU: ++ case TCG_COND_GEU: ++ tcg_out_insn_simpleReg(s, OPC_CMPULT, ret, a, b); ++ break; ++ case TCG_COND_LEU: ++ case TCG_COND_GTU: ++ tcg_out_insn_simpleReg(s, OPC_CMPULE, ret, a, b); ++ break; ++ }//cond ++ }//else ++ switch(cond) { ++ case TCG_COND_ALWAYS: ++ case TCG_COND_NEVER: ++ case TCG_COND_EQ: ++ case TCG_COND_LT: ++ case TCG_COND_LE: ++ case TCG_COND_LTU: ++ case TCG_COND_LEU: ++ break; ++ case TCG_COND_NE: ++ case TCG_COND_GE: ++ case TCG_COND_GT: ++ case TCG_COND_GEU: ++ case TCG_COND_GTU: ++ tcg_out_insn_bitImm(s, OPC_XOR_I, ret, ret, 0x1); ++ break; ++ } ++} ++ ++/* sw ++ * step1 tcg_out_cmp() ,"eq" and "ne" in the same case with the same insn; ++ * store compare result by TCG_REG_TMP, for step2; ++ * step2: jump address with compare result. in last "switch" section, we diff qe/ne by different case with different insn. ++ */ ++static void tcg_out_brcond(TCGContext *s, TCGType ext, TCGCond cond, TCGArg a, TCGArg b, bool b_const, TCGLabel *l) ++{ ++ intptr_t offset; ++ bool need_cmp; ++ ++ if (b_const && b == 0 && (cond == TCG_COND_EQ || cond == TCG_COND_NE)) { ++ need_cmp = false; ++ } else { ++ need_cmp = true; ++ tcg_out_cond_cmp(s, cond, TCG_REG_TMP, a, b, b_const); ++ } ++ ++ if (!l->has_value) { ++ tcg_out_reloc(s, s->code_ptr, R_SW_64_BRADDR, l, 0); ++ offset=0; //offset = tcg_in32(s) >> 5; br $31, 0, do not jump here! ++ } else { ++ offset = tcg_pcrel_diff(s, l->u.value_ptr) ; ++ offset = offset >> 2; ++ tcg_debug_assert(offset == sextract64(offset, 0, 21)); ++ } ++ ++ if (need_cmp) { ++ tcg_out_insn_br(s, OPC_BGT, TCG_REG_TMP, offset); //a cond b,jmp ++ } else if (cond == TCG_COND_EQ) { ++ tcg_out_insn_br(s, OPC_BEQ, a, offset); ++ } else { ++ tcg_out_insn_br(s, OPC_BNE, a, offset); ++ } ++} ++ ++/*sw ++ * contact with "tcg-target-con-str.h" ++ */ ++#define TCG_CT_CONST_ZERO 0x100 ++#define TCG_CT_CONST_LONG 0x200 ++#define TCG_CT_CONST_MONE 0x400 ++#define TCG_CT_CONST_ORRI 0x800 ++#define TCG_CT_CONST_WORD 0X1000 ++#define TCG_CT_CONST_U8 0x2000 ++#define TCG_CT_CONST_S8 0X4000 ++ ++#define ALL_GENERAL_REGS 0xffffffffu ++#define ALL_VECTOR_REGS 0xffffffff00000000ull ++ ++ ++#ifdef CONFIG_SOFTMMU ++/*sw #define ALL_QLDST_REGS */ ++#else ++ #define ALL_QLDST_REGS ALL_GENERAL_REGS ++#endif ++ ++/* sw test if a constant matches the constraint */ ++static bool tcg_target_const_match(int64_t val, TCGType type, int ct) ++{ ++ if (ct & TCG_CT_CONST) { ++ return 1; ++ } ++ if (type == TCG_TYPE_I32) { ++ val = (int32_t)val; ++ } ++ if ((ct & TCG_CT_CONST_U8) && 0 <= val && val <= 255) { ++ return 1; ++ } ++ if ((ct & TCG_CT_CONST_LONG)) { ++ return 1; ++ } ++ if ((ct & TCG_CT_CONST_MONE)) { ++ return 1; ++ } ++ if ((ct & TCG_CT_CONST_ORRI)) { ++ return 1; ++ } ++ if ((ct & TCG_CT_CONST_WORD)) { ++ return 1; ++ } ++ if ((ct & TCG_CT_CONST_ZERO) && val == 0) { ++ return 1; ++ } ++ return 0; ++} ++ ++static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg rd, TCGReg rn, intptr_t ofs) ++{ ++ switch (type) { ++ case TCG_TYPE_I32: ++ tcg_out_ldst(s, OPC_LDW, rd, rn, ofs, sigExt); ++ break; ++ case TCG_TYPE_I64: ++ tcg_out_ldst(s, OPC_LDL, rd, rn, ofs, sigExt); ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++} ++ ++static void tcg_out_st(TCGContext *s, TCGType type, TCGReg rd, TCGReg rn, intptr_t ofs) ++{ ++ switch (type) { ++ case TCG_TYPE_I32: ++ tcg_out_insn_ldst(s, OPC_STW, rd, rn, ofs); ++ break; ++ case TCG_TYPE_I64: ++ tcg_out_insn_ldst(s, OPC_STL, rd, rn, ofs); ++ break; ++ default: ++ g_assert_not_reached(); ++ } ++} ++ ++static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, TCGReg base, intptr_t ofs) ++{ ++ if (type <= TCG_TYPE_I64 && val == 0) { ++ tcg_out_st(s, type, TCG_REG_ZERO, base, ofs); ++ return true; ++ } ++ return false; ++} ++ ++static void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd, TCGReg rn, int64_t imm64) ++{ ++ if (imm64 >= 0) { ++ if(0 <=imm64 && imm64 <= 255) { ++ /* we use tcg_out_insn_bitImm because imm64 is between 0~255 */ ++ tcg_out_insn_bitImm(s, OPC_ADDL_I, rd, rn, imm64); ++ }//aimm>0 && aimm == sextract64(aim, 0, 8) ++ else { ++ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, imm64); ++ tcg_out_insn_simpleReg(s, OPC_ADDL, rd, rn, TCG_REG_TMP); ++ }//aimm>0 && aimm != sextract64(aim, 0, 8) ++ } else { ++ if(0 < -imm64 && -imm64 <= 255) { ++ /* we use tcg_out_insn_bitImm because -imm64 is between 0~255 */ ++ tcg_out_insn_bitImm(s, OPC_SUBL_I, rd, rn, -imm64); ++ }//aimm<0 && aimm == sextract64(aim, 0, 8) ++ else { ++ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, -imm64); ++ tcg_out_insn_simpleReg(s, OPC_SUBL, rd, rn, TCG_REG_TMP); ++ }//aimm<0 && aimm != sextract64(aim, 0, 8) ++ } ++} ++ ++static void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target) ++{ ++ ptrdiff_t offset = tcg_pcrel_diff(s, target) >> 2; ++ tcg_debug_assert(offset == sextract64(offset, 0, 21)); ++ tcg_out_insn_br(s, OPC_BR, TCG_REG_ZERO, offset); ++} ++ ++static void tcg_out_goto_long(TCGContext *s, const tcg_insn_unit *target) ++{ ++ ptrdiff_t offset = tcg_pcrel_diff(s, target) >> 2; ++ if (0 <= offset && offset <= 0x1fffff) { ++ tcg_out_insn_br(s, OPC_BR, TCG_REG_ZERO, offset); ++ } else { ++ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, (intptr_t)target); ++ tcg_out_insn_jump(s, OPC_JMP, TCG_REG_ZERO, TCG_REG_TMP, 0); ++ } ++} ++ ++ ++/*sw ++* call subroutine ++*/ ++static void tcg_out_call(TCGContext *s, const tcg_insn_unit *target) ++{ ++ ptrdiff_t offset = tcg_pcrel_diff(s, target) >> 2; ++ if (offset == sextract64(offset, 0, 21)) { ++ tcg_out_insn_br(s, OPC_BSR, TCG_REG_RA, offset); ++ } else { ++ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, (intptr_t)target); ++ tcg_out_insn_jump(s, OPC_CALL, TCG_REG_RA, TCG_REG_TMP, 0); ++ } ++} ++ ++void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx, uintptr_t jmp_rw, uintptr_t addr) ++{ ++ tcg_debug_assert(0); ++ //sw not support ++} ++ ++static inline void tcg_out_goto_label(TCGContext *s, TCGLabel *l) ++{ ++ if (!l->has_value) { ++ tcg_out_reloc(s, s->code_ptr, R_SW_64_BRADDR, l, 0); ++ tcg_out_insn_br(s, OPC_BR, TCG_REG_ZERO, 0); ++ } else { ++ tcg_out_goto(s, l->u.value_ptr); ++ } ++} ++ ++/* sw ++ * resut: rd=rn(64,64-m]:rm(64-m,0] ++ * 1: rn(m,0]--->TCG_REG_TMP(64,64-m] ++ * 2: rm(64,64-m]--->rm(64-m,0] ++ * 3: rd=TCG_REG_TMP(64,64-m]:rm(64-m,0] ++ */ ++static inline void tcg_out_extr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm, unsigned int m) ++{ ++ int bits = ext ? 64 : 32; ++ int max = bits - 1; ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_REG_TMP, rn, bits - (m & max)); ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP2, rm, (m & max)); ++ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2); ++} ++ ++/* sw ++ * loop right shift ++ */ ++static inline void tcg_out_rotr_Imm(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int m) ++{ ++ int bits = ext ? 64 : 32; ++ int max = bits - 1; ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_REG_TMP, rn, bits - (m & max)); ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP2, rn, (m & max)); ++ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2); ++} ++ ++/* sw loop right shift ++ */ ++static inline void tcg_out_rotr_Reg(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm) ++{ ++ int bits = ext ? 64 : 32; ++ //get TCG_REG_TMP=64-[rm] ++ tcg_out_insn_simpleImm(s, OPC_SUBL_I, TCG_REG_TMP, rm, bits); ++ tcg_out_insn_bitReg(s, OPC_ORNOT, TCG_REG_TMP, TCG_REG_ZERO, TCG_REG_TMP); ++ ++ tcg_out_insn_bitReg(s, OPC_SLL, TCG_REG_TMP2, rn, TCG_REG_TMP); //get rn right part to TCG_REG_TMP ++ tcg_out_insn_bitReg(s, OPC_SRL, TCG_REG_TMP, rn, rm); //get rn left part to TCG_REG_TMP ++ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2); ++} ++ ++/* sw ++ * loop left shift ++ */ ++static inline void tcg_out_rotl_Imm(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int m) ++{ ++ int bits = ext ? 64 : 32; ++ int max = bits - 1; ++ ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP, rn, bits -(m & max)); ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_REG_TMP2, rn, (m & max)); //get rn left part to TCG_REG_TMP ++ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2); //get rn right part to left ++} ++ ++ ++/* sw loop left shift ++ */ ++static inline void tcg_out_rotl_Reg(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm) ++{ ++ int bits = ext ? 64 : 32; ++ tcg_out_insn_simpleImm(s, OPC_SUBL_I, TCG_REG_TMP, rm, bits); //rm = 64-rm ++ tcg_out_insn_bitReg(s, OPC_ORNOT, TCG_REG_TMP, TCG_REG_ZERO, TCG_REG_TMP); ++ ++ tcg_out_insn_bitReg(s, OPC_SRL, TCG_REG_TMP2, rn, TCG_REG_TMP); //get rn left part to TCG_REG_TMP ++ tcg_out_insn_bitReg(s, OPC_SLL, TCG_REG_TMP, rn, rm); //get rn right part to left ++ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2); ++} ++ ++ ++ ++static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg args[TCG_MAX_OP_ARGS], const int const_args[TCG_MAX_OP_ARGS]) ++{ ++ /* 99% of the time, we can signal the use of extension registers ++ by looking to see if the opcode handles 64-bit data. */ ++ TCGType ext = (tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0; ++ /* Hoist the loads of the most common arguments. */ ++ TCGArg a0 = args[0]; ++ TCGArg a1 = args[1]; ++ TCGArg a2 = args[2]; ++ int c2 = const_args[2]; ++ ++ /* Some operands are defined with "rZ" constraint, a register or ++ the zero register. These need not actually test args[I] == 0. */ ++ #define REG0(I) (const_args[I] ? TCG_REG_ZERO : (TCGReg)args[I]) ++ ++ switch (opc) { ++ case INDEX_op_exit_tb: ++ /* Reuse the zeroing that exists for goto_ptr. */ ++ if (a0 == 0) { ++ tcg_out_goto_long(s, tcg_code_gen_epilogue); ++ } else { ++ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0); ++ tcg_out_goto_long(s, tb_ret_addr); ++ } ++ break; ++ ++ case INDEX_op_goto_tb: ++ if (s->tb_jmp_insn_offset != NULL) { ++ /* TCG_TARGET_HAS_direct_jump */ ++ tcg_debug_assert(0); ++ /* not support here */ ++ } else { ++ /* !TCG_TARGET_HAS_direct_jump */ ++ tcg_debug_assert(s->tb_jmp_target_addr != NULL); ++ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP, TCG_REG_ZERO, (uintptr_t)(s->tb_jmp_target_addr + a0)); ++ } ++ tcg_out_insn_jump(s, OPC_JMP, TCG_REG_ZERO, TCG_REG_TMP, 0); ++ set_jmp_reset_offset(s, a0); ++ break; ++ ++ case INDEX_op_goto_ptr: ++ tcg_out_insn_jump(s, OPC_JMP, TCG_REG_ZERO, a0, 0); ++ break; ++ ++ case INDEX_op_br: ++ tcg_out_goto_label(s, arg_label(a0)); ++ break; ++ ++ case INDEX_op_ld8u_i32: ++ case INDEX_op_ld8u_i64: ++ tcg_out_ldst(s, OPC_LDBU, a0, a1, a2, 0); ++ break; ++ case INDEX_op_ld8s_i32: ++ case INDEX_op_ld8s_i64: ++ tcg_out_ldst(s, OPC_LDBU, a0, a1, a2, 1); ++ break; ++ case INDEX_op_ld16u_i32: ++ case INDEX_op_ld16u_i64: ++ tcg_out_ldst(s, OPC_LDHU, a0, a1, a2, 0); ++ break; ++ case INDEX_op_ld16s_i32: ++ case INDEX_op_ld16s_i64: ++ tcg_out_ldst(s, OPC_LDHU, a0, a1, a2, 1); ++ break; ++ case INDEX_op_ld_i32: ++ tcg_out_ldst(s, OPC_LDW, a0, a1, a2, 1); ++ break; ++ case INDEX_op_ld32u_i64: ++ tcg_out_ldst(s, OPC_LDW, a0, a1, a2, 0); ++ break; ++ case INDEX_op_ld32s_i64: ++ tcg_out_ldst(s, OPC_LDW, a0, a1, a2, 1); ++ break; ++ case INDEX_op_ld_i64: ++ tcg_out_ldst(s, OPC_LDL, a0, a1, a2, 1); ++ break; ++ case INDEX_op_st8_i32: ++ case INDEX_op_st8_i64: ++ tcg_out_ldst(s, OPC_STB, a0, a1, a2, 0); ++ break; ++ case INDEX_op_st16_i32: ++ case INDEX_op_st16_i64: ++ tcg_out_ldst(s, OPC_STH, a0, a1, a2, 0); ++ break; ++ case INDEX_op_st_i32: ++ case INDEX_op_st32_i64: ++ tcg_out_ldst(s, OPC_STW, a0, a1, a2, 0); ++ break; ++ case INDEX_op_st_i64: ++ tcg_out_ldst(s, OPC_STL, a0, a1, a2, 0); ++ break; ++ ++ case INDEX_op_add_i32: ++ a2 = (int32_t)a2; ++ if (c2) { ++ tcg_out_addsubi(s, ext, a0, a1, a2); ++ } else { ++ tcg_out_insn_simpleReg(s, OPC_ADDL, a0, a1, a2); ++ } ++ break; ++ case INDEX_op_add_i64: ++ if (c2) { ++ tcg_out_addsubi(s, ext, a0, a1, a2); ++ } else { ++ tcg_out_insn_simpleReg(s, OPC_ADDL, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_sub_i32: ++ a2 = (int32_t)a2; ++ if (c2) { ++ tcg_out_addsubi(s, ext, a0, a1, -a2); ++ } else { ++ tcg_out_insn_simpleReg(s, OPC_SUBL, a0, a1, a2); ++ } ++ break; ++ case INDEX_op_sub_i64: ++ if (c2) { ++ tcg_out_addsubi(s, ext, a0, a1, -a2); ++ } else { ++ tcg_out_insn_simpleReg(s, OPC_SUBL, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_neg_i64: ++ case INDEX_op_neg_i32: ++ tcg_out_insn_bitReg(s, OPC_SUBL, a0, TCG_REG_ZERO, a1); ++ break; ++ ++ case INDEX_op_and_i32: ++ a2 = (int32_t)a2; ++ if (c2) { ++ tcg_out_insn_bit(s, OPC_AND_I, OPC_AND, a0, a1, a2); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_AND, a0, a1, a2); ++ } ++ break; ++ case INDEX_op_and_i64: ++ if (c2) { ++ tcg_out_insn_bit(s, OPC_AND_I, OPC_AND, a0, a1, a2); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_AND, a0, a1, a2); ++ } ++ break; ++ case INDEX_op_andc_i32: ++ a2 = (int32_t)a2; ++ tcg_debug_assert(0); ++ if (c2) { ++ tcg_out_insn_bit(s, OPC_AND_I, OPC_AND, a0, a1, ~a2); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_BIC, a0, a1, a2); ++ } ++ break; ++ case INDEX_op_andc_i64: ++ tcg_debug_assert(0); ++ if (c2) { ++ tcg_out_insn_bit(s, OPC_AND_I, OPC_AND, a0, a1, ~a2); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_BIC, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_or_i32: ++ a2 = (int32_t)a2; ++ if (c2) { ++ tcg_out_insn_bit(s, OPC_BIS_I, OPC_BIS, a0, a1, a2); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_BIS, a0, a1, a2); ++ } ++ break; ++ case INDEX_op_or_i64: ++ if (c2) { ++ tcg_out_insn_bit(s, OPC_BIS_I, OPC_BIS, a0, a1, a2); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_BIS, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_orc_i32: ++ a2 = (int32_t)a2; ++ tcg_debug_assert(0); ++ if (c2) { ++ tcg_out_insn_bit(s, OPC_BIS_I, OPC_BIS, a0, a1, ~a2); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_ORNOT, a0, a1, a2); ++ } ++ break; ++ case INDEX_op_orc_i64: ++ tcg_debug_assert(0); ++ if (c2) { ++ tcg_out_insn_bit(s, OPC_BIS_I, OPC_BIS, a0, a1, ~a2); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_ORNOT, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_xor_i32: ++ a2 = (int32_t)a2; ++ if (c2) { ++ tcg_out_insn_bit(s, OPC_XOR_I, OPC_XOR, a0, a1, a2); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_XOR, a0, a1, a2); ++ } ++ break; ++ case INDEX_op_xor_i64: ++ if (c2) { ++ tcg_out_insn_bit(s, OPC_XOR_I, OPC_XOR, a0, a1, a2); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_XOR, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_eqv_i32: ++ a2 = (int32_t)a2; ++ tcg_debug_assert(0); ++ if (c2) { ++ tcg_out_insn_bit(s, OPC_XOR_I, OPC_XOR, a0, a1, ~a2); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_EQV, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_eqv_i64: ++ tcg_debug_assert(0); ++ if (c2) { ++ tcg_out_insn_bit(s, OPC_XOR_I, OPC_XOR, a0, a1, ~a2); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_EQV, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_not_i64: ++ case INDEX_op_not_i32: ++ tcg_out_insn_bitReg(s, OPC_ORNOT, a0, TCG_REG_ZERO, a1); ++ break; ++ ++ case INDEX_op_mul_i64: ++ case INDEX_op_mul_i32: ++ tcg_out_insn_simpleReg(s, OPC_MULL, a0, a1, a2); ++ break; ++ ++ case INDEX_op_div_i64: /* a0=a1/a2 singed divide*/ ++ case INDEX_op_div_i32: ++ tcg_debug_assert(0); ++ break; ++ case INDEX_op_divu_i64: /* a0=a1/a2 unsigned divide */ ++ case INDEX_op_divu_i32: ++ tcg_debug_assert(0); ++ break; ++ ++ case INDEX_op_rem_i64: /* if a1=17,a2=4, 17/4=4...1, a0=1 */ ++ case INDEX_op_rem_i32: ++ tcg_debug_assert(0); ++ break; ++ case INDEX_op_remu_i64: ++ case INDEX_op_remu_i32: ++ tcg_debug_assert(0); ++ break; ++ ++ case INDEX_op_shl_i64: ++ case INDEX_op_shl_i32: /* sw logical left*/ ++ if (c2) { ++ int bits = ext ? 64 : 32; ++ int max = bits - 1; ++ tcg_out_insn_bitImm(s, OPC_SLL_I, a0, a1, a2&max); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_SLL, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_shr_i64: ++ case INDEX_op_shr_i32: /* sw logical right */ ++ if (c2) { ++ int bits = ext ? 64 : 32; ++ int max = bits - 1; ++ tcg_out_insn_bitImm(s, OPC_SRL_I, a0, a1, a2&max); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_SRL, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_sar_i64: ++ case INDEX_op_sar_i32: /* sw arithmetic right*/ ++ if (c2) { ++ int bits = ext ? 64 : 32; ++ int max = bits - 1; ++ tcg_out_insn_bitImm(s, OPC_SRA_I, a0, a1, a2&max); ++ } else { ++ tcg_out_insn_bitReg(s, OPC_SRA, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_rotr_i64: ++ case INDEX_op_rotr_i32: /* loop shift */ ++ if (c2) {/* loop right shift a2*/ ++ tcg_out_rotr_Imm(s, ext, a0, a1, a2); ++ } else { ++ tcg_out_rotr_Reg(s, ext, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_rotl_i64: ++ case INDEX_op_rotl_i32: /* loop shift */ ++ if (c2) {/* loop left shift a2*/ ++ tcg_out_rotl_Imm(s, ext, a0, a1, a2); ++ } else { ++ tcg_out_rotl_Reg(s, ext, a0, a1, a2); ++ } ++ break; ++ ++ case INDEX_op_clz_i64: /* counting leading zero numbers */ ++ case INDEX_op_clz_i32: ++ tcg_out_cltz(s, OPC_CTLZ, ext, a0, a1, a2, c2); ++ break; ++ case INDEX_op_ctz_i64: /* counting tailing zero numbers */ ++ case INDEX_op_ctz_i32: ++ tcg_out_cltz(s, OPC_CTTZ, ext, a0, a1, a2, c2); ++ break; ++ ++ case INDEX_op_brcond_i32: ++ a1 = (int32_t)a1; ++ tcg_out_brcond(s, ext, a2, a0, a1, const_args[1], arg_label(args[3])); ++ break; ++ ++ case INDEX_op_brcond_i64: ++ tcg_out_brcond(s, ext, a2, a0, a1, const_args[1], arg_label(args[3])); ++ break; ++ ++ case INDEX_op_setcond_i32: ++ a2 = (int32_t)a2; ++ tcg_out_setcond(s, args[3], a0, a1, a2); ++ break; ++ ++ case INDEX_op_setcond_i64: ++ tcg_out_setcond(s, args[3], a0, a1, a2); ++ break; ++ ++ case INDEX_op_movcond_i32: ++ a2 = (int32_t)a2; ++ tcg_out_movcond(s, args[5], a0, a1, a2, c2, REG0(3), REG0(4)); ++ break; ++ ++ /* FALLTHRU */ ++ case INDEX_op_movcond_i64: ++ tcg_out_movcond(s, args[5], a0, a1, a2, c2, REG0(3), REG0(4)); ++ break; ++ ++ case INDEX_op_qemu_ld_i32: ++ case INDEX_op_qemu_ld_i64: ++ tcg_out_qemu_ld(s, a0, a1, a2, ext); ++ break; ++ case INDEX_op_qemu_st_i32: ++ case INDEX_op_qemu_st_i64: ++ tcg_out_qemu_st(s, REG0(0), a1, a2); ++ break; ++ ++ case INDEX_op_bswap64_i64: /* 0x123456789abcdef--->0xefcdab8967452301 */ ++ tcg_debug_assert(0); ++ tcg_out_bswap64(s, a0, a1); ++ break; ++ case INDEX_op_bswap32_i64: /* 0x123456789abcdef--->0x67452301efcdab89 */ ++ tcg_debug_assert(0); ++ tcg_out_bswap32u(s, a0, a1); ++ break; ++ case INDEX_op_bswap32_i32: ++ tcg_debug_assert(0); ++ break; ++ case INDEX_op_bswap16_i64: /* 0x123456789abcdef--->0x23016745ab89efcd */ ++ case INDEX_op_bswap16_i32: ++ tcg_debug_assert(0); ++ break; ++ ++ case INDEX_op_ext8s_i64: ++ case INDEX_op_ext8s_i32: ++ tcg_out_insn_simpleReg(s, OPC_SEXTB, a0, TCG_REG_ZERO, a1); ++ break; ++ case INDEX_op_ext16s_i64: ++ case INDEX_op_ext16s_i32: ++ tcg_out_insn_simpleReg(s, OPC_SEXTH, a0, TCG_REG_ZERO, a1); ++ break; ++ case INDEX_op_ext_i32_i64: ++ case INDEX_op_ext32s_i64: ++ tcg_out_insn_simpleReg(s, OPC_ADDW, a0, TCG_REG_ZERO, a1); ++ break; ++ case INDEX_op_ext8u_i64: ++ case INDEX_op_ext8u_i32: ++ tcg_out_insn_simpleImm(s, OPC_EXT0B_I, a0, a1, 0x0); ++ break; ++ case INDEX_op_ext16u_i64: ++ case INDEX_op_ext16u_i32: ++ tcg_out_insn_simpleImm(s, OPC_EXT1B_I, a0, a1, 0x0); ++ break; ++ case INDEX_op_extu_i32_i64: ++ case INDEX_op_ext32u_i64: ++ tcg_out_movr(s, TCG_TYPE_I32, a0, a1); ++ break; ++ ++ case INDEX_op_deposit_i64: ++ case INDEX_op_deposit_i32: ++ tcg_out_dep(s, a0, a2, args[3], args[4]); ++ break; ++ ++ case INDEX_op_extract_i64: ++ case INDEX_op_extract_i32: ++ tcg_out_extract(s, a0, a1, a2, args[3]); ++ break; ++ ++ case INDEX_op_sextract_i64: ++ case INDEX_op_sextract_i32: ++ tcg_debug_assert(0); ++ break; ++ ++ case INDEX_op_extract2_i64: ++ case INDEX_op_extract2_i32: /* extract REG0(2) right args[3] bit to REG0(1) left ,save to a0*/ ++ tcg_debug_assert(0); ++ break; ++ ++ case INDEX_op_add2_i32: ++ tcg_debug_assert(0); ++ break; ++ case INDEX_op_add2_i64: ++ tcg_debug_assert(0); ++ break; ++ case INDEX_op_sub2_i32: ++ tcg_debug_assert(0); ++ break; ++ case INDEX_op_sub2_i64: ++ tcg_debug_assert(0); ++ break; ++ ++ case INDEX_op_muluh_i64: ++ tcg_out_insn_simpleReg(s, OPC_UMULH, a0, a1, a2); ++ break; ++ case INDEX_op_mulsh_i64: /* sw not support */ ++ tcg_out_mulsh64(s, a0, a1, a2); ++ break; ++ ++ case INDEX_op_mb: ++ break; ++ ++ case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ ++ case INDEX_op_mov_i64: ++ case INDEX_op_call: /* Always emitted via tcg_out_call. */ ++ default: ++ g_assert_not_reached(); ++ } ++ ++#undef REG0 ++} ++ ++ ++ ++/*sw ++* counting heading/tailing zero numbers ++*/ ++static void tcg_out_cltz(TCGContext *s, SW_64Insn opc_clz, TCGType ext, TCGReg rd, ++ TCGReg rn, TCGArg b, bool const_b) ++{ ++ /* cond1. b is a const, and b=64 or b=32 */ ++ if (const_b && b == (ext ? 64 : 32)) { ++ /* count rn zero numbers, and writes to rd */ ++ tcg_out_insn_simpleReg(s, opc_clz, rd, TCG_REG_ZERO, rn); ++ }else { ++ /* TCG_REG_TMP= counting rn heading/tailing zero numbers */ ++ tcg_out_insn_simpleReg(s, opc_clz, TCG_REG_TMP, TCG_REG_ZERO, rn); ++ ++ if (const_b) { ++ if (b == -1) { ++ /* cond2. b is const and b=-1 */ ++ /* if rn != 0 , rd= counting rn heading/tailing zero numbers, else rd = 0xffffffffffffffff*/ ++ tcg_out_insn_bitReg(s, OPC_ORNOT, TCG_REG_TMP2, TCG_REG_ZERO, TCG_REG_ZERO); ++ tcg_out_insn_complexReg(s, OPC_SELNE, rn, rd, TCG_REG_TMP, TCG_REG_TMP2); ++ } ++ else if (b == 0) { ++ /* cond3. b is const and b=0 */ ++ /* if rn != 0 , rd=counting rn heading/tailing zero numbers , else rd = TCG_REG_ZERO */ ++ tcg_out_insn_complexReg(s, OPC_SELNE, rn, rd, TCG_REG_TMP, TCG_REG_ZERO); ++ } else { ++ /* cond4. b is const */ ++ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP2, b); ++ /* if rn != 0 , rd=counting rn heading/tailing zero numbers , else mov b to rd */ ++ tcg_out_insn_complexReg(s, OPC_SELNE, rn, rd, TCG_REG_TMP, TCG_REG_TMP2); ++ } ++ } ++ else { ++ /* if b is register */ ++ tcg_out_insn_complexReg(s, OPC_SELNE, rn, rd, TCG_REG_TMP, b); ++ } ++ } ++} ++ ++/*sw ++ * unsigned 16bit, ab->ba ++ */ ++static inline void tcg_out_bswap16u(TCGContext *s, TCGReg rd, TCGReg rn) ++{ ++ TCGReg TCG_TMP0 = rn; ++ TCGReg TCG_TMP1 = rd; ++ /*t1=00b0*/ ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP1, TCG_TMP0, 8); ++ /*t1=(0000)000a*/ ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP0, TCG_TMP0, 8); ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP0, TCG_TMP0, 0x1); ++ /*t1=ooba*/ ++ tcg_out_insn_simpleReg(s, OPC_BIS, TCG_TMP1, TCG_TMP1, TCG_TMP0); ++} ++ ++/*sw ++ * signed 16bit, ab->ssba ++ */ ++static inline void tcg_out_bswap16s(TCGContext *s, TCGReg rd, TCGReg rn) ++{ ++ TCGReg TCG_TMP0 = rn; ++ TCGReg TCG_TMP1 = TCG_REG_TMP; ++ TCGReg TCG_TMP2 = rn; ++ /*t1=(ssss)ssb0*/ ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP1, TCG_TMP0, 8); ++ tcg_out_insn_simpleImm(s, OPC_ZAP_I, TCG_TMP1, TCG_TMP1, 0x2); ++ tcg_out_insn_simpleReg(s, OPC_SEXTH, TCG_TMP1, TCG_REG_ZERO, TCG_TMP1); ++ /*t2=(0000)000a*/ ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP2, TCG_TMP0, 8); ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP2, TCG_TMP2, 0x1); ++ /*t2=(ssss)ssba*/ ++ tcg_out_insn_simpleReg(s, OPC_BIS, TCG_TMP1, TCG_TMP1, TCG_TMP2); ++} ++ ++ ++/*sw ++ * signed 32bit, abcd -> ssdcba ++ */ ++static inline void tcg_out_bswap32s(TCGContext *s, TCGReg rd, TCGReg rn) ++{ ++ TCGReg TCG_TMP0 = rn; ++ TCGReg TCG_TMP3 = rd; ++ TCGReg TCG_TMP1 = TCG_REG_TMP; ++ TCGReg TCG_TMP2 = TCG_REG_TMP2; ++ /*swap32 -- 32-bit swap. a0 = abcd.*/ ++ ++ /* t3 = (ssss)d000 */ ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP3, TCG_TMP0, 24); ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP3, TCG_TMP3, 0x0f); ++ tcg_out_insn_simpleReg(s, OPC_SEXTB, TCG_TMP1, TCG_REG_ZERO, TCG_TMP0); ++ tcg_out_insn_simpleImm(s, OPC_ZAP_I, TCG_TMP1, TCG_TMP1, 0x0f); ++ tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1); ++ ++ /* t1 = 000a */ ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP1, TCG_TMP0, 24); ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP1, 0x1); ++ ++ /* t2 = 00c0 */ ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP2, TCG_TMP0, 0x2); ++ ++ /* t3 = (ssss)d00a */ ++ tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1); ++ ++ /* t1 = 0abc */ ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP1, TCG_TMP0, 8); ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP1, 0x7); ++ ++ /* t2 = 0c00 */ ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP2, TCG_TMP2, 8); ++ /* t1 = 00b0 */ ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP1, 0x2); ++ /* t3 = (ssss)dc0a */ ++ tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP2); ++ /* t3 = (ssss)dcba -- delay slot */ ++ tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1); ++} ++ ++/*sw ++ * unsigned 32bit, abcd->dcba ++ */ ++static void tcg_out_bswap32u(TCGContext *s, TCGReg rd, TCGReg rn) ++{ ++ TCGReg TCG_TMP0 = rn; ++ TCGReg TCG_TMP3 = rd; ++ TCGReg TCG_TMP1 = TCG_REG_TMP; ++ TCGReg TCG_TMP2 = TCG_REG_TMP2; ++ ++ /*bswap32u -- unsigned 32-bit swap. a0 = ....abcd.*/ ++ /* t1 = (0000)000d */ ++ tcg_out_insn_bitImm(s, OPC_AND_I, TCG_TMP1, TCG_TMP0, 0xff); ++ /* t3 = 000a */ ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP3, TCG_TMP0, 24); ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP3, TCG_TMP3, 0x1); ++ /* t1 = (0000)d000 */ ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP1, TCG_TMP1, 24); ++ /* t2 = 00c0 */ ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP2, TCG_TMP0, 0x2); ++ /* t3 = d00a */ ++ tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1); ++ /* t1 = 0abc */ ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP1, TCG_TMP0, 8); ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP1, 0x7); ++ /* t2 = 0c00 */ ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP2, TCG_TMP2, 8); ++ /* t1 = 00b0 */ ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP1, 0x2); ++ /* t3 = dc0a */ ++ tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP2); ++ /* t3 = dcba -- delay slot */ ++ tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1); ++} ++ ++ ++ ++/*sw ++ * swap 64bit, abcdefgh->hgfedcba ++ */ ++static void tcg_out_bswap64(TCGContext *s, TCGReg rd, TCGReg rn) ++{ ++ ++ TCGReg TCG_TMP0 = rn; ++ TCGReg TCG_TMP3 = rd; ++ TCGReg TCG_TMP1 = TCG_REG_TMP; ++ TCGReg TCG_TMP2 = TCG_REG_TMP2; ++ ++ /* bswap64 -- 64-bit swap. a0 = abcdefgh*/ ++ ++ /* t3 = h0000000 */ ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP3, TCG_TMP0, 56); ++ /* t1 = 0000000a */ ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP1, TCG_TMP0, 56); ++ /* t2 = 000000g0 */ ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP2, TCG_TMP0, 0x2); ++ /* t3 = h000000a */ ++ tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1); ++ /* t1 = 00000abc */ ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP1, TCG_TMP0, 40); ++ /* t2 = 0g000000 */ ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP2, TCG_TMP2, 40); ++ /* t1 = 000000b0 */ ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP1, 0x2); ++ /* t3 = hg00000a */ ++ tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP2); ++ /* t2 = 0000abcd */ ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP2, TCG_TMP0, 32); ++ /* t3 = hg0000ba */ ++ tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1); ++ /* t1 = 000000c0 */ ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP2, 0x2); ++ /* t2 = 0000000d */ ++ tcg_out_insn_bitImm(s, OPC_AND_I, TCG_TMP2, TCG_TMP2, 0xff); ++ /* t1 = 00000c00 */ ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP1, TCG_TMP1, 8); ++ /* t2 = 0000d000 */ ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP2, TCG_TMP2, 24); ++ /* t3 = hg000cba */ ++ tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1); ++ /* t1 = 00abcdef */ ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP1, TCG_TMP0, 16); ++ /* t3 = hg00dcba */ ++ tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP2); ++ /* t2 = 0000000f */ ++ tcg_out_insn_bitImm(s, OPC_AND_I, TCG_TMP2, TCG_TMP1, 0xff); ++ /* t1 = 000000e0 */ ++ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP1, 0x2); ++ /* t2 = 00f00000 */ ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP2, TCG_TMP2, 40); ++ /* t1 = 000e0000 */ ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP1, TCG_TMP1, 24); ++ /* t3 = hgf0dcba */ ++ tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP2); ++ /* t3 = hgfedcba -- delay slot */ ++ tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1); ++ ++} ++ ++static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, MemOpIdx oi, TCGType ext) ++{ ++#ifndef CONFIG_SOFTMMU ++ MemOp memop = get_memop(oi); ++ const TCGType otype = TCG_TYPE_I64; ++ ++ if (USE_GUEST_BASE) { ++ tcg_out_insn_simpleReg(s, OPC_ADDL, TCG_REG_GUEST_BASE, TCG_REG_GUEST_BASE, addr_reg); ++ tcg_out_qemu_ld_direct(s, memop, data_reg, TCG_REG_GUEST_BASE, otype, 0); ++ } else { ++ tcg_out_qemu_ld_direct(s, memop, data_reg, addr_reg, TCG_TYPE_I64, 0); ++ } ++#endif /* CONFIG_SOFTMMU */ ++ ++} ++ ++static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, ++ MemOpIdx oi) ++{ ++#ifndef CONFIG_SOFTMMU ++ MemOp memop = get_memop(oi); ++ const TCGType otype = TCG_TYPE_I64; ++ ++ if (USE_GUEST_BASE) { ++ tcg_out_insn_simpleReg(s, OPC_ADDL, TCG_REG_GUEST_BASE, TCG_REG_GUEST_BASE, addr_reg); ++ tcg_out_qemu_st_direct(s, memop, data_reg, TCG_REG_GUEST_BASE, otype, 0); ++ } else { ++ tcg_out_qemu_st_direct(s, memop, data_reg, addr_reg, TCG_TYPE_I64, 0); ++ } ++#endif /* CONFIG_SOFTMMU */ ++} ++ ++ ++/*sw ++ * if cond is successful, ret=1, otherwise ret = 0 ++ */ ++static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, ++ TCGReg arg1, TCGReg arg2) ++{ ++ switch(cond) { ++ case TCG_COND_EQ: ++ case TCG_COND_LT: ++ case TCG_COND_LE: ++ case TCG_COND_LTU: ++ case TCG_COND_LEU: ++ case TCG_COND_NE: ++ case TCG_COND_GE: ++ case TCG_COND_GT: ++ case TCG_COND_GEU: ++ case TCG_COND_GTU: ++ tcg_out_cond_cmp(s, cond, ret, arg1, arg2, 0); ++ break; ++ default: ++ tcg_abort(); ++ break; ++ } ++} ++/*sw ++ * cond(a1,a2), yes:v1->ret, no:v2->ret ++ */ ++static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret, ++ TCGReg a1, TCGReg a2, bool const_b, TCGReg v1, TCGReg v2) ++{ ++ tcg_out_cond_cmp(s, cond, TCG_REG_TMP, a1, a2, const_b); ++ tcg_out_insn_complexReg(s, OPC_SELLBS, TCG_REG_TMP, ret, v1, v2); ++} ++ ++ ++ ++/*sw ++ * extract rn[lsb, lsb+len-1] -> rd[0, len-1] ++ */ ++static void tcg_out_extract(TCGContext *s, TCGReg rd, TCGReg rn, int lsb, int len) ++{ ++ //get 000..111..0000 ++ tcg_out_insn_bitReg(s, OPC_ORNOT, TCG_REG_TMP, TCG_REG_ZERO, TCG_REG_ZERO); ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP, TCG_REG_TMP, 64 - len); ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, lsb); ++ /* get rn[lsb, lsb+len-1]-->rd[lsb, lsb+len-1] */ ++ tcg_out_insn_bitReg(s, OPC_AND, rd, rn, TCG_REG_TMP); ++ ++ /* rd[lsb, lsb+len-1] --> rd[0, len-1] */ ++ tcg_out_insn_bitImm(s, OPC_SRL_I, rd, rd, lsb); ++} ++ ++ ++/*sw ++ * depos: rd = rd[63:msb+1]:rn[msb,lsb]:rd[lsb-1,0] ++ * len = msb -lsb + 1 ++ */ ++static void tcg_out_dep(TCGContext *s, TCGReg rd, TCGReg rn, int lsb, int len) ++{ ++ ++ //get 000..111..0000 ++ tcg_out_insn_bitReg(s, OPC_ORNOT, TCG_REG_TMP, TCG_REG_ZERO, TCG_REG_ZERO); ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP, TCG_REG_TMP, 64 - len); ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, lsb); ++ ++ /* TCG_REG_TMP2 = rn[msb,lsb] */ ++ tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_REG_TMP2, rn, 64-len); ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP2, TCG_REG_TMP2, 64-len-lsb); ++ ++ /* clear rd[msb,lsb] */ ++ tcg_out_insn_bitReg(s, OPC_BIC, rd, rd, TCG_REG_TMP); ++ /* rd = rd[63:msb+1]:rn[msb,lsb]:rd[lsb-1,0] */ ++ tcg_out_insn_bitReg(s, OPC_BIS, rd, rd, TCG_REG_TMP2); ++} ++ ++/*sw ++ * get val_s64(rn) * val_s64(rm) -> res_128 ++ * res[127:64] -> rd ++ * warn:maybe rd=rn or rm ++ */ ++static void tcg_out_mulsh64(TCGContext *s, TCGReg rd, TCGReg rn, TCGReg rm) ++{ ++ tcg_out_insn_simpleReg(s, OPC_UMULH, TCG_REG_TMP, rn, rm); ++ ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP2, rn, 63); ++ tcg_out_insn_complexReg(s, OPC_SELEQ, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_ZERO, rm); ++ tcg_out_insn_simpleReg(s, OPC_SUBL, TCG_REG_TMP, TCG_REG_TMP, TCG_REG_TMP2); ++ ++ tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP2, rm, 63); ++ tcg_out_insn_complexReg(s, OPC_SELEQ, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_ZERO, rn); ++ tcg_out_insn_simpleReg(s, OPC_SUBL, rd, TCG_REG_TMP, TCG_REG_TMP2); ++} ++ ++typedef struct { ++ DebugFrameHeader h; ++ uint8_t fde_def_cfa[4]; ++ uint8_t fde_reg_ofs[8 * 2]; ++} DebugFrame; ++ ++#define ELF_HOST_MACHINE EM_SW_64 ++/* GDB doesn't appear to require proper setting of ELF_HOST_FLAGS, ++ which is good because they're really quite complicated for SW_64. */ ++ ++static const DebugFrame debug_frame = { ++ .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */ ++ .h.cie.id = -1, ++ .h.cie.version = 1, ++ .h.cie.code_align = 1, ++ .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */ ++ .h.cie.return_column = TCG_REG_RA, ++ ++ /* Total FDE size does not include the "len" member. */ ++ .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset), ++ ++ .fde_def_cfa = { ++ 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */ ++ (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ ++ (FRAME_SIZE >> 7) ++ }, ++ .fde_reg_ofs = { ++ 0x80 + 14, 1, /* DW_CFA_offset, */ ++ 0x80 + 13, 2, /* DW_CFA_offset, */ ++ 0x80 + 12, 3, /* DW_CFA_offset, */ ++ 0x80 + 11, 4, /* DW_CFA_offset, */ ++ 0x80 + 10, 5, /* DW_CFA_offset, */ ++ 0x80 + 9, 6, /* DW_CFA_offset, */ ++ 0x80 + 26, 7, /* DW_CFA_offset, ra, -24 */ ++ 0x80 + 15, 8, /* DW_CFA_offset, fp, -8 */ ++ } ++}; ++ ++void tcg_register_jit(const void *buf, size_t buf_size) ++{ ++ tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); ++} +diff --git a/tcg/sw64/tcg-target.h b/tcg/sw64/tcg-target.h +new file mode 100755 +index 0000000000..3093e4fece +--- /dev/null ++++ b/tcg/sw64/tcg-target.h +@@ -0,0 +1,123 @@ ++/* ++ * Initial TCG Implementation for sw_64 ++ * ++ */ ++ ++#ifndef SW_64_TCG_TARGET_H ++#define SW_64_TCG_TARGET_H ++ ++#define TCG_TARGET_INSN_UNIT_SIZE 4 ++ ++typedef enum { ++ TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3, ++ TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7, ++ TCG_REG_X8, TCG_REG_X9, TCG_REG_X10, TCG_REG_X11, ++ TCG_REG_X12, TCG_REG_X13, TCG_REG_X14, TCG_REG_X15, ++ TCG_REG_X16, TCG_REG_X17, TCG_REG_X18, TCG_REG_X19, ++ TCG_REG_X20, TCG_REG_X21, TCG_REG_X22, TCG_REG_X23, ++ TCG_REG_X24, TCG_REG_X25, TCG_REG_X26, TCG_REG_X27, ++ TCG_REG_X28, TCG_REG_X29, TCG_REG_X30, TCG_REG_X31, ++ ++ TCG_REG_F0=32, TCG_REG_F1, TCG_REG_F2, TCG_REG_F3, ++ TCG_REG_F4, TCG_REG_F5, TCG_REG_F6, TCG_REG_F7, ++ TCG_REG_F8, TCG_REG_F9, TCG_REG_F10, TCG_REG_F11, ++ TCG_REG_F12, TCG_REG_F13, TCG_REG_F14, TCG_REG_F15, ++ TCG_REG_F16, TCG_REG_F17, TCG_REG_F18, TCG_REG_F19, ++ TCG_REG_F20, TCG_REG_F21, TCG_REG_F22, TCG_REG_F23, ++ TCG_REG_F24, TCG_REG_F25, TCG_REG_F26, TCG_REG_F27, ++ TCG_REG_F28, TCG_REG_F29, TCG_REG_F30, TCG_REG_F31, ++ ++ /* Aliases. */ ++ TCG_REG_FP = TCG_REG_X15, ++ TCG_REG_RA = TCG_REG_X26, ++ TCG_REG_GP = TCG_REG_X29, ++ TCG_REG_SP = TCG_REG_X30, ++ TCG_REG_ZERO = TCG_REG_X31, ++ TCG_AREG0 = TCG_REG_X9, ++} TCGReg; ++ ++#define TCG_TARGET_NB_REGS 64 ++#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1) ++ ++/* used for function call generation */ ++#define TCG_REG_CALL_STACK TCG_REG_SP ++#define TCG_TARGET_STACK_ALIGN 16 ++#define TCG_TARGET_CALL_ALIGN_ARGS 1 /*luo*/ ++#define TCG_TARGET_CALL_STACK_OFFSET 0 /*luo*/ ++#define TCG_TARGET_HAS_neg_i64 1 ++#define TCG_TARGET_HAS_direct_jump 0 ++#define TCG_TARGET_HAS_goto_ptr 1 ++#define TCG_TARGET_HAS_qemu_st8_i32 0 ++#define TCG_TARGET_HAS_not_i32 1 ++#define TCG_TARGET_HAS_neg_i32 1 ++#define TCG_TARGET_HAS_div_i32 1 ++#define TCG_TARGET_HAS_movcond_i32 1 ++#define TCG_TARGET_HAS_rem_i32 0 ++#define TCG_TARGET_HAS_rot_i32 1 ++#define TCG_TARGET_HAS_deposit_i32 1 ++#define TCG_TARGET_HAS_extract_i32 1 ++#define TCG_TARGET_HAS_sextract_i32 0 ++#define TCG_TARGET_HAS_extract2_i32 0 ++#define TCG_TARGET_HAS_add2_i32 0 ++#define TCG_TARGET_HAS_sub2_i32 0 ++#define TCG_TARGET_HAS_sub2_i32 0 ++#define TCG_TARGET_HAS_mulu2_i32 0 ++#define TCG_TARGET_HAS_muluh_i32 0 ++#define TCG_TARGET_HAS_muls2_i32 0 ++#define TCG_TARGET_HAS_not_i32 1 ++#define TCG_TARGET_HAS_mulsh_i32 0 ++#define TCG_TARGET_HAS_ext8s_i32 0 ++#define TCG_TARGET_HAS_ext16s_i32 0 ++#define TCG_TARGET_HAS_ext8u_i32 1 ++#define TCG_TARGET_HAS_ext16u_i32 1 ++#define TCG_TARGET_HAS_bswap16_i32 0 ++#define TCG_TARGET_HAS_bswap32_i32 0 ++#define TCG_TARGET_HAS_andc_i32 0 ++#define TCG_TARGET_HAS_eqv_i32 0 ++#define TCG_TARGET_HAS_nand_i32 0 ++#define TCG_TARGET_HAS_nor_i32 0 ++#define TCG_TARGET_HAS_clz_i32 0 ++#define TCG_TARGET_HAS_ctz_i32 0 ++#define TCG_TARGET_HAS_orc_i32 0 ++#define TCG_TARGET_HAS_ctpop_i32 0 ++#define TCG_TARGET_HAS_movcond_i64 1 ++#define TCG_TARGET_HAS_div_i64 1 ++#define TCG_TARGET_HAS_rem_i64 0 ++#define TCG_TARGET_HAS_div2_i64 0 ++#define TCG_TARGET_HAS_rot_i64 1 ++#define TCG_TARGET_HAS_deposit_i64 1 ++#define TCG_TARGET_HAS_extract_i64 1 ++#define TCG_TARGET_HAS_sextract_i64 0 ++#define TCG_TARGET_HAS_extract2_i64 0 ++#define TCG_TARGET_HAS_extrl_i64_i32 0 ++#define TCG_TARGET_HAS_extrh_i64_i32 0 ++#define TCG_TARGET_HAS_ext8s_i64 0 ++#define TCG_TARGET_HAS_ext16s_i64 0 ++#define TCG_TARGET_HAS_ext32s_i64 1 ++#define TCG_TARGET_HAS_ext8u_i64 1 ++#define TCG_TARGET_HAS_ext16u_i64 1 ++#define TCG_TARGET_HAS_ext32u_i64 1 ++#define TCG_TARGET_HAS_bswap16_i64 0 ++#define TCG_TARGET_HAS_bswap32_i64 0 ++#define TCG_TARGET_HAS_bswap64_i64 0 ++#define TCG_TARGET_HAS_not_i64 1 ++#define TCG_TARGET_HAS_andc_i64 0 ++#define TCG_TARGET_HAS_orc_i64 1 ++#define TCG_TARGET_HAS_eqv_i64 0 ++#define TCG_TARGET_HAS_nand_i64 0 ++#define TCG_TARGET_HAS_nor_i64 0 ++#define TCG_TARGET_HAS_clz_i64 1 ++#define TCG_TARGET_HAS_ctz_i64 1 ++#define TCG_TARGET_HAS_ctpop_i64 0 ++#define TCG_TARGET_HAS_add2_i64 0 ++#define TCG_TARGET_HAS_sub2_i64 0 ++#define TCG_TARGET_HAS_mulu2_i64 0 ++#define TCG_TARGET_HAS_muls2_i64 0 ++#define TCG_TARGET_HAS_muluh_i64 1 ++#define TCG_TARGET_HAS_mulsh_i64 1 ++#define TCG_TARGET_DEFAULT_MO (0) ++#define TCG_TARGET_HAS_MEMORY_BSWAP 0 ++/* optional instructions */ ++void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t); ++#define TCG_TARGET_NEED_POOL_LABELS ++#endif /* SW_64_TCG_TARGET_H */ +diff --git a/tcg/sw64/tcg-target.opc.h b/tcg/sw64/tcg-target.opc.h +new file mode 100755 +index 0000000000..bce30accd9 +--- /dev/null ++++ b/tcg/sw64/tcg-target.opc.h +@@ -0,0 +1,15 @@ ++/* ++ * Copyright (c) 2019 Linaro ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or ++ * (at your option) any later version. ++ * ++ * See the COPYING file in the top-level directory for details. ++ * ++ * Target-specific opcodes for host vector expansion. These will be ++ * emitted by tcg_expand_vec_op. For those familiar with GCC internals, ++ * consider these to be UNSPEC with names. ++ */ ++ ++DEF(aa64_sshl_vec, 1, 2, 0, IMPLVEC) ++DEF(aa64_sli_vec, 1, 2, 1, IMPLVEC) +-- +2.27.0 + diff --git a/tap-return-err-when-tap-TUNGETIFF-fail.patch b/tap-return-err-when-tap-TUNGETIFF-fail.patch new file mode 100644 index 0000000000000000000000000000000000000000..f74fa19abc42f16414dad411c06590d66c612922 --- /dev/null +++ b/tap-return-err-when-tap-TUNGETIFF-fail.patch @@ -0,0 +1,30 @@ +From 48a38f409a25f26605d65346c8ed9403c4b36c80 Mon Sep 17 00:00:00 2001 +From: Yan Wang +Date: Thu, 10 Feb 2022 10:28:59 +0800 +Subject: [PATCH] tap: return err when tap TUNGETIFF fail + +When hotplug ovs kernel netcard, even tap TUNGETIFF failed, +the hotplug would go on and would lead to qemu assert. +The failure should lead to the free_fail. + +Signed-off-by: miaoyubo +Signed-off-by: Yan Wang +--- + net/tap.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/tap.c b/net/tap.c +index f716be3e3f..c5cbeaa7a2 100644 +--- a/net/tap.c ++++ b/net/tap.c +@@ -900,6 +900,7 @@ int net_init_tap(const Netdev *netdev, const char *name, + if (i == 0) { + vnet_hdr = tap_probe_vnet_hdr(fd, errp); + if (vnet_hdr < 0) { ++ ret = -1; + goto free_fail; + } + } else if (vnet_hdr != tap_probe_vnet_hdr(fd, NULL)) { +-- +2.27.0 + diff --git a/target-arm-Add-CPU-features-to-query-cpu-model-expan.patch b/target-arm-Add-CPU-features-to-query-cpu-model-expan.patch index 4047145033d7010acfb3cfb002feb920fb303f0d..3bb8d6a46f4c0d762f2590250931e6347629c30a 100644 --- a/target-arm-Add-CPU-features-to-query-cpu-model-expan.patch +++ b/target-arm-Add-CPU-features-to-query-cpu-model-expan.patch @@ -1,7 +1,7 @@ -From 274d25bdb2df13a26ad6d2a8a06fcc281a22f642 Mon Sep 17 00:00:00 2001 +From e6dd7faeea77206d7e6589cbb54ad43926457052 Mon Sep 17 00:00:00 2001 From: Peng Liang Date: Thu, 6 Aug 2020 16:14:58 +0800 -Subject: [PATCH 7/9] target/arm: Add CPU features to query-cpu-model-expansion +Subject: [PATCH] target/arm: Add CPU features to query-cpu-model-expansion Add CPU features to the result of query-cpu-model-expansion so that other applications (such as libvirt) can know the supported CPU @@ -9,6 +9,7 @@ features. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun --- target/arm/cpu.c | 27 +++++++++++++++++++++++++++ target/arm/cpu.h | 2 ++ @@ -16,7 +17,7 @@ Signed-off-by: Peng Liang 3 files changed, 31 insertions(+) diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index db46afba..dcf9f49e 100644 +index 3024f4a3f5..2d6a26336f 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -25,6 +25,8 @@ @@ -26,9 +27,9 @@ index db46afba..dcf9f49e 100644 +#include "qapi/qmp/qdict.h" +#include "qom/qom-qobject.h" #include "cpu.h" - #include "internals.h" - #include "exec/exec-all.h" -@@ -1403,6 +1405,31 @@ static const CPUFeatureDep feature_dependencies[] = { + #ifdef CONFIG_TCG + #include "hw/core/tcg-cpu-ops.h" +@@ -1580,6 +1582,31 @@ static const CPUFeatureDep feature_dependencies[] = { }, }; @@ -46,7 +47,7 @@ index db46afba..dcf9f49e 100644 + } + + name = cpu_features[i].name; -+ prop = object_property_find(obj, name, NULL); ++ prop = object_property_find(obj, name); + if (prop) { + QObject *value; + @@ -61,10 +62,10 @@ index db46afba..dcf9f49e 100644 void *opaque, Error **errp) { diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index 7bb481fb..068c3fa2 100644 +index 3dda33f347..947897d5ac 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h -@@ -3692,4 +3692,6 @@ static inline bool isar_feature_any_pmu_8_1(const ARMISARegisters *id) +@@ -4398,4 +4398,6 @@ static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id) #define cpu_isar_feature(name, cpu) \ ({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); }) @@ -72,10 +73,10 @@ index 7bb481fb..068c3fa2 100644 + #endif diff --git a/target/arm/monitor.c b/target/arm/monitor.c -index e2b1d117..7c2ff3c0 100644 +index 80c64fa355..4c6f1181d9 100644 --- a/target/arm/monitor.c +++ b/target/arm/monitor.c -@@ -219,6 +219,8 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, +@@ -217,6 +217,8 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, } } @@ -85,5 +86,5 @@ index e2b1d117..7c2ff3c0 100644 qobject_unref(qdict_out); } else { -- -2.25.1 +2.27.0 diff --git a/target-arm-Add-ID_AA64MMFR2_EL1.patch b/target-arm-Add-ID_AA64MMFR2_EL1.patch deleted file mode 100644 index eee33ae241bde2333d5308c7ca39297782598ccc..0000000000000000000000000000000000000000 --- a/target-arm-Add-ID_AA64MMFR2_EL1.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 3451fb922aa7b0fe532e508ca13d4ab4b3ec75bf Mon Sep 17 00:00:00 2001 -From: Richard Henderson -Date: Sat, 8 Feb 2020 12:58:13 +0000 -Subject: [PATCH 02/13] target/arm: Add ID_AA64MMFR2_EL1 - -Add definitions for all of the fields, up to ARMv8.5. -Convert the existing RESERVED register to a full register. -Query KVM for the value of the register for the host. - -Reviewed-by: Peter Maydell -Signed-off-by: Richard Henderson -Message-id: 20200208125816.14954-18-richard.henderson@linaro.org -Signed-off-by: Peter Maydell ---- - target/arm/cpu.h | 17 +++++++++++++++++ - target/arm/helper.c | 4 ++-- - target/arm/kvm64.c | 2 ++ - 3 files changed, 21 insertions(+), 2 deletions(-) - -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index fe310828..3e65bc50 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -866,6 +866,7 @@ struct ARMCPU { - uint64_t id_aa64pfr1; - uint64_t id_aa64mmfr0; - uint64_t id_aa64mmfr1; -+ uint64_t id_aa64mmfr2; - } isar; - uint32_t midr; - uint32_t revidr; -@@ -1762,6 +1763,22 @@ FIELD(ID_AA64MMFR1, PAN, 20, 4) - FIELD(ID_AA64MMFR1, SPECSEI, 24, 4) - FIELD(ID_AA64MMFR1, XNX, 28, 4) - -+FIELD(ID_AA64MMFR2, CNP, 0, 4) -+FIELD(ID_AA64MMFR2, UAO, 4, 4) -+FIELD(ID_AA64MMFR2, LSM, 8, 4) -+FIELD(ID_AA64MMFR2, IESB, 12, 4) -+FIELD(ID_AA64MMFR2, VARANGE, 16, 4) -+FIELD(ID_AA64MMFR2, CCIDX, 20, 4) -+FIELD(ID_AA64MMFR2, NV, 24, 4) -+FIELD(ID_AA64MMFR2, ST, 28, 4) -+FIELD(ID_AA64MMFR2, AT, 32, 4) -+FIELD(ID_AA64MMFR2, IDS, 36, 4) -+FIELD(ID_AA64MMFR2, FWB, 40, 4) -+FIELD(ID_AA64MMFR2, TTL, 48, 4) -+FIELD(ID_AA64MMFR2, BBM, 52, 4) -+FIELD(ID_AA64MMFR2, EVT, 56, 4) -+FIELD(ID_AA64MMFR2, E0PD, 60, 4) -+ - FIELD(ID_DFR0, COPDBG, 0, 4) - FIELD(ID_DFR0, COPSDBG, 4, 4) - FIELD(ID_DFR0, MMAPDBG, 8, 4) -diff --git a/target/arm/helper.c b/target/arm/helper.c -index b74c23a9..c50b1ba1 100644 ---- a/target/arm/helper.c -+++ b/target/arm/helper.c -@@ -6182,10 +6182,10 @@ void register_cp_regs_for_features(ARMCPU *cpu) - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1, - .access = PL1_R, .type = ARM_CP_CONST, - .resetvalue = cpu->isar.id_aa64mmfr1 }, -- { .name = "ID_AA64MMFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, -+ { .name = "ID_AA64MMFR2_EL1", .state = ARM_CP_STATE_AA64, - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 2, - .access = PL1_R, .type = ARM_CP_CONST, -- .resetvalue = 0 }, -+ .resetvalue = cpu->isar.id_aa64mmfr2 }, - { .name = "ID_AA64MMFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64, - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3, - .access = PL1_R, .type = ARM_CP_CONST, -diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c -index 4f0bf000..b794108a 100644 ---- a/target/arm/kvm64.c -+++ b/target/arm/kvm64.c -@@ -541,6 +541,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) - ARM64_SYS_REG(3, 0, 0, 7, 0)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1, - ARM64_SYS_REG(3, 0, 0, 7, 1)); -+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2, -+ ARM64_SYS_REG(3, 0, 0, 7, 2)); - - /* - * Note that if AArch32 support is not present in the host, --- -2.25.1 - diff --git a/target-arm-Add-_aa64_-and-_any_-versions-of-pmu_8_1-.patch b/target-arm-Add-_aa64_-and-_any_-versions-of-pmu_8_1-.patch deleted file mode 100644 index 7516ed8108de271970e600dbd03c964611b3b0ba..0000000000000000000000000000000000000000 --- a/target-arm-Add-_aa64_-and-_any_-versions-of-pmu_8_1-.patch +++ /dev/null @@ -1,166 +0,0 @@ -From 515975da851ca9567053bcf0487fde4447dfdc4f Mon Sep 17 00:00:00 2001 -From: Peter Maydell -Date: Fri, 14 Feb 2020 17:51:04 +0000 -Subject: [PATCH 06/13] target/arm: Add _aa64_ and _any_ versions of pmu_8_1 - isar checks -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add the 64-bit version of the "is this a v8.1 PMUv3?" -ID register check function, and the _any_ version that -checks for either AArch32 or AArch64 support. We'll use -this in a later commit. - -We don't (yet) do any isar_feature checks on ID_AA64DFR1_EL1, -but we move id_aa64dfr1 into the ARMISARegisters struct with -id_aa64dfr0, for consistency. - -Reviewed-by: Richard Henderson -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Peter Maydell -Message-id: 20200214175116.9164-10-peter.maydell@linaro.org ---- - target/arm/cpu.c | 3 ++- - target/arm/cpu.h | 15 +++++++++++++-- - target/arm/cpu64.c | 8 ++++---- - target/arm/helper.c | 12 +++++++----- - 4 files changed, 26 insertions(+), 12 deletions(-) - -diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index 7e9b85a2..bb2edf4e 100644 ---- a/target/arm/cpu.c -+++ b/target/arm/cpu.c -@@ -1522,7 +1522,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) - cpu); - #endif - } else { -- cpu->id_aa64dfr0 = FIELD_DP64(cpu->id_aa64dfr0, ID_AA64DFR0, PMUVER, 0); -+ cpu->isar.id_aa64dfr0 = -+ FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMUVER, 0); - cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, PERFMON, 0); - cpu->pmceid0 = 0; - cpu->pmceid1 = 0; -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index 2d8d27e8..230130be 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -868,6 +868,8 @@ struct ARMCPU { - uint64_t id_aa64mmfr0; - uint64_t id_aa64mmfr1; - uint64_t id_aa64mmfr2; -+ uint64_t id_aa64dfr0; -+ uint64_t id_aa64dfr1; - } isar; - uint32_t midr; - uint32_t revidr; -@@ -884,8 +886,6 @@ struct ARMCPU { - uint32_t id_mmfr2; - uint32_t id_mmfr3; - uint32_t id_mmfr4; -- uint64_t id_aa64dfr0; -- uint64_t id_aa64dfr1; - uint64_t id_aa64afr0; - uint64_t id_aa64afr1; - uint32_t dbgdidr; -@@ -3657,6 +3657,17 @@ static inline bool isar_feature_aa64_bti(const ARMISARegisters *id) - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0; - } - -+static inline bool isar_feature_aa64_pmu_8_1(const ARMISARegisters *id) -+{ -+ return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 && -+ FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; -+} -+ -+static inline bool isar_feature_any_pmu_8_1(const ARMISARegisters *id) -+{ -+ return isar_feature_aa64_pmu_8_1(id) || isar_feature_aa32_pmu_8_1(id); -+} -+ - /* - * Forward to the above feature tests given an ARMCPU pointer. - */ -diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index afdabbeb..aa96548f 100644 ---- a/target/arm/cpu64.c -+++ b/target/arm/cpu64.c -@@ -137,7 +137,7 @@ static void aarch64_a57_initfn(Object *obj) - cpu->isar.id_isar5 = 0x00011121; - cpu->isar.id_isar6 = 0; - cpu->isar.id_aa64pfr0 = 0x00002222; -- cpu->id_aa64dfr0 = 0x10305106; -+ cpu->isar.id_aa64dfr0 = 0x10305106; - cpu->isar.id_aa64isar0 = 0x00011120; - cpu->isar.id_aa64mmfr0 = 0x00001124; - cpu->dbgdidr = 0x3516d000; -@@ -191,7 +191,7 @@ static void aarch64_a53_initfn(Object *obj) - cpu->isar.id_isar5 = 0x00011121; - cpu->isar.id_isar6 = 0; - cpu->isar.id_aa64pfr0 = 0x00002222; -- cpu->id_aa64dfr0 = 0x10305106; -+ cpu->isar.id_aa64dfr0 = 0x10305106; - cpu->isar.id_aa64isar0 = 0x00011120; - cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */ - cpu->dbgdidr = 0x3516d000; -@@ -244,7 +244,7 @@ static void aarch64_a72_initfn(Object *obj) - cpu->isar.id_isar4 = 0x00011142; - cpu->isar.id_isar5 = 0x00011121; - cpu->isar.id_aa64pfr0 = 0x00002222; -- cpu->id_aa64dfr0 = 0x10305106; -+ cpu->isar.id_aa64dfr0 = 0x10305106; - cpu->isar.id_aa64isar0 = 0x00011120; - cpu->isar.id_aa64mmfr0 = 0x00001124; - cpu->dbgdidr = 0x3516d000; -@@ -276,7 +276,7 @@ static void aarch64_kunpeng_920_initfn(Object *obj) - cpu->midr = 0x480fd010; - cpu->ctr = 0x84448004; - cpu->isar.id_aa64pfr0 = 0x11001111; -- cpu->id_aa64dfr0 = 0x110305408; -+ cpu->isar.id_aa64dfr0 = 0x110305408; - cpu->isar.id_aa64isar0 = 0x10211120; - cpu->isar.id_aa64mmfr0 = 0x101125; - } -diff --git a/target/arm/helper.c b/target/arm/helper.c -index 3f06ca19..a71f4ef6 100644 ---- a/target/arm/helper.c -+++ b/target/arm/helper.c -@@ -23,6 +23,7 @@ - #include "hw/semihosting/semihost.h" - #include "sysemu/cpus.h" - #include "sysemu/kvm.h" -+#include "sysemu/tcg.h" - #include "qemu/range.h" - #include "qapi/qapi-commands-machine-target.h" - #include "qapi/error.h" -@@ -5611,9 +5612,10 @@ static void define_debug_regs(ARMCPU *cpu) - * check that if they both exist then they agree. - */ - if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { -- assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, BRPS) == brps); -- assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, WRPS) == wrps); -- assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) == ctx_cmps); -+ assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) == brps); -+ assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) == wrps); -+ assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) -+ == ctx_cmps); - } - - define_one_arm_cp_reg(cpu, &dbgdidr); -@@ -6112,11 +6114,11 @@ void register_cp_regs_for_features(ARMCPU *cpu) - { .name = "ID_AA64DFR0_EL1", .state = ARM_CP_STATE_AA64, - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0, - .access = PL1_R, .type = ARM_CP_CONST, -- .resetvalue = cpu->id_aa64dfr0 }, -+ .resetvalue = cpu->isar.id_aa64dfr0 }, - { .name = "ID_AA64DFR1_EL1", .state = ARM_CP_STATE_AA64, - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 1, - .access = PL1_R, .type = ARM_CP_CONST, -- .resetvalue = cpu->id_aa64dfr1 }, -+ .resetvalue = cpu->isar.id_aa64dfr1 }, - { .name = "ID_AA64DFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 2, - .access = PL1_R, .type = ARM_CP_CONST, --- -2.25.1 - diff --git a/target-arm-Add-and-use-FIELD-definitions-for-ID_AA64.patch b/target-arm-Add-and-use-FIELD-definitions-for-ID_AA64.patch deleted file mode 100644 index 66e4ec4ad078aacdd4e7cb9a76244e1460487551..0000000000000000000000000000000000000000 --- a/target-arm-Add-and-use-FIELD-definitions-for-ID_AA64.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 4001f3040937094660eab44dbb49b86817317ea9 Mon Sep 17 00:00:00 2001 -From: Peter Maydell -Date: Fri, 14 Feb 2020 17:51:01 +0000 -Subject: [PATCH 03/13] target/arm: Add and use FIELD definitions for - ID_AA64DFR0_EL1 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add FIELD() definitions for the ID_AA64DFR0_EL1 and use them -where we currently have hard-coded bit values. - -Reviewed-by: Philippe Mathieu-Daudé -Reviewed-by: Richard Henderson -Signed-off-by: Peter Maydell -Message-id: 20200214175116.9164-7-peter.maydell@linaro.org ---- - target/arm/cpu.c | 2 +- - target/arm/cpu.h | 10 ++++++++++ - target/arm/helper.c | 6 +++--- - 3 files changed, 14 insertions(+), 4 deletions(-) - -diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index 811e5c63..dbd05e01 100644 ---- a/target/arm/cpu.c -+++ b/target/arm/cpu.c -@@ -1522,7 +1522,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) - cpu); - #endif - } else { -- cpu->id_aa64dfr0 &= ~0xf00; -+ cpu->id_aa64dfr0 = FIELD_DP64(cpu->id_aa64dfr0, ID_AA64DFR0, PMUVER, 0); - cpu->id_dfr0 &= ~(0xf << 24); - cpu->pmceid0 = 0; - cpu->pmceid1 = 0; -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index 3e65bc50..91cc02b4 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -1779,6 +1779,16 @@ FIELD(ID_AA64MMFR2, BBM, 52, 4) - FIELD(ID_AA64MMFR2, EVT, 56, 4) - FIELD(ID_AA64MMFR2, E0PD, 60, 4) - -+FIELD(ID_AA64DFR0, DEBUGVER, 0, 4) -+FIELD(ID_AA64DFR0, TRACEVER, 4, 4) -+FIELD(ID_AA64DFR0, PMUVER, 8, 4) -+FIELD(ID_AA64DFR0, BRPS, 12, 4) -+FIELD(ID_AA64DFR0, WRPS, 20, 4) -+FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4) -+FIELD(ID_AA64DFR0, PMSVER, 32, 4) -+FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4) -+FIELD(ID_AA64DFR0, TRACEFILT, 40, 4) -+ - FIELD(ID_DFR0, COPDBG, 0, 4) - FIELD(ID_DFR0, COPSDBG, 4, 4) - FIELD(ID_DFR0, MMAPDBG, 8, 4) -diff --git a/target/arm/helper.c b/target/arm/helper.c -index c50b1ba1..419be640 100644 ---- a/target/arm/helper.c -+++ b/target/arm/helper.c -@@ -5611,9 +5611,9 @@ static void define_debug_regs(ARMCPU *cpu) - * check that if they both exist then they agree. - */ - if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { -- assert(extract32(cpu->id_aa64dfr0, 12, 4) == brps); -- assert(extract32(cpu->id_aa64dfr0, 20, 4) == wrps); -- assert(extract32(cpu->id_aa64dfr0, 28, 4) == ctx_cmps); -+ assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, BRPS) == brps); -+ assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, WRPS) == wrps); -+ assert(FIELD_EX64(cpu->id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) == ctx_cmps); - } - - define_one_arm_cp_reg(cpu, &dbgdidr); --- -2.25.1 - diff --git a/target-arm-Add-isar_feature-tests-for-PAN-ATS1E1.patch b/target-arm-Add-isar_feature-tests-for-PAN-ATS1E1.patch deleted file mode 100644 index d6e29be12e1bbf6ef55d43bf35960e2168fc51e8..0000000000000000000000000000000000000000 --- a/target-arm-Add-isar_feature-tests-for-PAN-ATS1E1.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 6f18e959eabf9c752659eb3851f193bf343346c5 Mon Sep 17 00:00:00 2001 -From: Richard Henderson -Date: Sat, 8 Feb 2020 12:57:59 +0000 -Subject: [PATCH 01/13] target/arm: Add isar_feature tests for PAN + ATS1E1 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Include definitions for all of the bits in ID_MMFR3. -We already have a definition for ID_AA64MMFR1.PAN. - -Reviewed-by: Alex Bennée -Reviewed-by: Peter Maydell -Signed-off-by: Richard Henderson -Message-id: 20200208125816.14954-4-richard.henderson@linaro.org -Signed-off-by: Peter Maydell ---- - target/arm/cpu.h | 29 +++++++++++++++++++++++++++++ - 1 file changed, 29 insertions(+) - -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index 86eb79cd..fe310828 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -1680,6 +1680,15 @@ FIELD(ID_ISAR6, FHM, 8, 4) - FIELD(ID_ISAR6, SB, 12, 4) - FIELD(ID_ISAR6, SPECRES, 16, 4) - -+FIELD(ID_MMFR3, CMAINTVA, 0, 4) -+FIELD(ID_MMFR3, CMAINTSW, 4, 4) -+FIELD(ID_MMFR3, BPMAINT, 8, 4) -+FIELD(ID_MMFR3, MAINTBCST, 12, 4) -+FIELD(ID_MMFR3, PAN, 16, 4) -+FIELD(ID_MMFR3, COHWALK, 20, 4) -+FIELD(ID_MMFR3, CMEMSZ, 24, 4) -+FIELD(ID_MMFR3, SUPERSEC, 28, 4) -+ - FIELD(ID_MMFR4, SPECSEI, 0, 4) - FIELD(ID_MMFR4, AC2, 4, 4) - FIELD(ID_MMFR4, XNX, 8, 4) -@@ -3445,6 +3454,16 @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id) - return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 4; - } - -+static inline bool isar_feature_aa32_pan(const ARMISARegisters *id) -+{ -+ return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) != 0; -+} -+ -+static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id) -+{ -+ return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) >= 2; -+} -+ - /* - * 64-bit feature tests via id registers. - */ -@@ -3589,6 +3608,16 @@ static inline bool isar_feature_aa64_lor(const ARMISARegisters *id) - return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0; - } - -+static inline bool isar_feature_aa64_pan(const ARMISARegisters *id) -+{ -+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0; -+} -+ -+static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id) -+{ -+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2; -+} -+ - static inline bool isar_feature_aa64_bti(const ARMISARegisters *id) - { - return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0; --- -2.25.1 - diff --git a/target-arm-Add-more-CPU-features.patch b/target-arm-Add-more-CPU-features.patch index a22e5177300d305df8c0430ee21e29c587bd5399..4b8c01d5038e29505e5b4d19d4467e5054de792a 100644 --- a/target-arm-Add-more-CPU-features.patch +++ b/target-arm-Add-more-CPU-features.patch @@ -1,21 +1,22 @@ -From 3eee1e4ff1ca342e760f759c727abc41780d0afa Mon Sep 17 00:00:00 2001 +From 85d5b46d8225c5875b8b3ff68967d46bcde9a549 Mon Sep 17 00:00:00 2001 From: Peng Liang Date: Tue, 11 Aug 2020 10:28:10 +0800 -Subject: [PATCH 9/9] target/arm: Add more CPU features +Subject: [PATCH] target/arm: Add more CPU features Add i8mm, bf16, and dgh CPU features for AArch64. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun --- target/arm/cpu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index dcf9f49e..7ae2d3da 100644 +index 2d6a26336f..1c1647a0a8 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c -@@ -1132,6 +1132,9 @@ static struct CPUFeatureInfo cpu_features[] = { +@@ -1309,6 +1309,9 @@ static struct CPUFeatureInfo cpu_features[] = { FIELD_INFO("fhm", ID_ISAR6, FHM, false, 1, 0, true), FIELD_INFO("sb", ID_ISAR6, SB, false, 1, 0, true), FIELD_INFO("specres", ID_ISAR6, SPECRES, false, 1, 0, true), @@ -26,5 +27,5 @@ index dcf9f49e..7ae2d3da 100644 FIELD_INFO("cmaintva", ID_MMFR3, CMAINTVA, false, 1, 0, true), FIELD_INFO("cmaintsw", ID_MMFR3, CMAINTSW, false, 1, 0, true), -- -2.25.1 +2.27.0 diff --git a/target-arm-Add-the-kvm_adjvtime-vcpu-property-for-Co.patch b/target-arm-Add-the-kvm_adjvtime-vcpu-property-for-Co.patch deleted file mode 100644 index 49c7dc63022ec1196b8c225b1c5291fbbe10e1ad..0000000000000000000000000000000000000000 --- a/target-arm-Add-the-kvm_adjvtime-vcpu-property-for-Co.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 427975fbc87c3d999ee4d13b65a95ba496c148d6 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Fri, 29 May 2020 11:02:44 +0800 -Subject: [PATCH] target/arm: Add the kvm_adjvtime vcpu property for Cortex-A72 - -Add the kvm_adjvtime vcpu property for ARM Cortex-A72 cpu model, -so that virtual time adjust will be enabled for it. - -Signed-off-by: Ying Fang - -diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index b30ca7c9..15f4ee92 100644 ---- a/target/arm/cpu64.c -+++ b/target/arm/cpu64.c -@@ -257,6 +257,9 @@ static void aarch64_a72_initfn(Object *obj) - cpu->gic_vpribits = 5; - cpu->gic_vprebits = 5; - define_arm_cp_regs(cpu, cortex_a72_a57_a53_cp_reginfo); -+ if(kvm_enabled()) { -+ kvm_arm_add_vcpu_properties(obj); -+ } - } - - static void aarch64_kunpeng_920_initfn(Object *obj) --- -2.23.0 - diff --git a/target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch b/target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch index 81ad2961b00130a741079e0f38c56b7dffdcf803..84645718d5fb1bcc3179bdf28f61d9d954d2dc9e 100644 --- a/target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch +++ b/target-arm-Allow-ID-registers-to-synchronize-to-KVM.patch @@ -1,7 +1,7 @@ -From 79a60f0eeb56faf5d162ca566d1cd9988c3e4d60 Mon Sep 17 00:00:00 2001 +From 0272c52e36ab95389e665ca19b129178b0b46eac Mon Sep 17 00:00:00 2001 From: Peng Liang Date: Thu, 6 Aug 2020 16:14:40 +0800 -Subject: [PATCH 4/9] target/arm: Allow ID registers to synchronize to KVM +Subject: [PATCH] target/arm: Allow ID registers to synchronize to KVM There are 2 steps to synchronize the values of system registers from CPU state to KVM: @@ -26,6 +26,7 @@ KVM. If the write is successful, then write to (index,value) list. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun --- target/arm/helper.c | 31 ++++++++++++++++++++----------- target/arm/kvm.c | 38 ++++++++++++++++++++++++++++++++++++++ @@ -33,18 +34,18 @@ Signed-off-by: Peng Liang 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c -index 459af431..97b6b861 100644 +index b8ea1dc1f6..79f77705c3 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c -@@ -32,6 +32,7 @@ - #include "arm_ldst.h" +@@ -35,6 +35,7 @@ #include "exec/cpu_ldst.h" + #include "semihosting/common-semi.h" #endif +#include "kvm_arm.h" #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */ - -@@ -267,30 +268,38 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) + #define PMCR_NUM_COUNTERS 4 /* QEMU IMPDEF choice */ +@@ -149,30 +150,38 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) ok = false; continue; } @@ -95,10 +96,10 @@ index 459af431..97b6b861 100644 cpu->cpreg_values[i] = newval; } diff --git a/target/arm/kvm.c b/target/arm/kvm.c -index 4f131f68..229b17ce 100644 +index bbf1ce7ba3..59d556724f 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c -@@ -457,6 +457,44 @@ out: +@@ -514,6 +514,44 @@ out: return ret; } @@ -144,10 +145,10 @@ index 4f131f68..229b17ce 100644 { CPUState *cs = CPU(cpu); diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h -index 0de5f83e..9b7104d6 100644 +index b7f78b5215..f8e0e64363 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h -@@ -400,4 +400,7 @@ static inline const char *its_class_name(void) +@@ -528,4 +528,7 @@ static inline const char *its_class_name(void) } } @@ -156,5 +157,5 @@ index 0de5f83e..9b7104d6 100644 + #endif -- -2.25.1 +2.27.0 diff --git a/target-arm-Allow-reading-flags-from-FPSCR-for-M-prof.patch b/target-arm-Allow-reading-flags-from-FPSCR-for-M-prof.patch deleted file mode 100644 index ca4b796b58600aa35771d26a247690dfca413cc9..0000000000000000000000000000000000000000 --- a/target-arm-Allow-reading-flags-from-FPSCR-for-M-prof.patch +++ /dev/null @@ -1,41 +0,0 @@ -From cdc6896659b85f7ed8f7552850312e55170de0c5 Mon Sep 17 00:00:00 2001 -From: Christophe Lyon -Date: Fri, 25 Oct 2019 11:57:11 +0200 -Subject: [PATCH] target/arm: Allow reading flags from FPSCR for M-profile - -rt==15 is a special case when reading the flags: it means the -destination is APSR. This patch avoids rejecting -vmrs apsr_nzcv, fpscr -as illegal instruction. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Christophe Lyon -Message-id: 20191025095711.10853-1-christophe.lyon@linaro.org -[PMM: updated the comment] -Reviewed-by: Peter Maydell -Signed-off-by: Peter Maydell -(cherry picked from commit 2529ab43b8a05534494704e803e0332d111d8b91) -Signed-off-by: Michael Roth ---- - target/arm/translate-vfp.inc.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c -index ef45cecbea..75406fd9db 100644 ---- a/target/arm/translate-vfp.inc.c -+++ b/target/arm/translate-vfp.inc.c -@@ -704,9 +704,10 @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a) - if (arm_dc_feature(s, ARM_FEATURE_M)) { - /* - * The only M-profile VFP vmrs/vmsr sysreg is FPSCR. -- * Writes to R15 are UNPREDICTABLE; we choose to undef. -+ * Accesses to R15 are UNPREDICTABLE; we choose to undef. -+ * (FPSCR -> r15 is a special case which writes to the PSR flags.) - */ -- if (a->rt == 15 || a->reg != ARM_VFP_FPSCR) { -+ if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) { - return false; - } - } --- -2.23.0 diff --git a/target-arm-Define-an-aa32_pmu_8_1-isar-feature-test-.patch b/target-arm-Define-an-aa32_pmu_8_1-isar-feature-test-.patch deleted file mode 100644 index bfcce54936d4cb8c8ca1de997a6d0d469dab3bc1..0000000000000000000000000000000000000000 --- a/target-arm-Define-an-aa32_pmu_8_1-isar-feature-test-.patch +++ /dev/null @@ -1,248 +0,0 @@ -From 2eded1a4deeb5dd8d28414e54948bcf773f6b540 Mon Sep 17 00:00:00 2001 -From: Peter Maydell -Date: Fri, 14 Feb 2020 17:51:03 +0000 -Subject: [PATCH 05/13] target/arm: Define an aa32_pmu_8_1 isar feature test - function - -Instead of open-coding a check on the ID_DFR0 PerfMon ID register -field, create a standardly-named isar_feature for "does AArch32 have -a v8.1 PMUv3" and use it. - -This entails moving the id_dfr0 field into the ARMISARegisters struct. - -Reviewed-by: Richard Henderson -Signed-off-by: Peter Maydell -Message-id: 20200214175116.9164-9-peter.maydell@linaro.org ---- - hw/intc/armv7m_nvic.c | 2 +- - target/arm/cpu.c | 26 +++++++++++++------------- - target/arm/cpu.h | 9 ++++++++- - target/arm/cpu64.c | 6 +++--- - target/arm/helper.c | 5 ++--- - 5 files changed, 27 insertions(+), 21 deletions(-) - -diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c -index 9f8f0d3f..0741db7b 100644 ---- a/hw/intc/armv7m_nvic.c -+++ b/hw/intc/armv7m_nvic.c -@@ -1223,7 +1223,7 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) - case 0xd44: /* PFR1. */ - return cpu->id_pfr1; - case 0xd48: /* DFR0. */ -- return cpu->id_dfr0; -+ return cpu->isar.id_dfr0; - case 0xd4c: /* AFR0. */ - return cpu->id_afr0; - case 0xd50: /* MMFR0. */ -diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index 6ad211b1..7e9b85a2 100644 ---- a/target/arm/cpu.c -+++ b/target/arm/cpu.c -@@ -1523,7 +1523,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) - #endif - } else { - cpu->id_aa64dfr0 = FIELD_DP64(cpu->id_aa64dfr0, ID_AA64DFR0, PMUVER, 0); -- cpu->id_dfr0 = FIELD_DP32(cpu->id_dfr0, ID_DFR0, PERFMON, 0); -+ cpu->isar.id_dfr0 = FIELD_DP32(cpu->isar.id_dfr0, ID_DFR0, PERFMON, 0); - cpu->pmceid0 = 0; - cpu->pmceid1 = 0; - } -@@ -1761,7 +1761,7 @@ static void arm1136_r2_initfn(Object *obj) - cpu->reset_sctlr = 0x00050078; - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x1; -- cpu->id_dfr0 = 0x2; -+ cpu->isar.id_dfr0 = 0x2; - cpu->id_afr0 = 0x3; - cpu->id_mmfr0 = 0x01130003; - cpu->id_mmfr1 = 0x10030302; -@@ -1793,7 +1793,7 @@ static void arm1136_initfn(Object *obj) - cpu->reset_sctlr = 0x00050078; - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x1; -- cpu->id_dfr0 = 0x2; -+ cpu->isar.id_dfr0 = 0x2; - cpu->id_afr0 = 0x3; - cpu->id_mmfr0 = 0x01130003; - cpu->id_mmfr1 = 0x10030302; -@@ -1826,7 +1826,7 @@ static void arm1176_initfn(Object *obj) - cpu->reset_sctlr = 0x00050078; - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x11; -- cpu->id_dfr0 = 0x33; -+ cpu->isar.id_dfr0 = 0x33; - cpu->id_afr0 = 0; - cpu->id_mmfr0 = 0x01130003; - cpu->id_mmfr1 = 0x10030302; -@@ -1856,7 +1856,7 @@ static void arm11mpcore_initfn(Object *obj) - cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */ - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x1; -- cpu->id_dfr0 = 0; -+ cpu->isar.id_dfr0 = 0; - cpu->id_afr0 = 0x2; - cpu->id_mmfr0 = 0x01100103; - cpu->id_mmfr1 = 0x10020302; -@@ -1888,7 +1888,7 @@ static void cortex_m3_initfn(Object *obj) - cpu->pmsav7_dregion = 8; - cpu->id_pfr0 = 0x00000030; - cpu->id_pfr1 = 0x00000200; -- cpu->id_dfr0 = 0x00100000; -+ cpu->isar.id_dfr0 = 0x00100000; - cpu->id_afr0 = 0x00000000; - cpu->id_mmfr0 = 0x00000030; - cpu->id_mmfr1 = 0x00000000; -@@ -1919,7 +1919,7 @@ static void cortex_m4_initfn(Object *obj) - cpu->isar.mvfr2 = 0x00000000; - cpu->id_pfr0 = 0x00000030; - cpu->id_pfr1 = 0x00000200; -- cpu->id_dfr0 = 0x00100000; -+ cpu->isar.id_dfr0 = 0x00100000; - cpu->id_afr0 = 0x00000000; - cpu->id_mmfr0 = 0x00000030; - cpu->id_mmfr1 = 0x00000000; -@@ -1952,7 +1952,7 @@ static void cortex_m33_initfn(Object *obj) - cpu->isar.mvfr2 = 0x00000040; - cpu->id_pfr0 = 0x00000030; - cpu->id_pfr1 = 0x00000210; -- cpu->id_dfr0 = 0x00200000; -+ cpu->isar.id_dfr0 = 0x00200000; - cpu->id_afr0 = 0x00000000; - cpu->id_mmfr0 = 0x00101F40; - cpu->id_mmfr1 = 0x00000000; -@@ -2003,7 +2003,7 @@ static void cortex_r5_initfn(Object *obj) - cpu->midr = 0x411fc153; /* r1p3 */ - cpu->id_pfr0 = 0x0131; - cpu->id_pfr1 = 0x001; -- cpu->id_dfr0 = 0x010400; -+ cpu->isar.id_dfr0 = 0x010400; - cpu->id_afr0 = 0x0; - cpu->id_mmfr0 = 0x0210030; - cpu->id_mmfr1 = 0x00000000; -@@ -2058,7 +2058,7 @@ static void cortex_a8_initfn(Object *obj) - cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x1031; - cpu->id_pfr1 = 0x11; -- cpu->id_dfr0 = 0x400; -+ cpu->isar.id_dfr0 = 0x400; - cpu->id_afr0 = 0; - cpu->id_mmfr0 = 0x31100003; - cpu->id_mmfr1 = 0x20000000; -@@ -2131,7 +2131,7 @@ static void cortex_a9_initfn(Object *obj) - cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x1031; - cpu->id_pfr1 = 0x11; -- cpu->id_dfr0 = 0x000; -+ cpu->isar.id_dfr0 = 0x000; - cpu->id_afr0 = 0; - cpu->id_mmfr0 = 0x00100103; - cpu->id_mmfr1 = 0x20000000; -@@ -2196,7 +2196,7 @@ static void cortex_a7_initfn(Object *obj) - cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x00001131; - cpu->id_pfr1 = 0x00011011; -- cpu->id_dfr0 = 0x02010555; -+ cpu->isar.id_dfr0 = 0x02010555; - cpu->id_afr0 = 0x00000000; - cpu->id_mmfr0 = 0x10101105; - cpu->id_mmfr1 = 0x40000000; -@@ -2242,7 +2242,7 @@ static void cortex_a15_initfn(Object *obj) - cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x00001131; - cpu->id_pfr1 = 0x00011011; -- cpu->id_dfr0 = 0x02010555; -+ cpu->isar.id_dfr0 = 0x02010555; - cpu->id_afr0 = 0x00000000; - cpu->id_mmfr0 = 0x10201105; - cpu->id_mmfr1 = 0x20000000; -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index 91cc02b4..2d8d27e8 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -860,6 +860,7 @@ struct ARMCPU { - uint32_t mvfr0; - uint32_t mvfr1; - uint32_t mvfr2; -+ uint32_t id_dfr0; - uint64_t id_aa64isar0; - uint64_t id_aa64isar1; - uint64_t id_aa64pfr0; -@@ -875,7 +876,6 @@ struct ARMCPU { - uint32_t reset_sctlr; - uint32_t id_pfr0; - uint32_t id_pfr1; -- uint32_t id_dfr0; - uint64_t pmceid0; - uint64_t pmceid1; - uint32_t id_afr0; -@@ -3491,6 +3491,13 @@ static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id) - return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) >= 2; - } - -+static inline bool isar_feature_aa32_pmu_8_1(const ARMISARegisters *id) -+{ -+ /* 0xf means "non-standard IMPDEF PMU" */ -+ return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 4 && -+ FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; -+} -+ - /* - * 64-bit feature tests via id registers. - */ -diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index 15f4ee92..afdabbeb 100644 ---- a/target/arm/cpu64.c -+++ b/target/arm/cpu64.c -@@ -123,7 +123,7 @@ static void aarch64_a57_initfn(Object *obj) - cpu->reset_sctlr = 0x00c50838; - cpu->id_pfr0 = 0x00000131; - cpu->id_pfr1 = 0x00011011; -- cpu->id_dfr0 = 0x03010066; -+ cpu->isar.id_dfr0 = 0x03010066; - cpu->id_afr0 = 0x00000000; - cpu->id_mmfr0 = 0x10101105; - cpu->id_mmfr1 = 0x40000000; -@@ -177,7 +177,7 @@ static void aarch64_a53_initfn(Object *obj) - cpu->reset_sctlr = 0x00c50838; - cpu->id_pfr0 = 0x00000131; - cpu->id_pfr1 = 0x00011011; -- cpu->id_dfr0 = 0x03010066; -+ cpu->isar.id_dfr0 = 0x03010066; - cpu->id_afr0 = 0x00000000; - cpu->id_mmfr0 = 0x10101105; - cpu->id_mmfr1 = 0x40000000; -@@ -231,7 +231,7 @@ static void aarch64_a72_initfn(Object *obj) - cpu->reset_sctlr = 0x00c50838; - cpu->id_pfr0 = 0x00000131; - cpu->id_pfr1 = 0x00011011; -- cpu->id_dfr0 = 0x03010066; -+ cpu->isar.id_dfr0 = 0x03010066; - cpu->id_afr0 = 0x00000000; - cpu->id_mmfr0 = 0x10201105; - cpu->id_mmfr1 = 0x40000000; -diff --git a/target/arm/helper.c b/target/arm/helper.c -index 419be640..3f06ca19 100644 ---- a/target/arm/helper.c -+++ b/target/arm/helper.c -@@ -5907,7 +5907,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) - { .name = "ID_DFR0", .state = ARM_CP_STATE_BOTH, - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 2, - .access = PL1_R, .type = ARM_CP_CONST, -- .resetvalue = cpu->id_dfr0 }, -+ .resetvalue = cpu->isar.id_dfr0 }, - { .name = "ID_AFR0", .state = ARM_CP_STATE_BOTH, - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 3, - .access = PL1_R, .type = ARM_CP_CONST, -@@ -6050,8 +6050,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) - } else { - define_arm_cp_regs(cpu, not_v7_cp_reginfo); - } -- if (FIELD_EX32(cpu->id_dfr0, ID_DFR0, PERFMON) >= 4 && -- FIELD_EX32(cpu->id_dfr0, ID_DFR0, PERFMON) != 0xf) { -+ if (cpu_isar_feature(aa32_pmu_8_1, cpu)) { - ARMCPRegInfo v81_pmu_regs[] = { - { .name = "PMCEID2", .state = ARM_CP_STATE_AA32, - .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 4, --- -2.25.1 - diff --git a/target-arm-Don-t-abort-on-M-profile-exception-return.patch b/target-arm-Don-t-abort-on-M-profile-exception-return.patch deleted file mode 100644 index b6796e25b8b04c76a117ad129cb807a0da93da45..0000000000000000000000000000000000000000 --- a/target-arm-Don-t-abort-on-M-profile-exception-return.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 9027d3fba605d8f6093342ebe4a1da450d374630 Mon Sep 17 00:00:00 2001 -From: Peter Maydell -Date: Thu, 22 Aug 2019 14:15:34 +0100 -Subject: [PATCH] target/arm: Don't abort on M-profile exception return in - linux-user mode - -An attempt to do an exception-return (branch to one of the magic -addresses) in linux-user mode for M-profile should behave like -a normal branch, because linux-user mode is always going to be -in 'handler' mode. This used to work, but we broke it when we added -support for the M-profile security extension in commit d02a8698d7ae2bfed. - -In that commit we allowed even handler-mode calls to magic return -values to be checked for and dealt with by causing an -EXCP_EXCEPTION_EXIT exception to be taken, because this is -needed for the FNC_RETURN return-from-non-secure-function-call -handling. For system mode we added a check in do_v7m_exception_exit() -to make any spurious calls from Handler mode behave correctly, but -forgot that linux-user mode would also be affected. - -How an attempted return-from-non-secure-function-call in linux-user -mode should be handled is not clear -- on real hardware it would -result in return to secure code (not to the Linux kernel) which -could then handle the error in any way it chose. For QEMU we take -the simple approach of treating this erroneous return the same way -it would be handled on a CPU without the security extensions -- -treat it as a normal branch. - -The upshot of all this is that for linux-user mode we should never -do any of the bx_excret magic, so the code change is simple. - -This ought to be a weird corner case that only affects broken guest -code (because Linux user processes should never be attempting to do -exception returns or NS function returns), except that the code that -assigns addresses in RAM for the process and stack in our linux-user -code does not attempt to avoid this magic address range, so -legitimate code attempting to return to a trampoline routine on the -stack can fall into this case. This change fixes those programs, -but we should also look at restricting the range of memory we -use for M-profile linux-user guests to the area that would be -real RAM in hardware. - -Cc: qemu-stable@nongnu.org -Reported-by: Christophe Lyon -Reviewed-by: Richard Henderson -Signed-off-by: Peter Maydell -Message-id: 20190822131534.16602-1-peter.maydell@linaro.org -Fixes: https://bugs.launchpad.net/qemu/+bug/1840922 -Signed-off-by: Peter Maydell -(cherry picked from commit 5e5584c89f36b302c666bc6db535fd3f7ff35ad2) -Signed-off-by: Michael Roth ---- - target/arm/translate.c | 21 ++++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) - -diff --git a/target/arm/translate.c b/target/arm/translate.c -index 7853462b21..24cb4ba075 100644 ---- a/target/arm/translate.c -+++ b/target/arm/translate.c -@@ -952,10 +952,27 @@ static inline void gen_bx(DisasContext *s, TCGv_i32 var) - store_cpu_field(var, thumb); - } - --/* Set PC and Thumb state from var. var is marked as dead. -+/* -+ * Set PC and Thumb state from var. var is marked as dead. - * For M-profile CPUs, include logic to detect exception-return - * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC, - * and BX reg, and no others, and happens only for code in Handler mode. -+ * The Security Extension also requires us to check for the FNC_RETURN -+ * which signals a function return from non-secure state; this can happen -+ * in both Handler and Thread mode. -+ * To avoid having to do multiple comparisons in inline generated code, -+ * we make the check we do here loose, so it will match for EXC_RETURN -+ * in Thread mode. For system emulation do_v7m_exception_exit() checks -+ * for these spurious cases and returns without doing anything (giving -+ * the same behaviour as for a branch to a non-magic address). -+ * -+ * In linux-user mode it is unclear what the right behaviour for an -+ * attempted FNC_RETURN should be, because in real hardware this will go -+ * directly to Secure code (ie not the Linux kernel) which will then treat -+ * the error in any way it chooses. For QEMU we opt to make the FNC_RETURN -+ * attempt behave the way it would on a CPU without the security extension, -+ * which is to say "like a normal branch". That means we can simply treat -+ * all branches as normal with no magic address behaviour. - */ - static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var) - { -@@ -963,10 +980,12 @@ static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var) - * s->base.is_jmp that we need to do the rest of the work later. - */ - gen_bx(s, var); -+#ifndef CONFIG_USER_ONLY - if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) || - (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) { - s->base.is_jmp = DISAS_BX_EXCRET; - } -+#endif - } - - static inline void gen_bx_excret_final_code(DisasContext *s) --- -2.23.0 diff --git a/target-arm-Enable-ARMv8.2-ATS1E1-in-cpu-max.patch b/target-arm-Enable-ARMv8.2-ATS1E1-in-cpu-max.patch deleted file mode 100644 index d6e82fae2dc02954d37eb723f930bccd28b70618..0000000000000000000000000000000000000000 --- a/target-arm-Enable-ARMv8.2-ATS1E1-in-cpu-max.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 69eedbfc873ded9bf35439b813e9f6a7431dc727 Mon Sep 17 00:00:00 2001 -From: Richard Henderson -Date: Sat, 8 Feb 2020 12:58:12 +0000 -Subject: [PATCH 09/13] target/arm: Enable ARMv8.2-ATS1E1 in -cpu max - -This includes enablement of ARMv8.1-PAN. - -Reviewed-by: Peter Maydell -Signed-off-by: Richard Henderson -Message-id: 20200208125816.14954-17-richard.henderson@linaro.org -Signed-off-by: Peter Maydell ---- - target/arm/cpu.c | 4 ++++ - target/arm/cpu64.c | 5 +++++ - 2 files changed, 9 insertions(+) - -diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index a23c71db..119bd275 100644 ---- a/target/arm/cpu.c -+++ b/target/arm/cpu.c -@@ -2484,6 +2484,10 @@ static void arm_max_initfn(Object *obj) - t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */ - cpu->isar.mvfr2 = t; - -+ t = cpu->id_mmfr3; -+ t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */ -+ cpu->id_mmfr3 = t; -+ - t = cpu->id_mmfr4; - t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */ - cpu->id_mmfr4 = t; -diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index 7ad8b5e2..a0d07fd7 100644 ---- a/target/arm/cpu64.c -+++ b/target/arm/cpu64.c -@@ -362,6 +362,7 @@ static void aarch64_max_initfn(Object *obj) - t = cpu->isar.id_aa64mmfr1; - t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */ - t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); -+ t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */ - cpu->isar.id_aa64mmfr1 = t; - - /* Replicate the same data to the 32-bit id registers. */ -@@ -382,6 +383,10 @@ static void aarch64_max_initfn(Object *obj) - u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1); - cpu->isar.id_isar6 = u; - -+ u = cpu->id_mmfr3; -+ u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */ -+ cpu->id_mmfr3 = u; -+ - /* - * FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet, - * so do not set MVFR1.FPHP. Strictly speaking this is not legal, --- -2.25.1 - diff --git a/target-arm-Fix-PAuth-sbox-functions.patch b/target-arm-Fix-PAuth-sbox-functions.patch deleted file mode 100644 index ac8d05065f766eb8ca90cd00de6a60350c2306c3..0000000000000000000000000000000000000000 --- a/target-arm-Fix-PAuth-sbox-functions.patch +++ /dev/null @@ -1,49 +0,0 @@ -From a7149fc18020c3d432c31838069dcfcb745299bf Mon Sep 17 00:00:00 2001 -From: zhanghailiang -Date: Sat, 20 Jun 2020 12:01:30 +0800 -Subject: [PATCH] target/arm: Fix PAuth sbox functions - -In the PAC computation, sbox was applied over wrong bits. -As this is a 4-bit sbox, bit index should be incremented by 4 instead of 16. - -Test vector from QARMA paper (https://eprint.iacr.org/2016/444.pdf) was -used to verify one computation of the pauth_computepac() function which -uses sbox2. - -Launchpad: https://bugs.launchpad.net/bugs/1859713 -Reviewed-by: Richard Henderson -Signed-off-by: Vincent DEHORS -Signed-off-by: Adrien GRASSEIN -Message-id: 20200116230809.19078-2-richard.henderson@linaro.org -Reviewed-by: Peter Maydell -Signed-off-by: Peter Maydell -Signed-off-by: zhanghailiang ---- - target/arm/pauth_helper.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/target/arm/pauth_helper.c b/target/arm/pauth_helper.c -index d3194f20..0a5f41e1 100644 ---- a/target/arm/pauth_helper.c -+++ b/target/arm/pauth_helper.c -@@ -89,7 +89,7 @@ static uint64_t pac_sub(uint64_t i) - uint64_t o = 0; - int b; - -- for (b = 0; b < 64; b += 16) { -+ for (b = 0; b < 64; b += 4) { - o |= (uint64_t)sub[(i >> b) & 0xf] << b; - } - return o; -@@ -104,7 +104,7 @@ static uint64_t pac_inv_sub(uint64_t i) - uint64_t o = 0; - int b; - -- for (b = 0; b < 64; b += 16) { -+ for (b = 0; b < 64; b += 4) { - o |= (uint64_t)inv_sub[(i >> b) & 0xf] << b; - } - return o; --- -2.23.0 - diff --git a/target-arm-Fix-some-compile-errors.patch b/target-arm-Fix-some-compile-errors.patch new file mode 100644 index 0000000000000000000000000000000000000000..2a0e1e9dda1b6552e33a9a5b93806e3c1d0d9305 --- /dev/null +++ b/target-arm-Fix-some-compile-errors.patch @@ -0,0 +1,89 @@ +From 6a5a391c9c6f6c0cd105ce3495acc10868bad884 Mon Sep 17 00:00:00 2001 +From: Dongxu Sun +Date: Tue, 15 Feb 2022 14:40:48 +0800 +Subject: [PATCH] target/arm: Fix some compile errors + +fix compile errors like: + "implicit declaration of function 'kvm_arm_cpu_feature_supported'"; + "undefined reference to 'kvm_arm_get_one_reg'" + "undefined reference to 'kvm_arm_set_one_reg'" + "'kvmval' may be used uninitialized" + "'oldval' may be used uninitialized" + +Signed-off-by: Dongxu Sun +--- + target/arm/helper.c | 4 ++-- + target/arm/kvm_arm.h | 23 ++++++++++++++++++++--- + 2 files changed, 22 insertions(+), 5 deletions(-) + +diff --git a/target/arm/helper.c b/target/arm/helper.c +index 1dd5d64d96..80737a8d7b 100644 +--- a/target/arm/helper.c ++++ b/target/arm/helper.c +@@ -168,8 +168,8 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) + if (kvm_sync) { + if (is_id_reg(ri)) { + /* Only sync if we can sync to KVM successfully. */ +- uint64_t oldval; +- uint64_t kvmval; ++ uint64_t oldval = 0; ++ uint64_t kvmval = 0; + + if (kvm_arm_get_one_reg(cpu, cpu->cpreg_indexes[i], &oldval)) { + continue; +diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h +index 82145607ec..8b644b3924 100644 +--- a/target/arm/kvm_arm.h ++++ b/target/arm/kvm_arm.h +@@ -377,6 +377,9 @@ void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa); + + int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level); + ++int kvm_arm_get_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *target); ++int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *source); ++ + #else + + /* +@@ -403,6 +406,11 @@ static inline bool kvm_arm_steal_time_supported(void) + return false; + } + ++static inline bool kvm_arm_cpu_feature_supported(void) ++{ ++ return false; ++} ++ + /* + * These functions should never actually be called without KVM support. + */ +@@ -451,6 +459,18 @@ static inline void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map) + g_assert_not_reached(); + } + ++static inline int kvm_arm_get_one_reg(ARMCPU *cpu, uint64_t regidx, ++ uint64_t *target) ++{ ++ g_assert_not_reached(); ++} ++ ++static inline int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, ++ uint64_t *source) ++{ ++ g_assert_not_reached(); ++} ++ + #endif + + static inline const char *gic_class_name(void) +@@ -535,7 +555,4 @@ static inline const char *its_class_name(void) + } + } + +-int kvm_arm_get_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *target); +-int kvm_arm_set_one_reg(ARMCPU *cpu, uint64_t regidx, uint64_t *source); +- + #endif +-- +2.27.0 + diff --git a/target-arm-Fix-write-redundant-values-to-kvm.patch b/target-arm-Fix-write-redundant-values-to-kvm.patch index e165d04bafdd3fa3ceca0a1c0af68dfc0bb95df4..db03f8b6710f725610022f78d7b5c33a27ff3acc 100644 --- a/target-arm-Fix-write-redundant-values-to-kvm.patch +++ b/target-arm-Fix-write-redundant-values-to-kvm.patch @@ -1,4 +1,4 @@ -From 479c384f2944f52f9199bffa191b587a3f02663c Mon Sep 17 00:00:00 2001 +From 9680adfba5ca871f69a6fbd15b92571fc2a52d78 Mon Sep 17 00:00:00 2001 From: Peng Liang Date: Wed, 9 Dec 2020 19:35:08 +0800 Subject: [PATCH] target/arm: Fix write redundant values to kvm @@ -10,15 +10,16 @@ for other registers. (cherry-picked from a0d7a9de807639fcfcbe1fe037cb8772d459a9cf) Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun --- target/arm/helper.c | 73 ++++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c -index b262f5d6c5..bddd355fa0 100644 +index 4c7b4cadfa..1dd5d64d96 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c -@@ -252,6 +252,16 @@ static bool raw_accessors_invalid(const ARMCPRegInfo *ri) +@@ -134,6 +134,16 @@ static bool raw_accessors_invalid(const ARMCPRegInfo *ri) return true; } @@ -35,7 +36,7 @@ index b262f5d6c5..bddd355fa0 100644 bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) { /* Write the coprocessor state from cpu->env to the (index,value) list. */ -@@ -268,38 +278,53 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) +@@ -150,38 +160,53 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) ok = false; continue; } diff --git a/target-arm-Free-TCG-temps-in-trans_VMOV_64_sp.patch b/target-arm-Free-TCG-temps-in-trans_VMOV_64_sp.patch deleted file mode 100644 index a46232f8ba04e1e2a956d8493dc1515fcf1f272a..0000000000000000000000000000000000000000 --- a/target-arm-Free-TCG-temps-in-trans_VMOV_64_sp.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 38fb634853ac6547326d9f88b9a068d9fc6b4ad4 Mon Sep 17 00:00:00 2001 -From: Peter Maydell -Date: Tue, 27 Aug 2019 13:19:31 +0100 -Subject: [PATCH] target/arm: Free TCG temps in trans_VMOV_64_sp() -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The function neon_store_reg32() doesn't free the TCG temp that it -is passed, so the caller must do that. We got this right in most -places but forgot to free the TCG temps in trans_VMOV_64_sp(). - -Cc: qemu-stable@nongnu.org -Signed-off-by: Peter Maydell -Reviewed-by: Richard Henderson -Reviewed-by: Philippe Mathieu-Daudé -Message-id: 20190827121931.26836-1-peter.maydell@linaro.org -(cherry picked from commit 342d27581bd3ecdb995e4fc55fcd383cf3242888) -Signed-off-by: Michael Roth ---- - target/arm/translate-vfp.inc.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c -index 092eb5ec53..ef45cecbea 100644 ---- a/target/arm/translate-vfp.inc.c -+++ b/target/arm/translate-vfp.inc.c -@@ -881,8 +881,10 @@ static bool trans_VMOV_64_sp(DisasContext *s, arg_VMOV_64_sp *a) - /* gpreg to fpreg */ - tmp = load_reg(s, a->rt); - neon_store_reg32(tmp, a->vm); -+ tcg_temp_free_i32(tmp); - tmp = load_reg(s, a->rt2); - neon_store_reg32(tmp, a->vm + 1); -+ tcg_temp_free_i32(tmp); - } - - return true; --- -2.23.0 diff --git a/target-arm-Move-DBGDIDR-into-ARMISARegisters.patch b/target-arm-Move-DBGDIDR-into-ARMISARegisters.patch deleted file mode 100644 index e7f2833ee889363902a3e063bffbbff4b4e2c6af..0000000000000000000000000000000000000000 --- a/target-arm-Move-DBGDIDR-into-ARMISARegisters.patch +++ /dev/null @@ -1,158 +0,0 @@ -From df641941e6fd7fef78e5c77c9a809a7a8e148589 Mon Sep 17 00:00:00 2001 -From: Peter Maydell -Date: Fri, 14 Feb 2020 17:51:06 +0000 -Subject: [PATCH 08/13] target/arm: Move DBGDIDR into ARMISARegisters - -We're going to want to read the DBGDIDR register from KVM in -a subsequent commit, which means it needs to be in the -ARMISARegisters sub-struct. Move it. - -Signed-off-by: Peter Maydell -Reviewed-by: Richard Henderson -Message-id: 20200214175116.9164-12-peter.maydell@linaro.org ---- - target/arm/cpu.c | 8 ++++---- - target/arm/cpu.h | 2 +- - target/arm/cpu64.c | 6 +++--- - target/arm/helper.c | 2 +- - target/arm/internals.h | 6 +++--- - 5 files changed, 12 insertions(+), 12 deletions(-) - -diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index bb2edf4e..a23c71db 100644 ---- a/target/arm/cpu.c -+++ b/target/arm/cpu.c -@@ -2070,7 +2070,7 @@ static void cortex_a8_initfn(Object *obj) - cpu->isar.id_isar2 = 0x21232031; - cpu->isar.id_isar3 = 0x11112131; - cpu->isar.id_isar4 = 0x00111142; -- cpu->dbgdidr = 0x15141000; -+ cpu->isar.dbgdidr = 0x15141000; - cpu->clidr = (1 << 27) | (2 << 24) | 3; - cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */ - cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */ -@@ -2143,7 +2143,7 @@ static void cortex_a9_initfn(Object *obj) - cpu->isar.id_isar2 = 0x21232041; - cpu->isar.id_isar3 = 0x11112131; - cpu->isar.id_isar4 = 0x00111142; -- cpu->dbgdidr = 0x35141000; -+ cpu->isar.dbgdidr = 0x35141000; - cpu->clidr = (1 << 27) | (1 << 24) | 3; - cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */ - cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */ -@@ -2211,7 +2211,7 @@ static void cortex_a7_initfn(Object *obj) - cpu->isar.id_isar2 = 0x21232041; - cpu->isar.id_isar3 = 0x11112131; - cpu->isar.id_isar4 = 0x10011142; -- cpu->dbgdidr = 0x3515f005; -+ cpu->isar.dbgdidr = 0x3515f005; - cpu->clidr = 0x0a200023; - cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */ - cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */ -@@ -2254,7 +2254,7 @@ static void cortex_a15_initfn(Object *obj) - cpu->isar.id_isar2 = 0x21232041; - cpu->isar.id_isar3 = 0x11112131; - cpu->isar.id_isar4 = 0x10011142; -- cpu->dbgdidr = 0x3515f021; -+ cpu->isar.dbgdidr = 0x3515f021; - cpu->clidr = 0x0a200023; - cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */ - cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */ -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index 4b1ae32b..3040aa40 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -861,6 +861,7 @@ struct ARMCPU { - uint32_t mvfr1; - uint32_t mvfr2; - uint32_t id_dfr0; -+ uint32_t dbgdidr; - uint64_t id_aa64isar0; - uint64_t id_aa64isar1; - uint64_t id_aa64pfr0; -@@ -888,7 +889,6 @@ struct ARMCPU { - uint32_t id_mmfr4; - uint64_t id_aa64afr0; - uint64_t id_aa64afr1; -- uint32_t dbgdidr; - uint32_t clidr; - uint64_t mp_affinity; /* MP ID without feature bits */ - /* The elements of this array are the CCSIDR values for each cache, -diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index aa96548f..7ad8b5e2 100644 ---- a/target/arm/cpu64.c -+++ b/target/arm/cpu64.c -@@ -140,7 +140,7 @@ static void aarch64_a57_initfn(Object *obj) - cpu->isar.id_aa64dfr0 = 0x10305106; - cpu->isar.id_aa64isar0 = 0x00011120; - cpu->isar.id_aa64mmfr0 = 0x00001124; -- cpu->dbgdidr = 0x3516d000; -+ cpu->isar.dbgdidr = 0x3516d000; - cpu->clidr = 0x0a200023; - cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ - cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ -@@ -194,7 +194,7 @@ static void aarch64_a53_initfn(Object *obj) - cpu->isar.id_aa64dfr0 = 0x10305106; - cpu->isar.id_aa64isar0 = 0x00011120; - cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */ -- cpu->dbgdidr = 0x3516d000; -+ cpu->isar.dbgdidr = 0x3516d000; - cpu->clidr = 0x0a200023; - cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ - cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */ -@@ -247,7 +247,7 @@ static void aarch64_a72_initfn(Object *obj) - cpu->isar.id_aa64dfr0 = 0x10305106; - cpu->isar.id_aa64isar0 = 0x00011120; - cpu->isar.id_aa64mmfr0 = 0x00001124; -- cpu->dbgdidr = 0x3516d000; -+ cpu->isar.dbgdidr = 0x3516d000; - cpu->clidr = 0x0a200023; - cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ - cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ -diff --git a/target/arm/helper.c b/target/arm/helper.c -index c1ff4b6b..60ff7c0f 100644 ---- a/target/arm/helper.c -+++ b/target/arm/helper.c -@@ -5597,7 +5597,7 @@ static void define_debug_regs(ARMCPU *cpu) - ARMCPRegInfo dbgdidr = { - .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL0_R, .accessfn = access_tda, -- .type = ARM_CP_CONST, .resetvalue = cpu->dbgdidr, -+ .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr, - }; - - /* Note that all these register fields hold "number of Xs minus 1". */ -diff --git a/target/arm/internals.h b/target/arm/internals.h -index a72d0a6c..1d01ecc4 100644 ---- a/target/arm/internals.h -+++ b/target/arm/internals.h -@@ -867,7 +867,7 @@ static inline int arm_num_brps(ARMCPU *cpu) - if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { - return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1; - } else { -- return FIELD_EX32(cpu->dbgdidr, DBGDIDR, BRPS) + 1; -+ return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, BRPS) + 1; - } - } - -@@ -881,7 +881,7 @@ static inline int arm_num_wrps(ARMCPU *cpu) - if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { - return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1; - } else { -- return FIELD_EX32(cpu->dbgdidr, DBGDIDR, WRPS) + 1; -+ return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, WRPS) + 1; - } - } - -@@ -895,7 +895,7 @@ static inline int arm_num_ctx_cmps(ARMCPU *cpu) - if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { - return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) + 1; - } else { -- return FIELD_EX32(cpu->dbgdidr, DBGDIDR, CTX_CMPS) + 1; -+ return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, CTX_CMPS) + 1; - } - } - --- -2.25.1 - diff --git a/target-arm-Read-debug-related-ID-registers-from-KVM.patch b/target-arm-Read-debug-related-ID-registers-from-KVM.patch deleted file mode 100644 index 1be7cd1713a456204efcb412c1d76398991ef77d..0000000000000000000000000000000000000000 --- a/target-arm-Read-debug-related-ID-registers-from-KVM.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 9cda8af5af9e95e7b0ff683d0fb661c1ffcba8d8 Mon Sep 17 00:00:00 2001 -From: Peter Maydell -Date: Fri, 14 Feb 2020 17:51:07 +0000 -Subject: [PATCH 11/13] target/arm: Read debug-related ID registers from KVM - -Now we have isar_feature test functions that look at fields in the -ID_AA64DFR0_EL1 and ID_DFR0 ID registers, add the code that reads -these register values from KVM so that the checks behave correctly -when we're using KVM. - -No isar_feature function tests ID_AA64DFR1_EL1 or DBGDIDR yet, but we -add it to maintain the invariant that every field in the -ARMISARegisters struct is populated for a KVM CPU and can be relied -on. This requirement isn't actually written down yet, so add a note -to the relevant comment. - -Signed-off-by: Peter Maydell -Reviewed-by: Richard Henderson -Message-id: 20200214175116.9164-13-peter.maydell@linaro.org ---- - target/arm/cpu.h | 5 +++++ - target/arm/kvm32.c | 8 ++++++++ - target/arm/kvm64.c | 36 ++++++++++++++++++++++++++++++++++++ - 3 files changed, 49 insertions(+) - -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index a78c30c3..56d8cd8c 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -848,6 +848,11 @@ struct ARMCPU { - * prefix means a constant register. - * Some of these registers are split out into a substructure that - * is shared with the translators to control the ISA. -+ * -+ * Note that if you add an ID register to the ARMISARegisters struct -+ * you need to also update the 32-bit and 64-bit versions of the -+ * kvm_arm_get_host_cpu_features() function to correctly populate the -+ * field by reading the value from the KVM vCPU. - */ - struct ARMISARegisters { - uint32_t id_isar0; -diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c -index 2247148e..e984d52d 100644 ---- a/target/arm/kvm32.c -+++ b/target/arm/kvm32.c -@@ -93,6 +93,9 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) - ahcf->isar.id_isar6 = 0; - } - -+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0, -+ ARM_CP15_REG32(0, 0, 1, 2)); -+ - err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0, - KVM_REG_ARM | KVM_REG_SIZE_U32 | - KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR0); -@@ -121,6 +124,11 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) - ahcf->isar.id_mmfr4 = 0; - } - -+ /* -+ * There is no way to read DBGDIDR, because currently 32-bit KVM -+ * doesn't implement debug at all. Leave it at zero. -+ */ -+ - kvm_arm_destroy_scratch_host_vcpu(fdarray); - - if (err < 0) { -diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c -index 276d1466..2a88b8df 100644 ---- a/target/arm/kvm64.c -+++ b/target/arm/kvm64.c -@@ -533,6 +533,10 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) - } else { - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr1, - ARM64_SYS_REG(3, 0, 0, 4, 1)); -+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr0, -+ ARM64_SYS_REG(3, 0, 0, 5, 0)); -+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64dfr1, -+ ARM64_SYS_REG(3, 0, 0, 5, 1)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar0, - ARM64_SYS_REG(3, 0, 0, 6, 0)); - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1, -@@ -551,6 +555,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) - * than skipping the reads and leaving 0, as we must avoid - * considering the values in every case. - */ -+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0, -+ ARM64_SYS_REG(3, 0, 0, 1, 2)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, - ARM64_SYS_REG(3, 0, 0, 1, 4)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1, -@@ -582,6 +588,36 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) - ARM64_SYS_REG(3, 0, 0, 3, 1)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2, - ARM64_SYS_REG(3, 0, 0, 3, 2)); -+ -+ /* -+ * DBGDIDR is a bit complicated because the kernel doesn't -+ * provide an accessor for it in 64-bit mode, which is what this -+ * scratch VM is in, and there's no architected "64-bit sysreg -+ * which reads the same as the 32-bit register" the way there is -+ * for other ID registers. Instead we synthesize a value from the -+ * AArch64 ID_AA64DFR0, the same way the kernel code in -+ * arch/arm64/kvm/sys_regs.c:trap_dbgidr() does. -+ * We only do this if the CPU supports AArch32 at EL1. -+ */ -+ if (FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL1) >= 2) { -+ int wrps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, WRPS); -+ int brps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, BRPS); -+ int ctx_cmps = -+ FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS); -+ int version = 6; /* ARMv8 debug architecture */ -+ bool has_el3 = -+ !!FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL3); -+ uint32_t dbgdidr = 0; -+ -+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, WRPS, wrps); -+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, BRPS, brps); -+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, CTX_CMPS, ctx_cmps); -+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, VERSION, version); -+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, NSUHD_IMP, has_el3); -+ dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, SE_IMP, has_el3); -+ dbgdidr |= (1 << 15); /* RES1 bit */ -+ ahcf->isar.dbgdidr = dbgdidr; -+ } - } - - kvm_arm_destroy_scratch_host_vcpu(fdarray); --- -2.25.1 - diff --git a/target-arm-Stop-assuming-DBGDIDR-always-exists.patch b/target-arm-Stop-assuming-DBGDIDR-always-exists.patch deleted file mode 100644 index c7648c5430ebd61b2267a184ad16828dd8d25015..0000000000000000000000000000000000000000 --- a/target-arm-Stop-assuming-DBGDIDR-always-exists.patch +++ /dev/null @@ -1,186 +0,0 @@ -From 1d4d4cda9637ec09f8cf30785f68b58cd46815c8 Mon Sep 17 00:00:00 2001 -From: Peter Maydell -Date: Fri, 14 Feb 2020 17:51:05 +0000 -Subject: [PATCH 07/13] target/arm: Stop assuming DBGDIDR always exists - -The AArch32 DBGDIDR defines properties like the number of -breakpoints, watchpoints and context-matching comparators. On an -AArch64 CPU, the register may not even exist if AArch32 is not -supported at EL1. - -Currently we hard-code use of DBGDIDR to identify the number of -breakpoints etc; this works for all our TCG CPUs, but will break if -we ever add an AArch64-only CPU. We also have an assert() that the -AArch32 and AArch64 registers match, which currently works only by -luck for KVM because we don't populate either of these ID registers -from the KVM vCPU and so they are both zero. - -Clean this up so we have functions for finding the number -of breakpoints, watchpoints and context comparators which look -in the appropriate ID register. - -This allows us to drop the "check that AArch64 and AArch32 agree -on the number of breakpoints etc" asserts: - * we no longer look at the AArch32 versions unless that's the - right place to be looking - * it's valid to have a CPU (eg AArch64-only) where they don't match - * we shouldn't have been asserting the validity of ID registers - in a codepath used with KVM anyway - -Signed-off-by: Peter Maydell -Reviewed-by: Richard Henderson -Message-id: 20200214175116.9164-11-peter.maydell@linaro.org ---- - target/arm/cpu.h | 7 +++++++ - target/arm/debug_helper.c | 6 +++--- - target/arm/helper.c | 21 +++++--------------- - target/arm/internals.h | 42 +++++++++++++++++++++++++++++++++++++++ - 4 files changed, 57 insertions(+), 19 deletions(-) - -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index 230130be..4b1ae32b 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -1798,6 +1798,13 @@ FIELD(ID_DFR0, MPROFDBG, 20, 4) - FIELD(ID_DFR0, PERFMON, 24, 4) - FIELD(ID_DFR0, TRACEFILT, 28, 4) - -+FIELD(DBGDIDR, SE_IMP, 12, 1) -+FIELD(DBGDIDR, NSUHD_IMP, 14, 1) -+FIELD(DBGDIDR, VERSION, 16, 4) -+FIELD(DBGDIDR, CTX_CMPS, 20, 4) -+FIELD(DBGDIDR, BRPS, 24, 4) -+FIELD(DBGDIDR, WRPS, 28, 4) -+ - FIELD(MVFR0, SIMDREG, 0, 4) - FIELD(MVFR0, FPSP, 4, 4) - FIELD(MVFR0, FPDP, 8, 4) -diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c -index dde80273..3f8f667d 100644 ---- a/target/arm/debug_helper.c -+++ b/target/arm/debug_helper.c -@@ -16,8 +16,8 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn) - { - CPUARMState *env = &cpu->env; - uint64_t bcr = env->cp15.dbgbcr[lbn]; -- int brps = extract32(cpu->dbgdidr, 24, 4); -- int ctx_cmps = extract32(cpu->dbgdidr, 20, 4); -+ int brps = arm_num_brps(cpu); -+ int ctx_cmps = arm_num_ctx_cmps(cpu); - int bt; - uint32_t contextidr; - -@@ -28,7 +28,7 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn) - * case DBGWCR_EL1.LBN must indicate that breakpoint). - * We choose the former. - */ -- if (lbn > brps || lbn < (brps - ctx_cmps)) { -+ if (lbn >= brps || lbn < (brps - ctx_cmps)) { - return false; - } - -diff --git a/target/arm/helper.c b/target/arm/helper.c -index a71f4ef6..c1ff4b6b 100644 ---- a/target/arm/helper.c -+++ b/target/arm/helper.c -@@ -5601,23 +5601,12 @@ static void define_debug_regs(ARMCPU *cpu) - }; - - /* Note that all these register fields hold "number of Xs minus 1". */ -- brps = extract32(cpu->dbgdidr, 24, 4); -- wrps = extract32(cpu->dbgdidr, 28, 4); -- ctx_cmps = extract32(cpu->dbgdidr, 20, 4); -+ brps = arm_num_brps(cpu); -+ wrps = arm_num_wrps(cpu); -+ ctx_cmps = arm_num_ctx_cmps(cpu); - - assert(ctx_cmps <= brps); - -- /* The DBGDIDR and ID_AA64DFR0_EL1 define various properties -- * of the debug registers such as number of breakpoints; -- * check that if they both exist then they agree. -- */ -- if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { -- assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) == brps); -- assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) == wrps); -- assert(FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) -- == ctx_cmps); -- } -- - define_one_arm_cp_reg(cpu, &dbgdidr); - define_arm_cp_regs(cpu, debug_cp_reginfo); - -@@ -5625,7 +5614,7 @@ static void define_debug_regs(ARMCPU *cpu) - define_arm_cp_regs(cpu, debug_lpae_cp_reginfo); - } - -- for (i = 0; i < brps + 1; i++) { -+ for (i = 0; i < brps; i++) { - ARMCPRegInfo dbgregs[] = { - { .name = "DBGBVR", .state = ARM_CP_STATE_BOTH, - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4, -@@ -5644,7 +5633,7 @@ static void define_debug_regs(ARMCPU *cpu) - define_arm_cp_regs(cpu, dbgregs); - } - -- for (i = 0; i < wrps + 1; i++) { -+ for (i = 0; i < wrps; i++) { - ARMCPRegInfo dbgregs[] = { - { .name = "DBGWVR", .state = ARM_CP_STATE_BOTH, - .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6, -diff --git a/target/arm/internals.h b/target/arm/internals.h -index 232d9638..a72d0a6c 100644 ---- a/target/arm/internals.h -+++ b/target/arm/internals.h -@@ -857,6 +857,48 @@ static inline uint32_t arm_debug_exception_fsr(CPUARMState *env) - } - } - -+/** -+ * arm_num_brps: Return number of implemented breakpoints. -+ * Note that the ID register BRPS field is "number of bps - 1", -+ * and we return the actual number of breakpoints. -+ */ -+static inline int arm_num_brps(ARMCPU *cpu) -+{ -+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { -+ return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, BRPS) + 1; -+ } else { -+ return FIELD_EX32(cpu->dbgdidr, DBGDIDR, BRPS) + 1; -+ } -+} -+ -+/** -+ * arm_num_wrps: Return number of implemented watchpoints. -+ * Note that the ID register WRPS field is "number of wps - 1", -+ * and we return the actual number of watchpoints. -+ */ -+static inline int arm_num_wrps(ARMCPU *cpu) -+{ -+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { -+ return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, WRPS) + 1; -+ } else { -+ return FIELD_EX32(cpu->dbgdidr, DBGDIDR, WRPS) + 1; -+ } -+} -+ -+/** -+ * arm_num_ctx_cmps: Return number of implemented context comparators. -+ * Note that the ID register CTX_CMPS field is "number of cmps - 1", -+ * and we return the actual number of comparators. -+ */ -+static inline int arm_num_ctx_cmps(ARMCPU *cpu) -+{ -+ if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { -+ return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) + 1; -+ } else { -+ return FIELD_EX32(cpu->dbgdidr, DBGDIDR, CTX_CMPS) + 1; -+ } -+} -+ - /* Note make_memop_idx reserves 4 bits for mmu_idx, and MO_BSWAP is bit 3. - * Thus a TCGMemOpIdx, without any MO_ALIGN bits, fits in 8 bits. - */ --- -2.25.1 - diff --git a/target-arm-Test-correct-register-in-aa32_pan-and-aa3.patch b/target-arm-Test-correct-register-in-aa32_pan-and-aa3.patch deleted file mode 100644 index ecbaf7750c42aab1efade6d50e53fd7e92762883..0000000000000000000000000000000000000000 --- a/target-arm-Test-correct-register-in-aa32_pan-and-aa3.patch +++ /dev/null @@ -1,453 +0,0 @@ -From 2bc630dc858bd0c010b7c375ebf1e8f4b4e0e346 Mon Sep 17 00:00:00 2001 -From: Peter Maydell -Date: Fri, 14 Feb 2020 17:51:13 +0000 -Subject: [PATCH 10/13] target/arm: Test correct register in aa32_pan and - aa32_ats1e1 checks - -The isar_feature_aa32_pan and isar_feature_aa32_ats1e1 functions -are supposed to be testing fields in ID_MMFR3; but a cut-and-paste -error meant we were looking at MVFR0 instead. - -Fix the functions to look at the right register; this requires -us to move at least id_mmfr3 to the ARMISARegisters struct; we -choose to move all the ID_MMFRn registers for consistency. - -Fixes: 3d6ad6bb466f -Signed-off-by: Peter Maydell -Reviewed-by: Richard Henderson -Message-id: 20200214175116.9164-19-peter.maydell@linaro.org ---- - hw/intc/armv7m_nvic.c | 8 ++-- - target/arm/cpu.c | 96 +++++++++++++++++++++---------------------- - target/arm/cpu.h | 14 +++---- - target/arm/cpu64.c | 28 ++++++------- - target/arm/helper.c | 12 +++--- - target/arm/kvm32.c | 17 ++++++++ - target/arm/kvm64.c | 10 +++++ - 7 files changed, 106 insertions(+), 79 deletions(-) - -diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c -index 0741db7b..f7ef6ad1 100644 ---- a/hw/intc/armv7m_nvic.c -+++ b/hw/intc/armv7m_nvic.c -@@ -1227,13 +1227,13 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) - case 0xd4c: /* AFR0. */ - return cpu->id_afr0; - case 0xd50: /* MMFR0. */ -- return cpu->id_mmfr0; -+ return cpu->isar.id_mmfr0; - case 0xd54: /* MMFR1. */ -- return cpu->id_mmfr1; -+ return cpu->isar.id_mmfr1; - case 0xd58: /* MMFR2. */ -- return cpu->id_mmfr2; -+ return cpu->isar.id_mmfr2; - case 0xd5c: /* MMFR3. */ -- return cpu->id_mmfr3; -+ return cpu->isar.id_mmfr3; - case 0xd60: /* ISAR0. */ - return cpu->isar.id_isar0; - case 0xd64: /* ISAR1. */ -diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index 119bd275..c3728e3d 100644 ---- a/target/arm/cpu.c -+++ b/target/arm/cpu.c -@@ -1764,9 +1764,9 @@ static void arm1136_r2_initfn(Object *obj) - cpu->id_pfr1 = 0x1; - cpu->isar.id_dfr0 = 0x2; - cpu->id_afr0 = 0x3; -- cpu->id_mmfr0 = 0x01130003; -- cpu->id_mmfr1 = 0x10030302; -- cpu->id_mmfr2 = 0x01222110; -+ cpu->isar.id_mmfr0 = 0x01130003; -+ cpu->isar.id_mmfr1 = 0x10030302; -+ cpu->isar.id_mmfr2 = 0x01222110; - cpu->isar.id_isar0 = 0x00140011; - cpu->isar.id_isar1 = 0x12002111; - cpu->isar.id_isar2 = 0x11231111; -@@ -1796,9 +1796,9 @@ static void arm1136_initfn(Object *obj) - cpu->id_pfr1 = 0x1; - cpu->isar.id_dfr0 = 0x2; - cpu->id_afr0 = 0x3; -- cpu->id_mmfr0 = 0x01130003; -- cpu->id_mmfr1 = 0x10030302; -- cpu->id_mmfr2 = 0x01222110; -+ cpu->isar.id_mmfr0 = 0x01130003; -+ cpu->isar.id_mmfr1 = 0x10030302; -+ cpu->isar.id_mmfr2 = 0x01222110; - cpu->isar.id_isar0 = 0x00140011; - cpu->isar.id_isar1 = 0x12002111; - cpu->isar.id_isar2 = 0x11231111; -@@ -1829,9 +1829,9 @@ static void arm1176_initfn(Object *obj) - cpu->id_pfr1 = 0x11; - cpu->isar.id_dfr0 = 0x33; - cpu->id_afr0 = 0; -- cpu->id_mmfr0 = 0x01130003; -- cpu->id_mmfr1 = 0x10030302; -- cpu->id_mmfr2 = 0x01222100; -+ cpu->isar.id_mmfr0 = 0x01130003; -+ cpu->isar.id_mmfr1 = 0x10030302; -+ cpu->isar.id_mmfr2 = 0x01222100; - cpu->isar.id_isar0 = 0x0140011; - cpu->isar.id_isar1 = 0x12002111; - cpu->isar.id_isar2 = 0x11231121; -@@ -1859,9 +1859,9 @@ static void arm11mpcore_initfn(Object *obj) - cpu->id_pfr1 = 0x1; - cpu->isar.id_dfr0 = 0; - cpu->id_afr0 = 0x2; -- cpu->id_mmfr0 = 0x01100103; -- cpu->id_mmfr1 = 0x10020302; -- cpu->id_mmfr2 = 0x01222000; -+ cpu->isar.id_mmfr0 = 0x01100103; -+ cpu->isar.id_mmfr1 = 0x10020302; -+ cpu->isar.id_mmfr2 = 0x01222000; - cpu->isar.id_isar0 = 0x00100011; - cpu->isar.id_isar1 = 0x12002111; - cpu->isar.id_isar2 = 0x11221011; -@@ -1891,10 +1891,10 @@ static void cortex_m3_initfn(Object *obj) - cpu->id_pfr1 = 0x00000200; - cpu->isar.id_dfr0 = 0x00100000; - cpu->id_afr0 = 0x00000000; -- cpu->id_mmfr0 = 0x00000030; -- cpu->id_mmfr1 = 0x00000000; -- cpu->id_mmfr2 = 0x00000000; -- cpu->id_mmfr3 = 0x00000000; -+ cpu->isar.id_mmfr0 = 0x00000030; -+ cpu->isar.id_mmfr1 = 0x00000000; -+ cpu->isar.id_mmfr2 = 0x00000000; -+ cpu->isar.id_mmfr3 = 0x00000000; - cpu->isar.id_isar0 = 0x01141110; - cpu->isar.id_isar1 = 0x02111000; - cpu->isar.id_isar2 = 0x21112231; -@@ -1922,10 +1922,10 @@ static void cortex_m4_initfn(Object *obj) - cpu->id_pfr1 = 0x00000200; - cpu->isar.id_dfr0 = 0x00100000; - cpu->id_afr0 = 0x00000000; -- cpu->id_mmfr0 = 0x00000030; -- cpu->id_mmfr1 = 0x00000000; -- cpu->id_mmfr2 = 0x00000000; -- cpu->id_mmfr3 = 0x00000000; -+ cpu->isar.id_mmfr0 = 0x00000030; -+ cpu->isar.id_mmfr1 = 0x00000000; -+ cpu->isar.id_mmfr2 = 0x00000000; -+ cpu->isar.id_mmfr3 = 0x00000000; - cpu->isar.id_isar0 = 0x01141110; - cpu->isar.id_isar1 = 0x02111000; - cpu->isar.id_isar2 = 0x21112231; -@@ -1955,10 +1955,10 @@ static void cortex_m33_initfn(Object *obj) - cpu->id_pfr1 = 0x00000210; - cpu->isar.id_dfr0 = 0x00200000; - cpu->id_afr0 = 0x00000000; -- cpu->id_mmfr0 = 0x00101F40; -- cpu->id_mmfr1 = 0x00000000; -- cpu->id_mmfr2 = 0x01000000; -- cpu->id_mmfr3 = 0x00000000; -+ cpu->isar.id_mmfr0 = 0x00101F40; -+ cpu->isar.id_mmfr1 = 0x00000000; -+ cpu->isar.id_mmfr2 = 0x01000000; -+ cpu->isar.id_mmfr3 = 0x00000000; - cpu->isar.id_isar0 = 0x01101110; - cpu->isar.id_isar1 = 0x02212000; - cpu->isar.id_isar2 = 0x20232232; -@@ -2006,10 +2006,10 @@ static void cortex_r5_initfn(Object *obj) - cpu->id_pfr1 = 0x001; - cpu->isar.id_dfr0 = 0x010400; - cpu->id_afr0 = 0x0; -- cpu->id_mmfr0 = 0x0210030; -- cpu->id_mmfr1 = 0x00000000; -- cpu->id_mmfr2 = 0x01200000; -- cpu->id_mmfr3 = 0x0211; -+ cpu->isar.id_mmfr0 = 0x0210030; -+ cpu->isar.id_mmfr1 = 0x00000000; -+ cpu->isar.id_mmfr2 = 0x01200000; -+ cpu->isar.id_mmfr3 = 0x0211; - cpu->isar.id_isar0 = 0x02101111; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232141; -@@ -2061,10 +2061,10 @@ static void cortex_a8_initfn(Object *obj) - cpu->id_pfr1 = 0x11; - cpu->isar.id_dfr0 = 0x400; - cpu->id_afr0 = 0; -- cpu->id_mmfr0 = 0x31100003; -- cpu->id_mmfr1 = 0x20000000; -- cpu->id_mmfr2 = 0x01202000; -- cpu->id_mmfr3 = 0x11; -+ cpu->isar.id_mmfr0 = 0x31100003; -+ cpu->isar.id_mmfr1 = 0x20000000; -+ cpu->isar.id_mmfr2 = 0x01202000; -+ cpu->isar.id_mmfr3 = 0x11; - cpu->isar.id_isar0 = 0x00101111; - cpu->isar.id_isar1 = 0x12112111; - cpu->isar.id_isar2 = 0x21232031; -@@ -2134,10 +2134,10 @@ static void cortex_a9_initfn(Object *obj) - cpu->id_pfr1 = 0x11; - cpu->isar.id_dfr0 = 0x000; - cpu->id_afr0 = 0; -- cpu->id_mmfr0 = 0x00100103; -- cpu->id_mmfr1 = 0x20000000; -- cpu->id_mmfr2 = 0x01230000; -- cpu->id_mmfr3 = 0x00002111; -+ cpu->isar.id_mmfr0 = 0x00100103; -+ cpu->isar.id_mmfr1 = 0x20000000; -+ cpu->isar.id_mmfr2 = 0x01230000; -+ cpu->isar.id_mmfr3 = 0x00002111; - cpu->isar.id_isar0 = 0x00101111; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232041; -@@ -2199,10 +2199,10 @@ static void cortex_a7_initfn(Object *obj) - cpu->id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x02010555; - cpu->id_afr0 = 0x00000000; -- cpu->id_mmfr0 = 0x10101105; -- cpu->id_mmfr1 = 0x40000000; -- cpu->id_mmfr2 = 0x01240000; -- cpu->id_mmfr3 = 0x02102211; -+ cpu->isar.id_mmfr0 = 0x10101105; -+ cpu->isar.id_mmfr1 = 0x40000000; -+ cpu->isar.id_mmfr2 = 0x01240000; -+ cpu->isar.id_mmfr3 = 0x02102211; - /* a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but - * table 4-41 gives 0x02101110, which includes the arm div insns. - */ -@@ -2245,10 +2245,10 @@ static void cortex_a15_initfn(Object *obj) - cpu->id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x02010555; - cpu->id_afr0 = 0x00000000; -- cpu->id_mmfr0 = 0x10201105; -- cpu->id_mmfr1 = 0x20000000; -- cpu->id_mmfr2 = 0x01240000; -- cpu->id_mmfr3 = 0x02102211; -+ cpu->isar.id_mmfr0 = 0x10201105; -+ cpu->isar.id_mmfr1 = 0x20000000; -+ cpu->isar.id_mmfr2 = 0x01240000; -+ cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232041; -@@ -2484,13 +2484,13 @@ static void arm_max_initfn(Object *obj) - t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */ - cpu->isar.mvfr2 = t; - -- t = cpu->id_mmfr3; -+ t = cpu->isar.id_mmfr3; - t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */ -- cpu->id_mmfr3 = t; -+ cpu->isar.id_mmfr3 = t; - -- t = cpu->id_mmfr4; -+ t = cpu->isar.id_mmfr4; - t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */ -- cpu->id_mmfr4 = t; -+ cpu->isar.id_mmfr4 = t; - } - #endif - } -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index 3040aa40..a78c30c3 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -857,6 +857,11 @@ struct ARMCPU { - uint32_t id_isar4; - uint32_t id_isar5; - uint32_t id_isar6; -+ uint32_t id_mmfr0; -+ uint32_t id_mmfr1; -+ uint32_t id_mmfr2; -+ uint32_t id_mmfr3; -+ uint32_t id_mmfr4; - uint32_t mvfr0; - uint32_t mvfr1; - uint32_t mvfr2; -@@ -882,11 +887,6 @@ struct ARMCPU { - uint64_t pmceid0; - uint64_t pmceid1; - uint32_t id_afr0; -- uint32_t id_mmfr0; -- uint32_t id_mmfr1; -- uint32_t id_mmfr2; -- uint32_t id_mmfr3; -- uint32_t id_mmfr4; - uint64_t id_aa64afr0; - uint64_t id_aa64afr1; - uint32_t clidr; -@@ -3490,12 +3490,12 @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id) - - static inline bool isar_feature_aa32_pan(const ARMISARegisters *id) - { -- return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) != 0; -+ return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) != 0; - } - - static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id) - { -- return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) >= 2; -+ return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) >= 2; - } - - static inline bool isar_feature_aa32_pmu_8_1(const ARMISARegisters *id) -diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index a0d07fd7..d450b8c8 100644 ---- a/target/arm/cpu64.c -+++ b/target/arm/cpu64.c -@@ -125,10 +125,10 @@ static void aarch64_a57_initfn(Object *obj) - cpu->id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x03010066; - cpu->id_afr0 = 0x00000000; -- cpu->id_mmfr0 = 0x10101105; -- cpu->id_mmfr1 = 0x40000000; -- cpu->id_mmfr2 = 0x01260000; -- cpu->id_mmfr3 = 0x02102211; -+ cpu->isar.id_mmfr0 = 0x10101105; -+ cpu->isar.id_mmfr1 = 0x40000000; -+ cpu->isar.id_mmfr2 = 0x01260000; -+ cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; -@@ -179,10 +179,10 @@ static void aarch64_a53_initfn(Object *obj) - cpu->id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x03010066; - cpu->id_afr0 = 0x00000000; -- cpu->id_mmfr0 = 0x10101105; -- cpu->id_mmfr1 = 0x40000000; -- cpu->id_mmfr2 = 0x01260000; -- cpu->id_mmfr3 = 0x02102211; -+ cpu->isar.id_mmfr0 = 0x10101105; -+ cpu->isar.id_mmfr1 = 0x40000000; -+ cpu->isar.id_mmfr2 = 0x01260000; -+ cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; -@@ -233,10 +233,10 @@ static void aarch64_a72_initfn(Object *obj) - cpu->id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x03010066; - cpu->id_afr0 = 0x00000000; -- cpu->id_mmfr0 = 0x10201105; -- cpu->id_mmfr1 = 0x40000000; -- cpu->id_mmfr2 = 0x01260000; -- cpu->id_mmfr3 = 0x02102211; -+ cpu->isar.id_mmfr0 = 0x10201105; -+ cpu->isar.id_mmfr1 = 0x40000000; -+ cpu->isar.id_mmfr2 = 0x01260000; -+ cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; -@@ -383,9 +383,9 @@ static void aarch64_max_initfn(Object *obj) - u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1); - cpu->isar.id_isar6 = u; - -- u = cpu->id_mmfr3; -+ u = cpu->isar.id_mmfr3; - u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */ -- cpu->id_mmfr3 = u; -+ cpu->isar.id_mmfr3 = u; - - /* - * FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet, -diff --git a/target/arm/helper.c b/target/arm/helper.c -index 60ff7c0f..49cd7a7e 100644 ---- a/target/arm/helper.c -+++ b/target/arm/helper.c -@@ -5906,19 +5906,19 @@ void register_cp_regs_for_features(ARMCPU *cpu) - { .name = "ID_MMFR0", .state = ARM_CP_STATE_BOTH, - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 4, - .access = PL1_R, .type = ARM_CP_CONST, -- .resetvalue = cpu->id_mmfr0 }, -+ .resetvalue = cpu->isar.id_mmfr0 }, - { .name = "ID_MMFR1", .state = ARM_CP_STATE_BOTH, - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 5, - .access = PL1_R, .type = ARM_CP_CONST, -- .resetvalue = cpu->id_mmfr1 }, -+ .resetvalue = cpu->isar.id_mmfr1 }, - { .name = "ID_MMFR2", .state = ARM_CP_STATE_BOTH, - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 6, - .access = PL1_R, .type = ARM_CP_CONST, -- .resetvalue = cpu->id_mmfr2 }, -+ .resetvalue = cpu->isar.id_mmfr2 }, - { .name = "ID_MMFR3", .state = ARM_CP_STATE_BOTH, - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 7, - .access = PL1_R, .type = ARM_CP_CONST, -- .resetvalue = cpu->id_mmfr3 }, -+ .resetvalue = cpu->isar.id_mmfr3 }, - { .name = "ID_ISAR0", .state = ARM_CP_STATE_BOTH, - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0, - .access = PL1_R, .type = ARM_CP_CONST, -@@ -5946,7 +5946,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) - { .name = "ID_MMFR4", .state = ARM_CP_STATE_BOTH, - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 6, - .access = PL1_R, .type = ARM_CP_CONST, -- .resetvalue = cpu->id_mmfr4 }, -+ .resetvalue = cpu->isar.id_mmfr4 }, - { .name = "ID_ISAR6", .state = ARM_CP_STATE_BOTH, - .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 7, - .access = PL1_R, .type = ARM_CP_CONST, -@@ -6426,7 +6426,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) - define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo); - define_arm_cp_regs(cpu, vmsa_cp_reginfo); - /* TTCBR2 is introduced with ARMv8.2-A32HPD. */ -- if (FIELD_EX32(cpu->id_mmfr4, ID_MMFR4, HPDS) != 0) { -+ if (FIELD_EX32(cpu->isar.id_mmfr4, ID_MMFR4, HPDS) != 0) { - define_one_arm_cp_reg(cpu, &ttbcr2_reginfo); - } - } -diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c -index ee158830..2247148e 100644 ---- a/target/arm/kvm32.c -+++ b/target/arm/kvm32.c -@@ -104,6 +104,23 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) - * Fortunately there is not yet anything in there that affects migration. - */ - -+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, -+ ARM_CP15_REG32(0, 0, 1, 4)); -+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1, -+ ARM_CP15_REG32(0, 0, 1, 5)); -+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2, -+ ARM_CP15_REG32(0, 0, 1, 6)); -+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3, -+ ARM_CP15_REG32(0, 0, 1, 7)); -+ if (read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4, -+ ARM_CP15_REG32(0, 0, 2, 6))) { -+ /* -+ * Older kernels don't support reading ID_MMFR4 (a new in v8 -+ * register); assume it's zero. -+ */ -+ ahcf->isar.id_mmfr4 = 0; -+ } -+ - kvm_arm_destroy_scratch_host_vcpu(fdarray); - - if (err < 0) { -diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c -index b794108a..276d1466 100644 ---- a/target/arm/kvm64.c -+++ b/target/arm/kvm64.c -@@ -551,6 +551,14 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) - * than skipping the reads and leaving 0, as we must avoid - * considering the values in every case. - */ -+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, -+ ARM64_SYS_REG(3, 0, 0, 1, 4)); -+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr1, -+ ARM64_SYS_REG(3, 0, 0, 1, 5)); -+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr2, -+ ARM64_SYS_REG(3, 0, 0, 1, 6)); -+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr3, -+ ARM64_SYS_REG(3, 0, 0, 1, 7)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0, - ARM64_SYS_REG(3, 0, 0, 2, 0)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1, -@@ -563,6 +571,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) - ARM64_SYS_REG(3, 0, 0, 2, 4)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5, - ARM64_SYS_REG(3, 0, 0, 2, 5)); -+ err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr4, -+ ARM64_SYS_REG(3, 0, 0, 2, 6)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6, - ARM64_SYS_REG(3, 0, 0, 2, 7)); - --- -2.25.1 - diff --git a/target-arm-Update-ID-fields.patch b/target-arm-Update-ID-fields.patch deleted file mode 100644 index 94ed8027c9e238f384e767bc88c209749eee234e..0000000000000000000000000000000000000000 --- a/target-arm-Update-ID-fields.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 47c76d73a435884b66ce6417cb853893099be5eb Mon Sep 17 00:00:00 2001 -From: Peng Liang -Date: Tue, 11 Aug 2020 10:18:57 +0800 -Subject: [PATCH 8/9] target/arm: Update ID fields - -Update definitions for ID fields, up to ARMv8.6. - -Signed-off-by: zhanghailiang -Signed-off-by: Peng Liang ---- - target/arm/cpu.h | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index 068c3fa2..eb875e11 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -1691,6 +1691,8 @@ FIELD(ID_ISAR6, DP, 4, 4) - FIELD(ID_ISAR6, FHM, 8, 4) - FIELD(ID_ISAR6, SB, 12, 4) - FIELD(ID_ISAR6, SPECRES, 16, 4) -+FIELD(ID_ISAR6, BF16, 20, 4) -+FIELD(ID_ISAR6, I8MM, 24, 4) - - FIELD(ID_MMFR3, CMAINTVA, 0, 4) - FIELD(ID_MMFR3, CMAINTSW, 4, 4) -@@ -1736,6 +1738,9 @@ FIELD(ID_AA64ISAR1, GPI, 28, 4) - FIELD(ID_AA64ISAR1, FRINTTS, 32, 4) - FIELD(ID_AA64ISAR1, SB, 36, 4) - FIELD(ID_AA64ISAR1, SPECRES, 40, 4) -+FIELD(ID_AA64ISAR1, BF16, 44, 4) -+FIELD(ID_AA64ISAR1, DGH, 48, 4) -+FIELD(ID_AA64ISAR1, I8MM, 52, 4) - - FIELD(ID_AA64PFR0, EL0, 0, 4) - FIELD(ID_AA64PFR0, EL1, 4, 4) -@@ -1746,11 +1751,18 @@ FIELD(ID_AA64PFR0, ADVSIMD, 20, 4) - FIELD(ID_AA64PFR0, GIC, 24, 4) - FIELD(ID_AA64PFR0, RAS, 28, 4) - FIELD(ID_AA64PFR0, SVE, 32, 4) -+FIELD(ID_AA64PFR0, SEL2, 36, 4) -+FIELD(ID_AA64PFR0, MPAM, 40, 4) -+FIELD(ID_AA64PFR0, AMU, 44, 4) -+FIELD(ID_AA64PFR0, DIT, 44, 4) -+FIELD(ID_AA64PFR0, CSV2, 56, 4) -+FIELD(ID_AA64PFR0, CSV3, 60, 4) - - FIELD(ID_AA64PFR1, BT, 0, 4) - FIELD(ID_AA64PFR1, SBSS, 4, 4) - FIELD(ID_AA64PFR1, MTE, 8, 4) - FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4) -+FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4) - - FIELD(ID_AA64MMFR0, PARANGE, 0, 4) - FIELD(ID_AA64MMFR0, ASIDBITS, 4, 4) -@@ -1764,6 +1776,8 @@ FIELD(ID_AA64MMFR0, TGRAN16_2, 32, 4) - FIELD(ID_AA64MMFR0, TGRAN64_2, 36, 4) - FIELD(ID_AA64MMFR0, TGRAN4_2, 40, 4) - FIELD(ID_AA64MMFR0, EXS, 44, 4) -+FIELD(ID_AA64MMFR0, FGT, 56, 4) -+FIELD(ID_AA64MMFR0, ECV, 60, 4) - - FIELD(ID_AA64MMFR1, HAFDBS, 0, 4) - FIELD(ID_AA64MMFR1, VMIDBITS, 4, 4) -@@ -1773,6 +1787,8 @@ FIELD(ID_AA64MMFR1, LO, 16, 4) - FIELD(ID_AA64MMFR1, PAN, 20, 4) - FIELD(ID_AA64MMFR1, SPECSEI, 24, 4) - FIELD(ID_AA64MMFR1, XNX, 28, 4) -+FIELD(ID_AA64MMFR1, TWED, 32, 4) -+FIELD(ID_AA64MMFR1, ETS, 36, 4) - - FIELD(ID_AA64MMFR2, CNP, 0, 4) - FIELD(ID_AA64MMFR2, UAO, 4, 4) -@@ -1799,6 +1815,7 @@ FIELD(ID_AA64DFR0, CTX_CMPS, 28, 4) - FIELD(ID_AA64DFR0, PMSVER, 32, 4) - FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4) - FIELD(ID_AA64DFR0, TRACEFILT, 40, 4) -+FIELD(ID_AA64DFR0, MUPMU, 48, 4) - - FIELD(ID_DFR0, COPDBG, 0, 4) - FIELD(ID_DFR0, COPSDBG, 4, 4) --- -2.25.1 - diff --git a/target-arm-Update-the-ID-registers-of-Kunpeng-920.patch b/target-arm-Update-the-ID-registers-of-Kunpeng-920.patch index 586dcbb1998a3e0e910feec54d326f577154711e..b632a31c8a51205849560417d40db9ce0a8c5c39 100644 --- a/target-arm-Update-the-ID-registers-of-Kunpeng-920.patch +++ b/target-arm-Update-the-ID-registers-of-Kunpeng-920.patch @@ -1,4 +1,4 @@ -From b54ca94f19a9b22537712638ae05d2095258eb80 Mon Sep 17 00:00:00 2001 +From e2cb8b57278357c0a42cf7722b8c28b6f8d7585c Mon Sep 17 00:00:00 2001 From: Peng Liang Date: Sat, 19 Sep 2020 09:04:45 +0800 Subject: [PATCH] target/arm: Update the ID registers of Kunpeng-920 @@ -8,15 +8,16 @@ Let's update them. The values are read from Kunpeng-920 by calling read_sysreg_s. Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun --- target/arm/cpu64.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index 726d123d8e..a1649f8844 100644 +index 287e7ac91c..3ec788fc29 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c -@@ -275,10 +275,33 @@ static void aarch64_kunpeng_920_initfn(Object *obj) +@@ -262,10 +262,33 @@ static void aarch64_kunpeng_920_initfn(Object *obj) cpu->midr = 0x480fd010; cpu->ctr = 0x84448004; @@ -39,8 +40,8 @@ index 726d123d8e..a1649f8844 100644 + cpu->isar.regs[MVFR2] = 0; + cpu->isar.regs[MVFR2] = 0; + cpu->isar.regs[MVFR2] = 0; -+ cpu->id_pfr0 = 0; -+ cpu->id_pfr1 = 0; ++ cpu->isar.regs[ID_PFR0] = 0; ++ cpu->isar.regs[ID_PFR1] = 0; + cpu->isar.regs[ID_AA64PFR0] = 0x0000010011111111; cpu->isar.regs[ID_AA64DFR0] = 0x110305408; - cpu->isar.regs[ID_AA64ISAR0] = 0x10211120; @@ -51,7 +52,7 @@ index 726d123d8e..a1649f8844 100644 + cpu->isar.regs[ID_AA64MMFR2] = 0x00001011; } - static void cpu_max_get_sve_vq(Object *obj, Visitor *v, const char *name, + void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) -- -2.23.0 +2.27.0 diff --git a/target-arm-Use-FIELD-macros-for-clearing-ID_DFR0-PER.patch b/target-arm-Use-FIELD-macros-for-clearing-ID_DFR0-PER.patch deleted file mode 100644 index 0e32f85104cb492dba2d0e72aa6138342ef960db..0000000000000000000000000000000000000000 --- a/target-arm-Use-FIELD-macros-for-clearing-ID_DFR0-PER.patch +++ /dev/null @@ -1,36 +0,0 @@ -From f54cdca97bf86f5ca1df8471bc229b89797b287e Mon Sep 17 00:00:00 2001 -From: Peter Maydell -Date: Fri, 14 Feb 2020 17:51:02 +0000 -Subject: [PATCH 04/13] target/arm: Use FIELD macros for clearing ID_DFR0 - PERFMON field -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -We already define FIELD macros for ID_DFR0, so use them in the -one place where we're doing direct bit value manipulation. - -Reviewed-by: Philippe Mathieu-Daudé -Reviewed-by: Richard Henderson -Signed-off-by: Peter Maydell -Message-id: 20200214175116.9164-8-peter.maydell@linaro.org ---- - target/arm/cpu.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index dbd05e01..6ad211b1 100644 ---- a/target/arm/cpu.c -+++ b/target/arm/cpu.c -@@ -1523,7 +1523,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) - #endif - } else { - cpu->id_aa64dfr0 = FIELD_DP64(cpu->id_aa64dfr0, ID_AA64DFR0, PMUVER, 0); -- cpu->id_dfr0 &= ~(0xf << 24); -+ cpu->id_dfr0 = FIELD_DP32(cpu->id_dfr0, ID_DFR0, PERFMON, 0); - cpu->pmceid0 = 0; - cpu->pmceid1 = 0; - } --- -2.25.1 - diff --git a/target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch b/target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch index 455dc843c105743750f7bc573b6fb86f3a5861b8..a8d5ac0be9b6943904393406d3104f1a7a9353e1 100644 --- a/target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch +++ b/target-arm-clear-EL2-and-EL3-only-when-kvm-is-not-en.patch @@ -1,4 +1,4 @@ -From ad6ce039cab07b6a99ccaa36fbb0043ae85a74c9 Mon Sep 17 00:00:00 2001 +From 20bd52038a960e0c959af38a5d3d7a6601db8e8b Mon Sep 17 00:00:00 2001 From: Peng Liang Date: Mon, 21 Sep 2020 22:14:20 +0800 Subject: [PATCH] target/arm: clear EL2 and EL3 only when kvm is not enabled @@ -11,24 +11,25 @@ effect. Hence, clear EL2 and EL3 only when kvm is not enabled for backwards compatibility. Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun --- target/arm/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index 7ae2d3da56..3f62336acf 100644 +index 1c1647a0a8..65163f5135 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c -@@ -1996,7 +1996,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) +@@ -2283,7 +2283,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) } } -- if (!cpu->has_el3) { -+ if (!cpu->has_el3 && !kvm_enabled()) { +- if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3) { ++ if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3 && !kvm_enabled()) { /* If the has_el3 CPU property is disabled then we need to disable the * feature. */ -@@ -2037,7 +2037,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) +@@ -2324,7 +2324,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) cpu->pmceid1 = 0; } @@ -38,5 +39,5 @@ index 7ae2d3da56..3f62336acf 100644 * registers if we don't have EL2. These are id_pfr1[15:12] and * id_aa64pfr0_el1[11:8]. -- -2.23.0 +2.27.0 diff --git a/target-arm-convert-isar-regs-to-array.patch b/target-arm-convert-isar-regs-to-array.patch index 528371212aad42f034db62858b1a2da2cdcba79d..14e9a0865434bed3b0bba3038a3fb1540bbb29b8 100644 --- a/target-arm-convert-isar-regs-to-array.patch +++ b/target-arm-convert-isar-regs-to-array.patch @@ -1,7 +1,7 @@ -From ac92f0f7bbf7cf063ba45fbfaf7e7970dd76544a Mon Sep 17 00:00:00 2001 +From bd8514594f0226b4599019ff123321138bb04d39 Mon Sep 17 00:00:00 2001 From: Peng Liang Date: Thu, 6 Aug 2020 16:14:25 +0800 -Subject: [PATCH 1/9] target/arm: convert isar regs to array +Subject: [PATCH] target/arm: convert isar regs to array The isar in ARMCPU is a struct, each field of which represents an ID register. It's not convenient for us to support CPU feature in AArch64. @@ -12,62 +12,108 @@ AArch32 to 64-bits. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun --- - hw/intc/armv7m_nvic.c | 28 +-- - target/arm/cpu.c | 440 +++++++++++++++++++++-------------------- - target/arm/cpu.h | 178 +++++++++-------- - target/arm/cpu64.c | 158 +++++++-------- - target/arm/helper.c | 54 ++--- - target/arm/internals.h | 15 +- - target/arm/kvm64.c | 68 +++---- - 7 files changed, 478 insertions(+), 463 deletions(-) + hw/intc/armv7m_nvic.c | 32 +-- + target/arm/cpu.c | 105 ++++----- + target/arm/cpu.h | 298 ++++++++++++------------ + target/arm/cpu64.c | 234 +++++++++---------- + target/arm/cpu_tcg.c | 503 +++++++++++++++++++++-------------------- + target/arm/helper.c | 64 +++--- + target/arm/hvf/hvf.c | 20 +- + target/arm/internals.h | 14 +- + target/arm/kvm64.c | 81 +++---- + 9 files changed, 683 insertions(+), 668 deletions(-) diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c -index f7ef6ad1..5013ec97 100644 +index 13df002ce4..4b12b209b7 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c -@@ -1223,29 +1223,29 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) +@@ -1273,17 +1273,17 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_pfr0; ++ return cpu->isar.regs[ID_PFR0]; case 0xd44: /* PFR1. */ - return cpu->id_pfr1; + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } +- return cpu->isar.id_pfr1; ++ return cpu->isar.regs[ID_PFR1]; case 0xd48: /* DFR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } - return cpu->isar.id_dfr0; + return cpu->isar.regs[ID_DFR0]; case 0xd4c: /* AFR0. */ - return cpu->id_afr0; - case 0xd50: /* MMFR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; +@@ -1293,52 +1293,52 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } - return cpu->isar.id_mmfr0; + return cpu->isar.regs[ID_MMFR0]; case 0xd54: /* MMFR1. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } - return cpu->isar.id_mmfr1; + return cpu->isar.regs[ID_MMFR1]; case 0xd58: /* MMFR2. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } - return cpu->isar.id_mmfr2; + return cpu->isar.regs[ID_MMFR2]; case 0xd5c: /* MMFR3. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } - return cpu->isar.id_mmfr3; + return cpu->isar.regs[ID_MMFR3]; case 0xd60: /* ISAR0. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } - return cpu->isar.id_isar0; + return cpu->isar.regs[ID_ISAR0]; case 0xd64: /* ISAR1. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } - return cpu->isar.id_isar1; + return cpu->isar.regs[ID_ISAR1]; case 0xd68: /* ISAR2. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } - return cpu->isar.id_isar2; + return cpu->isar.regs[ID_ISAR2]; case 0xd6c: /* ISAR3. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } - return cpu->isar.id_isar3; + return cpu->isar.regs[ID_ISAR3]; case 0xd70: /* ISAR4. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } - return cpu->isar.id_isar4; + return cpu->isar.regs[ID_ISAR4]; case 0xd74: /* ISAR5. */ + if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) { + goto bad_offset; + } - return cpu->isar.id_isar5; + return cpu->isar.regs[ID_ISAR5]; case 0xd78: /* CLIDR */ return cpu->clidr; case 0xd7c: /* CTR */ -@@ -1450,11 +1450,11 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) +@@ -1548,11 +1548,11 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) } return cpu->env.v7m.fpdscr[attrs.secure]; case 0xf40: /* MVFR0 */ @@ -83,10 +129,10 @@ index f7ef6ad1..5013ec97 100644 bad_offset: qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset); diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index c3728e3d..5bcdad0c 100644 +index a211804fd3..f1ce0474a3 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c -@@ -170,9 +170,9 @@ static void arm_cpu_reset(CPUState *s) +@@ -176,9 +176,9 @@ static void arm_cpu_reset(DeviceState *dev) g_hash_table_foreach(cpu->cp_regs, cp_reg_check_reset, cpu); env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid; @@ -97,11 +143,11 @@ index c3728e3d..5bcdad0c 100644 + env->vfp.xregs[ARM_VFP_MVFR1] = cpu->isar.regs[MVFR1]; + env->vfp.xregs[ARM_VFP_MVFR2] = cpu->isar.regs[MVFR2]; - cpu->power_state = cpu->start_powered_off ? PSCI_OFF : PSCI_ON; - s->halted = cpu->start_powered_off; -@@ -1251,19 +1251,19 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) - unset_feature(env, ARM_FEATURE_VFP3); - unset_feature(env, ARM_FEATURE_VFP4); + cpu->power_state = s->start_powered_off ? PSCI_OFF : PSCI_ON; + +@@ -1520,20 +1520,20 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + uint64_t t; + uint32_t u; - t = cpu->isar.id_aa64isar1; + t = cpu->isar.regs[ID_AA64ISAR1]; @@ -118,6 +164,7 @@ index c3728e3d..5bcdad0c 100644 - u = cpu->isar.id_isar6; + u = cpu->isar.regs[ID_ISAR6]; u = FIELD_DP32(u, ID_ISAR6, JSCVT, 0); + u = FIELD_DP32(u, ID_ISAR6, BF16, 0); - cpu->isar.id_isar6 = u; + cpu->isar.regs[ID_ISAR6] = u; @@ -125,11 +172,11 @@ index c3728e3d..5bcdad0c 100644 + u = cpu->isar.regs[MVFR0]; u = FIELD_DP32(u, MVFR0, FPSP, 0); u = FIELD_DP32(u, MVFR0, FPDP, 0); - u = FIELD_DP32(u, MVFR0, FPTRAP, 0); -@@ -1271,17 +1271,17 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) - u = FIELD_DP32(u, MVFR0, FPSQRT, 0); - u = FIELD_DP32(u, MVFR0, FPSHVEC, 0); - u = FIELD_DP32(u, MVFR0, FPROUND, 0); + u = FIELD_DP32(u, MVFR0, FPDIVIDE, 0); +@@ -1543,20 +1543,20 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + u = FIELD_DP32(u, MVFR0, FPTRAP, 0); + u = FIELD_DP32(u, MVFR0, FPSHVEC, 0); + } - cpu->isar.mvfr0 = u; + cpu->isar.regs[MVFR0] = u; @@ -138,6 +185,9 @@ index c3728e3d..5bcdad0c 100644 u = FIELD_DP32(u, MVFR1, FPFTZ, 0); u = FIELD_DP32(u, MVFR1, FPDNAN, 0); u = FIELD_DP32(u, MVFR1, FPHP, 0); + if (arm_feature(env, ARM_FEATURE_M)) { + u = FIELD_DP32(u, MVFR1, FP16, 0); + } - cpu->isar.mvfr1 = u; + cpu->isar.regs[MVFR1] = u; @@ -149,7 +199,7 @@ index c3728e3d..5bcdad0c 100644 } if (!cpu->has_neon) { -@@ -1290,56 +1290,56 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) +@@ -1565,43 +1565,43 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) unset_feature(env, ARM_FEATURE_NEON); @@ -162,6 +212,8 @@ index c3728e3d..5bcdad0c 100644 - t = cpu->isar.id_aa64isar1; + t = cpu->isar.regs[ID_AA64ISAR1]; t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 0); + t = FIELD_DP64(t, ID_AA64ISAR1, BF16, 0); + t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 0); - cpu->isar.id_aa64isar1 = t; + cpu->isar.regs[ID_AA64ISAR1] = t; @@ -182,27 +234,30 @@ index c3728e3d..5bcdad0c 100644 + u = cpu->isar.regs[ID_ISAR6]; u = FIELD_DP32(u, ID_ISAR6, DP, 0); u = FIELD_DP32(u, ID_ISAR6, FHM, 0); + u = FIELD_DP32(u, ID_ISAR6, BF16, 0); + u = FIELD_DP32(u, ID_ISAR6, I8MM, 0); - cpu->isar.id_isar6 = u; + cpu->isar.regs[ID_ISAR6] = u; -- u = cpu->isar.mvfr1; -+ u = cpu->isar.regs[MVFR1]; - u = FIELD_DP32(u, MVFR1, SIMDLS, 0); - u = FIELD_DP32(u, MVFR1, SIMDINT, 0); - u = FIELD_DP32(u, MVFR1, SIMDSP, 0); - u = FIELD_DP32(u, MVFR1, SIMDHP, 0); - u = FIELD_DP32(u, MVFR1, SIMDFMAC, 0); -- cpu->isar.mvfr1 = u; -+ cpu->isar.regs[MVFR1] = u; - -- u = cpu->isar.mvfr2; -+ u = cpu->isar.regs[MVFR2]; - u = FIELD_DP32(u, MVFR2, SIMDMISC, 0); -- cpu->isar.mvfr2 = u; -+ cpu->isar.regs[MVFR2] = u; + if (!arm_feature(env, ARM_FEATURE_M)) { +- u = cpu->isar.mvfr1; ++ u = cpu->isar.regs[MVFR1]; + u = FIELD_DP32(u, MVFR1, SIMDLS, 0); + u = FIELD_DP32(u, MVFR1, SIMDINT, 0); + u = FIELD_DP32(u, MVFR1, SIMDSP, 0); + u = FIELD_DP32(u, MVFR1, SIMDHP, 0); +- cpu->isar.mvfr1 = u; ++ cpu->isar.regs[MVFR1] = u; + +- u = cpu->isar.mvfr2; ++ u = cpu->isar.regs[MVFR2]; + u = FIELD_DP32(u, MVFR2, SIMDMISC, 0); +- cpu->isar.mvfr2 = u; ++ cpu->isar.regs[MVFR2] = u; + } } - if (!cpu->has_neon && !cpu->has_vfp) { +@@ -1609,22 +1609,22 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) uint64_t t; uint32_t u; @@ -223,10 +278,17 @@ index c3728e3d..5bcdad0c 100644 u = FIELD_DP32(u, MVFR0, SIMDREG, 0); - cpu->isar.mvfr0 = u; + cpu->isar.regs[MVFR0] = u; + + /* Despite the name, this field covers both VFP and Neon */ +- u = cpu->isar.mvfr1; ++ u = cpu->isar.regs[MVFR1]; + u = FIELD_DP32(u, MVFR1, SIMDFMAC, 0); +- cpu->isar.mvfr1 = u; ++ cpu->isar.regs[MVFR1] = u; } if (arm_feature(env, ARM_FEATURE_M) && !cpu->has_dsp) { -@@ -1347,19 +1347,19 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) +@@ -1632,19 +1632,19 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) unset_feature(env, ARM_FEATURE_THUMB_DSP); @@ -252,16 +314,18 @@ index c3728e3d..5bcdad0c 100644 } /* Some features automatically imply others: */ -@@ -1499,7 +1499,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) +@@ -1785,8 +1785,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + /* Disable the security extension feature bits in the processor feature * registers as well. These are id_pfr1[7:4] and id_aa64pfr0[15:12]. */ - cpu->id_pfr1 &= ~0xf0; +- cpu->isar.id_pfr1 &= ~0xf0; - cpu->isar.id_aa64pfr0 &= ~0xf000; ++ cpu->isar.regs[ID_PFR1] &= ~0xf0; + cpu->isar.regs[ID_AA64PFR0] &= ~0xf000; } if (!cpu->has_el2) { -@@ -1522,9 +1522,10 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) +@@ -1809,9 +1809,10 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) cpu); #endif } else { @@ -275,794 +339,375 @@ index c3728e3d..5bcdad0c 100644 cpu->pmceid0 = 0; cpu->pmceid1 = 0; } -@@ -1534,7 +1535,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) +@@ -1821,8 +1822,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) * registers if we don't have EL2. These are id_pfr1[15:12] and * id_aa64pfr0_el1[11:8]. */ - cpu->isar.id_aa64pfr0 &= ~0xf00; +- cpu->isar.id_pfr1 &= ~0xf000; + cpu->isar.regs[ID_AA64PFR0] &= ~0xf00; - cpu->id_pfr1 &= ~0xf000; ++ cpu->isar.regs[ID_PFR1] &= ~0xf000; } -@@ -1675,13 +1676,15 @@ static void arm926_initfn(Object *obj) - * ARMv5 does not have the ID_ISAR registers, but we can still - * set the field to indicate Jazelle support within QEMU. - */ -- cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); -+ cpu->isar.regs[ID_ISAR1] = FIELD_DP32(cpu->isar.regs[ID_ISAR1], ID_ISAR1, -+ JAZELLE, 1); - /* - * Similarly, we need to set MVFR0 fields to enable double precision - * and short vector support even though ARMv5 doesn't have this register. + #ifndef CONFIG_USER_ONLY +@@ -1831,8 +1832,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) + * Disable the MTE feature bits if we do not have tag-memory + * provided by the machine. + */ +- cpu->isar.id_aa64pfr1 = +- FIELD_DP64(cpu->isar.id_aa64pfr1, ID_AA64PFR1, MTE, 0); ++ cpu->isar.regs[ID_AA64PFR1] = ++ FIELD_DP64(cpu->isar.regs[ID_AA64PFR1], ID_AA64PFR1, MTE, 0); + } + #endif + +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index e33f37b70a..3dda33f347 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -69,6 +69,41 @@ + #define ARMV7M_EXCP_PENDSV 14 + #define ARMV7M_EXCP_SYSTICK 15 + ++typedef enum CPUIDReg { ++ MIDR_EL1, ++ ID_ISAR0, ++ ID_ISAR1, ++ ID_ISAR2, ++ ID_ISAR3, ++ ID_ISAR4, ++ ID_ISAR5, ++ ID_ISAR6, ++ ID_PFR0, ++ ID_PFR1, ++ ID_PFR2, ++ ID_MMFR0, ++ ID_MMFR1, ++ ID_MMFR2, ++ ID_MMFR3, ++ ID_MMFR4, ++ ID_AA64ISAR0, ++ ID_AA64ISAR1, ++ ID_AA64PFR0, ++ ID_AA64PFR1, ++ ID_AA64MMFR0, ++ ID_AA64MMFR1, ++ ID_AA64MMFR2, ++ ID_AA64DFR0, ++ ID_AA64DFR1, ++ ID_AA64ZFR0, ++ ID_DFR0, ++ MVFR0, ++ MVFR1, ++ MVFR2, ++ DBGDIDR, ++ ID_MAX, ++} CPUIDReg; ++ + /* For M profile, some registers are banked secure vs non-secure; + * these are represented as a 2-element array where the first element + * is the non-secure copy and the second is the secure copy. +@@ -922,36 +957,7 @@ struct ARMCPU { + * field by reading the value from the KVM vCPU. */ -- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); -- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); -+ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, -+ FPSHVEC, 1); -+ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPDP, 1); + struct ARMISARegisters { +- uint32_t id_isar0; +- uint32_t id_isar1; +- uint32_t id_isar2; +- uint32_t id_isar3; +- uint32_t id_isar4; +- uint32_t id_isar5; +- uint32_t id_isar6; +- uint32_t id_mmfr0; +- uint32_t id_mmfr1; +- uint32_t id_mmfr2; +- uint32_t id_mmfr3; +- uint32_t id_mmfr4; +- uint32_t id_pfr0; +- uint32_t id_pfr1; +- uint32_t id_pfr2; +- uint32_t mvfr0; +- uint32_t mvfr1; +- uint32_t mvfr2; +- uint32_t id_dfr0; +- uint32_t dbgdidr; +- uint64_t id_aa64isar0; +- uint64_t id_aa64isar1; +- uint64_t id_aa64pfr0; +- uint64_t id_aa64pfr1; +- uint64_t id_aa64mmfr0; +- uint64_t id_aa64mmfr1; +- uint64_t id_aa64mmfr2; +- uint64_t id_aa64dfr0; +- uint64_t id_aa64dfr1; +- uint64_t id_aa64zfr0; ++ uint64_t regs[ID_MAX]; + } isar; + uint64_t midr; + uint32_t revidr; +@@ -3729,103 +3735,103 @@ static inline target_ulong cpu_untagged_addr(CPUState *cs, target_ulong x) + */ + static inline bool isar_feature_aa32_thumb_div(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR0], ID_ISAR0, DIVIDE) != 0; } - static void arm946_initfn(Object *obj) -@@ -1717,13 +1720,15 @@ static void arm1026_initfn(Object *obj) - * ARMv5 does not have the ID_ISAR registers, but we can still - * set the field to indicate Jazelle support within QEMU. - */ -- cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); -+ cpu->isar.regs[ID_ISAR1] = FIELD_DP32(cpu->isar.regs[ID_ISAR1], ID_ISAR1, -+ JAZELLE, 1); - /* - * Similarly, we need to set MVFR0 fields to enable double precision - * and short vector support even though ARMv5 doesn't have this register. - */ -- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); -- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); -+ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, -+ FPSHVEC, 1); -+ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPDP, 1); + static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1; ++ return FIELD_EX32(id->regs[ID_ISAR0], ID_ISAR0, DIVIDE) > 1; + } - { - /* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */ -@@ -1756,22 +1761,22 @@ static void arm1136_r2_initfn(Object *obj) - set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); - cpu->midr = 0x4107b362; - cpu->reset_fpsid = 0x410120b4; -- cpu->isar.mvfr0 = 0x11111111; -- cpu->isar.mvfr1 = 0x00000000; -+ cpu->isar.regs[MVFR0] = 0x11111111; -+ cpu->isar.regs[MVFR1] = 0x00000000; - cpu->ctr = 0x1dd20d2; - cpu->reset_sctlr = 0x00050078; - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x1; -- cpu->isar.id_dfr0 = 0x2; -+ cpu->isar.regs[ID_DFR0] = 0x2; - cpu->id_afr0 = 0x3; -- cpu->isar.id_mmfr0 = 0x01130003; -- cpu->isar.id_mmfr1 = 0x10030302; -- cpu->isar.id_mmfr2 = 0x01222110; -- cpu->isar.id_isar0 = 0x00140011; -- cpu->isar.id_isar1 = 0x12002111; -- cpu->isar.id_isar2 = 0x11231111; -- cpu->isar.id_isar3 = 0x01102131; -- cpu->isar.id_isar4 = 0x141; -+ cpu->isar.regs[ID_MMFR0] = 0x01130003; -+ cpu->isar.regs[ID_MMFR1] = 0x10030302; -+ cpu->isar.regs[ID_MMFR2] = 0x01222110; -+ cpu->isar.regs[ID_ISAR0] = 0x00140011; -+ cpu->isar.regs[ID_ISAR1] = 0x12002111; -+ cpu->isar.regs[ID_ISAR2] = 0x11231111; -+ cpu->isar.regs[ID_ISAR3] = 0x01102131; -+ cpu->isar.regs[ID_ISAR4] = 0x141; - cpu->reset_auxcr = 7; + static inline bool isar_feature_aa32_lob(const ARMISARegisters *id) + { + /* (M-profile) low-overhead loops and branch future */ +- return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3; ++ return FIELD_EX32(id->regs[ID_ISAR0], ID_ISAR0, CMPBRANCH) >= 3; } -@@ -1788,22 +1793,22 @@ static void arm1136_initfn(Object *obj) - set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); - cpu->midr = 0x4117b363; - cpu->reset_fpsid = 0x410120b4; -- cpu->isar.mvfr0 = 0x11111111; -- cpu->isar.mvfr1 = 0x00000000; -+ cpu->isar.regs[MVFR0] = 0x11111111; -+ cpu->isar.regs[MVFR1] = 0x00000000; - cpu->ctr = 0x1dd20d2; - cpu->reset_sctlr = 0x00050078; - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x1; -- cpu->isar.id_dfr0 = 0x2; -+ cpu->isar.regs[ID_DFR0] = 0x2; - cpu->id_afr0 = 0x3; -- cpu->isar.id_mmfr0 = 0x01130003; -- cpu->isar.id_mmfr1 = 0x10030302; -- cpu->isar.id_mmfr2 = 0x01222110; -- cpu->isar.id_isar0 = 0x00140011; -- cpu->isar.id_isar1 = 0x12002111; -- cpu->isar.id_isar2 = 0x11231111; -- cpu->isar.id_isar3 = 0x01102131; -- cpu->isar.id_isar4 = 0x141; -+ cpu->isar.regs[ID_MMFR0] = 0x01130003; -+ cpu->isar.regs[ID_MMFR1] = 0x10030302; -+ cpu->isar.regs[ID_MMFR2] = 0x01222110; -+ cpu->isar.regs[ID_ISAR0] = 0x00140011; -+ cpu->isar.regs[ID_ISAR1] = 0x12002111; -+ cpu->isar.regs[ID_ISAR2] = 0x11231111; -+ cpu->isar.regs[ID_ISAR3] = 0x01102131; -+ cpu->isar.regs[ID_ISAR4] = 0x141; - cpu->reset_auxcr = 7; + static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR1], ID_ISAR1, JAZELLE) != 0; } -@@ -1821,22 +1826,22 @@ static void arm1176_initfn(Object *obj) - set_feature(&cpu->env, ARM_FEATURE_EL3); - cpu->midr = 0x410fb767; - cpu->reset_fpsid = 0x410120b5; -- cpu->isar.mvfr0 = 0x11111111; -- cpu->isar.mvfr1 = 0x00000000; -+ cpu->isar.regs[MVFR0] = 0x11111111; -+ cpu->isar.regs[MVFR1] = 0x00000000; - cpu->ctr = 0x1dd20d2; - cpu->reset_sctlr = 0x00050078; - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x11; -- cpu->isar.id_dfr0 = 0x33; -+ cpu->isar.regs[ID_DFR0] = 0x33; - cpu->id_afr0 = 0; -- cpu->isar.id_mmfr0 = 0x01130003; -- cpu->isar.id_mmfr1 = 0x10030302; -- cpu->isar.id_mmfr2 = 0x01222100; -- cpu->isar.id_isar0 = 0x0140011; -- cpu->isar.id_isar1 = 0x12002111; -- cpu->isar.id_isar2 = 0x11231121; -- cpu->isar.id_isar3 = 0x01102131; -- cpu->isar.id_isar4 = 0x01141; -+ cpu->isar.regs[ID_MMFR0] = 0x01130003; -+ cpu->isar.regs[ID_MMFR1] = 0x10030302; -+ cpu->isar.regs[ID_MMFR2] = 0x01222100; -+ cpu->isar.regs[ID_ISAR0] = 0x0140011; -+ cpu->isar.regs[ID_ISAR1] = 0x12002111; -+ cpu->isar.regs[ID_ISAR2] = 0x11231121; -+ cpu->isar.regs[ID_ISAR3] = 0x01102131; -+ cpu->isar.regs[ID_ISAR4] = 0x01141; - cpu->reset_auxcr = 7; + static inline bool isar_feature_aa32_aes(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, AES) != 0; } -@@ -1852,21 +1857,21 @@ static void arm11mpcore_initfn(Object *obj) - set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); - cpu->midr = 0x410fb022; - cpu->reset_fpsid = 0x410120b4; -- cpu->isar.mvfr0 = 0x11111111; -- cpu->isar.mvfr1 = 0x00000000; -+ cpu->isar.regs[MVFR0] = 0x11111111; -+ cpu->isar.regs[MVFR1] = 0x00000000; - cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */ - cpu->id_pfr0 = 0x111; - cpu->id_pfr1 = 0x1; -- cpu->isar.id_dfr0 = 0; -+ cpu->isar.regs[ID_DFR0] = 0; - cpu->id_afr0 = 0x2; -- cpu->isar.id_mmfr0 = 0x01100103; -- cpu->isar.id_mmfr1 = 0x10020302; -- cpu->isar.id_mmfr2 = 0x01222000; -- cpu->isar.id_isar0 = 0x00100011; -- cpu->isar.id_isar1 = 0x12002111; -- cpu->isar.id_isar2 = 0x11221011; -- cpu->isar.id_isar3 = 0x01102131; -- cpu->isar.id_isar4 = 0x141; -+ cpu->isar.regs[ID_MMFR0] = 0x01100103; -+ cpu->isar.regs[ID_MMFR1] = 0x10020302; -+ cpu->isar.regs[ID_MMFR2] = 0x01222000; -+ cpu->isar.regs[ID_ISAR0] = 0x00100011; -+ cpu->isar.regs[ID_ISAR1] = 0x12002111; -+ cpu->isar.regs[ID_ISAR2] = 0x11221011; -+ cpu->isar.regs[ID_ISAR3] = 0x01102131; -+ cpu->isar.regs[ID_ISAR4] = 0x141; - cpu->reset_auxcr = 1; + static inline bool isar_feature_aa32_pmull(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) > 1; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, AES) > 1; } -@@ -1889,19 +1894,19 @@ static void cortex_m3_initfn(Object *obj) - cpu->pmsav7_dregion = 8; - cpu->id_pfr0 = 0x00000030; - cpu->id_pfr1 = 0x00000200; -- cpu->isar.id_dfr0 = 0x00100000; -+ cpu->isar.regs[ID_DFR0] = 0x00100000; - cpu->id_afr0 = 0x00000000; -- cpu->isar.id_mmfr0 = 0x00000030; -- cpu->isar.id_mmfr1 = 0x00000000; -- cpu->isar.id_mmfr2 = 0x00000000; -- cpu->isar.id_mmfr3 = 0x00000000; -- cpu->isar.id_isar0 = 0x01141110; -- cpu->isar.id_isar1 = 0x02111000; -- cpu->isar.id_isar2 = 0x21112231; -- cpu->isar.id_isar3 = 0x01111110; -- cpu->isar.id_isar4 = 0x01310102; -- cpu->isar.id_isar5 = 0x00000000; -- cpu->isar.id_isar6 = 0x00000000; -+ cpu->isar.regs[ID_MMFR0] = 0x00000030; -+ cpu->isar.regs[ID_MMFR1] = 0x00000000; -+ cpu->isar.regs[ID_MMFR2] = 0x00000000; -+ cpu->isar.regs[ID_MMFR3] = 0x00000000; -+ cpu->isar.regs[ID_ISAR0] = 0x01141110; -+ cpu->isar.regs[ID_ISAR1] = 0x02111000; -+ cpu->isar.regs[ID_ISAR2] = 0x21112231; -+ cpu->isar.regs[ID_ISAR3] = 0x01111110; -+ cpu->isar.regs[ID_ISAR4] = 0x01310102; -+ cpu->isar.regs[ID_ISAR5] = 0x00000000; -+ cpu->isar.regs[ID_ISAR6] = 0x00000000; + static inline bool isar_feature_aa32_sha1(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA1) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, SHA1) != 0; } - static void cortex_m4_initfn(Object *obj) -@@ -1915,24 +1920,24 @@ static void cortex_m4_initfn(Object *obj) - set_feature(&cpu->env, ARM_FEATURE_VFP4); - cpu->midr = 0x410fc240; /* r0p0 */ - cpu->pmsav7_dregion = 8; -- cpu->isar.mvfr0 = 0x10110021; -- cpu->isar.mvfr1 = 0x11000011; -- cpu->isar.mvfr2 = 0x00000000; -+ cpu->isar.regs[MVFR0] = 0x10110021; -+ cpu->isar.regs[MVFR1] = 0x11000011; -+ cpu->isar.regs[MVFR2] = 0x00000000; - cpu->id_pfr0 = 0x00000030; - cpu->id_pfr1 = 0x00000200; -- cpu->isar.id_dfr0 = 0x00100000; -+ cpu->isar.regs[ID_DFR0] = 0x00100000; - cpu->id_afr0 = 0x00000000; -- cpu->isar.id_mmfr0 = 0x00000030; -- cpu->isar.id_mmfr1 = 0x00000000; -- cpu->isar.id_mmfr2 = 0x00000000; -- cpu->isar.id_mmfr3 = 0x00000000; -- cpu->isar.id_isar0 = 0x01141110; -- cpu->isar.id_isar1 = 0x02111000; -- cpu->isar.id_isar2 = 0x21112231; -- cpu->isar.id_isar3 = 0x01111110; -- cpu->isar.id_isar4 = 0x01310102; -- cpu->isar.id_isar5 = 0x00000000; -- cpu->isar.id_isar6 = 0x00000000; -+ cpu->isar.regs[ID_MMFR0] = 0x00000030; -+ cpu->isar.regs[ID_MMFR1] = 0x00000000; -+ cpu->isar.regs[ID_MMFR2] = 0x00000000; -+ cpu->isar.regs[ID_MMFR3] = 0x00000000; -+ cpu->isar.regs[ID_ISAR0] = 0x01141110; -+ cpu->isar.regs[ID_ISAR1] = 0x02111000; -+ cpu->isar.regs[ID_ISAR2] = 0x21112231; -+ cpu->isar.regs[ID_ISAR3] = 0x01111110; -+ cpu->isar.regs[ID_ISAR4] = 0x01310102; -+ cpu->isar.regs[ID_ISAR5] = 0x00000000; -+ cpu->isar.regs[ID_ISAR6] = 0x00000000; + static inline bool isar_feature_aa32_sha2(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA2) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, SHA2) != 0; } - static void cortex_m33_initfn(Object *obj) -@@ -1948,24 +1953,24 @@ static void cortex_m33_initfn(Object *obj) - cpu->midr = 0x410fd213; /* r0p3 */ - cpu->pmsav7_dregion = 16; - cpu->sau_sregion = 8; -- cpu->isar.mvfr0 = 0x10110021; -- cpu->isar.mvfr1 = 0x11000011; -- cpu->isar.mvfr2 = 0x00000040; -+ cpu->isar.regs[MVFR0] = 0x10110021; -+ cpu->isar.regs[MVFR1] = 0x11000011; -+ cpu->isar.regs[MVFR2] = 0x00000040; - cpu->id_pfr0 = 0x00000030; - cpu->id_pfr1 = 0x00000210; -- cpu->isar.id_dfr0 = 0x00200000; -+ cpu->isar.regs[ID_DFR0] = 0x00200000; - cpu->id_afr0 = 0x00000000; -- cpu->isar.id_mmfr0 = 0x00101F40; -- cpu->isar.id_mmfr1 = 0x00000000; -- cpu->isar.id_mmfr2 = 0x01000000; -- cpu->isar.id_mmfr3 = 0x00000000; -- cpu->isar.id_isar0 = 0x01101110; -- cpu->isar.id_isar1 = 0x02212000; -- cpu->isar.id_isar2 = 0x20232232; -- cpu->isar.id_isar3 = 0x01111131; -- cpu->isar.id_isar4 = 0x01310132; -- cpu->isar.id_isar5 = 0x00000000; -- cpu->isar.id_isar6 = 0x00000000; -+ cpu->isar.regs[ID_MMFR0] = 0x00101F40; -+ cpu->isar.regs[ID_MMFR1] = 0x00000000; -+ cpu->isar.regs[ID_MMFR2] = 0x01000000; -+ cpu->isar.regs[ID_MMFR3] = 0x00000000; -+ cpu->isar.regs[ID_ISAR0] = 0x01101110; -+ cpu->isar.regs[ID_ISAR1] = 0x02212000; -+ cpu->isar.regs[ID_ISAR2] = 0x20232232; -+ cpu->isar.regs[ID_ISAR3] = 0x01111131; -+ cpu->isar.regs[ID_ISAR4] = 0x01310132; -+ cpu->isar.regs[ID_ISAR5] = 0x00000000; -+ cpu->isar.regs[ID_ISAR6] = 0x00000000; - cpu->clidr = 0x00000000; - cpu->ctr = 0x8000c000; + static inline bool isar_feature_aa32_crc32(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, CRC32) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, CRC32) != 0; } -@@ -2004,19 +2009,19 @@ static void cortex_r5_initfn(Object *obj) - cpu->midr = 0x411fc153; /* r1p3 */ - cpu->id_pfr0 = 0x0131; - cpu->id_pfr1 = 0x001; -- cpu->isar.id_dfr0 = 0x010400; -+ cpu->isar.regs[ID_DFR0] = 0x010400; - cpu->id_afr0 = 0x0; -- cpu->isar.id_mmfr0 = 0x0210030; -- cpu->isar.id_mmfr1 = 0x00000000; -- cpu->isar.id_mmfr2 = 0x01200000; -- cpu->isar.id_mmfr3 = 0x0211; -- cpu->isar.id_isar0 = 0x02101111; -- cpu->isar.id_isar1 = 0x13112111; -- cpu->isar.id_isar2 = 0x21232141; -- cpu->isar.id_isar3 = 0x01112131; -- cpu->isar.id_isar4 = 0x0010142; -- cpu->isar.id_isar5 = 0x0; -- cpu->isar.id_isar6 = 0x0; -+ cpu->isar.regs[ID_MMFR0] = 0x0210030; -+ cpu->isar.regs[ID_MMFR1] = 0x00000000; -+ cpu->isar.regs[ID_MMFR2] = 0x01200000; -+ cpu->isar.regs[ID_MMFR3] = 0x0211; -+ cpu->isar.regs[ID_ISAR0] = 0x02101111; -+ cpu->isar.regs[ID_ISAR1] = 0x13112111; -+ cpu->isar.regs[ID_ISAR2] = 0x21232141; -+ cpu->isar.regs[ID_ISAR3] = 0x01112131; -+ cpu->isar.regs[ID_ISAR4] = 0x0010142; -+ cpu->isar.regs[ID_ISAR5] = 0x0; -+ cpu->isar.regs[ID_ISAR6] = 0x0; - cpu->mp_is_up = true; - cpu->pmsav7_dregion = 16; - define_arm_cp_regs(cpu, cortexr5_cp_reginfo); -@@ -2028,8 +2033,8 @@ static void cortex_r5f_initfn(Object *obj) - cortex_r5_initfn(obj); - set_feature(&cpu->env, ARM_FEATURE_VFP3); -- cpu->isar.mvfr0 = 0x10110221; -- cpu->isar.mvfr1 = 0x00000011; -+ cpu->isar.regs[MVFR0] = 0x10110221; -+ cpu->isar.regs[MVFR1] = 0x00000011; + static inline bool isar_feature_aa32_rdm(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_isar5, ID_ISAR5, RDM) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, RDM) != 0; } - static const ARMCPRegInfo cortexa8_cp_reginfo[] = { -@@ -2053,24 +2058,24 @@ static void cortex_a8_initfn(Object *obj) - set_feature(&cpu->env, ARM_FEATURE_EL3); - cpu->midr = 0x410fc080; - cpu->reset_fpsid = 0x410330c0; -- cpu->isar.mvfr0 = 0x11110222; -- cpu->isar.mvfr1 = 0x00011111; -+ cpu->isar.regs[MVFR0] = 0x11110222; -+ cpu->isar.regs[MVFR1] = 0x00011111; - cpu->ctr = 0x82048004; - cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x1031; - cpu->id_pfr1 = 0x11; -- cpu->isar.id_dfr0 = 0x400; -+ cpu->isar.regs[ID_DFR0] = 0x400; - cpu->id_afr0 = 0; -- cpu->isar.id_mmfr0 = 0x31100003; -- cpu->isar.id_mmfr1 = 0x20000000; -- cpu->isar.id_mmfr2 = 0x01202000; -- cpu->isar.id_mmfr3 = 0x11; -- cpu->isar.id_isar0 = 0x00101111; -- cpu->isar.id_isar1 = 0x12112111; -- cpu->isar.id_isar2 = 0x21232031; -- cpu->isar.id_isar3 = 0x11112131; -- cpu->isar.id_isar4 = 0x00111142; -- cpu->isar.dbgdidr = 0x15141000; -+ cpu->isar.regs[ID_MMFR0] = 0x31100003; -+ cpu->isar.regs[ID_MMFR1] = 0x20000000; -+ cpu->isar.regs[ID_MMFR2] = 0x01202000; -+ cpu->isar.regs[ID_MMFR3] = 0x11; -+ cpu->isar.regs[ID_ISAR0] = 0x00101111; -+ cpu->isar.regs[ID_ISAR1] = 0x12112111; -+ cpu->isar.regs[ID_ISAR2] = 0x21232031; -+ cpu->isar.regs[ID_ISAR3] = 0x11112131; -+ cpu->isar.regs[ID_ISAR4] = 0x00111142; -+ cpu->isar.regs[DBGDIDR] = 0x15141000; - cpu->clidr = (1 << 27) | (2 << 24) | 3; - cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */ - cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */ -@@ -2126,24 +2131,24 @@ static void cortex_a9_initfn(Object *obj) - set_feature(&cpu->env, ARM_FEATURE_CBAR); - cpu->midr = 0x410fc090; - cpu->reset_fpsid = 0x41033090; -- cpu->isar.mvfr0 = 0x11110222; -- cpu->isar.mvfr1 = 0x01111111; -+ cpu->isar.regs[MVFR0] = 0x11110222; -+ cpu->isar.regs[MVFR1] = 0x01111111; - cpu->ctr = 0x80038003; - cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x1031; - cpu->id_pfr1 = 0x11; -- cpu->isar.id_dfr0 = 0x000; -+ cpu->isar.regs[ID_DFR0] = 0x000; - cpu->id_afr0 = 0; -- cpu->isar.id_mmfr0 = 0x00100103; -- cpu->isar.id_mmfr1 = 0x20000000; -- cpu->isar.id_mmfr2 = 0x01230000; -- cpu->isar.id_mmfr3 = 0x00002111; -- cpu->isar.id_isar0 = 0x00101111; -- cpu->isar.id_isar1 = 0x13112111; -- cpu->isar.id_isar2 = 0x21232041; -- cpu->isar.id_isar3 = 0x11112131; -- cpu->isar.id_isar4 = 0x00111142; -- cpu->isar.dbgdidr = 0x35141000; -+ cpu->isar.regs[ID_MMFR0] = 0x00100103; -+ cpu->isar.regs[ID_MMFR1] = 0x20000000; -+ cpu->isar.regs[ID_MMFR2] = 0x01230000; -+ cpu->isar.regs[ID_MMFR3] = 0x00002111; -+ cpu->isar.regs[ID_ISAR0] = 0x00101111; -+ cpu->isar.regs[ID_ISAR1] = 0x13112111; -+ cpu->isar.regs[ID_ISAR2] = 0x21232041; -+ cpu->isar.regs[ID_ISAR3] = 0x11112131; -+ cpu->isar.regs[ID_ISAR4] = 0x00111142; -+ cpu->isar.regs[DBGDIDR] = 0x35141000; - cpu->clidr = (1 << 27) | (1 << 24) | 3; - cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */ - cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */ -@@ -2191,27 +2196,27 @@ static void cortex_a7_initfn(Object *obj) - cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7; - cpu->midr = 0x410fc075; - cpu->reset_fpsid = 0x41023075; -- cpu->isar.mvfr0 = 0x10110222; -- cpu->isar.mvfr1 = 0x11111111; -+ cpu->isar.regs[MVFR0] = 0x10110222; -+ cpu->isar.regs[MVFR1] = 0x11111111; - cpu->ctr = 0x84448003; - cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x00001131; - cpu->id_pfr1 = 0x00011011; -- cpu->isar.id_dfr0 = 0x02010555; -+ cpu->isar.regs[ID_DFR0] = 0x02010555; - cpu->id_afr0 = 0x00000000; -- cpu->isar.id_mmfr0 = 0x10101105; -- cpu->isar.id_mmfr1 = 0x40000000; -- cpu->isar.id_mmfr2 = 0x01240000; -- cpu->isar.id_mmfr3 = 0x02102211; -+ cpu->isar.regs[ID_MMFR0] = 0x10101105; -+ cpu->isar.regs[ID_MMFR1] = 0x40000000; -+ cpu->isar.regs[ID_MMFR2] = 0x01240000; -+ cpu->isar.regs[ID_MMFR3] = 0x02102211; - /* a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but - * table 4-41 gives 0x02101110, which includes the arm div insns. - */ -- cpu->isar.id_isar0 = 0x02101110; -- cpu->isar.id_isar1 = 0x13112111; -- cpu->isar.id_isar2 = 0x21232041; -- cpu->isar.id_isar3 = 0x11112131; -- cpu->isar.id_isar4 = 0x10011142; -- cpu->isar.dbgdidr = 0x3515f005; -+ cpu->isar.regs[ID_ISAR0] = 0x02101110; -+ cpu->isar.regs[ID_ISAR1] = 0x13112111; -+ cpu->isar.regs[ID_ISAR2] = 0x21232041; -+ cpu->isar.regs[ID_ISAR3] = 0x11112131; -+ cpu->isar.regs[ID_ISAR4] = 0x10011142; -+ cpu->isar.regs[DBGDIDR] = 0x3515f005; - cpu->clidr = 0x0a200023; - cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */ - cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */ -@@ -2237,24 +2242,24 @@ static void cortex_a15_initfn(Object *obj) - cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15; - cpu->midr = 0x412fc0f1; - cpu->reset_fpsid = 0x410430f0; -- cpu->isar.mvfr0 = 0x10110222; -- cpu->isar.mvfr1 = 0x11111111; -+ cpu->isar.regs[MVFR0] = 0x10110222; -+ cpu->isar.regs[MVFR1] = 0x11111111; - cpu->ctr = 0x8444c004; - cpu->reset_sctlr = 0x00c50078; - cpu->id_pfr0 = 0x00001131; - cpu->id_pfr1 = 0x00011011; -- cpu->isar.id_dfr0 = 0x02010555; -+ cpu->isar.regs[ID_DFR0] = 0x02010555; - cpu->id_afr0 = 0x00000000; -- cpu->isar.id_mmfr0 = 0x10201105; -- cpu->isar.id_mmfr1 = 0x20000000; -- cpu->isar.id_mmfr2 = 0x01240000; -- cpu->isar.id_mmfr3 = 0x02102211; -- cpu->isar.id_isar0 = 0x02101110; -- cpu->isar.id_isar1 = 0x13112111; -- cpu->isar.id_isar2 = 0x21232041; -- cpu->isar.id_isar3 = 0x11112131; -- cpu->isar.id_isar4 = 0x10011142; -- cpu->isar.dbgdidr = 0x3515f021; -+ cpu->isar.regs[ID_MMFR0] = 0x10201105; -+ cpu->isar.regs[ID_MMFR1] = 0x20000000; -+ cpu->isar.regs[ID_MMFR2] = 0x01240000; -+ cpu->isar.regs[ID_MMFR3] = 0x02102211; -+ cpu->isar.regs[ID_ISAR0] = 0x02101110; -+ cpu->isar.regs[ID_ISAR1] = 0x13112111; -+ cpu->isar.regs[ID_ISAR2] = 0x21232041; -+ cpu->isar.regs[ID_ISAR3] = 0x11112131; -+ cpu->isar.regs[ID_ISAR4] = 0x10011142; -+ cpu->isar.regs[DBGDIDR] = 0x3515f021; - cpu->clidr = 0x0a200023; - cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */ - cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */ -@@ -2447,7 +2452,8 @@ static void arm_max_initfn(Object *obj) - cortex_a15_initfn(obj); - - /* old-style VFP short-vector support */ -- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); -+ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, -+ FPSHVEC, 1); - - #ifdef CONFIG_USER_ONLY - /* We don't set these in system emulation mode for the moment, -@@ -2458,39 +2464,39 @@ static void arm_max_initfn(Object *obj) - { - uint32_t t; - -- t = cpu->isar.id_isar5; -+ t = cpu->isar.regs[ID_ISAR5]; - t = FIELD_DP32(t, ID_ISAR5, AES, 2); - t = FIELD_DP32(t, ID_ISAR5, SHA1, 1); - t = FIELD_DP32(t, ID_ISAR5, SHA2, 1); - t = FIELD_DP32(t, ID_ISAR5, CRC32, 1); - t = FIELD_DP32(t, ID_ISAR5, RDM, 1); - t = FIELD_DP32(t, ID_ISAR5, VCMA, 1); -- cpu->isar.id_isar5 = t; -+ cpu->isar.regs[ID_ISAR5] = t; - -- t = cpu->isar.id_isar6; -+ t = cpu->isar.regs[ID_ISAR6]; - t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1); - t = FIELD_DP32(t, ID_ISAR6, DP, 1); - t = FIELD_DP32(t, ID_ISAR6, FHM, 1); - t = FIELD_DP32(t, ID_ISAR6, SB, 1); - t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1); -- cpu->isar.id_isar6 = t; -+ cpu->isar.regs[ID_ISAR6] = t; - -- t = cpu->isar.mvfr1; -+ t = cpu->isar.regs[MVFR1]; - t = FIELD_DP32(t, MVFR1, FPHP, 2); /* v8.0 FP support */ -- cpu->isar.mvfr1 = t; -+ cpu->isar.regs[MVFR1] = t; - -- t = cpu->isar.mvfr2; -+ t = cpu->isar.regs[MVFR2]; - t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */ - t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */ -- cpu->isar.mvfr2 = t; -+ cpu->isar.regs[MVFR2] = t; - -- t = cpu->isar.id_mmfr3; -+ t = cpu->isar.regs[ID_MMFR3]; - t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */ -- cpu->isar.id_mmfr3 = t; -+ cpu->isar.regs[ID_MMFR3] = t; - -- t = cpu->isar.id_mmfr4; -+ t = cpu->isar.regs[ID_MMFR4]; - t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */ -- cpu->isar.id_mmfr4 = t; -+ cpu->isar.regs[ID_MMFR4] = t; - } - #endif - } -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index 56d8cd8c..7bb481fb 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -63,6 +63,37 @@ - #define ARMV7M_EXCP_PENDSV 14 - #define ARMV7M_EXCP_SYSTICK 15 - -+typedef enum CPUIDReg { -+ MIDR_EL1, -+ ID_ISAR0, -+ ID_ISAR1, -+ ID_ISAR2, -+ ID_ISAR3, -+ ID_ISAR4, -+ ID_ISAR5, -+ ID_ISAR6, -+ ID_MMFR0, -+ ID_MMFR1, -+ ID_MMFR2, -+ ID_MMFR3, -+ ID_MMFR4, -+ ID_AA64ISAR0, -+ ID_AA64ISAR1, -+ ID_AA64PFR0, -+ ID_AA64PFR1, -+ ID_AA64MMFR0, -+ ID_AA64MMFR1, -+ ID_AA64MMFR2, -+ ID_AA64DFR0, -+ ID_AA64DFR1, -+ ID_DFR0, -+ MVFR0, -+ MVFR1, -+ MVFR2, -+ DBGDIDR, -+ ID_MAX, -+} CPUIDReg; -+ - /* For M profile, some registers are banked secure vs non-secure; - * these are represented as a 2-element array where the first element - * is the non-secure copy and the second is the secure copy. -@@ -855,32 +886,7 @@ struct ARMCPU { - * field by reading the value from the KVM vCPU. - */ - struct ARMISARegisters { -- uint32_t id_isar0; -- uint32_t id_isar1; -- uint32_t id_isar2; -- uint32_t id_isar3; -- uint32_t id_isar4; -- uint32_t id_isar5; -- uint32_t id_isar6; -- uint32_t id_mmfr0; -- uint32_t id_mmfr1; -- uint32_t id_mmfr2; -- uint32_t id_mmfr3; -- uint32_t id_mmfr4; -- uint32_t mvfr0; -- uint32_t mvfr1; -- uint32_t mvfr2; -- uint32_t id_dfr0; -- uint32_t dbgdidr; -- uint64_t id_aa64isar0; -- uint64_t id_aa64isar1; -- uint64_t id_aa64pfr0; -- uint64_t id_aa64pfr1; -- uint64_t id_aa64mmfr0; -- uint64_t id_aa64mmfr1; -- uint64_t id_aa64mmfr2; -- uint64_t id_aa64dfr0; -- uint64_t id_aa64dfr1; -+ uint64_t regs[ID_MAX]; - } isar; - uint32_t midr; - uint32_t revidr; -@@ -3358,77 +3364,77 @@ extern const uint64_t pred_esz_masks[4]; - */ - static inline bool isar_feature_thumb_div(const ARMISARegisters *id) + static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id) { -- return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) != 0; -+ return FIELD_EX32(id->regs[ID_ISAR0], ID_ISAR0, DIVIDE) != 0; +- return FIELD_EX32(id->id_isar5, ID_ISAR5, VCMA) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, VCMA) != 0; } - static inline bool isar_feature_arm_div(const ARMISARegisters *id) + static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id) { -- return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1; -+ return FIELD_EX32(id->regs[ID_ISAR0], ID_ISAR0, DIVIDE) > 1; +- return FIELD_EX32(id->id_isar6, ID_ISAR6, JSCVT) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, JSCVT) != 0; } - static inline bool isar_feature_jazelle(const ARMISARegisters *id) + static inline bool isar_feature_aa32_dp(const ARMISARegisters *id) { -- return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0; -+ return FIELD_EX32(id->regs[ID_ISAR1], ID_ISAR1, JAZELLE) != 0; +- return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, DP) != 0; } - static inline bool isar_feature_aa32_aes(const ARMISARegisters *id) + static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id) { -- return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) != 0; -+ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, AES) != 0; +- return FIELD_EX32(id->id_isar6, ID_ISAR6, FHM) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, FHM) != 0; } - static inline bool isar_feature_aa32_pmull(const ARMISARegisters *id) + static inline bool isar_feature_aa32_sb(const ARMISARegisters *id) { -- return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) > 1; -+ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, AES) > 1; +- return FIELD_EX32(id->id_isar6, ID_ISAR6, SB) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, SB) != 0; } - static inline bool isar_feature_aa32_sha1(const ARMISARegisters *id) + static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id) { -- return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA1) != 0; -+ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, SHA1) != 0; +- return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, SPECRES) != 0; } - static inline bool isar_feature_aa32_sha2(const ARMISARegisters *id) + static inline bool isar_feature_aa32_bf16(const ARMISARegisters *id) { -- return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA2) != 0; -+ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, SHA2) != 0; +- return FIELD_EX32(id->id_isar6, ID_ISAR6, BF16) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, BF16) != 0; } - static inline bool isar_feature_aa32_crc32(const ARMISARegisters *id) + static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id) { -- return FIELD_EX32(id->id_isar5, ID_ISAR5, CRC32) != 0; -+ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, CRC32) != 0; +- return FIELD_EX32(id->id_isar6, ID_ISAR6, I8MM) != 0; ++ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, I8MM) != 0; } - static inline bool isar_feature_aa32_rdm(const ARMISARegisters *id) + static inline bool isar_feature_aa32_ras(const ARMISARegisters *id) { -- return FIELD_EX32(id->id_isar5, ID_ISAR5, RDM) != 0; -+ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, RDM) != 0; +- return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0; ++ return FIELD_EX32(id->regs[ID_PFR0], ID_PFR0, RAS) != 0; } - static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id) + static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id) { -- return FIELD_EX32(id->id_isar5, ID_ISAR5, VCMA) != 0; -+ return FIELD_EX32(id->regs[ID_ISAR5], ID_ISAR5, VCMA) != 0; +- return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0; ++ return FIELD_EX32(id->regs[ID_PFR1], ID_PFR1, MPROGMOD) != 0; } - static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id) + static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id) +@@ -3834,16 +3840,16 @@ static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id) + * Return true if M-profile state handling insns + * (VSCCLRM, CLRM, FPCTX access insns) are implemented + */ +- return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3; ++ return FIELD_EX32(id->regs[ID_PFR1], ID_PFR1, SECURITY) >= 3; + } + + static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) { -- return FIELD_EX32(id->id_isar6, ID_ISAR6, JSCVT) != 0; -+ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, JSCVT) != 0; + /* Sadly this is encoded differently for A-profile and M-profile */ + if (isar_feature_aa32_mprofile(id)) { +- return FIELD_EX32(id->mvfr1, MVFR1, FP16) > 0; ++ return FIELD_EX32(id->regs[MVFR1], MVFR1, FP16) > 0; + } else { +- return FIELD_EX32(id->mvfr1, MVFR1, FPHP) >= 3; ++ return FIELD_EX32(id->regs[MVFR1], MVFR1, FPHP) >= 3; + } + } + +@@ -3855,7 +3861,7 @@ static inline bool isar_feature_aa32_mve(const ARMISARegisters *id) + * else for A-profile. + */ + return isar_feature_aa32_mprofile(id) && +- FIELD_EX32(id->mvfr1, MVFR1, MVE) > 0; ++ FIELD_EX32(id->regs[MVFR1], MVFR1, MVE) > 0; } - static inline bool isar_feature_aa32_dp(const ARMISARegisters *id) - { -- return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0; -+ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, DP) != 0; + static inline bool isar_feature_aa32_mve_fp(const ARMISARegisters *id) +@@ -3866,7 +3872,7 @@ static inline bool isar_feature_aa32_mve_fp(const ARMISARegisters *id) + * else for A-profile. + */ + return isar_feature_aa32_mprofile(id) && +- FIELD_EX32(id->mvfr1, MVFR1, MVE) >= 2; ++ FIELD_EX32(id->regs[MVFR1], MVFR1, MVE) >= 2; } - static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id) - { -- return FIELD_EX32(id->id_isar6, ID_ISAR6, FHM) != 0; -+ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, FHM) != 0; + static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id) +@@ -3875,42 +3881,42 @@ static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id) + * Return true if either VFP or SIMD is implemented. + * In this case, a minimum of VFP w/ D0-D15. + */ +- return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) > 0; ++ return FIELD_EX32(id->regs[MVFR0], MVFR0, SIMDREG) > 0; } - static inline bool isar_feature_aa32_sb(const ARMISARegisters *id) + static inline bool isar_feature_aa32_simd_r32(const ARMISARegisters *id) { -- return FIELD_EX32(id->id_isar6, ID_ISAR6, SB) != 0; -+ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, SB) != 0; + /* Return true if D16-D31 are implemented */ +- return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) >= 2; ++ return FIELD_EX32(id->regs[MVFR0], MVFR0, SIMDREG) >= 2; } - static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id) + static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id) { -- return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0; -+ return FIELD_EX32(id->regs[ID_ISAR6], ID_ISAR6, SPECRES) != 0; +- return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0; ++ return FIELD_EX32(id->regs[MVFR0], MVFR0, FPSHVEC) > 0; } - static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) -@@ -3438,24 +3444,24 @@ static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) - * the ARMv8.2-FP16 extension is implemented for aa32 mode. - * At which point we can properly set and check MVFR1.FPHP. - */ -- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1; -+ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, FP) == 1; + static inline bool isar_feature_aa32_fpsp_v2(const ARMISARegisters *id) + { + /* Return true if CPU supports single precision floating point, VFPv2 */ +- return FIELD_EX32(id->mvfr0, MVFR0, FPSP) > 0; ++ return FIELD_EX32(id->regs[MVFR0], MVFR0, FPSP) > 0; } - static inline bool isar_feature_aa32_fp_d32(const ARMISARegisters *id) + static inline bool isar_feature_aa32_fpsp_v3(const ARMISARegisters *id) { - /* Return true if D16-D31 are implemented */ -- return FIELD_EX64(id->mvfr0, MVFR0, SIMDREG) >= 2; -+ return FIELD_EX64(id->regs[MVFR0], MVFR0, SIMDREG) >= 2; + /* Return true if CPU supports single precision floating point, VFPv3 */ +- return FIELD_EX32(id->mvfr0, MVFR0, FPSP) >= 2; ++ return FIELD_EX32(id->regs[MVFR0], MVFR0, FPSP) >= 2; } - static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id) + static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id) { -- return FIELD_EX64(id->mvfr0, MVFR0, FPSHVEC) > 0; -+ return FIELD_EX64(id->regs[MVFR0], MVFR0, FPSHVEC) > 0; + /* Return true if CPU supports double precision floating point, VFPv2 */ +- return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0; ++ return FIELD_EX32(id->regs[MVFR0], MVFR0, FPDP) > 0; } - static inline bool isar_feature_aa32_fpdp(const ARMISARegisters *id) + static inline bool isar_feature_aa32_fpdp_v3(const ARMISARegisters *id) { - /* Return true if CPU supports double precision floating point */ -- return FIELD_EX64(id->mvfr0, MVFR0, FPDP) > 0; -+ return FIELD_EX64(id->regs[MVFR0], MVFR0, FPDP) > 0; + /* Return true if CPU supports double precision floating point, VFPv3 */ +- return FIELD_EX32(id->mvfr0, MVFR0, FPDP) >= 2; ++ return FIELD_EX32(id->regs[MVFR0], MVFR0, FPDP) >= 2; } - /* -@@ -3465,49 +3471,49 @@ static inline bool isar_feature_aa32_fpdp(const ARMISARegisters *id) + static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id) +@@ -3925,12 +3931,12 @@ static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id) */ static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id) { -- return FIELD_EX64(id->mvfr1, MVFR1, FPHP) > 0; -+ return FIELD_EX64(id->regs[MVFR1], MVFR1, FPHP) > 0; +- return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 0; ++ return FIELD_EX32(id->regs[MVFR1], MVFR1, FPHP) > 0; } static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id) { -- return FIELD_EX64(id->mvfr1, MVFR1, FPHP) > 1; -+ return FIELD_EX64(id->regs[MVFR1], MVFR1, FPHP) > 1; +- return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 1; ++ return FIELD_EX32(id->regs[MVFR1], MVFR1, FPHP) > 1; + } + + /* +@@ -3942,86 +3948,86 @@ static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id) + */ + static inline bool isar_feature_aa32_simdfmac(const ARMISARegisters *id) + { +- return FIELD_EX32(id->mvfr1, MVFR1, SIMDFMAC) != 0; ++ return FIELD_EX32(id->regs[MVFR1], MVFR1, SIMDFMAC) != 0; } static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id) { -- return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 1; -+ return FIELD_EX64(id->regs[MVFR2], MVFR2, FPMISC) >= 1; +- return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 1; ++ return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 1; } static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id) { -- return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 2; -+ return FIELD_EX64(id->regs[MVFR2], MVFR2, FPMISC) >= 2; +- return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 2; ++ return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 2; } static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id) { -- return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 3; -+ return FIELD_EX64(id->regs[MVFR2], MVFR2, FPMISC) >= 3; +- return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 3; ++ return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 3; } static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id) { -- return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 4; -+ return FIELD_EX64(id->regs[MVFR2], MVFR2, FPMISC) >= 4; +- return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 4; ++ return FIELD_EX32(id->regs[MVFR2], MVFR2, FPMISC) >= 4; + } + + static inline bool isar_feature_aa32_pxn(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr0, ID_MMFR0, VMSA) >= 4; ++ return FIELD_EX32(id->regs[ID_MMFR0], ID_MMFR0, VMSA) >= 4; } static inline bool isar_feature_aa32_pan(const ARMISARegisters *id) @@ -1086,8 +731,53 @@ index 56d8cd8c..7bb481fb 100644 + FIELD_EX32(id->regs[ID_DFR0], ID_DFR0, PERFMON) != 0xf; } + static inline bool isar_feature_aa32_pmu_8_4(const ARMISARegisters *id) + { + /* 0xf means "non-standard IMPDEF PMU" */ +- return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 5 && +- FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; ++ return FIELD_EX32(id->regs[ID_DFR0], ID_DFR0, PERFMON) >= 5 && ++ FIELD_EX32(id->regs[ID_DFR0], ID_DFR0, PERFMON) != 0xf; + } + + static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr4, ID_MMFR4, HPDS) != 0; ++ return FIELD_EX32(id->regs[ID_MMFR4], ID_MMFR4, HPDS) != 0; + } + + static inline bool isar_feature_aa32_ac2(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr4, ID_MMFR4, AC2) != 0; ++ return FIELD_EX32(id->regs[ID_MMFR4], ID_MMFR4, AC2) != 0; + } + + static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr4, ID_MMFR4, CCIDX) != 0; ++ return FIELD_EX32(id->regs[ID_MMFR4], ID_MMFR4, CCIDX) != 0; + } + + static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_mmfr4, ID_MMFR4, XNX) != 0; ++ return FIELD_EX32(id->regs[ID_MMFR4], ID_MMFR4, XNX) != 0; + } + + static inline bool isar_feature_aa32_dit(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0; ++ return FIELD_EX32(id->regs[ID_PFR0], ID_PFR0, DIT) != 0; + } + + static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id) + { +- return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0; ++ return FIELD_EX32(id->regs[ID_PFR2], ID_PFR2, SSBS) != 0; + } + /* -@@ -3515,92 +3521,92 @@ static inline bool isar_feature_aa32_pmu_8_1(const ARMISARegisters *id) +@@ -4029,92 +4035,92 @@ static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id) */ static inline bool isar_feature_aa64_aes(const ARMISARegisters *id) { @@ -1161,391 +851,1462 @@ index 56d8cd8c..7bb481fb 100644 + return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, DP) != 0; } - static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id) + static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, FHM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, FHM) != 0; + } + + static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, TS) != 0; + } + + static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, TS) >= 2; + } + + static inline bool isar_feature_aa64_rndr(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RNDR) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, RNDR) != 0; + } + + static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, JSCVT) != 0; + } + + static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, FCMA) != 0; + } + + static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) +@@ -4123,7 +4129,7 @@ static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) + * Return true if any form of pauth is enabled, as this + * predicate controls migration of the 128-bit keys. + */ +- return (id->id_aa64isar1 & ++ return (id->regs[ID_AA64ISAR1] & + (FIELD_DP64(0, ID_AA64ISAR1, APA, 0xf) | + FIELD_DP64(0, ID_AA64ISAR1, API, 0xf) | + FIELD_DP64(0, ID_AA64ISAR1, GPA, 0xf) | +@@ -4136,221 +4142,221 @@ static inline bool isar_feature_aa64_pauth_arch(const ARMISARegisters *id) + * Return true if pauth is enabled with the architected QARMA algorithm. + * QEMU will always set APA+GPA to the same value. + */ +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, APA) != 0; + } + + static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) == 2; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, TLB) == 2; + } + + static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, TLB) != 0; + } + + static inline bool isar_feature_aa64_sb(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, SB) != 0; + } + + static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SPECRES) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, SPECRES) != 0; + } + + static inline bool isar_feature_aa64_frint(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, FRINTTS) != 0; + } + + static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, DPB) != 0; + } + + static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, DPB) >= 2; + } + + static inline bool isar_feature_aa64_bf16(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, BF16) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, BF16) != 0; + } + + static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id) + { + /* We always set the AdvSIMD and FP fields identically. */ +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) != 0xf; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, FP) != 0xf; + } + + static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id) + { + /* We always set the AdvSIMD and FP fields identically wrt FP16. */ +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, FP) == 1; + } + + static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL0) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, EL0) >= 2; + } + + static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, EL1) >= 2; + } + + static inline bool isar_feature_aa64_sve(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, SVE) != 0; + } + + static inline bool isar_feature_aa64_sel2(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SEL2) != 0; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, SEL2) != 0; + } + + static inline bool isar_feature_aa64_vh(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0; ++ return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, VH) != 0; + } + + static inline bool isar_feature_aa64_lor(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0; ++ return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, LO) != 0; + } + + static inline bool isar_feature_aa64_pan(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0; ++ return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, PAN) != 0; + } + + static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, PAN) >= 2; + } + + static inline bool isar_feature_aa64_uao(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0; ++ return FIELD_EX64(id->regs[ID_AA64MMFR2], ID_AA64MMFR2, UAO) != 0; + } + + static inline bool isar_feature_aa64_st(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0; ++ return FIELD_EX64(id->regs[ID_AA64MMFR2], ID_AA64MMFR2, ST) != 0; + } + + static inline bool isar_feature_aa64_bti(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0; ++ return FIELD_EX64(id->regs[ID_AA64PFR1], ID_AA64PFR1, BT) != 0; + } + + static inline bool isar_feature_aa64_mte_insn_reg(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) != 0; ++ return FIELD_EX64(id->regs[ID_AA64PFR1], ID_AA64PFR1, MTE) != 0; + } + + static inline bool isar_feature_aa64_mte(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64PFR1], ID_AA64PFR1, MTE) >= 2; + } + + static inline bool isar_feature_aa64_pmu_8_1(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 && +- FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; ++ return FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) >= 4 && ++ FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) != 0xf; + } + + static inline bool isar_feature_aa64_pmu_8_4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 && +- FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; ++ return FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) >= 5 && ++ FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) != 0xf; + } + + static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, LRCPC) != 0; + } + + static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, LRCPC) >= 2; + } + + static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, I8MM) != 0; + } + + static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0; ++ return FIELD_EX64(id->regs[ID_AA64MMFR2], ID_AA64MMFR2, CCIDX) != 0; + } + + static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0; ++ return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, XNX) != 0; + } + + static inline bool isar_feature_aa64_dit(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0; ++ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, DIT) != 0; + } + + static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0; ++ return FIELD_EX64(id->regs[ID_AA64PFR1], ID_AA64PFR1, SSBS) != 0; + } + + static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, SVEVER) != 0; + } + + static inline bool isar_feature_aa64_sve2_aes(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, AES) != 0; + } + + static inline bool isar_feature_aa64_sve2_pmull128(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) >= 2; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, AES) >= 2; + } + + static inline bool isar_feature_aa64_sve2_bitperm(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BITPERM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, BITPERM) != 0; + } + + static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BFLOAT16) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, BFLOAT16) != 0; + } + + static inline bool isar_feature_aa64_sve2_sha3(const ARMISARegisters *id) + { +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SHA3) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, SHA3) != 0; + } + + static inline bool isar_feature_aa64_sve2_sm4(const ARMISARegisters *id) { -- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, FHM) != 0; -+ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, FHM) != 0; +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SM4) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, SM4) != 0; } - static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id) + static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id) { -- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0; -+ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, TS) != 0; +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, I8MM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, I8MM) != 0; } - static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id) + static inline bool isar_feature_aa64_sve_f32mm(const ARMISARegisters *id) { -- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2; -+ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, TS) >= 2; +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F32MM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, F32MM) != 0; } - static inline bool isar_feature_aa64_rndr(const ARMISARegisters *id) + static inline bool isar_feature_aa64_sve_f64mm(const ARMISARegisters *id) { -- return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RNDR) != 0; -+ return FIELD_EX64(id->regs[ID_AA64ISAR0], ID_AA64ISAR0, RNDR) != 0; +- return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F64MM) != 0; ++ return FIELD_EX64(id->regs[ID_AA64ZFR0], ID_AA64ZFR0, F64MM) != 0; } - static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id) - { -- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0; -+ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, JSCVT) != 0; + /* +diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c +index 1b56261964..96a49a3158 100644 +--- a/target/arm/cpu64.c ++++ b/target/arm/cpu64.c +@@ -108,31 +108,31 @@ static void aarch64_a57_initfn(Object *obj) + cpu->midr = 0x411fd070; + cpu->revidr = 0x00000000; + cpu->reset_fpsid = 0x41034070; +- cpu->isar.mvfr0 = 0x10110222; +- cpu->isar.mvfr1 = 0x12111111; +- cpu->isar.mvfr2 = 0x00000043; ++ cpu->isar.regs[MVFR0] = 0x10110222; ++ cpu->isar.regs[MVFR1] = 0x12111111; ++ cpu->isar.regs[MVFR2] = 0x00000043; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50838; +- cpu->isar.id_pfr0 = 0x00000131; +- cpu->isar.id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x03010066; ++ cpu->isar.regs[ID_PFR0] = 0x00000131; ++ cpu->isar.regs[ID_PFR1] = 0x00011011; ++ cpu->isar.regs[ID_DFR0] = 0x03010066; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10101105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_isar6 = 0; +- cpu->isar.id_aa64pfr0 = 0x00002222; +- cpu->isar.id_aa64dfr0 = 0x10305106; +- cpu->isar.id_aa64isar0 = 0x00011120; +- cpu->isar.id_aa64mmfr0 = 0x00001124; +- cpu->isar.dbgdidr = 0x3516d000; ++ cpu->isar.regs[ID_MMFR0] = 0x10101105; ++ cpu->isar.regs[ID_MMFR1] = 0x40000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01260000; ++ cpu->isar.regs[ID_MMFR3] = 0x02102211; ++ cpu->isar.regs[ID_ISAR0] = 0x02101110; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232042; ++ cpu->isar.regs[ID_ISAR3] = 0x01112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00011142; ++ cpu->isar.regs[ID_ISAR5] = 0x00011121; ++ cpu->isar.regs[ID_ISAR6] = 0; ++ cpu->isar.regs[ID_AA64PFR0] = 0x00002222; ++ cpu->isar.regs[ID_AA64DFR0] = 0x10305106; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x00001124; ++ cpu->isar.regs[DBGDIDR] = 0x3516d000; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ +@@ -161,31 +161,31 @@ static void aarch64_a53_initfn(Object *obj) + cpu->midr = 0x410fd034; + cpu->revidr = 0x00000000; + cpu->reset_fpsid = 0x41034070; +- cpu->isar.mvfr0 = 0x10110222; +- cpu->isar.mvfr1 = 0x12111111; +- cpu->isar.mvfr2 = 0x00000043; ++ cpu->isar.regs[MVFR0] = 0x10110222; ++ cpu->isar.regs[MVFR1] = 0x12111111; ++ cpu->isar.regs[MVFR2] = 0x00000043; + cpu->ctr = 0x84448004; /* L1Ip = VIPT */ + cpu->reset_sctlr = 0x00c50838; +- cpu->isar.id_pfr0 = 0x00000131; +- cpu->isar.id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x03010066; ++ cpu->isar.regs[ID_PFR0] = 0x00000131; ++ cpu->isar.regs[ID_PFR1] = 0x00011011; ++ cpu->isar.regs[ID_DFR0] = 0x03010066; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10101105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_isar6 = 0; +- cpu->isar.id_aa64pfr0 = 0x00002222; +- cpu->isar.id_aa64dfr0 = 0x10305106; +- cpu->isar.id_aa64isar0 = 0x00011120; +- cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */ +- cpu->isar.dbgdidr = 0x3516d000; ++ cpu->isar.regs[ID_MMFR0] = 0x10101105; ++ cpu->isar.regs[ID_MMFR1] = 0x40000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01260000; ++ cpu->isar.regs[ID_MMFR3] = 0x02102211; ++ cpu->isar.regs[ID_ISAR0] = 0x02101110; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232042; ++ cpu->isar.regs[ID_ISAR3] = 0x01112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00011142; ++ cpu->isar.regs[ID_ISAR5] = 0x00011121; ++ cpu->isar.regs[ID_ISAR6] = 0; ++ cpu->isar.regs[ID_AA64PFR0] = 0x00002222; ++ cpu->isar.regs[ID_AA64DFR0] = 0x10305106; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x00001122; /* 40 bit physical addr */ ++ cpu->isar.regs[DBGDIDR] = 0x3516d000; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */ +@@ -214,30 +214,30 @@ static void aarch64_a72_initfn(Object *obj) + cpu->midr = 0x410fd083; + cpu->revidr = 0x00000000; + cpu->reset_fpsid = 0x41034080; +- cpu->isar.mvfr0 = 0x10110222; +- cpu->isar.mvfr1 = 0x12111111; +- cpu->isar.mvfr2 = 0x00000043; ++ cpu->isar.regs[MVFR0] = 0x10110222; ++ cpu->isar.regs[MVFR1] = 0x12111111; ++ cpu->isar.regs[MVFR2] = 0x00000043; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50838; +- cpu->isar.id_pfr0 = 0x00000131; +- cpu->isar.id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x03010066; ++ cpu->isar.regs[ID_PFR0] = 0x00000131; ++ cpu->isar.regs[ID_PFR1] = 0x00011011; ++ cpu->isar.regs[ID_DFR0] = 0x03010066; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x10201105; +- cpu->isar.id_mmfr1 = 0x40000000; +- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr3 = 0x02102211; +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar3 = 0x01112131; +- cpu->isar.id_isar4 = 0x00011142; +- cpu->isar.id_isar5 = 0x00011121; +- cpu->isar.id_aa64pfr0 = 0x00002222; +- cpu->isar.id_aa64dfr0 = 0x10305106; +- cpu->isar.id_aa64isar0 = 0x00011120; +- cpu->isar.id_aa64mmfr0 = 0x00001124; +- cpu->isar.dbgdidr = 0x3516d000; ++ cpu->isar.regs[ID_MMFR0] = 0x10201105; ++ cpu->isar.regs[ID_MMFR1] = 0x40000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01260000; ++ cpu->isar.regs[ID_MMFR3] = 0x02102211; ++ cpu->isar.regs[ID_ISAR0] = 0x02101110; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232042; ++ cpu->isar.regs[ID_ISAR3] = 0x01112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00011142; ++ cpu->isar.regs[ID_ISAR5] = 0x00011121; ++ cpu->isar.regs[ID_AA64PFR0] = 0x00002222; ++ cpu->isar.regs[ID_AA64DFR0] = 0x10305106; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x00001124; ++ cpu->isar.regs[DBGDIDR] = 0x3516d000; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ +@@ -262,10 +262,10 @@ static void aarch64_kunpeng_920_initfn(Object *obj) + + cpu->midr = 0x480fd010; + cpu->ctr = 0x84448004; +- cpu->isar.id_aa64pfr0 = 0x11001111; +- cpu->isar.id_aa64dfr0 = 0x110305408; +- cpu->isar.id_aa64isar0 = 0x10211120; +- cpu->isar.id_aa64mmfr0 = 0x101125; ++ cpu->isar.regs[ID_AA64PFR0] = 0x11001111; ++ cpu->isar.regs[ID_AA64DFR0] = 0x110305408; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x10211120; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x101125; } - static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id) - { -- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0; -+ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, FCMA) != 0; + void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) +@@ -566,9 +566,9 @@ static void cpu_arm_set_sve(Object *obj, bool value, Error **errp) + return; + } + +- t = cpu->isar.id_aa64pfr0; ++ t = cpu->isar.regs[ID_AA64PFR0]; + t = FIELD_DP64(t, ID_AA64PFR0, SVE, value); +- cpu->isar.id_aa64pfr0 = t; ++ cpu->isar.regs[ID_AA64PFR0] = t; } - static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) -@@ -3611,7 +3617,7 @@ static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) - * defined algorithms, and thus API+GPI, and this predicate controls - * migration of the 128-bit keys. - */ -- return (id->id_aa64isar1 & -+ return (id->regs[ID_AA64ISAR1] & - (FIELD_DP64(0, ID_AA64ISAR1, APA, 0xf) | - FIELD_DP64(0, ID_AA64ISAR1, API, 0xf) | - FIELD_DP64(0, ID_AA64ISAR1, GPA, 0xf) | -@@ -3620,59 +3626,59 @@ static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id) + #ifdef CONFIG_USER_ONLY +@@ -662,12 +662,12 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) + error_append_hint(errp, "Add pauth=on to the CPU property list.\n"); + } + +- t = cpu->isar.id_aa64isar1; ++ t = cpu->isar.regs[ID_AA64ISAR1]; + t = FIELD_DP64(t, ID_AA64ISAR1, APA, arch_val); + t = FIELD_DP64(t, ID_AA64ISAR1, GPA, arch_val); + t = FIELD_DP64(t, ID_AA64ISAR1, API, impdef_val); + t = FIELD_DP64(t, ID_AA64ISAR1, GPI, impdef_val); +- cpu->isar.id_aa64isar1 = t; ++ cpu->isar.regs[ID_AA64ISAR1] = t; + } + + static Property arm_cpu_pauth_property = +@@ -736,7 +736,7 @@ static void aarch64_max_initfn(Object *obj) + t = FIELD_DP64(t, MIDR_EL1, REVISION, 0); + cpu->midr = t; + +- t = cpu->isar.id_aa64isar0; ++ t = cpu->isar.regs[ID_AA64ISAR0]; + t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* AES + PMULL */ + t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1); + t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* SHA512 */ +@@ -751,9 +751,9 @@ static void aarch64_max_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */ + t = FIELD_DP64(t, ID_AA64ISAR0, TLB, 2); /* FEAT_TLBIRANGE */ + t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1); +- cpu->isar.id_aa64isar0 = t; ++ cpu->isar.regs[ID_AA64ISAR0] = t; + +- t = cpu->isar.id_aa64isar1; ++ t = cpu->isar.regs[ID_AA64ISAR1]; + t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2); + t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1); + t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1); +@@ -763,17 +763,17 @@ static void aarch64_max_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1); + t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 2); /* ARMv8.4-RCPC */ + t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1); +- cpu->isar.id_aa64isar1 = t; ++ cpu->isar.regs[ID_AA64ISAR1] = t; + +- t = cpu->isar.id_aa64pfr0; ++ t = cpu->isar.regs[ID_AA64PFR0]; + t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1); + t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); + t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); + t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1); + t = FIELD_DP64(t, ID_AA64PFR0, DIT, 1); +- cpu->isar.id_aa64pfr0 = t; ++ cpu->isar.regs[ID_AA64PFR0] = t; + +- t = cpu->isar.id_aa64pfr1; ++ t = cpu->isar.regs[ID_AA64PFR1]; + t = FIELD_DP64(t, ID_AA64PFR1, BT, 1); + t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2); + /* +@@ -782,28 +782,28 @@ static void aarch64_max_initfn(Object *obj) + * we do for EL2 with the virtualization=on property. + */ + t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3); +- cpu->isar.id_aa64pfr1 = t; ++ cpu->isar.regs[ID_AA64PFR1] = t; + +- t = cpu->isar.id_aa64mmfr0; ++ t = cpu->isar.regs[ID_AA64MMFR0]; + t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 5); /* PARange: 48 bits */ +- cpu->isar.id_aa64mmfr0 = t; ++ cpu->isar.regs[ID_AA64MMFR0] = t; + +- t = cpu->isar.id_aa64mmfr1; ++ t = cpu->isar.regs[ID_AA64MMFR1]; + t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */ + t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); + t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); + t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */ + t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* VMID16 */ + t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* TTS2UXN */ +- cpu->isar.id_aa64mmfr1 = t; ++ cpu->isar.regs[ID_AA64MMFR1] = t; + +- t = cpu->isar.id_aa64mmfr2; ++ t = cpu->isar.regs[ID_AA64MMFR2]; + t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1); + t = FIELD_DP64(t, ID_AA64MMFR2, CNP, 1); /* TTCNP */ + t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */ +- cpu->isar.id_aa64mmfr2 = t; ++ cpu->isar.regs[ID_AA64MMFR2] = t; + +- t = cpu->isar.id_aa64zfr0; ++ t = cpu->isar.regs[ID_AA64ZFR0]; + t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 1); + t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* PMULL */ + t = FIELD_DP64(t, ID_AA64ZFR0, BITPERM, 1); +@@ -813,19 +813,19 @@ static void aarch64_max_initfn(Object *obj) + t = FIELD_DP64(t, ID_AA64ZFR0, I8MM, 1); + t = FIELD_DP64(t, ID_AA64ZFR0, F32MM, 1); + t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1); +- cpu->isar.id_aa64zfr0 = t; ++ cpu->isar.regs[ID_AA64ZFR0] = t; + + /* Replicate the same data to the 32-bit id registers. */ +- u = cpu->isar.id_isar5; ++ u = cpu->isar.regs[ID_ISAR5]; + u = FIELD_DP32(u, ID_ISAR5, AES, 2); /* AES + PMULL */ + u = FIELD_DP32(u, ID_ISAR5, SHA1, 1); + u = FIELD_DP32(u, ID_ISAR5, SHA2, 1); + u = FIELD_DP32(u, ID_ISAR5, CRC32, 1); + u = FIELD_DP32(u, ID_ISAR5, RDM, 1); + u = FIELD_DP32(u, ID_ISAR5, VCMA, 1); +- cpu->isar.id_isar5 = u; ++ cpu->isar.regs[ID_ISAR5] = u; + +- u = cpu->isar.id_isar6; ++ u = cpu->isar.regs[ID_ISAR6]; + u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1); + u = FIELD_DP32(u, ID_ISAR6, DP, 1); + u = FIELD_DP32(u, ID_ISAR6, FHM, 1); +@@ -833,39 +833,39 @@ static void aarch64_max_initfn(Object *obj) + u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1); + u = FIELD_DP32(u, ID_ISAR6, BF16, 1); + u = FIELD_DP32(u, ID_ISAR6, I8MM, 1); +- cpu->isar.id_isar6 = u; ++ cpu->isar.regs[ID_ISAR6] = u; - static inline bool isar_feature_aa64_sb(const ARMISARegisters *id) - { -- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0; -+ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, SB) != 0; - } +- u = cpu->isar.id_pfr0; ++ u = cpu->isar.regs[ID_PFR0]; + u = FIELD_DP32(u, ID_PFR0, DIT, 1); +- cpu->isar.id_pfr0 = u; ++ cpu->isar.regs[ID_PFR0] = u; - static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id) - { -- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SPECRES) != 0; -+ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, SPECRES) != 0; - } +- u = cpu->isar.id_pfr2; ++ u = cpu->isar.regs[ID_PFR2]; + u = FIELD_DP32(u, ID_PFR2, SSBS, 1); +- cpu->isar.id_pfr2 = u; ++ cpu->isar.regs[ID_PFR2] = u; - static inline bool isar_feature_aa64_frint(const ARMISARegisters *id) - { -- return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0; -+ return FIELD_EX64(id->regs[ID_AA64ISAR1], ID_AA64ISAR1, FRINTTS) != 0; - } +- u = cpu->isar.id_mmfr3; ++ u = cpu->isar.regs[ID_MMFR3]; + u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */ +- cpu->isar.id_mmfr3 = u; ++ cpu->isar.regs[ID_MMFR3] = u; - static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id) - { - /* We always set the AdvSIMD and FP fields identically wrt FP16. */ -- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1; -+ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, FP) == 1; - } +- u = cpu->isar.id_mmfr4; ++ u = cpu->isar.regs[ID_MMFR4]; + u = FIELD_DP32(u, ID_MMFR4, HPDS, 1); /* AA32HPD */ + u = FIELD_DP32(u, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */ + u = FIELD_DP32(u, ID_MMFR4, CNP, 1); /* TTCNP */ + u = FIELD_DP32(u, ID_MMFR4, XNX, 1); /* TTS2UXN */ +- cpu->isar.id_mmfr4 = u; ++ cpu->isar.regs[ID_MMFR4] = u; + +- t = cpu->isar.id_aa64dfr0; ++ t = cpu->isar.regs[ID_AA64DFR0]; + t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* v8.4-PMU */ +- cpu->isar.id_aa64dfr0 = t; ++ cpu->isar.regs[ID_AA64DFR0] = t; + +- u = cpu->isar.id_dfr0; ++ u = cpu->isar.regs[ID_DFR0]; + u = FIELD_DP32(u, ID_DFR0, PERFMON, 5); /* v8.4-PMU */ +- cpu->isar.id_dfr0 = u; ++ cpu->isar.regs[ID_DFR0] = u; - static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id) - { -- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL0) >= 2; -+ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, EL0) >= 2; - } +- u = cpu->isar.mvfr1; ++ u = cpu->isar.regs[MVFR1]; + u = FIELD_DP32(u, MVFR1, FPHP, 3); /* v8.2-FP16 */ + u = FIELD_DP32(u, MVFR1, SIMDHP, 2); /* v8.2-FP16 */ +- cpu->isar.mvfr1 = u; ++ cpu->isar.regs[MVFR1] = u; - static inline bool isar_feature_aa64_sve(const ARMISARegisters *id) - { -- return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0; -+ return FIELD_EX64(id->regs[ID_AA64PFR0], ID_AA64PFR0, SVE) != 0; + #ifdef CONFIG_USER_ONLY + /* For usermode -cpu max we can use a larger and more efficient DCZ +@@ -903,18 +903,18 @@ static void aarch64_a64fx_initfn(Object *obj) + cpu->revidr = 0x00000000; + cpu->ctr = 0x86668006; + cpu->reset_sctlr = 0x30000180; +- cpu->isar.id_aa64pfr0 = 0x0000000101111111; /* No RAS Extensions */ +- cpu->isar.id_aa64pfr1 = 0x0000000000000000; +- cpu->isar.id_aa64dfr0 = 0x0000000010305408; +- cpu->isar.id_aa64dfr1 = 0x0000000000000000; ++ cpu->isar.regs[ID_AA64PFR0] = 0x0000000101111111; /* No RAS Extensions */ ++ cpu->isar.regs[ID_AA64PFR1] = 0x0000000000000000; ++ cpu->isar.regs[ID_AA64DFR0] = 0x0000000010305408; ++ cpu->isar.regs[ID_AA64DFR1] = 0x0000000000000000; + cpu->id_aa64afr0 = 0x0000000000000000; + cpu->id_aa64afr1 = 0x0000000000000000; +- cpu->isar.id_aa64mmfr0 = 0x0000000000001122; +- cpu->isar.id_aa64mmfr1 = 0x0000000011212100; +- cpu->isar.id_aa64mmfr2 = 0x0000000000001011; +- cpu->isar.id_aa64isar0 = 0x0000000010211120; +- cpu->isar.id_aa64isar1 = 0x0000000000010001; +- cpu->isar.id_aa64zfr0 = 0x0000000000000000; ++ cpu->isar.regs[ID_AA64MMFR0] = 0x0000000000001122; ++ cpu->isar.regs[ID_AA64MMFR1] = 0x0000000011212100; ++ cpu->isar.regs[ID_AA64MMFR2] = 0x0000000000001011; ++ cpu->isar.regs[ID_AA64ISAR0] = 0x0000000010211120; ++ cpu->isar.regs[ID_AA64ISAR1] = 0x0000000000010001; ++ cpu->isar.regs[ID_AA64ZFR0] = 0x0000000000000000; + cpu->clidr = 0x0000000080000023; + cpu->ccsidr[0] = 0x7007e01c; /* 64KB L1 dcache */ + cpu->ccsidr[1] = 0x2007e01c; /* 64KB L1 icache */ +diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c +index 13d0e9b195..be9c3166fb 100644 +--- a/target/arm/cpu_tcg.c ++++ b/target/arm/cpu_tcg.c +@@ -65,14 +65,16 @@ static void arm926_initfn(Object *obj) + * ARMv5 does not have the ID_ISAR registers, but we can still + * set the field to indicate Jazelle support within QEMU. + */ +- cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); ++ cpu->isar.regs[ID_ISAR1] = FIELD_DP32(cpu->isar.regs[ID_ISAR1], ID_ISAR1, ++ JAZELLE, 1); + /* + * Similarly, we need to set MVFR0 fields to enable vfp and short vector + * support even though ARMv5 doesn't have this register. + */ +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1); +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSHVEC, ++ 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSP, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPDP, 1); } - static inline bool isar_feature_aa64_lor(const ARMISARegisters *id) - { -- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0; -+ return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, LO) != 0; - } + static void arm946_initfn(Object *obj) +@@ -107,14 +109,16 @@ static void arm1026_initfn(Object *obj) + * ARMv5 does not have the ID_ISAR registers, but we can still + * set the field to indicate Jazelle support within QEMU. + */ +- cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); ++ cpu->isar.regs[ID_ISAR1] = FIELD_DP32(cpu->isar.regs[ID_ISAR1], ID_ISAR1, ++ JAZELLE, 1); + /* + * Similarly, we need to set MVFR0 fields to enable vfp and short vector + * support even though ARMv5 doesn't have this register. + */ +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSP, 1); +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSHVEC, ++ 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSP, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPDP, 1); - static inline bool isar_feature_aa64_pan(const ARMISARegisters *id) - { -- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0; -+ return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, PAN) != 0; + { + /* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */ +@@ -147,22 +151,22 @@ static void arm1136_r2_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); + cpu->midr = 0x4107b362; + cpu->reset_fpsid = 0x410120b4; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; ++ cpu->isar.regs[MVFR0] = 0x11111111; ++ cpu->isar.regs[MVFR1] = 0x00000000; + cpu->ctr = 0x1dd20d2; + cpu->reset_sctlr = 0x00050078; +- cpu->isar.id_pfr0 = 0x111; +- cpu->isar.id_pfr1 = 0x1; +- cpu->isar.id_dfr0 = 0x2; ++ cpu->isar.regs[ID_PFR0] = 0x111; ++ cpu->isar.regs[ID_PFR1] = 0x1; ++ cpu->isar.regs[ID_DFR0] = 0x2; + cpu->id_afr0 = 0x3; +- cpu->isar.id_mmfr0 = 0x01130003; +- cpu->isar.id_mmfr1 = 0x10030302; +- cpu->isar.id_mmfr2 = 0x01222110; +- cpu->isar.id_isar0 = 0x00140011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11231111; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; ++ cpu->isar.regs[ID_MMFR0] = 0x01130003; ++ cpu->isar.regs[ID_MMFR1] = 0x10030302; ++ cpu->isar.regs[ID_MMFR2] = 0x01222110; ++ cpu->isar.regs[ID_ISAR0] = 0x00140011; ++ cpu->isar.regs[ID_ISAR1] = 0x12002111; ++ cpu->isar.regs[ID_ISAR2] = 0x11231111; ++ cpu->isar.regs[ID_ISAR3] = 0x01102131; ++ cpu->isar.regs[ID_ISAR4] = 0x141; + cpu->reset_auxcr = 7; } - static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id) - { -- return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2; -+ return FIELD_EX64(id->regs[ID_AA64MMFR1], ID_AA64MMFR1, PAN) >= 2; +@@ -178,22 +182,22 @@ static void arm1136_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_CACHE_BLOCK_OPS); + cpu->midr = 0x4117b363; + cpu->reset_fpsid = 0x410120b4; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; ++ cpu->isar.regs[MVFR0] = 0x11111111; ++ cpu->isar.regs[MVFR1] = 0x00000000; + cpu->ctr = 0x1dd20d2; + cpu->reset_sctlr = 0x00050078; +- cpu->isar.id_pfr0 = 0x111; +- cpu->isar.id_pfr1 = 0x1; +- cpu->isar.id_dfr0 = 0x2; ++ cpu->isar.regs[ID_PFR0] = 0x111; ++ cpu->isar.regs[ID_PFR1] = 0x1; ++ cpu->isar.regs[ID_DFR0] = 0x2; + cpu->id_afr0 = 0x3; +- cpu->isar.id_mmfr0 = 0x01130003; +- cpu->isar.id_mmfr1 = 0x10030302; +- cpu->isar.id_mmfr2 = 0x01222110; +- cpu->isar.id_isar0 = 0x00140011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11231111; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; ++ cpu->isar.regs[ID_MMFR0] = 0x01130003; ++ cpu->isar.regs[ID_MMFR1] = 0x10030302; ++ cpu->isar.regs[ID_MMFR2] = 0x01222110; ++ cpu->isar.regs[ID_ISAR0] = 0x00140011; ++ cpu->isar.regs[ID_ISAR1] = 0x12002111; ++ cpu->isar.regs[ID_ISAR2] = 0x11231111; ++ cpu->isar.regs[ID_ISAR3] = 0x01102131; ++ cpu->isar.regs[ID_ISAR4] = 0x141; + cpu->reset_auxcr = 7; } - static inline bool isar_feature_aa64_bti(const ARMISARegisters *id) - { -- return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0; -+ return FIELD_EX64(id->regs[ID_AA64PFR1], ID_AA64PFR1, BT) != 0; +@@ -210,22 +214,22 @@ static void arm1176_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_EL3); + cpu->midr = 0x410fb767; + cpu->reset_fpsid = 0x410120b5; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; ++ cpu->isar.regs[MVFR0] = 0x11111111; ++ cpu->isar.regs[MVFR1] = 0x00000000; + cpu->ctr = 0x1dd20d2; + cpu->reset_sctlr = 0x00050078; +- cpu->isar.id_pfr0 = 0x111; +- cpu->isar.id_pfr1 = 0x11; +- cpu->isar.id_dfr0 = 0x33; ++ cpu->isar.regs[ID_PFR0] = 0x111; ++ cpu->isar.regs[ID_PFR1] = 0x11; ++ cpu->isar.regs[ID_DFR0] = 0x33; + cpu->id_afr0 = 0; +- cpu->isar.id_mmfr0 = 0x01130003; +- cpu->isar.id_mmfr1 = 0x10030302; +- cpu->isar.id_mmfr2 = 0x01222100; +- cpu->isar.id_isar0 = 0x0140011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11231121; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x01141; ++ cpu->isar.regs[ID_MMFR0] = 0x01130003; ++ cpu->isar.regs[ID_MMFR1] = 0x10030302; ++ cpu->isar.regs[ID_MMFR2] = 0x01222100; ++ cpu->isar.regs[ID_ISAR0] = 0x0140011; ++ cpu->isar.regs[ID_ISAR1] = 0x12002111; ++ cpu->isar.regs[ID_ISAR2] = 0x11231121; ++ cpu->isar.regs[ID_ISAR3] = 0x01102131; ++ cpu->isar.regs[ID_ISAR4] = 0x01141; + cpu->reset_auxcr = 7; } - static inline bool isar_feature_aa64_pmu_8_1(const ARMISARegisters *id) - { -- return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 && -- FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; -+ return FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) >= 4 && -+ FIELD_EX64(id->regs[ID_AA64DFR0], ID_AA64DFR0, PMUVER) != 0xf; +@@ -240,21 +244,21 @@ static void arm11mpcore_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS); + cpu->midr = 0x410fb022; + cpu->reset_fpsid = 0x410120b4; +- cpu->isar.mvfr0 = 0x11111111; +- cpu->isar.mvfr1 = 0x00000000; ++ cpu->isar.regs[MVFR0] = 0x11111111; ++ cpu->isar.regs[MVFR1] = 0x00000000; + cpu->ctr = 0x1d192992; /* 32K icache 32K dcache */ +- cpu->isar.id_pfr0 = 0x111; +- cpu->isar.id_pfr1 = 0x1; +- cpu->isar.id_dfr0 = 0; ++ cpu->isar.regs[ID_PFR0] = 0x111; ++ cpu->isar.regs[ID_PFR1] = 0x1; ++ cpu->isar.regs[ID_DFR0] = 0; + cpu->id_afr0 = 0x2; +- cpu->isar.id_mmfr0 = 0x01100103; +- cpu->isar.id_mmfr1 = 0x10020302; +- cpu->isar.id_mmfr2 = 0x01222000; +- cpu->isar.id_isar0 = 0x00100011; +- cpu->isar.id_isar1 = 0x12002111; +- cpu->isar.id_isar2 = 0x11221011; +- cpu->isar.id_isar3 = 0x01102131; +- cpu->isar.id_isar4 = 0x141; ++ cpu->isar.regs[ID_MMFR0] = 0x01100103; ++ cpu->isar.regs[ID_MMFR1] = 0x10020302; ++ cpu->isar.regs[ID_MMFR2] = 0x01222000; ++ cpu->isar.regs[ID_ISAR0] = 0x00100011; ++ cpu->isar.regs[ID_ISAR1] = 0x12002111; ++ cpu->isar.regs[ID_ISAR2] = 0x11221011; ++ cpu->isar.regs[ID_ISAR3] = 0x01102131; ++ cpu->isar.regs[ID_ISAR4] = 0x141; + cpu->reset_auxcr = 1; } - static inline bool isar_feature_any_pmu_8_1(const ARMISARegisters *id) -diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index d450b8c8..fe648752 100644 ---- a/target/arm/cpu64.c -+++ b/target/arm/cpu64.c -@@ -116,31 +116,31 @@ static void aarch64_a57_initfn(Object *obj) - cpu->midr = 0x411fd070; - cpu->revidr = 0x00000000; - cpu->reset_fpsid = 0x41034070; +@@ -278,24 +282,24 @@ static void cortex_a8_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_EL3); + cpu->midr = 0x410fc080; + cpu->reset_fpsid = 0x410330c0; +- cpu->isar.mvfr0 = 0x11110222; +- cpu->isar.mvfr1 = 0x00011111; ++ cpu->isar.regs[MVFR0] = 0x11110222; ++ cpu->isar.regs[MVFR1] = 0x00011111; + cpu->ctr = 0x82048004; + cpu->reset_sctlr = 0x00c50078; +- cpu->isar.id_pfr0 = 0x1031; +- cpu->isar.id_pfr1 = 0x11; +- cpu->isar.id_dfr0 = 0x400; ++ cpu->isar.regs[ID_PFR0] = 0x1031; ++ cpu->isar.regs[ID_PFR1] = 0x11; ++ cpu->isar.regs[ID_DFR0] = 0x400; + cpu->id_afr0 = 0; +- cpu->isar.id_mmfr0 = 0x31100003; +- cpu->isar.id_mmfr1 = 0x20000000; +- cpu->isar.id_mmfr2 = 0x01202000; +- cpu->isar.id_mmfr3 = 0x11; +- cpu->isar.id_isar0 = 0x00101111; +- cpu->isar.id_isar1 = 0x12112111; +- cpu->isar.id_isar2 = 0x21232031; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x00111142; +- cpu->isar.dbgdidr = 0x15141000; ++ cpu->isar.regs[ID_MMFR0] = 0x31100003; ++ cpu->isar.regs[ID_MMFR1] = 0x20000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01202000; ++ cpu->isar.regs[ID_MMFR3] = 0x11; ++ cpu->isar.regs[ID_ISAR0] = 0x00101111; ++ cpu->isar.regs[ID_ISAR1] = 0x12112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232031; ++ cpu->isar.regs[ID_ISAR3] = 0x11112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00111142; ++ cpu->isar.regs[DBGDIDR] = 0x15141000; + cpu->clidr = (1 << 27) | (2 << 24) | 3; + cpu->ccsidr[0] = 0xe007e01a; /* 16k L1 dcache. */ + cpu->ccsidr[1] = 0x2007e01a; /* 16k L1 icache. */ +@@ -352,24 +356,24 @@ static void cortex_a9_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_CBAR); + cpu->midr = 0x410fc090; + cpu->reset_fpsid = 0x41033090; +- cpu->isar.mvfr0 = 0x11110222; +- cpu->isar.mvfr1 = 0x01111111; ++ cpu->isar.regs[MVFR0] = 0x11110222; ++ cpu->isar.regs[MVFR1] = 0x01111111; + cpu->ctr = 0x80038003; + cpu->reset_sctlr = 0x00c50078; +- cpu->isar.id_pfr0 = 0x1031; +- cpu->isar.id_pfr1 = 0x11; +- cpu->isar.id_dfr0 = 0x000; ++ cpu->isar.regs[ID_PFR0] = 0x1031; ++ cpu->isar.regs[ID_PFR1] = 0x11; ++ cpu->isar.regs[ID_DFR0] = 0x000; + cpu->id_afr0 = 0; +- cpu->isar.id_mmfr0 = 0x00100103; +- cpu->isar.id_mmfr1 = 0x20000000; +- cpu->isar.id_mmfr2 = 0x01230000; +- cpu->isar.id_mmfr3 = 0x00002111; +- cpu->isar.id_isar0 = 0x00101111; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232041; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x00111142; +- cpu->isar.dbgdidr = 0x35141000; ++ cpu->isar.regs[ID_MMFR0] = 0x00100103; ++ cpu->isar.regs[ID_MMFR1] = 0x20000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01230000; ++ cpu->isar.regs[ID_MMFR3] = 0x00002111; ++ cpu->isar.regs[ID_ISAR0] = 0x00101111; ++ cpu->isar.regs[ID_ISAR1] = 0x13112111; ++ cpu->isar.regs[ID_ISAR2] = 0x21232041; ++ cpu->isar.regs[ID_ISAR3] = 0x11112131; ++ cpu->isar.regs[ID_ISAR4] = 0x00111142; ++ cpu->isar.regs[DBGDIDR] = 0x35141000; + cpu->clidr = (1 << 27) | (1 << 24) | 3; + cpu->ccsidr[0] = 0xe00fe019; /* 16k L1 dcache. */ + cpu->ccsidr[1] = 0x200fe019; /* 16k L1 icache. */ +@@ -417,28 +421,28 @@ static void cortex_a7_initfn(Object *obj) + cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7; + cpu->midr = 0x410fc075; + cpu->reset_fpsid = 0x41023075; - cpu->isar.mvfr0 = 0x10110222; -- cpu->isar.mvfr1 = 0x12111111; -- cpu->isar.mvfr2 = 0x00000043; +- cpu->isar.mvfr1 = 0x11111111; + cpu->isar.regs[MVFR0] = 0x10110222; -+ cpu->isar.regs[MVFR1] = 0x12111111; -+ cpu->isar.regs[MVFR2] = 0x00000043; - cpu->ctr = 0x8444c004; - cpu->reset_sctlr = 0x00c50838; - cpu->id_pfr0 = 0x00000131; - cpu->id_pfr1 = 0x00011011; -- cpu->isar.id_dfr0 = 0x03010066; -+ cpu->isar.regs[ID_DFR0] = 0x03010066; ++ cpu->isar.regs[MVFR1] = 0x11111111; + cpu->ctr = 0x84448003; + cpu->reset_sctlr = 0x00c50078; +- cpu->isar.id_pfr0 = 0x00001131; +- cpu->isar.id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x02010555; ++ cpu->isar.regs[ID_PFR0] = 0x00001131; ++ cpu->isar.regs[ID_PFR1] = 0x00011011; ++ cpu->isar.regs[ID_DFR0] = 0x02010555; cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x10101105; - cpu->isar.id_mmfr1 = 0x40000000; -- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr2 = 0x01240000; - cpu->isar.id_mmfr3 = 0x02102211; -- cpu->isar.id_isar0 = 0x02101110; -- cpu->isar.id_isar1 = 0x13112111; -- cpu->isar.id_isar2 = 0x21232042; -- cpu->isar.id_isar3 = 0x01112131; -- cpu->isar.id_isar4 = 0x00011142; -- cpu->isar.id_isar5 = 0x00011121; -- cpu->isar.id_isar6 = 0; -- cpu->isar.id_aa64pfr0 = 0x00002222; -- cpu->isar.id_aa64dfr0 = 0x10305106; -- cpu->isar.id_aa64isar0 = 0x00011120; -- cpu->isar.id_aa64mmfr0 = 0x00001124; -- cpu->isar.dbgdidr = 0x3516d000; + cpu->isar.regs[ID_MMFR0] = 0x10101105; + cpu->isar.regs[ID_MMFR1] = 0x40000000; -+ cpu->isar.regs[ID_MMFR2] = 0x01260000; ++ cpu->isar.regs[ID_MMFR2] = 0x01240000; + cpu->isar.regs[ID_MMFR3] = 0x02102211; + /* + * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but + * table 4-41 gives 0x02101110, which includes the arm div insns. + */ +- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_isar1 = 0x13112111; +- cpu->isar.id_isar2 = 0x21232041; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x10011142; +- cpu->isar.dbgdidr = 0x3515f005; + cpu->isar.regs[ID_ISAR0] = 0x02101110; + cpu->isar.regs[ID_ISAR1] = 0x13112111; -+ cpu->isar.regs[ID_ISAR2] = 0x21232042; -+ cpu->isar.regs[ID_ISAR3] = 0x01112131; -+ cpu->isar.regs[ID_ISAR4] = 0x00011142; -+ cpu->isar.regs[ID_ISAR5] = 0x00011121; -+ cpu->isar.regs[ID_ISAR6] = 0; -+ cpu->isar.regs[ID_AA64PFR0] = 0x00002222; -+ cpu->isar.regs[ID_AA64DFR0] = 0x10305106; -+ cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; -+ cpu->isar.regs[ID_AA64MMFR0] = 0x00001124; -+ cpu->isar.regs[DBGDIDR] = 0x3516d000; ++ cpu->isar.regs[ID_ISAR2] = 0x21232041; ++ cpu->isar.regs[ID_ISAR3] = 0x11112131; ++ cpu->isar.regs[ID_ISAR4] = 0x10011142; ++ cpu->isar.regs[DBGDIDR] = 0x3515f005; cpu->clidr = 0x0a200023; - cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ - cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ -@@ -170,31 +170,31 @@ static void aarch64_a53_initfn(Object *obj) - cpu->midr = 0x410fd034; - cpu->revidr = 0x00000000; - cpu->reset_fpsid = 0x41034070; + cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */ + cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */ +@@ -463,24 +467,24 @@ static void cortex_a15_initfn(Object *obj) + cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15; + cpu->midr = 0x412fc0f1; + cpu->reset_fpsid = 0x410430f0; - cpu->isar.mvfr0 = 0x10110222; -- cpu->isar.mvfr1 = 0x12111111; -- cpu->isar.mvfr2 = 0x00000043; +- cpu->isar.mvfr1 = 0x11111111; + cpu->isar.regs[MVFR0] = 0x10110222; -+ cpu->isar.regs[MVFR1] = 0x12111111; -+ cpu->isar.regs[MVFR2] = 0x00000043; - cpu->ctr = 0x84448004; /* L1Ip = VIPT */ - cpu->reset_sctlr = 0x00c50838; - cpu->id_pfr0 = 0x00000131; - cpu->id_pfr1 = 0x00011011; -- cpu->isar.id_dfr0 = 0x03010066; -+ cpu->isar.regs[ID_DFR0] = 0x03010066; ++ cpu->isar.regs[MVFR1] = 0x11111111; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50078; +- cpu->isar.id_pfr0 = 0x00001131; +- cpu->isar.id_pfr1 = 0x00011011; +- cpu->isar.id_dfr0 = 0x02010555; ++ cpu->isar.regs[ID_PFR0] = 0x00001131; ++ cpu->isar.regs[ID_PFR1] = 0x00011011; ++ cpu->isar.regs[ID_DFR0] = 0x02010555; cpu->id_afr0 = 0x00000000; -- cpu->isar.id_mmfr0 = 0x10101105; -- cpu->isar.id_mmfr1 = 0x40000000; -- cpu->isar.id_mmfr2 = 0x01260000; +- cpu->isar.id_mmfr0 = 0x10201105; +- cpu->isar.id_mmfr1 = 0x20000000; +- cpu->isar.id_mmfr2 = 0x01240000; - cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; -- cpu->isar.id_isar2 = 0x21232042; -- cpu->isar.id_isar3 = 0x01112131; -- cpu->isar.id_isar4 = 0x00011142; -- cpu->isar.id_isar5 = 0x00011121; -- cpu->isar.id_isar6 = 0; -- cpu->isar.id_aa64pfr0 = 0x00002222; -- cpu->isar.id_aa64dfr0 = 0x10305106; -- cpu->isar.id_aa64isar0 = 0x00011120; -- cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */ -- cpu->isar.dbgdidr = 0x3516d000; -+ cpu->isar.regs[ID_MMFR0] = 0x10101105; -+ cpu->isar.regs[ID_MMFR1] = 0x40000000; -+ cpu->isar.regs[ID_MMFR2] = 0x01260000; +- cpu->isar.id_isar2 = 0x21232041; +- cpu->isar.id_isar3 = 0x11112131; +- cpu->isar.id_isar4 = 0x10011142; +- cpu->isar.dbgdidr = 0x3515f021; ++ cpu->isar.regs[ID_MMFR0] = 0x10201105; ++ cpu->isar.regs[ID_MMFR1] = 0x20000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01240000; + cpu->isar.regs[ID_MMFR3] = 0x02102211; + cpu->isar.regs[ID_ISAR0] = 0x02101110; + cpu->isar.regs[ID_ISAR1] = 0x13112111; -+ cpu->isar.regs[ID_ISAR2] = 0x21232042; -+ cpu->isar.regs[ID_ISAR3] = 0x01112131; -+ cpu->isar.regs[ID_ISAR4] = 0x00011142; -+ cpu->isar.regs[ID_ISAR5] = 0x00011121; -+ cpu->isar.regs[ID_ISAR6] = 0; -+ cpu->isar.regs[ID_AA64PFR0] = 0x00002222; -+ cpu->isar.regs[ID_AA64DFR0] = 0x10305106; -+ cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; -+ cpu->isar.regs[ID_AA64MMFR0] = 0x00001122; /* 40 bit physical addr */ -+ cpu->isar.regs[DBGDIDR] = 0x3516d000; ++ cpu->isar.regs[ID_ISAR2] = 0x21232041; ++ cpu->isar.regs[ID_ISAR3] = 0x11112131; ++ cpu->isar.regs[ID_ISAR4] = 0x10011142; ++ cpu->isar.regs[DBGDIDR] = 0x3515f021; cpu->clidr = 0x0a200023; - cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ - cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */ -@@ -224,30 +224,30 @@ static void aarch64_a72_initfn(Object *obj) - cpu->midr = 0x410fd083; - cpu->revidr = 0x00000000; - cpu->reset_fpsid = 0x41034080; -- cpu->isar.mvfr0 = 0x10110222; -- cpu->isar.mvfr1 = 0x12111111; -- cpu->isar.mvfr2 = 0x00000043; -+ cpu->isar.regs[MVFR0] = 0x10110222; -+ cpu->isar.regs[MVFR1] = 0x12111111; -+ cpu->isar.regs[MVFR2] = 0x00000043; - cpu->ctr = 0x8444c004; - cpu->reset_sctlr = 0x00c50838; - cpu->id_pfr0 = 0x00000131; - cpu->id_pfr1 = 0x00011011; -- cpu->isar.id_dfr0 = 0x03010066; -+ cpu->isar.regs[ID_DFR0] = 0x03010066; + cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */ + cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */ +@@ -504,21 +508,21 @@ static void cortex_m0_initfn(Object *obj) + * by looking at ID register fields. We use the same values as + * for the M3. + */ +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000200; +- cpu->isar.id_dfr0 = 0x00100000; ++ cpu->isar.regs[ID_PFR0] = 0x00000030; ++ cpu->isar.regs[ID_PFR1] = 0x00000200; ++ cpu->isar.regs[ID_DFR0] = 0x00100000; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00000030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x00000000; +- cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01141110; +- cpu->isar.id_isar1 = 0x02111000; +- cpu->isar.id_isar2 = 0x21112231; +- cpu->isar.id_isar3 = 0x01111110; +- cpu->isar.id_isar4 = 0x01310102; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00000030; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x00000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000000; ++ cpu->isar.regs[ID_ISAR0] = 0x01141110; ++ cpu->isar.regs[ID_ISAR1] = 0x02111000; ++ cpu->isar.regs[ID_ISAR2] = 0x21112231; ++ cpu->isar.regs[ID_ISAR3] = 0x01111110; ++ cpu->isar.regs[ID_ISAR4] = 0x01310102; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + } + + static void cortex_m3_initfn(Object *obj) +@@ -529,21 +533,21 @@ static void cortex_m3_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_M_MAIN); + cpu->midr = 0x410fc231; + cpu->pmsav7_dregion = 8; +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000200; +- cpu->isar.id_dfr0 = 0x00100000; ++ cpu->isar.regs[ID_PFR0] = 0x00000030; ++ cpu->isar.regs[ID_PFR1] = 0x00000200; ++ cpu->isar.regs[ID_DFR0] = 0x00100000; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00000030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x00000000; +- cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01141110; +- cpu->isar.id_isar1 = 0x02111000; +- cpu->isar.id_isar2 = 0x21112231; +- cpu->isar.id_isar3 = 0x01111110; +- cpu->isar.id_isar4 = 0x01310102; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00000030; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x00000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000000; ++ cpu->isar.regs[ID_ISAR0] = 0x01141110; ++ cpu->isar.regs[ID_ISAR1] = 0x02111000; ++ cpu->isar.regs[ID_ISAR2] = 0x21112231; ++ cpu->isar.regs[ID_ISAR3] = 0x01111110; ++ cpu->isar.regs[ID_ISAR4] = 0x01310102; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + } + + static void cortex_m4_initfn(Object *obj) +@@ -556,24 +560,24 @@ static void cortex_m4_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); + cpu->midr = 0x410fc240; /* r0p0 */ + cpu->pmsav7_dregion = 8; +- cpu->isar.mvfr0 = 0x10110021; +- cpu->isar.mvfr1 = 0x11000011; +- cpu->isar.mvfr2 = 0x00000000; +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000200; +- cpu->isar.id_dfr0 = 0x00100000; ++ cpu->isar.regs[MVFR0] = 0x10110021; ++ cpu->isar.regs[MVFR1] = 0x11000011; ++ cpu->isar.regs[MVFR2] = 0x00000000; ++ cpu->isar.regs[ID_PFR0] = 0x00000030; ++ cpu->isar.regs[ID_PFR1] = 0x00000200; ++ cpu->isar.regs[ID_DFR0] = 0x00100000; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00000030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x00000000; +- cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01141110; +- cpu->isar.id_isar1 = 0x02111000; +- cpu->isar.id_isar2 = 0x21112231; +- cpu->isar.id_isar3 = 0x01111110; +- cpu->isar.id_isar4 = 0x01310102; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00000030; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x00000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000000; ++ cpu->isar.regs[ID_ISAR0] = 0x01141110; ++ cpu->isar.regs[ID_ISAR1] = 0x02111000; ++ cpu->isar.regs[ID_ISAR2] = 0x21112231; ++ cpu->isar.regs[ID_ISAR3] = 0x01111110; ++ cpu->isar.regs[ID_ISAR4] = 0x01310102; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + } + + static void cortex_m7_initfn(Object *obj) +@@ -586,24 +590,24 @@ static void cortex_m7_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP); + cpu->midr = 0x411fc272; /* r1p2 */ + cpu->pmsav7_dregion = 8; +- cpu->isar.mvfr0 = 0x10110221; +- cpu->isar.mvfr1 = 0x12000011; +- cpu->isar.mvfr2 = 0x00000040; +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000200; +- cpu->isar.id_dfr0 = 0x00100000; ++ cpu->isar.regs[MVFR0] = 0x10110221; ++ cpu->isar.regs[MVFR1] = 0x12000011; ++ cpu->isar.regs[MVFR2] = 0x00000040; ++ cpu->isar.regs[ID_PFR0] = 0x00000030; ++ cpu->isar.regs[ID_PFR1] = 0x00000200; ++ cpu->isar.regs[ID_DFR0] = 0x00100000; cpu->id_afr0 = 0x00000000; -- cpu->isar.id_mmfr0 = 0x10201105; -- cpu->isar.id_mmfr1 = 0x40000000; -- cpu->isar.id_mmfr2 = 0x01260000; -- cpu->isar.id_mmfr3 = 0x02102211; -- cpu->isar.id_isar0 = 0x02101110; +- cpu->isar.id_mmfr0 = 0x00100030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01000000; +- cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01101110; +- cpu->isar.id_isar1 = 0x02112000; +- cpu->isar.id_isar2 = 0x20232231; +- cpu->isar.id_isar3 = 0x01111131; +- cpu->isar.id_isar4 = 0x01310132; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00100030; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000000; ++ cpu->isar.regs[ID_ISAR0] = 0x01101110; ++ cpu->isar.regs[ID_ISAR1] = 0x02112000; ++ cpu->isar.regs[ID_ISAR2] = 0x20232231; ++ cpu->isar.regs[ID_ISAR3] = 0x01111131; ++ cpu->isar.regs[ID_ISAR4] = 0x01310132; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + } + + static void cortex_m33_initfn(Object *obj) +@@ -618,24 +622,24 @@ static void cortex_m33_initfn(Object *obj) + cpu->midr = 0x410fd213; /* r0p3 */ + cpu->pmsav7_dregion = 16; + cpu->sau_sregion = 8; +- cpu->isar.mvfr0 = 0x10110021; +- cpu->isar.mvfr1 = 0x11000011; +- cpu->isar.mvfr2 = 0x00000040; +- cpu->isar.id_pfr0 = 0x00000030; +- cpu->isar.id_pfr1 = 0x00000210; +- cpu->isar.id_dfr0 = 0x00200000; ++ cpu->isar.regs[MVFR0] = 0x10110021; ++ cpu->isar.regs[MVFR1] = 0x11000011; ++ cpu->isar.regs[MVFR2] = 0x00000040; ++ cpu->isar.regs[ID_PFR0] = 0x00000030; ++ cpu->isar.regs[ID_PFR1] = 0x00000210; ++ cpu->isar.regs[ID_DFR0] = 0x00200000; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00101F40; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01000000; +- cpu->isar.id_mmfr3 = 0x00000000; +- cpu->isar.id_isar0 = 0x01101110; +- cpu->isar.id_isar1 = 0x02212000; +- cpu->isar.id_isar2 = 0x20232232; +- cpu->isar.id_isar3 = 0x01111131; +- cpu->isar.id_isar4 = 0x01310132; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00101F40; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000000; ++ cpu->isar.regs[ID_ISAR0] = 0x01101110; ++ cpu->isar.regs[ID_ISAR1] = 0x02212000; ++ cpu->isar.regs[ID_ISAR2] = 0x20232232; ++ cpu->isar.regs[ID_ISAR3] = 0x01111131; ++ cpu->isar.regs[ID_ISAR4] = 0x01310132; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + cpu->clidr = 0x00000000; + cpu->ctr = 0x8000c000; + } +@@ -655,24 +659,24 @@ static void cortex_m55_initfn(Object *obj) + cpu->pmsav7_dregion = 16; + cpu->sau_sregion = 8; + /* These are the MVFR* values for the FPU + full MVE configuration */ +- cpu->isar.mvfr0 = 0x10110221; +- cpu->isar.mvfr1 = 0x12100211; +- cpu->isar.mvfr2 = 0x00000040; +- cpu->isar.id_pfr0 = 0x20000030; +- cpu->isar.id_pfr1 = 0x00000230; +- cpu->isar.id_dfr0 = 0x10200000; ++ cpu->isar.regs[MVFR0] = 0x10110221; ++ cpu->isar.regs[MVFR1] = 0x12100211; ++ cpu->isar.regs[MVFR2] = 0x00000040; ++ cpu->isar.regs[ID_PFR0] = 0x20000030; ++ cpu->isar.regs[ID_PFR1] = 0x00000230; ++ cpu->isar.regs[ID_DFR0] = 0x10200000; + cpu->id_afr0 = 0x00000000; +- cpu->isar.id_mmfr0 = 0x00111040; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01000000; +- cpu->isar.id_mmfr3 = 0x00000011; +- cpu->isar.id_isar0 = 0x01103110; +- cpu->isar.id_isar1 = 0x02212000; +- cpu->isar.id_isar2 = 0x20232232; +- cpu->isar.id_isar3 = 0x01111131; +- cpu->isar.id_isar4 = 0x01310132; +- cpu->isar.id_isar5 = 0x00000000; +- cpu->isar.id_isar6 = 0x00000000; ++ cpu->isar.regs[ID_MMFR0] = 0x00111040; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01000000; ++ cpu->isar.regs[ID_MMFR3] = 0x00000011; ++ cpu->isar.regs[ID_ISAR0] = 0x01103110; ++ cpu->isar.regs[ID_ISAR1] = 0x02212000; ++ cpu->isar.regs[ID_ISAR2] = 0x20232232; ++ cpu->isar.regs[ID_ISAR3] = 0x01111131; ++ cpu->isar.regs[ID_ISAR4] = 0x01310132; ++ cpu->isar.regs[ID_ISAR5] = 0x00000000; ++ cpu->isar.regs[ID_ISAR6] = 0x00000000; + cpu->clidr = 0x00000000; /* caches not implemented */ + cpu->ctr = 0x8303c003; + } +@@ -697,21 +701,21 @@ static void cortex_r5_initfn(Object *obj) + set_feature(&cpu->env, ARM_FEATURE_PMSA); + set_feature(&cpu->env, ARM_FEATURE_PMU); + cpu->midr = 0x411fc153; /* r1p3 */ +- cpu->isar.id_pfr0 = 0x0131; +- cpu->isar.id_pfr1 = 0x001; +- cpu->isar.id_dfr0 = 0x010400; ++ cpu->isar.regs[ID_PFR0] = 0x0131; ++ cpu->isar.regs[ID_PFR1] = 0x001; ++ cpu->isar.regs[ID_DFR0] = 0x010400; + cpu->id_afr0 = 0x0; +- cpu->isar.id_mmfr0 = 0x0210030; +- cpu->isar.id_mmfr1 = 0x00000000; +- cpu->isar.id_mmfr2 = 0x01200000; +- cpu->isar.id_mmfr3 = 0x0211; +- cpu->isar.id_isar0 = 0x02101111; - cpu->isar.id_isar1 = 0x13112111; -- cpu->isar.id_isar2 = 0x21232042; +- cpu->isar.id_isar2 = 0x21232141; - cpu->isar.id_isar3 = 0x01112131; -- cpu->isar.id_isar4 = 0x00011142; -- cpu->isar.id_isar5 = 0x00011121; -- cpu->isar.id_aa64pfr0 = 0x00002222; -- cpu->isar.id_aa64dfr0 = 0x10305106; -- cpu->isar.id_aa64isar0 = 0x00011120; -- cpu->isar.id_aa64mmfr0 = 0x00001124; -- cpu->isar.dbgdidr = 0x3516d000; -+ cpu->isar.regs[ID_MMFR0] = 0x10201105; -+ cpu->isar.regs[ID_MMFR1] = 0x40000000; -+ cpu->isar.regs[ID_MMFR2] = 0x01260000; -+ cpu->isar.regs[ID_MMFR3] = 0x02102211; -+ cpu->isar.regs[ID_ISAR0] = 0x02101110; +- cpu->isar.id_isar4 = 0x0010142; +- cpu->isar.id_isar5 = 0x0; +- cpu->isar.id_isar6 = 0x0; ++ cpu->isar.regs[ID_MMFR0] = 0x0210030; ++ cpu->isar.regs[ID_MMFR1] = 0x00000000; ++ cpu->isar.regs[ID_MMFR2] = 0x01200000; ++ cpu->isar.regs[ID_MMFR3] = 0x0211; ++ cpu->isar.regs[ID_ISAR0] = 0x02101111; + cpu->isar.regs[ID_ISAR1] = 0x13112111; -+ cpu->isar.regs[ID_ISAR2] = 0x21232042; ++ cpu->isar.regs[ID_ISAR2] = 0x21232141; + cpu->isar.regs[ID_ISAR3] = 0x01112131; -+ cpu->isar.regs[ID_ISAR4] = 0x00011142; -+ cpu->isar.regs[ID_ISAR5] = 0x00011121; -+ cpu->isar.regs[ID_AA64PFR0] = 0x00002222; -+ cpu->isar.regs[ID_AA64DFR0] = 0x10305106; -+ cpu->isar.regs[ID_AA64ISAR0] = 0x00011120; -+ cpu->isar.regs[ID_AA64MMFR0] = 0x00001124; -+ cpu->isar.regs[DBGDIDR] = 0x3516d000; - cpu->clidr = 0x0a200023; - cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ - cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ -@@ -275,10 +275,10 @@ static void aarch64_kunpeng_920_initfn(Object *obj) ++ cpu->isar.regs[ID_ISAR4] = 0x0010142; ++ cpu->isar.regs[ID_ISAR5] = 0x0; ++ cpu->isar.regs[ID_ISAR6] = 0x0; + cpu->mp_is_up = true; + cpu->pmsav7_dregion = 16; + define_arm_cp_regs(cpu, cortexr5_cp_reginfo); +@@ -722,8 +726,8 @@ static void cortex_r5f_initfn(Object *obj) + ARMCPU *cpu = ARM_CPU(obj); - cpu->midr = 0x480fd010; - cpu->ctr = 0x84448004; -- cpu->isar.id_aa64pfr0 = 0x11001111; -- cpu->isar.id_aa64dfr0 = 0x110305408; -- cpu->isar.id_aa64isar0 = 0x10211120; -- cpu->isar.id_aa64mmfr0 = 0x101125; -+ cpu->isar.regs[ID_AA64PFR0] = 0x11001111; -+ cpu->isar.regs[ID_AA64DFR0] = 0x110305408; -+ cpu->isar.regs[ID_AA64ISAR0] = 0x10211120; -+ cpu->isar.regs[ID_AA64MMFR0] = 0x101125; + cortex_r5_initfn(obj); +- cpu->isar.mvfr0 = 0x10110221; +- cpu->isar.mvfr1 = 0x00000011; ++ cpu->isar.regs[MVFR0] = 0x10110221; ++ cpu->isar.regs[MVFR1] = 0x00000011; } - static void cpu_max_get_sve_vq(Object *obj, Visitor *v, const char *name, -@@ -321,7 +321,7 @@ static void aarch64_max_initfn(Object *obj) - uint32_t u; - aarch64_a57_initfn(obj); - -- t = cpu->isar.id_aa64isar0; -+ t = cpu->isar.regs[ID_AA64ISAR0]; - t = FIELD_DP64(t, ID_AA64ISAR0, AES, 2); /* AES + PMULL */ - t = FIELD_DP64(t, ID_AA64ISAR0, SHA1, 1); - t = FIELD_DP64(t, ID_AA64ISAR0, SHA2, 2); /* SHA512 */ -@@ -335,9 +335,9 @@ static void aarch64_max_initfn(Object *obj) - t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1); - t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */ - t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1); -- cpu->isar.id_aa64isar0 = t; -+ cpu->isar.regs[ID_AA64ISAR0] = t; - -- t = cpu->isar.id_aa64isar1; -+ t = cpu->isar.regs[ID_AA64ISAR1]; - t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1); - t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1); - t = FIELD_DP64(t, ID_AA64ISAR1, APA, 1); /* PAuth, architected only */ -@@ -347,45 +347,45 @@ static void aarch64_max_initfn(Object *obj) - t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1); - t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1); - t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1); -- cpu->isar.id_aa64isar1 = t; -+ cpu->isar.regs[ID_AA64ISAR1] = t; - -- t = cpu->isar.id_aa64pfr0; -+ t = cpu->isar.regs[ID_AA64PFR0]; - t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1); - t = FIELD_DP64(t, ID_AA64PFR0, FP, 1); - t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1); -- cpu->isar.id_aa64pfr0 = t; -+ cpu->isar.regs[ID_AA64PFR0] = t; - -- t = cpu->isar.id_aa64pfr1; -+ t = cpu->isar.regs[ID_AA64PFR1]; - t = FIELD_DP64(t, ID_AA64PFR1, BT, 1); -- cpu->isar.id_aa64pfr1 = t; -+ cpu->isar.regs[ID_AA64PFR1] = t; - -- t = cpu->isar.id_aa64mmfr1; -+ t = cpu->isar.regs[ID_AA64MMFR1]; - t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */ - t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); - t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */ -- cpu->isar.id_aa64mmfr1 = t; -+ cpu->isar.regs[ID_AA64MMFR1] = t; - - /* Replicate the same data to the 32-bit id registers. */ -- u = cpu->isar.id_isar5; -+ u = cpu->isar.regs[ID_ISAR5]; - u = FIELD_DP32(u, ID_ISAR5, AES, 2); /* AES + PMULL */ - u = FIELD_DP32(u, ID_ISAR5, SHA1, 1); - u = FIELD_DP32(u, ID_ISAR5, SHA2, 1); - u = FIELD_DP32(u, ID_ISAR5, CRC32, 1); - u = FIELD_DP32(u, ID_ISAR5, RDM, 1); - u = FIELD_DP32(u, ID_ISAR5, VCMA, 1); -- cpu->isar.id_isar5 = u; -+ cpu->isar.regs[ID_ISAR5] = u; - -- u = cpu->isar.id_isar6; -+ u = cpu->isar.regs[ID_ISAR6]; - u = FIELD_DP32(u, ID_ISAR6, JSCVT, 1); - u = FIELD_DP32(u, ID_ISAR6, DP, 1); - u = FIELD_DP32(u, ID_ISAR6, FHM, 1); - u = FIELD_DP32(u, ID_ISAR6, SB, 1); - u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1); -- cpu->isar.id_isar6 = u; -+ cpu->isar.regs[ID_ISAR6] = u; + static void ti925t_initfn(Object *obj) +@@ -942,7 +946,8 @@ static void arm_max_initfn(Object *obj) + cortex_a15_initfn(obj); -- u = cpu->isar.id_mmfr3; -+ u = cpu->isar.regs[ID_MMFR3]; - u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */ -- cpu->isar.id_mmfr3 = u; -+ cpu->isar.regs[ID_MMFR3] = u; + /* old-style VFP short-vector support */ +- cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); ++ cpu->isar.regs[MVFR0] = FIELD_DP32(cpu->isar.regs[MVFR0], MVFR0, FPSHVEC, ++ 1); - /* - * FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet, + #ifdef CONFIG_USER_ONLY + /* +@@ -954,16 +959,16 @@ static void arm_max_initfn(Object *obj) + { + uint32_t t; + +- t = cpu->isar.id_isar5; ++ t = cpu->isar.regs[ID_ISAR5]; + t = FIELD_DP32(t, ID_ISAR5, AES, 2); + t = FIELD_DP32(t, ID_ISAR5, SHA1, 1); + t = FIELD_DP32(t, ID_ISAR5, SHA2, 1); + t = FIELD_DP32(t, ID_ISAR5, CRC32, 1); + t = FIELD_DP32(t, ID_ISAR5, RDM, 1); + t = FIELD_DP32(t, ID_ISAR5, VCMA, 1); +- cpu->isar.id_isar5 = t; ++ cpu->isar.regs[ID_ISAR5] = t; + +- t = cpu->isar.id_isar6; ++ t = cpu->isar.regs[ID_ISAR6]; + t = FIELD_DP32(t, ID_ISAR6, JSCVT, 1); + t = FIELD_DP32(t, ID_ISAR6, DP, 1); + t = FIELD_DP32(t, ID_ISAR6, FHM, 1); +@@ -971,36 +976,36 @@ static void arm_max_initfn(Object *obj) + t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1); + t = FIELD_DP32(t, ID_ISAR6, BF16, 1); + t = FIELD_DP32(t, ID_ISAR6, I8MM, 1); +- cpu->isar.id_isar6 = t; ++ cpu->isar.regs[ID_ISAR6] = t; + +- t = cpu->isar.mvfr1; ++ t = cpu->isar.regs[MVFR1]; + t = FIELD_DP32(t, MVFR1, FPHP, 3); /* v8.2-FP16 */ + t = FIELD_DP32(t, MVFR1, SIMDHP, 2); /* v8.2-FP16 */ +- cpu->isar.mvfr1 = t; ++ cpu->isar.regs[MVFR1] = t; + +- t = cpu->isar.mvfr2; ++ t = cpu->isar.regs[MVFR2]; + t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */ + t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */ +- cpu->isar.mvfr2 = t; ++ cpu->isar.regs[MVFR2] = t; + +- t = cpu->isar.id_mmfr3; ++ t = cpu->isar.regs[ID_MMFR3]; + t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */ +- cpu->isar.id_mmfr3 = t; ++ cpu->isar.regs[ID_MMFR3] = t; + +- t = cpu->isar.id_mmfr4; ++ t = cpu->isar.regs[ID_MMFR4]; + t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */ + t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */ + t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* TTCNP */ + t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* TTS2UXN */ +- cpu->isar.id_mmfr4 = t; ++ cpu->isar.regs[ID_MMFR4] = t; + +- t = cpu->isar.id_pfr0; ++ t = cpu->isar.regs[ID_PFR0]; + t = FIELD_DP32(t, ID_PFR0, DIT, 1); +- cpu->isar.id_pfr0 = t; ++ cpu->isar.regs[ID_PFR0] = t; + +- t = cpu->isar.id_pfr2; ++ t = cpu->isar.regs[ID_PFR2]; + t = FIELD_DP32(t, ID_PFR2, SSBS, 1); +- cpu->isar.id_pfr2 = t; ++ cpu->isar.regs[ID_PFR2] = t; + } + #endif /* CONFIG_USER_ONLY */ + } diff --git a/target/arm/helper.c b/target/arm/helper.c -index 49cd7a7e..459af431 100644 +index 9b317899a6..b8ea1dc1f6 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c -@@ -5597,7 +5597,7 @@ static void define_debug_regs(ARMCPU *cpu) - ARMCPRegInfo dbgdidr = { - .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0, - .access = PL0_R, .accessfn = access_tda, -- .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr, -+ .type = ARM_CP_CONST, .resetvalue = cpu->isar.regs[DBGDIDR], - }; +@@ -6547,12 +6547,12 @@ static void define_debug_regs(ARMCPU *cpu) + * use AArch32. Given that bit 15 is RES1, if the value is 0 then + * the register must not exist for this cpu. + */ +- if (cpu->isar.dbgdidr != 0) { ++ if (cpu->isar.regs[DBGDIDR] != 0) { + ARMCPRegInfo dbgdidr = { + .name = "DBGDIDR", .cp = 14, .crn = 0, .crm = 0, + .opc1 = 0, .opc2 = 0, + .access = PL0_R, .accessfn = access_tda, +- .type = ARM_CP_CONST, .resetvalue = cpu->isar.dbgdidr, ++ .type = ARM_CP_CONST, .resetvalue = cpu->isar.regs[DBGDIDR], + }; + define_one_arm_cp_reg(cpu, &dbgdidr); + } +@@ -6707,7 +6707,7 @@ static void define_pmu_regs(ARMCPU *cpu) + static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) + { + ARMCPU *cpu = env_archcpu(env); +- uint64_t pfr1 = cpu->isar.id_pfr1; ++ uint64_t pfr1 = cpu->isar.regs[ID_PFR1]; - /* Note that all these register fields hold "number of Xs minus 1". */ -@@ -5672,7 +5672,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) + if (env->gicv3state) { + pfr1 |= 1 << 28; +@@ -6719,7 +6719,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri) { ARMCPU *cpu = env_archcpu(env); @@ -1554,168 +2315,250 @@ index 49cd7a7e..459af431 100644 if (env->gicv3state) { pfr0 |= 1 << 24; -@@ -5898,7 +5898,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) - { .name = "ID_DFR0", .state = ARM_CP_STATE_BOTH, +@@ -7501,7 +7501,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, +- .resetvalue = cpu->isar.id_pfr0 }, ++ .resetvalue = cpu->isar.regs[ID_PFR0] }, + /* ID_PFR1 is not a plain ARM_CP_CONST because we don't know + * the value of the GIC field until after we define these regs. + */ +@@ -7515,7 +7515,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_dfr0 }, + .resetvalue = cpu->isar.regs[ID_DFR0] }, { .name = "ID_AFR0", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST, -@@ -5906,51 +5906,51 @@ void register_cp_regs_for_features(ARMCPU *cpu) - { .name = "ID_MMFR0", .state = ARM_CP_STATE_BOTH, +@@ -7525,62 +7525,62 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 4, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_mmfr0 }, + .resetvalue = cpu->isar.regs[ID_MMFR0] }, { .name = "ID_MMFR1", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 5, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_mmfr1 }, + .resetvalue = cpu->isar.regs[ID_MMFR1] }, { .name = "ID_MMFR2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 6, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_mmfr2 }, + .resetvalue = cpu->isar.regs[ID_MMFR2] }, { .name = "ID_MMFR3", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 1, .opc2 = 7, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_mmfr3 }, + .resetvalue = cpu->isar.regs[ID_MMFR3] }, { .name = "ID_ISAR0", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_isar0 }, + .resetvalue = cpu->isar.regs[ID_ISAR0] }, { .name = "ID_ISAR1", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_isar1 }, + .resetvalue = cpu->isar.regs[ID_ISAR1] }, { .name = "ID_ISAR2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_isar2 }, + .resetvalue = cpu->isar.regs[ID_ISAR2] }, { .name = "ID_ISAR3", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_isar3 }, + .resetvalue = cpu->isar.regs[ID_ISAR3] }, { .name = "ID_ISAR4", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 4, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_isar4 }, + .resetvalue = cpu->isar.regs[ID_ISAR4] }, { .name = "ID_ISAR5", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 5, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_isar5 }, + .resetvalue = cpu->isar.regs[ID_ISAR5] }, { .name = "ID_MMFR4", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 6, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_mmfr4 }, + .resetvalue = cpu->isar.regs[ID_MMFR4] }, { .name = "ID_ISAR6", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 7, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa32_tid3, - .resetvalue = cpu->isar.id_isar6 }, + .resetvalue = cpu->isar.regs[ID_ISAR6] }, REGINFO_SENTINEL }; define_arm_cp_regs(cpu, v6_idregs); -@@ -6074,7 +6074,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) - { .name = "ID_AA64PFR1_EL1", .state = ARM_CP_STATE_AA64, +@@ -7630,7 +7630,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .access = PL1_R, + #ifdef CONFIG_USER_ONLY + .type = ARM_CP_CONST, +- .resetvalue = cpu->isar.id_aa64pfr0 ++ .resetvalue = cpu->isar.regs[ID_AA64PFR0] + #else + .type = ARM_CP_NO_RAW, + .accessfn = access_aa64_tid3, +@@ -7642,7 +7642,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64pfr1}, + .resetvalue = cpu->isar.regs[ID_AA64PFR1]}, { .name = "ID_AA64PFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, -@@ -6103,11 +6103,11 @@ void register_cp_regs_for_features(ARMCPU *cpu) - { .name = "ID_AA64DFR0_EL1", .state = ARM_CP_STATE_AA64, +@@ -7657,7 +7657,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 4, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_aa64zfr0 }, ++ .resetvalue = cpu->isar.regs[ID_AA64ZFR0] }, + { .name = "ID_AA64PFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 5, + .access = PL1_R, .type = ARM_CP_CONST, +@@ -7677,12 +7677,12 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64dfr0 }, + .resetvalue = cpu->isar.regs[ID_AA64DFR0] }, { .name = "ID_AA64DFR1_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64dfr1 }, + .resetvalue = cpu->isar.regs[ID_AA64DFR1] }, { .name = "ID_AA64DFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, -@@ -6135,11 +6135,11 @@ void register_cp_regs_for_features(ARMCPU *cpu) - { .name = "ID_AA64ISAR0_EL1", .state = ARM_CP_STATE_AA64, +@@ -7717,12 +7717,12 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64isar0 }, + .resetvalue = cpu->isar.regs[ID_AA64ISAR0] }, { .name = "ID_AA64ISAR1_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64isar1 }, + .resetvalue = cpu->isar.regs[ID_AA64ISAR1] }, { .name = "ID_AA64ISAR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, -@@ -6167,15 +6167,15 @@ void register_cp_regs_for_features(ARMCPU *cpu) - { .name = "ID_AA64MMFR0_EL1", .state = ARM_CP_STATE_AA64, +@@ -7757,17 +7757,17 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64mmfr0 }, + .resetvalue = cpu->isar.regs[ID_AA64MMFR0] }, { .name = "ID_AA64MMFR1_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64mmfr1 }, + .resetvalue = cpu->isar.regs[ID_AA64MMFR1] }, { .name = "ID_AA64MMFR2_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.id_aa64mmfr2 }, + .resetvalue = cpu->isar.regs[ID_AA64MMFR2] }, { .name = "ID_AA64MMFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST, -@@ -6199,15 +6199,15 @@ void register_cp_regs_for_features(ARMCPU *cpu) - { .name = "MVFR0_EL1", .state = ARM_CP_STATE_AA64, +@@ -7797,17 +7797,17 @@ void register_cp_regs_for_features(ARMCPU *cpu) .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 0, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.mvfr0 }, + .resetvalue = cpu->isar.regs[MVFR0] }, { .name = "MVFR1_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.mvfr1 }, + .resetvalue = cpu->isar.regs[MVFR1] }, { .name = "MVFR2_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2, .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, - .resetvalue = cpu->isar.mvfr2 }, + .resetvalue = cpu->isar.regs[MVFR2] }, { .name = "MVFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST, -@@ -6426,7 +6426,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) - define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo); - define_arm_cp_regs(cpu, vmsa_cp_reginfo); - /* TTCBR2 is introduced with ARMv8.2-A32HPD. */ -- if (FIELD_EX32(cpu->isar.id_mmfr4, ID_MMFR4, HPDS) != 0) { -+ if (FIELD_EX32(cpu->isar.regs[ID_MMFR4], ID_MMFR4, HPDS) != 0) { - define_one_arm_cp_reg(cpu, &ttbcr2_reginfo); - } - } +@@ -7817,7 +7817,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 4, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, +- .resetvalue = cpu->isar.id_pfr2 }, ++ .resetvalue = cpu->isar.regs[ID_PFR2] }, + { .name = "MVFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5, + .access = PL1_R, .type = ARM_CP_CONST, +diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c +index 0dc96560d3..66ad698df1 100644 +--- a/target/arm/hvf/hvf.c ++++ b/target/arm/hvf/hvf.c +@@ -449,15 +449,15 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + int reg; + uint64_t *val; + } regs[] = { +- { HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.id_aa64pfr0 }, +- { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.id_aa64pfr1 }, +- { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.id_aa64dfr0 }, +- { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.id_aa64dfr1 }, +- { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.id_aa64isar0 }, +- { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.id_aa64isar1 }, +- { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.id_aa64mmfr0 }, +- { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.id_aa64mmfr1 }, +- { HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.id_aa64mmfr2 }, ++ { HV_SYS_REG_ID_AA64PFR0_EL1, &host_isar.regs[ID_AA64PFR0] }, ++ { HV_SYS_REG_ID_AA64PFR1_EL1, &host_isar.regs[ID_AA64PFR1] }, ++ { HV_SYS_REG_ID_AA64DFR0_EL1, &host_isar.regs[ID_AA64DFR0] }, ++ { HV_SYS_REG_ID_AA64DFR1_EL1, &host_isar.regs[ID_AA64DFR1] }, ++ { HV_SYS_REG_ID_AA64ISAR0_EL1, &host_isar.regs[ID_AA64ISAR0] }, ++ { HV_SYS_REG_ID_AA64ISAR1_EL1, &host_isar.regs[ID_AA64ISAR1] }, ++ { HV_SYS_REG_ID_AA64MMFR0_EL1, &host_isar.regs[ID_AA64MMFR0] }, ++ { HV_SYS_REG_ID_AA64MMFR1_EL1, &host_isar.regs[ID_AA64MMFR1] }, ++ { HV_SYS_REG_ID_AA64MMFR2_EL1, &host_isar.regs[ID_AA64MMFR2] }, + }; + hv_vcpu_t fd; + hv_return_t r = HV_SUCCESS; +@@ -593,7 +593,7 @@ int hvf_arch_init_vcpu(CPUState *cpu) + + /* We're limited to underlying hardware caps, override internal versions */ + ret = hv_vcpu_get_sys_reg(cpu->hvf->fd, HV_SYS_REG_ID_AA64MMFR0_EL1, +- &arm_cpu->isar.id_aa64mmfr0); ++ &arm_cpu->isar.regs[ID_AA64MMFR0]); + assert_hvf_ok(ret); + + return 0; diff --git a/target/arm/internals.h b/target/arm/internals.h -index 1d01ecc4..2da13ba8 100644 +index 89f7610ebc..0ea225e480 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h -@@ -237,7 +237,7 @@ static inline unsigned int arm_pamax(ARMCPU *cpu) +@@ -254,7 +254,7 @@ static inline unsigned int arm_pamax(ARMCPU *cpu) [5] = 48, }; unsigned int parange = @@ -1724,7 +2567,7 @@ index 1d01ecc4..2da13ba8 100644 /* id_aa64mmfr0 is a read-only register so values outside of the * supported mappings can be considered an implementation error. */ -@@ -865,9 +865,9 @@ static inline uint32_t arm_debug_exception_fsr(CPUARMState *env) +@@ -808,9 +808,9 @@ static inline uint32_t arm_debug_exception_fsr(CPUARMState *env) static inline int arm_num_brps(ARMCPU *cpu) { if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { @@ -1736,7 +2579,7 @@ index 1d01ecc4..2da13ba8 100644 } } -@@ -879,9 +879,9 @@ static inline int arm_num_brps(ARMCPU *cpu) +@@ -822,9 +822,9 @@ static inline int arm_num_brps(ARMCPU *cpu) static inline int arm_num_wrps(ARMCPU *cpu) { if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { @@ -1748,13 +2591,12 @@ index 1d01ecc4..2da13ba8 100644 } } -@@ -893,9 +893,10 @@ static inline int arm_num_wrps(ARMCPU *cpu) +@@ -836,9 +836,9 @@ static inline int arm_num_wrps(ARMCPU *cpu) static inline int arm_num_ctx_cmps(ARMCPU *cpu) { if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { - return FIELD_EX64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS) + 1; -+ return FIELD_EX64(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, -+ CTX_CMPS) + 1; ++ return FIELD_EX64(cpu->isar.regs[ID_AA64DFR0], ID_AA64DFR0, CTX_CMPS) + 1; } else { - return FIELD_EX32(cpu->isar.dbgdidr, DBGDIDR, CTX_CMPS) + 1; + return FIELD_EX32(cpu->isar.regs[DBGDIDR], DBGDIDR, CTX_CMPS) + 1; @@ -1762,11 +2604,11 @@ index 1d01ecc4..2da13ba8 100644 } diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c -index 2a88b8df..06cf31e8 100644 +index e790d6c9a5..4f97e516c2 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c -@@ -455,7 +455,7 @@ static inline void unset_feature(uint64_t *features, int feature) - *features &= ~(1ULL << feature); +@@ -468,7 +468,7 @@ void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa) + } } -static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id) @@ -1774,7 +2616,7 @@ index 2a88b8df..06cf31e8 100644 { uint64_t ret; struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)&ret }; -@@ -509,7 +509,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) +@@ -528,7 +528,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) ahcf->target = init.target; ahcf->dtb_compatible = "arm,arm-v8"; @@ -1783,7 +2625,7 @@ index 2a88b8df..06cf31e8 100644 ARM64_SYS_REG(3, 0, 0, 4, 0)); if (unlikely(err < 0)) { /* -@@ -528,24 +528,24 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) +@@ -547,24 +547,24 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) * ??? Either of these sounds like too much effort just * to work around running a modern host kernel. */ @@ -1817,10 +2659,19 @@ index 2a88b8df..06cf31e8 100644 ARM64_SYS_REG(3, 0, 0, 7, 2)); /* -@@ -555,38 +555,38 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) +@@ -574,44 +574,44 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) * than skipping the reads and leaving 0, as we must avoid * considering the values in every case. */ +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr0, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_PFR0], + ARM64_SYS_REG(3, 0, 0, 1, 0)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_PFR1], + ARM64_SYS_REG(3, 0, 0, 1, 1)); +- err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2, ++ err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_PFR2], + ARM64_SYS_REG(3, 0, 0, 3, 4)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0, + err |= read_sys_reg32(fdarray[2], &ahcf->isar.regs[ID_DFR0], ARM64_SYS_REG(3, 0, 0, 1, 2)); @@ -1872,7 +2723,7 @@ index 2a88b8df..06cf31e8 100644 ARM64_SYS_REG(3, 0, 0, 3, 2)); /* -@@ -599,14 +599,16 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) +@@ -624,14 +624,17 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) * arch/arm64/kvm/sys_regs.c:trap_dbgidr() does. * We only do this if the CPU supports AArch32 at EL1. */ @@ -1880,13 +2731,14 @@ index 2a88b8df..06cf31e8 100644 - int wrps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, WRPS); - int brps = FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, BRPS); + if (FIELD_EX32(ahcf->isar.regs[ID_AA64PFR0], ID_AA64PFR0, EL1) >= 2) { -+ int wrps = FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], -+ ID_AA64DFR0, WRPS); -+ int brps = FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], -+ ID_AA64DFR0, BRPS); ++ int wrps = FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], ID_AA64DFR0, ++ WRPS); ++ int brps = FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], ID_AA64DFR0, ++ BRPS); int ctx_cmps = - FIELD_EX64(ahcf->isar.id_aa64dfr0, ID_AA64DFR0, CTX_CMPS); -+ FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], ID_AA64DFR0, CTX_CMPS); ++ FIELD_EX64(ahcf->isar.regs[ID_AA64DFR0], ID_AA64DFR0, ++ CTX_CMPS); int version = 6; /* ARMv8 debug architecture */ bool has_el3 = - !!FIELD_EX32(ahcf->isar.id_aa64pfr0, ID_AA64PFR0, EL3); @@ -1894,7 +2746,7 @@ index 2a88b8df..06cf31e8 100644 uint32_t dbgdidr = 0; dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, WRPS, wrps); -@@ -616,7 +618,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) +@@ -641,7 +644,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, NSUHD_IMP, has_el3); dbgdidr = FIELD_DP32(dbgdidr, DBGDIDR, SE_IMP, has_el3); dbgdidr |= (1 << 15); /* RES1 bit */ @@ -1903,6 +2755,27 @@ index 2a88b8df..06cf31e8 100644 } } +@@ -649,9 +652,9 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + + /* Add feature bits that can't appear until after VCPU init. */ + if (sve_supported) { +- t = ahcf->isar.id_aa64pfr0; ++ t = ahcf->isar.regs[ID_AA64PFR0]; + t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1); +- ahcf->isar.id_aa64pfr0 = t; ++ ahcf->isar.regs[ID_AA64PFR0] = t; + + /* + * Before v5.1, KVM did not support SVE and did not expose +@@ -659,7 +662,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) + * not expose the register to "user" requests like this + * unless the host supports SVE. + */ +- err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64zfr0, ++ err |= read_sys_reg64(fdarray[2], &ahcf->isar.regs[ID_AA64ZFR0], + ARM64_SYS_REG(3, 0, 0, 4, 4)); + } + -- -2.25.1 +2.27.0 diff --git a/target-arm-cpu-Add-the-kvm-no-adjvtime-CPU-property.patch b/target-arm-cpu-Add-the-kvm-no-adjvtime-CPU-property.patch deleted file mode 100644 index 41c67cf1b8024af9f48888ecd782e9927a2f166e..0000000000000000000000000000000000000000 --- a/target-arm-cpu-Add-the-kvm-no-adjvtime-CPU-property.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 860035652c7866b033762f6d90f81d5ddedf855c Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 22 Apr 2020 17:08:43 +0800 -Subject: [PATCH] target/arm/cpu: Add the kvm-no-adjvtime CPU property - -kvm-no-adjvtime is a KVM specific CPU property and a first of its -kind. To accommodate it we also add kvm_arm_add_vcpu_properties() -and a KVM specific CPU properties description to the CPU features -document. - -Signed-off-by: Andrew Jones -Message-id: 20200120101023.16030-7-drjones@redhat.com -Reviewed-by: Peter Maydell -Signed-off-by: Peter Maydell - -diff --git a/hw/arm/virt.c b/hw/arm/virt.c -index e9a2a959..cfda6cc5 100644 ---- a/hw/arm/virt.c -+++ b/hw/arm/virt.c -@@ -1748,6 +1748,11 @@ static void machvirt_init(MachineState *machine) - } - } - -+ if (vmc->kvm_no_adjvtime && -+ object_property_find(cpuobj, "kvm-no-adjvtime", NULL)) { -+ object_property_set_bool(cpuobj, true, "kvm-no-adjvtime", NULL); -+ } -+ - if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) { - object_property_set_bool(cpuobj, false, "pmu", NULL); - } -diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h -index 43a6ce91..a9d6977a 100644 ---- a/include/hw/arm/virt.h -+++ b/include/hw/arm/virt.h -@@ -107,6 +107,7 @@ typedef struct { - bool claim_edge_triggered_timers; - bool smbios_old_sys_ver; - bool no_highmem_ecam; -+ bool kvm_no_adjvtime; - } VirtMachineClass; - - typedef struct { -diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index bc3da9a3..39bbe7e2 100644 ---- a/target/arm/cpu.c -+++ b/target/arm/cpu.c -@@ -2441,6 +2441,7 @@ static void arm_max_initfn(Object *obj) - - if (kvm_enabled()) { - kvm_arm_set_cpu_features_from_host(cpu); -+ kvm_arm_add_vcpu_properties(obj); - } else { - cortex_a15_initfn(obj); - -@@ -2629,6 +2630,7 @@ static void arm_host_initfn(Object *obj) - ARMCPU *cpu = ARM_CPU(obj); - - kvm_arm_set_cpu_features_from_host(cpu); -+ kvm_arm_add_vcpu_properties(obj); - arm_cpu_post_init(obj); - } - -diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index dbf44b92..b30ca7c9 100644 ---- a/target/arm/cpu64.c -+++ b/target/arm/cpu64.c -@@ -312,6 +312,7 @@ static void aarch64_max_initfn(Object *obj) - - if (kvm_enabled()) { - kvm_arm_set_cpu_features_from_host(cpu); -+ kvm_arm_add_vcpu_properties(obj); - } else { - uint64_t t; - uint32_t u; -diff --git a/target/arm/kvm.c b/target/arm/kvm.c -index 21fb7ecd..327b3bc3 100644 ---- a/target/arm/kvm.c -+++ b/target/arm/kvm.c -@@ -16,6 +16,8 @@ - #include "qemu-common.h" - #include "qemu/timer.h" - #include "qemu/error-report.h" -+#include "qom/object.h" -+#include "qapi/error.h" - #include "sysemu/sysemu.h" - #include "sysemu/kvm.h" - #include "sysemu/kvm_int.h" -@@ -162,6 +164,32 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) - env->features = arm_host_cpu_features.features; - } - -+static bool kvm_no_adjvtime_get(Object *obj, Error **errp) -+{ -+ return !ARM_CPU(obj)->kvm_adjvtime; -+} -+ -+static void kvm_no_adjvtime_set(Object *obj, bool value, Error **errp) -+{ -+ ARM_CPU(obj)->kvm_adjvtime = !value; -+} -+ -+/* KVM VCPU properties should be prefixed with "kvm-". */ -+void kvm_arm_add_vcpu_properties(Object *obj) -+{ -+ if (!kvm_enabled()) { -+ return; -+ } -+ -+ ARM_CPU(obj)->kvm_adjvtime = true; -+ object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get, -+ kvm_no_adjvtime_set, &error_abort); -+ object_property_set_description(obj, "kvm-no-adjvtime", -+ "Set on to disable the adjustment of " -+ "the virtual counter. VM stopped time " -+ "will be counted.", &error_abort); -+} -+ - int kvm_arm_get_max_vm_ipa_size(MachineState *ms) - { - KVMState *s = KVM_STATE(ms->accelerator); -diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h -index 97560d4e..0de5f83e 100644 ---- a/target/arm/kvm_arm.h -+++ b/target/arm/kvm_arm.h -@@ -230,6 +230,15 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf); - */ - void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu); - -+/** -+ * kvm_arm_add_vcpu_properties: -+ * @obj: The CPU object to add the properties to -+ * -+ * Add all KVM specific CPU properties to the CPU object. These -+ * are the CPU properties with "kvm-" prefixed names. -+ */ -+void kvm_arm_add_vcpu_properties(Object *obj); -+ - /** - * kvm_arm_get_max_vm_ipa_size: - * @ms: Machine state handle -@@ -294,6 +303,8 @@ static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) - cpu->host_cpu_probe_failed = true; - } - -+static inline void kvm_arm_add_vcpu_properties(Object *obj) {} -+ - static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms) - { - return -ENOENT; --- -2.23.0 diff --git a/target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch b/target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch index cf9bb73b8f5bf63c5e073042ca137266fd28e894..edb4ea44c77e024c9104895c149040f364c11f79 100644 --- a/target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch +++ b/target-arm-ignore-evtstrm-and-cpuid-CPU-features.patch @@ -1,4 +1,4 @@ -From dfedc889fafd35efd4f8382b7672bf0e556f9f45 Mon Sep 17 00:00:00 2001 +From 4558dc5590b89b1252baea2734c2b3668566e5cb Mon Sep 17 00:00:00 2001 From: Peng Liang Date: Mon, 7 Sep 2020 14:07:07 +0800 Subject: [PATCH] target/arm: ignore evtstrm and cpuid CPU features @@ -14,16 +14,17 @@ However, they are exposed by getauxval() and /proc/cpuinfo. Hence, let's report and ignore the CPU features if someone set them. Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun --- target/arm/cpu64.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index 7de20848..726d123d 100644 +index 9e5179afbe..287e7ac91c 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c -@@ -506,10 +506,37 @@ static void arm_cpu_parse_featurestr(const char *typename, char *features, - } +@@ -982,10 +982,37 @@ static gchar *aarch64_gdb_arch_name(CPUState *cs) + return g_strdup("aarch64"); } +static const char *unconfigurable_feats[] = { @@ -62,5 +63,5 @@ index 7de20848..726d123d 100644 prop->property = g_strdup(name); prop->value = g_strdup(val); -- -2.28.0 +2.27.0 diff --git a/target-arm-introduce-CPU-feature-dependency-mechanis.patch b/target-arm-introduce-CPU-feature-dependency-mechanis.patch index 8c47cba243d4890cfc205c6c9b5b04b37705664f..aecfbf8991d1fc259c2efe06cf4a32bec39ac1e0 100644 --- a/target-arm-introduce-CPU-feature-dependency-mechanis.patch +++ b/target-arm-introduce-CPU-feature-dependency-mechanis.patch @@ -1,7 +1,7 @@ -From da538bb9d1acc22543a2b7b07ae35a62386bf226 Mon Sep 17 00:00:00 2001 +From 632d58d1b908ee979074b589417f446c0a3be35d Mon Sep 17 00:00:00 2001 From: Peng Liang Date: Thu, 6 Aug 2020 16:14:46 +0800 -Subject: [PATCH 5/9] target/arm: introduce CPU feature dependency mechanism +Subject: [PATCH] target/arm: introduce CPU feature dependency mechanism Some CPU features are dependent on other CPU features. For example, ID_AA64PFR0_EL1.FP field and ID_AA64PFR0_EL1.AdvSIMD must have the same @@ -21,15 +21,16 @@ user, then b and c is disabled automatically. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun --- target/arm/cpu.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index 3f63312c..d5576538 100644 +index c081ecc12b..ee09642dae 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c -@@ -1306,6 +1306,103 @@ static struct CPUFeatureInfo cpu_features[] = { +@@ -1483,6 +1483,103 @@ static struct CPUFeatureInfo cpu_features[] = { }, }; @@ -133,7 +134,7 @@ index 3f63312c..d5576538 100644 static void arm_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { -@@ -1342,13 +1439,45 @@ static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name, +@@ -1519,13 +1616,45 @@ static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name, } if (value) { @@ -150,7 +151,7 @@ index 3f63312c..d5576538 100644 + continue; + } + -+ object_property_set_bool(obj, true, d->from.name, &local_err); ++ object_property_set_bool(obj, d->from.name, true, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; @@ -170,7 +171,7 @@ index 3f63312c..d5576538 100644 + continue; + } + -+ object_property_set_bool(obj, false, d->to.name, &local_err); ++ object_property_set_bool(obj, d->to.name, false, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; @@ -180,5 +181,5 @@ index 3f63312c..d5576538 100644 } -- -2.25.1 +2.27.0 diff --git a/target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch b/target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch index 0477419196061a5e452363845ffd4591bfc5ef21..d5bc0e88ed89005c6d4cf66d4c90eafb314bc048 100644 --- a/target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch +++ b/target-arm-introduce-KVM_CAP_ARM_CPU_FEATURE.patch @@ -1,13 +1,14 @@ -From 7ed595242f52d0654982d41a9c2a63be2bc3378e Mon Sep 17 00:00:00 2001 +From 536aa9ecc3cb25c81c2df56230c690257189d4ef Mon Sep 17 00:00:00 2001 From: Peng Liang Date: Thu, 6 Aug 2020 16:14:55 +0800 -Subject: [PATCH 6/9] target/arm: introduce KVM_CAP_ARM_CPU_FEATURE +Subject: [PATCH] target/arm: introduce KVM_CAP_ARM_CPU_FEATURE Introduce KVM_CAP_ARM_CPU_FEATURE to check whether KVM supports to set CPU features in ARM. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun --- linux-headers/linux/kvm.h | 2 ++ target/arm/cpu.c | 5 +++++ @@ -16,12 +17,12 @@ Signed-off-by: Peng Liang 4 files changed, 28 insertions(+) diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h -index 744e888e..4844edc3 100644 +index bcaf66cc4d..5d8e42b8f8 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h -@@ -995,6 +995,8 @@ struct kvm_ppc_resize_hpt { - #define KVM_CAP_ARM_PTRAUTH_ADDRESS 171 - #define KVM_CAP_ARM_PTRAUTH_GENERIC 172 +@@ -1113,6 +1113,8 @@ struct kvm_ppc_resize_hpt { + #define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204 + #define KVM_CAP_ARM_MTE 205 +#define KVM_CAP_ARM_CPU_FEATURE 555 + @@ -29,10 +30,10 @@ index 744e888e..4844edc3 100644 struct kvm_irq_routing_irqchip { diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index d5576538..db46afba 100644 +index ee09642dae..3024f4a3f5 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c -@@ -1427,6 +1427,11 @@ static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name, +@@ -1604,6 +1604,11 @@ static void arm_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name, Error *local_err = NULL; bool value; @@ -45,11 +46,11 @@ index d5576538..db46afba 100644 qdev_prop_set_after_realize(dev, name, errp); return; diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c -index 06cf31e8..05345556 100644 +index 4f97e516c2..b34a87fd24 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c -@@ -644,6 +644,20 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) - return true; +@@ -827,6 +827,20 @@ static int kvm_arm_sve_set_vls(CPUState *cs) + return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); } +bool kvm_arm_cpu_feature_supported(void) @@ -70,12 +71,12 @@ index 06cf31e8..05345556 100644 int kvm_arch_init_vcpu(CPUState *cs) diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h -index 9b7104d6..49e80878 100644 +index f8e0e64363..82145607ec 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h -@@ -239,6 +239,13 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu); +@@ -306,6 +306,13 @@ bool kvm_arm_pmu_supported(void); */ - void kvm_arm_add_vcpu_properties(Object *obj); + bool kvm_arm_sve_supported(void); +/** + * kvm_arm_cpu_feature_supported: @@ -88,5 +89,5 @@ index 9b7104d6..49e80878 100644 * kvm_arm_get_max_vm_ipa_size: * @ms: Machine state handle -- -2.25.1 +2.27.0 diff --git a/target-arm-kvm-Implement-virtual-time-adjustment.patch b/target-arm-kvm-Implement-virtual-time-adjustment.patch deleted file mode 100644 index 86450c4d8f1739527a7065ec9242706605487b0e..0000000000000000000000000000000000000000 --- a/target-arm-kvm-Implement-virtual-time-adjustment.patch +++ /dev/null @@ -1,290 +0,0 @@ -From 77ee224418fac859acecd9aca4d18555ced42db6 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Tue, 21 Apr 2020 17:32:31 +0800 -Subject: [PATCH 3/4] target/arm/kvm: Implement virtual time adjustment - -When a VM is stopped (such as when it's paused) guest virtual time -should stop counting. Otherwise, when the VM is resumed it will -experience time jumps and its kernel may report soft lockups. Not -counting virtual time while the VM is stopped has the side effect -of making the guest's time appear to lag when compared with real -time, and even with time derived from the physical counter. For -this reason, this change, which is enabled by default, comes with -a KVM CPU feature allowing it to be disabled, restoring legacy -behavior. - -This patch only provides the implementation of the virtual time -adjustment. A subsequent patch will provide the CPU property -allowing the change to be enabled and disabled. - -Reported-by: Bijan Mottahedeh -Signed-off-by: Andrew Jones -Message-id: 20200120101023.16030-6-drjones@redhat.com -Reviewed-by: Peter Maydell -Signed-off-by: Peter Maydell ---- - target/arm/cpu.h | 7 ++++ - target/arm/kvm.c | 92 ++++++++++++++++++++++++++++++++++++++++++++ - target/arm/kvm32.c | 2 + - target/arm/kvm64.c | 2 + - target/arm/kvm_arm.h | 37 ++++++++++++++++++ - target/arm/machine.c | 7 ++++ - 6 files changed, 147 insertions(+) - -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index 94c990cd..e19531a7 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -816,6 +816,13 @@ struct ARMCPU { - /* KVM init features for this CPU */ - uint32_t kvm_init_features[7]; - -+ /* KVM CPU state */ -+ -+ /* KVM virtual time adjustment */ -+ bool kvm_adjvtime; -+ bool kvm_vtime_dirty; -+ uint64_t kvm_vtime; -+ - /* Uniprocessor system with MP extensions */ - bool mp_is_up; - -diff --git a/target/arm/kvm.c b/target/arm/kvm.c -index cc7a46df..21fb7ecd 100644 ---- a/target/arm/kvm.c -+++ b/target/arm/kvm.c -@@ -336,6 +336,22 @@ static int compare_u64(const void *a, const void *b) - return 0; - } - -+/* -+ * cpreg_values are sorted in ascending order by KVM register ID -+ * (see kvm_arm_init_cpreg_list). This allows us to cheaply find -+ * the storage for a KVM register by ID with a binary search. -+ */ -+static uint64_t *kvm_arm_get_cpreg_ptr(ARMCPU *cpu, uint64_t regidx) -+{ -+ uint64_t *res; -+ -+ res = bsearch(®idx, cpu->cpreg_indexes, cpu->cpreg_array_len, -+ sizeof(uint64_t), compare_u64); -+ assert(res); -+ -+ return &cpu->cpreg_values[res - cpu->cpreg_indexes]; -+} -+ - /* Initialize the ARMCPU cpreg list according to the kernel's - * definition of what CPU registers it knows about (and throw away - * the previous TCG-created cpreg list). -@@ -489,6 +505,23 @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level) - return ok; - } - -+void kvm_arm_cpu_pre_save(ARMCPU *cpu) -+{ -+ /* KVM virtual time adjustment */ -+ if (cpu->kvm_vtime_dirty) { -+ *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT) = cpu->kvm_vtime; -+ } -+} -+ -+void kvm_arm_cpu_post_load(ARMCPU *cpu) -+{ -+ /* KVM virtual time adjustment */ -+ if (cpu->kvm_adjvtime) { -+ cpu->kvm_vtime = *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT); -+ cpu->kvm_vtime_dirty = true; -+ } -+} -+ - void kvm_arm_reset_vcpu(ARMCPU *cpu) - { - int ret; -@@ -556,6 +589,50 @@ int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu) - return 0; - } - -+void kvm_arm_get_virtual_time(CPUState *cs) -+{ -+ ARMCPU *cpu = ARM_CPU(cs); -+ struct kvm_one_reg reg = { -+ .id = KVM_REG_ARM_TIMER_CNT, -+ .addr = (uintptr_t)&cpu->kvm_vtime, -+ }; -+ int ret; -+ -+ if (cpu->kvm_vtime_dirty) { -+ return; -+ } -+ -+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); -+ if (ret) { -+ error_report("Failed to get KVM_REG_ARM_TIMER_CNT"); -+ abort(); -+ } -+ -+ cpu->kvm_vtime_dirty = true; -+} -+ -+void kvm_arm_put_virtual_time(CPUState *cs) -+{ -+ ARMCPU *cpu = ARM_CPU(cs); -+ struct kvm_one_reg reg = { -+ .id = KVM_REG_ARM_TIMER_CNT, -+ .addr = (uintptr_t)&cpu->kvm_vtime, -+ }; -+ int ret; -+ -+ if (!cpu->kvm_vtime_dirty) { -+ return; -+ } -+ -+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); -+ if (ret) { -+ error_report("Failed to set KVM_REG_ARM_TIMER_CNT"); -+ abort(); -+ } -+ -+ cpu->kvm_vtime_dirty = false; -+} -+ - int kvm_put_vcpu_events(ARMCPU *cpu) - { - CPUARMState *env = &cpu->env; -@@ -667,6 +744,21 @@ MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) - return MEMTXATTRS_UNSPECIFIED; - } - -+void kvm_arm_vm_state_change(void *opaque, int running, RunState state) -+{ -+ CPUState *cs = opaque; -+ ARMCPU *cpu = ARM_CPU(cs); -+ -+ if (running) { -+ if (cpu->kvm_adjvtime) { -+ kvm_arm_put_virtual_time(cs); -+ } -+ } else { -+ if (cpu->kvm_adjvtime) { -+ kvm_arm_get_virtual_time(cs); -+ } -+ } -+} - - int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) - { -diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c -index 51f78f72..ee158830 100644 ---- a/target/arm/kvm32.c -+++ b/target/arm/kvm32.c -@@ -195,6 +195,8 @@ int kvm_arch_init_vcpu(CPUState *cs) - return -EINVAL; - } - -+ qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs); -+ - /* Determine init features for this CPU */ - memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features)); - if (cpu->start_powered_off) { -diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c -index f2f0a92e..4f0bf000 100644 ---- a/target/arm/kvm64.c -+++ b/target/arm/kvm64.c -@@ -609,6 +609,8 @@ int kvm_arch_init_vcpu(CPUState *cs) - return -EINVAL; - } - -+ qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs); -+ - /* Determine init features for this CPU */ - memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features)); - if (cpu->start_powered_off) { -diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h -index 32d97ce5..97560d4e 100644 ---- a/target/arm/kvm_arm.h -+++ b/target/arm/kvm_arm.h -@@ -113,6 +113,23 @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level); - */ - bool write_kvmstate_to_list(ARMCPU *cpu); - -+/** -+ * kvm_arm_cpu_pre_save: -+ * @cpu: ARMCPU -+ * -+ * Called after write_kvmstate_to_list() from cpu_pre_save() to update -+ * the cpreg list with KVM CPU state. -+ */ -+void kvm_arm_cpu_pre_save(ARMCPU *cpu); -+ -+/** -+ * kvm_arm_cpu_post_load: -+ * @cpu: ARMCPU -+ * -+ * Called from cpu_post_load() to update KVM CPU state from the cpreg list. -+ */ -+void kvm_arm_cpu_post_load(ARMCPU *cpu); -+ - /** - * kvm_arm_reset_vcpu: - * @cpu: ARMCPU -@@ -241,6 +258,24 @@ int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu); - */ - int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu); - -+/** -+ * kvm_arm_get_virtual_time: -+ * @cs: CPUState -+ * -+ * Gets the VCPU's virtual counter and stores it in the KVM CPU state. -+ */ -+void kvm_arm_get_virtual_time(CPUState *cs); -+ -+/** -+ * kvm_arm_put_virtual_time: -+ * @cs: CPUState -+ * -+ * Sets the VCPU's virtual counter to the value stored in the KVM CPU state. -+ */ -+void kvm_arm_put_virtual_time(CPUState *cs); -+ -+void kvm_arm_vm_state_change(void *opaque, int running, RunState state); -+ - int kvm_arm_vgic_probe(void); - - void kvm_arm_pmu_set_irq(CPUState *cs, int irq); -@@ -272,6 +307,8 @@ static inline int kvm_arm_vgic_probe(void) - static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) {} - static inline void kvm_arm_pmu_init(CPUState *cs) {} - -+static inline void kvm_arm_get_virtual_time(CPUState *cs) {} -+static inline void kvm_arm_put_virtual_time(CPUState *cs) {} - #endif - - static inline const char *gic_class_name(void) -diff --git a/target/arm/machine.c b/target/arm/machine.c -index 3fd319a3..ee3c59a6 100644 ---- a/target/arm/machine.c -+++ b/target/arm/machine.c -@@ -644,6 +644,12 @@ static int cpu_pre_save(void *opaque) - /* This should never fail */ - abort(); - } -+ -+ /* -+ * kvm_arm_cpu_pre_save() must be called after -+ * write_kvmstate_to_list() -+ */ -+ kvm_arm_cpu_pre_save(cpu); - } else { - if (!write_cpustate_to_list(cpu, false)) { - /* This should never fail. */ -@@ -746,6 +752,7 @@ static int cpu_post_load(void *opaque, int version_id) - * we're using it. - */ - write_list_to_cpustate(cpu); -+ kvm_arm_cpu_post_load(cpu); - } else { - if (!write_list_to_cpustate(cpu)) { - return -1; --- -2.23.0 diff --git a/target-arm-kvm-trivial-Clean-up-header-documentation.patch b/target-arm-kvm-trivial-Clean-up-header-documentation.patch deleted file mode 100644 index 8c28c63b1e9fa89ace5860f635f07e2d9b221bbe..0000000000000000000000000000000000000000 --- a/target-arm-kvm-trivial-Clean-up-header-documentation.patch +++ /dev/null @@ -1,144 +0,0 @@ -From c057499f90af4be8b26f57f8755aca0ddfcf9467 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Tue, 21 Apr 2020 16:52:07 +0800 -Subject: [PATCH 1/4] target/arm/kvm: trivial: Clean up header documentation - -Signed-off-by: Andrew Jones -Message-id: 20200120101023.16030-2-drjones@redhat.com -Reviewed-by: Peter Maydell -Signed-off-by: Peter Maydell ---- - target/arm/kvm_arm.h | 38 +++++++++++++++++++++++--------------- - 1 file changed, 23 insertions(+), 15 deletions(-) - -diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h -index a9f3ccab..32d97ce5 100644 ---- a/target/arm/kvm_arm.h -+++ b/target/arm/kvm_arm.h -@@ -61,8 +61,8 @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group, - int kvm_arm_init_cpreg_list(ARMCPU *cpu); - - /** -- * kvm_arm_reg_syncs_via_cpreg_list -- * regidx: KVM register index -+ * kvm_arm_reg_syncs_via_cpreg_list: -+ * @regidx: KVM register index - * - * Return true if this KVM register should be synchronized via the - * cpreg list of arbitrary system registers, false if it is synchronized -@@ -71,8 +71,8 @@ int kvm_arm_init_cpreg_list(ARMCPU *cpu); - bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx); - - /** -- * kvm_arm_cpreg_level -- * regidx: KVM register index -+ * kvm_arm_cpreg_level: -+ * @regidx: KVM register index - * - * Return the level of this coprocessor/system register. Return value is - * either KVM_PUT_RUNTIME_STATE, KVM_PUT_RESET_STATE, or KVM_PUT_FULL_STATE. -@@ -134,6 +134,8 @@ void kvm_arm_init_serror_injection(CPUState *cs); - * @cpu: ARMCPU - * - * Get VCPU related state from kvm. -+ * -+ * Returns: 0 if success else < 0 error code - */ - int kvm_get_vcpu_events(ARMCPU *cpu); - -@@ -142,6 +144,8 @@ int kvm_get_vcpu_events(ARMCPU *cpu); - * @cpu: ARMCPU - * - * Put VCPU related state to kvm. -+ * -+ * Returns: 0 if success else < 0 error code - */ - int kvm_put_vcpu_events(ARMCPU *cpu); - -@@ -191,10 +195,12 @@ typedef struct ARMHostCPUFeatures { - - /** - * kvm_arm_get_host_cpu_features: -- * @ahcc: ARMHostCPUClass to fill in -+ * @ahcf: ARMHostCPUClass to fill in - * - * Probe the capabilities of the host kernel's preferred CPU and fill - * in the ARMHostCPUClass struct accordingly. -+ * -+ * Returns true on success and false otherwise. - */ - bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf); - -@@ -208,26 +214,30 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf); - void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu); - - /** -- * kvm_arm_get_max_vm_ipa_size - Returns the number of bits in the -- * IPA address space supported by KVM -- * -+ * kvm_arm_get_max_vm_ipa_size: - * @ms: Machine state handle -+ * -+ * Returns the number of bits in the IPA address space supported by KVM - */ - int kvm_arm_get_max_vm_ipa_size(MachineState *ms); - - /** -- * kvm_arm_sync_mpstate_to_kvm -+ * kvm_arm_sync_mpstate_to_kvm: - * @cpu: ARMCPU - * - * If supported set the KVM MP_STATE based on QEMU's model. -+ * -+ * Returns 0 on success and -1 on failure. - */ - int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu); - - /** -- * kvm_arm_sync_mpstate_to_qemu -+ * kvm_arm_sync_mpstate_to_qemu: - * @cpu: ARMCPU - * - * If supported get the MP_STATE from KVM and store in QEMU's model. -+ * -+ * Returns 0 on success and aborts on failure. - */ - int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu); - -@@ -241,7 +251,8 @@ int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level); - - static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) - { -- /* This should never actually be called in the "not KVM" case, -+ /* -+ * This should never actually be called in the "not KVM" case, - * but set up the fields to indicate an error anyway. - */ - cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE; -@@ -310,23 +321,20 @@ bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit); - * - * Return: TRUE if any hardware breakpoints in use. - */ -- - bool kvm_arm_hw_debug_active(CPUState *cs); - - /** - * kvm_arm_copy_hw_debug_data: -- * - * @ptr: kvm_guest_debug_arch structure - * - * Copy the architecture specific debug registers into the - * kvm_guest_debug ioctl structure. - */ - struct kvm_guest_debug_arch; -- - void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr); - - /** -- * its_class_name -+ * its_class_name: - * - * Return the ITS class name to use depending on whether KVM acceleration - * and KVM CAP_SIGNAL_MSI are supported --- -2.23.0 diff --git a/target-arm-kvm64-kvm64-cpus-have-timer-registers.patch b/target-arm-kvm64-kvm64-cpus-have-timer-registers.patch deleted file mode 100644 index b8cec1bd36e2da9526a643229252ac6760eebecf..0000000000000000000000000000000000000000 --- a/target-arm-kvm64-kvm64-cpus-have-timer-registers.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 07bd62920f968da7d1d8962cc7fd3d29652d25f4 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Tue, 21 Apr 2020 17:04:13 +0800 -Subject: [PATCH 2/4] target/arm/kvm64: kvm64 cpus have timer registers - -Add the missing GENERIC_TIMER feature to kvm64 cpus. - -We don't currently use these registers when KVM is enabled, but it's -probably best we add the feature flag for consistency and potential -future use. There's also precedent, as we add the PMU feature flag to -KVM enabled guests, even though we don't use those registers either. - -This change was originally posted as a hunk of a different, never -merged patch from Bijan Mottahedeh. - -Signed-off-by: Andrew Jones -Reviewed-by: Richard Henderson -Message-id: 20200120101023.16030-4-drjones@redhat.com -Signed-off-by: Peter Maydell ---- - target/arm/kvm64.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c -index 22d19c9a..f2f0a92e 100644 ---- a/target/arm/kvm64.c -+++ b/target/arm/kvm64.c -@@ -587,6 +587,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) - set_feature(&features, ARM_FEATURE_NEON); - set_feature(&features, ARM_FEATURE_AARCH64); - set_feature(&features, ARM_FEATURE_PMU); -+ set_feature(&features, ARM_FEATURE_GENERIC_TIMER); - - ahcf->features = features; - --- -2.23.0 diff --git a/target-arm-monitor-Introduce-qmp_query_cpu_model_exp.patch b/target-arm-monitor-Introduce-qmp_query_cpu_model_exp.patch deleted file mode 100644 index 30f14bafcc5b70310e462e9b4f5ca5cb91708cef..0000000000000000000000000000000000000000 --- a/target-arm-monitor-Introduce-qmp_query_cpu_model_exp.patch +++ /dev/null @@ -1,373 +0,0 @@ -From c527fa45dd0bb03c7f35b79ff53f127297f96314 Mon Sep 17 00:00:00 2001 -From: Andrew Jones -Date: Thu, 31 Oct 2019 15:27:26 +0100 -Subject: [PATCH 12/13] target/arm/monitor: Introduce - qmp_query_cpu_model_expansion - -Add support for the query-cpu-model-expansion QMP command to Arm. We -do this selectively, only exposing CPU properties which represent -optional CPU features which the user may want to enable/disable. -Additionally we restrict the list of queryable cpu models to 'max', -'host', or the current type when KVM is in use. And, finally, we only -implement expansion type 'full', as Arm does not yet have a "base" -CPU type. More details and example queries are described in a new -document (docs/arm-cpu-features.rst). - -Note, certainly more features may be added to the list of advertised -features, e.g. 'vfp' and 'neon'. The only requirement is that we can -detect invalid configurations and emit failures at QMP query time. -For 'vfp' and 'neon' this will require some refactoring to share a -validation function between the QMP query and the CPU realize -functions. - -Signed-off-by: Andrew Jones -Reviewed-by: Richard Henderson -Reviewed-by: Eric Auger -Reviewed-by: Beata Michalska -Message-id: 20191031142734.8590-2-drjones@redhat.com -Signed-off-by: Peter Maydell ---- - docs/arm-cpu-features.rst | 137 +++++++++++++++++++++++++++++++++++ - qapi/machine-target.json | 6 +- - target/arm/monitor.c | 145 ++++++++++++++++++++++++++++++++++++++ - 3 files changed, 285 insertions(+), 3 deletions(-) - create mode 100644 docs/arm-cpu-features.rst - -diff --git a/docs/arm-cpu-features.rst b/docs/arm-cpu-features.rst -new file mode 100644 -index 00000000..c79dcffb ---- /dev/null -+++ b/docs/arm-cpu-features.rst -@@ -0,0 +1,137 @@ -+================ -+ARM CPU Features -+================ -+ -+Examples of probing and using ARM CPU features -+ -+Introduction -+============ -+ -+CPU features are optional features that a CPU of supporting type may -+choose to implement or not. In QEMU, optional CPU features have -+corresponding boolean CPU proprieties that, when enabled, indicate -+that the feature is implemented, and, conversely, when disabled, -+indicate that it is not implemented. An example of an ARM CPU feature -+is the Performance Monitoring Unit (PMU). CPU types such as the -+Cortex-A15 and the Cortex-A57, which respectively implement ARM -+architecture reference manuals ARMv7-A and ARMv8-A, may both optionally -+implement PMUs. For example, if a user wants to use a Cortex-A15 without -+a PMU, then the `-cpu` parameter should contain `pmu=off` on the QEMU -+command line, i.e. `-cpu cortex-a15,pmu=off`. -+ -+As not all CPU types support all optional CPU features, then whether or -+not a CPU property exists depends on the CPU type. For example, CPUs -+that implement the ARMv8-A architecture reference manual may optionally -+support the AArch32 CPU feature, which may be enabled by disabling the -+`aarch64` CPU property. A CPU type such as the Cortex-A15, which does -+not implement ARMv8-A, will not have the `aarch64` CPU property. -+ -+QEMU's support may be limited for some CPU features, only partially -+supporting the feature or only supporting the feature under certain -+configurations. For example, the `aarch64` CPU feature, which, when -+disabled, enables the optional AArch32 CPU feature, is only supported -+when using the KVM accelerator and when running on a host CPU type that -+supports the feature. -+ -+CPU Feature Probing -+=================== -+ -+Determining which CPU features are available and functional for a given -+CPU type is possible with the `query-cpu-model-expansion` QMP command. -+Below are some examples where `scripts/qmp/qmp-shell` (see the top comment -+block in the script for usage) is used to issue the QMP commands. -+ -+(1) Determine which CPU features are available for the `max` CPU type -+ (Note, we started QEMU with qemu-system-aarch64, so `max` is -+ implementing the ARMv8-A reference manual in this case):: -+ -+ (QEMU) query-cpu-model-expansion type=full model={"name":"max"} -+ { "return": { -+ "model": { "name": "max", "props": { -+ "pmu": true, "aarch64": true -+ }}}} -+ -+We see that the `max` CPU type has the `pmu` and `aarch64` CPU features. -+We also see that the CPU features are enabled, as they are all `true`. -+ -+(2) Let's try to disable the PMU:: -+ -+ (QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"pmu":false}} -+ { "return": { -+ "model": { "name": "max", "props": { -+ "pmu": false, "aarch64": true -+ }}}} -+ -+We see it worked, as `pmu` is now `false`. -+ -+(3) Let's try to disable `aarch64`, which enables the AArch32 CPU feature:: -+ -+ (QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"aarch64":false}} -+ {"error": { -+ "class": "GenericError", "desc": -+ "'aarch64' feature cannot be disabled unless KVM is enabled and 32-bit EL1 is supported" -+ }} -+ -+It looks like this feature is limited to a configuration we do not -+currently have. -+ -+(4) Let's try probing CPU features for the Cortex-A15 CPU type:: -+ -+ (QEMU) query-cpu-model-expansion type=full model={"name":"cortex-a15"} -+ {"return": {"model": {"name": "cortex-a15", "props": {"pmu": true}}}} -+ -+Only the `pmu` CPU feature is available. -+ -+A note about CPU feature dependencies -+------------------------------------- -+ -+It's possible for features to have dependencies on other features. I.e. -+it may be possible to change one feature at a time without error, but -+when attempting to change all features at once an error could occur -+depending on the order they are processed. It's also possible changing -+all at once doesn't generate an error, because a feature's dependencies -+are satisfied with other features, but the same feature cannot be changed -+independently without error. For these reasons callers should always -+attempt to make their desired changes all at once in order to ensure the -+collection is valid. -+ -+A note about CPU models and KVM -+------------------------------- -+ -+Named CPU models generally do not work with KVM. There are a few cases -+that do work, e.g. using the named CPU model `cortex-a57` with KVM on a -+seattle host, but mostly if KVM is enabled the `host` CPU type must be -+used. This means the guest is provided all the same CPU features as the -+host CPU type has. And, for this reason, the `host` CPU type should -+enable all CPU features that the host has by default. Indeed it's even -+a bit strange to allow disabling CPU features that the host has when using -+the `host` CPU type, but in the absence of CPU models it's the best we can -+do if we want to launch guests without all the host's CPU features enabled. -+ -+Enabling KVM also affects the `query-cpu-model-expansion` QMP command. The -+affect is not only limited to specific features, as pointed out in example -+(3) of "CPU Feature Probing", but also to which CPU types may be expanded. -+When KVM is enabled, only the `max`, `host`, and current CPU type may be -+expanded. This restriction is necessary as it's not possible to know all -+CPU types that may work with KVM, but it does impose a small risk of users -+experiencing unexpected errors. For example on a seattle, as mentioned -+above, the `cortex-a57` CPU type is also valid when KVM is enabled. -+Therefore a user could use the `host` CPU type for the current type, but -+then attempt to query `cortex-a57`, however that query will fail with our -+restrictions. This shouldn't be an issue though as management layers and -+users have been preferring the `host` CPU type for use with KVM for quite -+some time. Additionally, if the KVM-enabled QEMU instance running on a -+seattle host is using the `cortex-a57` CPU type, then querying `cortex-a57` -+will work. -+ -+Using CPU Features -+================== -+ -+After determining which CPU features are available and supported for a -+given CPU type, then they may be selectively enabled or disabled on the -+QEMU command line with that CPU type:: -+ -+ $ qemu-system-aarch64 -M virt -cpu max,pmu=off -+ -+The example above disables the PMU for the `max` CPU type. -+ -diff --git a/qapi/machine-target.json b/qapi/machine-target.json -index 55310a6a..04623224 100644 ---- a/qapi/machine-target.json -+++ b/qapi/machine-target.json -@@ -212,7 +212,7 @@ - ## - { 'struct': 'CpuModelExpansionInfo', - 'data': { 'model': 'CpuModelInfo' }, -- 'if': 'defined(TARGET_S390X) || defined(TARGET_I386)' } -+ 'if': 'defined(TARGET_S390X) || defined(TARGET_I386) || defined(TARGET_ARM)' } - - ## - # @query-cpu-model-expansion: -@@ -237,7 +237,7 @@ - # query-cpu-model-expansion while using these is not advised. - # - # Some architectures may not support all expansion types. s390x supports --# "full" and "static". -+# "full" and "static". Arm only supports "full". - # - # Returns: a CpuModelExpansionInfo. Returns an error if expanding CPU models is - # not supported, if the model cannot be expanded, if the model contains -@@ -251,7 +251,7 @@ - 'data': { 'type': 'CpuModelExpansionType', - 'model': 'CpuModelInfo' }, - 'returns': 'CpuModelExpansionInfo', -- 'if': 'defined(TARGET_S390X) || defined(TARGET_I386)' } -+ 'if': 'defined(TARGET_S390X) || defined(TARGET_I386) || defined(TARGET_ARM)' } - - ## - # @CpuDefinitionInfo: -diff --git a/target/arm/monitor.c b/target/arm/monitor.c -index 6ec6dd04..560970de 100644 ---- a/target/arm/monitor.c -+++ b/target/arm/monitor.c -@@ -23,7 +23,14 @@ - #include "qemu/osdep.h" - #include "hw/boards.h" - #include "kvm_arm.h" -+#include "qapi/error.h" -+#include "qapi/visitor.h" -+#include "qapi/qobject-input-visitor.h" -+#include "qapi/qapi-commands-machine-target.h" - #include "qapi/qapi-commands-misc-target.h" -+#include "qapi/qmp/qerror.h" -+#include "qapi/qmp/qdict.h" -+#include "qom/qom-qobject.h" - - static GICCapability *gic_cap_new(int version) - { -@@ -82,3 +89,141 @@ GICCapabilityList *qmp_query_gic_capabilities(Error **errp) - - return head; - } -+ -+/* -+ * These are cpu model features we want to advertise. The order here -+ * matters as this is the order in which qmp_query_cpu_model_expansion -+ * will attempt to set them. If there are dependencies between features, -+ * then the order that considers those dependencies must be used. -+ */ -+static const char *cpu_model_advertised_features[] = { -+ "aarch64", "pmu", -+ NULL -+}; -+ -+CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, -+ CpuModelInfo *model, -+ Error **errp) -+{ -+ CpuModelExpansionInfo *expansion_info; -+ const QDict *qdict_in = NULL; -+ QDict *qdict_out; -+ ObjectClass *oc; -+ Object *obj; -+ const char *name; -+ int i; -+ -+ if (type != CPU_MODEL_EXPANSION_TYPE_FULL) { -+ error_setg(errp, "The requested expansion type is not supported"); -+ return NULL; -+ } -+ -+ if (!kvm_enabled() && !strcmp(model->name, "host")) { -+ error_setg(errp, "The CPU type '%s' requires KVM", model->name); -+ return NULL; -+ } -+ -+ oc = cpu_class_by_name(TYPE_ARM_CPU, model->name); -+ if (!oc) { -+ error_setg(errp, "The CPU type '%s' is not a recognized ARM CPU type", -+ model->name); -+ return NULL; -+ } -+ -+ if (kvm_enabled()) { -+ const char *cpu_type = current_machine->cpu_type; -+ int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX); -+ bool supported = false; -+ -+ if (!strcmp(model->name, "host") || !strcmp(model->name, "max")) { -+ /* These are kvmarm's recommended cpu types */ -+ supported = true; -+ } else if (strlen(model->name) == len && -+ !strncmp(model->name, cpu_type, len)) { -+ /* KVM is enabled and we're using this type, so it works. */ -+ supported = true; -+ } -+ if (!supported) { -+ error_setg(errp, "We cannot guarantee the CPU type '%s' works " -+ "with KVM on this host", model->name); -+ return NULL; -+ } -+ } -+ -+ if (model->props) { -+ qdict_in = qobject_to(QDict, model->props); -+ if (!qdict_in) { -+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); -+ return NULL; -+ } -+ } -+ -+ obj = object_new(object_class_get_name(oc)); -+ -+ if (qdict_in) { -+ Visitor *visitor; -+ Error *err = NULL; -+ -+ visitor = qobject_input_visitor_new(model->props); -+ visit_start_struct(visitor, NULL, NULL, 0, &err); -+ if (err) { -+ visit_free(visitor); -+ object_unref(obj); -+ error_propagate(errp, err); -+ return NULL; -+ } -+ -+ i = 0; -+ while ((name = cpu_model_advertised_features[i++]) != NULL) { -+ if (qdict_get(qdict_in, name)) { -+ object_property_set(obj, visitor, name, &err); -+ if (err) { -+ break; -+ } -+ } -+ } -+ -+ if (!err) { -+ visit_check_struct(visitor, &err); -+ } -+ visit_end_struct(visitor, NULL); -+ visit_free(visitor); -+ if (err) { -+ object_unref(obj); -+ error_propagate(errp, err); -+ return NULL; -+ } -+ } -+ -+ expansion_info = g_new0(CpuModelExpansionInfo, 1); -+ expansion_info->model = g_malloc0(sizeof(*expansion_info->model)); -+ expansion_info->model->name = g_strdup(model->name); -+ -+ qdict_out = qdict_new(); -+ -+ i = 0; -+ while ((name = cpu_model_advertised_features[i++]) != NULL) { -+ ObjectProperty *prop = object_property_find(obj, name, NULL); -+ if (prop) { -+ Error *err = NULL; -+ QObject *value; -+ -+ assert(prop->get); -+ value = object_property_get_qobject(obj, name, &err); -+ assert(!err); -+ -+ qdict_put_obj(qdict_out, name, value); -+ } -+ } -+ -+ if (!qdict_size(qdict_out)) { -+ qobject_unref(qdict_out); -+ } else { -+ expansion_info->model->props = QOBJECT(qdict_out); -+ expansion_info->model->has_props = true; -+ } -+ -+ object_unref(obj); -+ -+ return expansion_info; -+} --- -2.25.1 - diff --git a/target-arm-monitor-query-cpu-model-expansion-crashed.patch b/target-arm-monitor-query-cpu-model-expansion-crashed.patch deleted file mode 100644 index 60973a7c2233a8e57f23d89c69a0c3a972835e8b..0000000000000000000000000000000000000000 --- a/target-arm-monitor-query-cpu-model-expansion-crashed.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 5d75b922480f3fbefe83b5bb5e241e56a16e1e3e Mon Sep 17 00:00:00 2001 -From: Liang Yan -Date: Fri, 7 Feb 2020 14:04:21 +0000 -Subject: [PATCH 13/13] target/arm/monitor: query-cpu-model-expansion crashed - qemu when using machine type none - -Commit e19afd566781 mentioned that target-arm only supports queryable -cpu models 'max', 'host', and the current type when KVM is in use. -The logic works well until using machine type none. - -For machine type none, cpu_type will be null if cpu option is not -set by command line, strlen(cpu_type) will terminate process. -So We add a check above it. - -This won't affect i386 and s390x since they do not use current_cpu. - -Signed-off-by: Liang Yan -Message-id: 20200203134251.12986-1-lyan@suse.com -Reviewed-by: Andrew Jones -Tested-by: Andrew Jones -Signed-off-by: Peter Maydell ---- - target/arm/monitor.c | 15 +++++++++------ - 1 file changed, 9 insertions(+), 6 deletions(-) - -diff --git a/target/arm/monitor.c b/target/arm/monitor.c -index 560970de..e2b1d117 100644 ---- a/target/arm/monitor.c -+++ b/target/arm/monitor.c -@@ -131,17 +131,20 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, - } - - if (kvm_enabled()) { -- const char *cpu_type = current_machine->cpu_type; -- int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX); - bool supported = false; - - if (!strcmp(model->name, "host") || !strcmp(model->name, "max")) { - /* These are kvmarm's recommended cpu types */ - supported = true; -- } else if (strlen(model->name) == len && -- !strncmp(model->name, cpu_type, len)) { -- /* KVM is enabled and we're using this type, so it works. */ -- supported = true; -+ } else if (current_machine->cpu_type) { -+ const char *cpu_type = current_machine->cpu_type; -+ int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX); -+ -+ if (strlen(model->name) == len && -+ !strncmp(model->name, cpu_type, len)) { -+ /* KVM is enabled and we're using this type, so it works. */ -+ supported = true; -+ } - } - if (!supported) { - error_setg(errp, "We cannot guarantee the CPU type '%s' works " --- -2.25.1 - diff --git a/target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch b/target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch index 91702dbe0cbcc5fff7a113ff2b75a90026521500..a9be076ecc13826d1f57e1fcd525721cee216342 100644 --- a/target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch +++ b/target-arm-only-set-ID_PFR1_EL1.GIC-for-AArch32-gues.patch @@ -1,4 +1,4 @@ -From 88e3146118230de8b99280db219a6a6c47bebce1 Mon Sep 17 00:00:00 2001 +From 3371917ea92265377f87692a717397267416c4aa Mon Sep 17 00:00:00 2001 From: Peng Liang Date: Wed, 16 Sep 2020 19:40:28 +0800 Subject: [PATCH] target/arm: only set ID_PFR1_EL1.GIC for AArch32 guest @@ -9,17 +9,18 @@ in AArch64 mode. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun --- target/arm/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/arm/helper.c b/target/arm/helper.c -index 97b6b86197..b262f5d6c5 100644 +index 79f77705c3..4c7b4cadfa 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c -@@ -5672,7 +5672,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) +@@ -6718,7 +6718,7 @@ static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) ARMCPU *cpu = env_archcpu(env); - uint64_t pfr1 = cpu->id_pfr1; + uint64_t pfr1 = cpu->isar.regs[ID_PFR1]; - if (env->gicv3state) { + if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && env->gicv3state) { @@ -27,5 +28,5 @@ index 97b6b86197..b262f5d6c5 100644 } return pfr1; -- -2.23.0 +2.27.0 diff --git a/target-arm-parse-cpu-feature-related-options.patch b/target-arm-parse-cpu-feature-related-options.patch index 066e231af6266d21eecaf5d0c519b8a6aa4069d6..b90027bc6316da9de2144979f3af20cc6fdf7777 100644 --- a/target-arm-parse-cpu-feature-related-options.patch +++ b/target-arm-parse-cpu-feature-related-options.patch @@ -1,7 +1,7 @@ -From dca1df05ce3d6b17d03203fc6fd94e23548216c7 Mon Sep 17 00:00:00 2001 +From abd51f8d46b916efb37cb2c8face176bc83c0d5d Mon Sep 17 00:00:00 2001 From: Peng Liang Date: Thu, 6 Aug 2020 16:14:35 +0800 -Subject: [PATCH 2/9] target/arm: parse cpu feature related options +Subject: [PATCH] target/arm: parse cpu feature related options The implementation of CPUClass::parse_features only supports CPU features in "feature=value" format. However, libvirt maybe send us a @@ -14,16 +14,17 @@ X86CPUClass::parse_features. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun --- target/arm/cpu64.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c -index fe648752..7de20848 100644 +index 96a49a3158..9e5179afbe 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c -@@ -506,6 +506,88 @@ static void arm_cpu_parse_featurestr(const char *typename, char *features, - } +@@ -982,6 +982,88 @@ static gchar *aarch64_gdb_arch_name(CPUState *cs) + return g_strdup("aarch64"); } +static void @@ -111,14 +112,14 @@ index fe648752..7de20848 100644 static void aarch64_cpu_class_init(ObjectClass *oc, void *data) { CPUClass *cc = CPU_CLASS(oc); -@@ -517,6 +599,7 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data) +@@ -991,6 +1073,7 @@ static void aarch64_cpu_class_init(ObjectClass *oc, void *data) cc->gdb_num_core_regs = 34; cc->gdb_core_xml_file = "aarch64-core.xml"; cc->gdb_arch_name = aarch64_gdb_arch_name; + cc->parse_features = aarch64_cpu_parse_features; - } - static void aarch64_cpu_instance_init(Object *obj) + object_class_property_add_bool(oc, "aarch64", aarch64_cpu_get_aarch64, + aarch64_cpu_set_aarch64); -- -2.25.1 +2.27.0 diff --git a/target-arm-register-CPU-features-for-property.patch b/target-arm-register-CPU-features-for-property.patch index ea42a63ea7620fc790d01ae94590fb4336e12c32..3d60d68c8cd96cca6e8c22d212b81f2c8378a637 100644 --- a/target-arm-register-CPU-features-for-property.patch +++ b/target-arm-register-CPU-features-for-property.patch @@ -1,7 +1,7 @@ -From f169b1f76cad9f727c701df853b05ad5e8d7f927 Mon Sep 17 00:00:00 2001 +From 9fd09aabba558b39ca949ef376d05bc0779fdda6 Mon Sep 17 00:00:00 2001 From: Peng Liang Date: Thu, 6 Aug 2020 16:14:37 +0800 -Subject: [PATCH 3/9] target/arm: register CPU features for property +Subject: [PATCH] target/arm: register CPU features for property The Arm architecture specifies a number of ID registers that are characterized as comprising a set of 4-bit ID fields. Each ID field @@ -28,16 +28,17 @@ not-implemented value) to disable a CPU feature safely. Signed-off-by: zhanghailiang Signed-off-by: Peng Liang +Signed-off-by: Dongxu Sun --- target/arm/cpu.c | 343 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 343 insertions(+) diff --git a/target/arm/cpu.c b/target/arm/cpu.c -index 5bcdad0c..3f63312c 100644 +index f1ce0474a3..c081ecc12b 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c -@@ -1034,6 +1034,347 @@ static void arm_set_init_svtor(Object *obj, Visitor *v, const char *name, - visit_type_uint32(v, name, &cpu->init_svtor, errp); +@@ -1211,6 +1211,347 @@ unsigned int gt_cntfrq_period_ns(ARMCPU *cpu) + NANOSECONDS_PER_SECOND / cpu->gt_cntfrq_hz : 1; } +/** @@ -224,7 +225,7 @@ index 5bcdad0c..3f63312c 100644 + FIELD_INFO("sve", ID_AA64PFR0, SVE, false, 1, 0, false), + + FIELD_INFO("bti", ID_AA64PFR1, BT, false, 1, 0, false), -+ FIELD_INFO("sbss", ID_AA64PFR1, SBSS, false, 1, 0, false), ++ FIELD_INFO("ssbs", ID_AA64PFR1, SSBS, false, 1, 0, false), + FIELD_INFO("mte", ID_AA64PFR1, MTE, false, 1, 0, false), + FIELD_INFO("ras_frac", ID_AA64PFR1, RAS_FRAC, false, 1, 0, false), + @@ -371,12 +372,12 @@ index 5bcdad0c..3f63312c 100644 + cpu_features[i].is_32bit)) { + continue; + } -+ op = object_property_find(OBJECT(cpu), cpu_features[i].name, NULL); ++ op = object_property_find(OBJECT(cpu), cpu_features[i].name); + if (!op) { + object_property_add(OBJECT(cpu), cpu_features[i].name, "bool", + arm_cpu_get_bit_prop, + arm_cpu_set_bit_prop, -+ NULL, &cpu_features[i], &error_abort); ++ NULL, &cpu_features[i]); + } + } +} @@ -384,15 +385,15 @@ index 5bcdad0c..3f63312c 100644 void arm_cpu_post_init(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); -@@ -1150,6 +1491,8 @@ void arm_cpu_post_init(Object *obj) +@@ -1319,6 +1660,8 @@ void arm_cpu_post_init(Object *obj) - qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property, - &error_abort); -+ -+ arm_cpu_register_feature_props(cpu); - } + qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property); - static void arm_cpu_finalizefn(Object *obj) ++ arm_cpu_register_feature_props(cpu); ++ + if (arm_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER)) { + qdev_property_add_static(DEVICE(cpu), &arm_cpu_gt_cntfrq_property); + } -- -2.25.1 +2.27.0 diff --git a/target-i386-Add-Snowridge-v2-no-MPX-CPU-model.patch b/target-i386-Add-Snowridge-v2-no-MPX-CPU-model.patch deleted file mode 100644 index eedd3356bf33b6fd02950740fa81330cbbed2895..0000000000000000000000000000000000000000 --- a/target-i386-Add-Snowridge-v2-no-MPX-CPU-model.patch +++ /dev/null @@ -1,43 +0,0 @@ -From ce4bb30a650773833cd1e86afcaa30e47259085c Mon Sep 17 00:00:00 2001 -From: Xiaoyao Li -Date: Sat, 12 Oct 2019 10:47:48 +0800 -Subject: [PATCH] target/i386: Add Snowridge-v2 (no MPX) CPU model - -Add new version of Snowridge CPU model that removes MPX feature. - -MPX support is being phased out by Intel. GCC has dropped it, Linux kernel -and KVM are also going to do that in the future. - -Signed-off-by: Xiaoyao Li -Message-Id: <20191012024748.127135-1-xiaoyao.li@intel.com> -Signed-off-by: Eduardo Habkost ---- - target/i386/cpu.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index d3742ef4ac..f09612f9da 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -2668,6 +2668,18 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_6_EAX_ARAT, - .xlevel = 0x80000008, - .model_id = "Intel Atom Processor (SnowRidge)", -+ .versions = (X86CPUVersionDefinition[]) { -+ { .version = 1 }, -+ { -+ .version = 2, -+ .props = (PropValue[]) { -+ { "mpx", "off" }, -+ { "model-id", "Intel Atom Processor (Snowridge, no MPX)" }, -+ { /* end of list */ }, -+ }, -+ }, -+ { /* end of list */ }, -+ }, - }, - { - .name = "KnightsMill", --- -2.27.0 - diff --git a/target-i386-Add-missed-security-features-to-Cooperla.patch b/target-i386-Add-missed-security-features-to-Cooperla.patch deleted file mode 100644 index d17e0c00e9a638c2c1dd715a7c6f1f1eb5a14474..0000000000000000000000000000000000000000 --- a/target-i386-Add-missed-security-features-to-Cooperla.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 97d5c6c621569b011a2122423d0f630bd71de5ff Mon Sep 17 00:00:00 2001 -From: Jingyi Wang -Date: Fri, 9 Jul 2021 11:17:19 +0800 -Subject: [PATCH] target/i386: Add missed security features to Cooperlake CPU - model - -It lacks two security feature bits in MSR_IA32_ARCH_CAPABILITIES in -current Cooperlake CPU model, so add them. - -This is part of uptream commit 2dea9d9 - -Signed-off-by: Xiaoyao Li -Signed-off-by: Paolo Bonzini -Signed-off-by: Jingyi Wang ---- - target/i386/cpu.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index 5329d73316..50d6ef9de4 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -2420,7 +2420,8 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_7_0_EDX_SPEC_CTRL_SSBD | CPUID_7_0_EDX_ARCH_CAPABILITIES, - .features[FEAT_ARCH_CAPABILITIES] = - MSR_ARCH_CAP_RDCL_NO | MSR_ARCH_CAP_IBRS_ALL | -- MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY | MSR_ARCH_CAP_MDS_NO, -+ MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY | MSR_ARCH_CAP_MDS_NO | -+ MSR_ARCH_CAP_PSCHANGE_MC_NO | MSR_ARCH_CAP_TAA_NO, - .features[FEAT_7_1_EAX] = - CPUID_7_1_EAX_AVX512_BF16, - /* --- -2.27.0 - diff --git a/target-i386-Add-new-bit-definitions-of-MSR_IA32_ARCH.patch b/target-i386-Add-new-bit-definitions-of-MSR_IA32_ARCH.patch deleted file mode 100644 index 3aff7ea35f37047933f6f4464b513feaa242cf69..0000000000000000000000000000000000000000 --- a/target-i386-Add-new-bit-definitions-of-MSR_IA32_ARCH.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 05b13a8de90abc6c1cfeca8b9c436e60e6d3142e Mon Sep 17 00:00:00 2001 -From: Xiaoyao Li -Date: Wed, 25 Dec 2019 14:30:17 +0800 -Subject: [PATCH] target/i386: Add new bit definitions of - MSR_IA32_ARCH_CAPABILITIES - -The bit 6, 7 and 8 of MSR_IA32_ARCH_CAPABILITIES are recently disclosed -for some security issues. Add the definitions for them to be used by named -CPU models. - -Signed-off-by: Xiaoyao Li -Message-Id: <20191225063018.20038-2-xiaoyao.li@intel.com> -Signed-off-by: Paolo Bonzini - -Signed-off-by: Jingyi Wang ---- - target/i386/cpu.h | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - -diff --git a/target/i386/cpu.h b/target/i386/cpu.h -index 58d8c48964..7ff8ddd464 100644 ---- a/target/i386/cpu.h -+++ b/target/i386/cpu.h -@@ -743,12 +743,15 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; - #define CPUID_TOPOLOGY_LEVEL_DIE (5U << 8) - - /* MSR Feature Bits */ --#define MSR_ARCH_CAP_RDCL_NO (1U << 0) --#define MSR_ARCH_CAP_IBRS_ALL (1U << 1) --#define MSR_ARCH_CAP_RSBA (1U << 2) -+#define MSR_ARCH_CAP_RDCL_NO (1U << 0) -+#define MSR_ARCH_CAP_IBRS_ALL (1U << 1) -+#define MSR_ARCH_CAP_RSBA (1U << 2) - #define MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY (1U << 3) --#define MSR_ARCH_CAP_SSB_NO (1U << 4) --#define MSR_ARCH_CAP_MDS_NO (1U << 5) -+#define MSR_ARCH_CAP_SSB_NO (1U << 4) -+#define MSR_ARCH_CAP_MDS_NO (1U << 5) -+#define MSR_ARCH_CAP_PSCHANGE_MC_NO (1U << 6) -+#define MSR_ARCH_CAP_TSX_CTRL_MSR (1U << 7) -+#define MSR_ARCH_CAP_TAA_NO (1U << 8) - - #define MSR_CORE_CAP_SPLIT_LOCK_DETECT (1U << 5) - --- -2.27.0 - diff --git a/target-i386-Export-TAA_NO-bit-to-guests.patch b/target-i386-Export-TAA_NO-bit-to-guests.patch deleted file mode 100644 index 8d995dc840bbace44c4d59b61f70167e960e2699..0000000000000000000000000000000000000000 --- a/target-i386-Export-TAA_NO-bit-to-guests.patch +++ /dev/null @@ -1,36 +0,0 @@ -From c828229e1dc4a3d0837071db4c08f7860dc24755 Mon Sep 17 00:00:00 2001 -From: Pawan Gupta -Date: Mon, 18 Nov 2019 23:23:27 -0800 -Subject: [PATCH] target/i386: Export TAA_NO bit to guests - -TSX Async Abort (TAA) is a side channel attack on internal buffers in -some Intel processors similar to Microachitectural Data Sampling (MDS). - -Some future Intel processors will use the ARCH_CAP_TAA_NO bit in the -IA32_ARCH_CAPABILITIES MSR to report that they are not vulnerable to -TAA. Make this bit available to guests. - -Signed-off-by: Pawan Gupta -Signed-off-by: Paolo Bonzini - -Signed-off-by: Jingyi Wang ---- - 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 29836cb2a5..5af4fca350 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -1209,7 +1209,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { - .feat_names = { - "rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry", - "ssb-no", "mds-no", "pschange-mc-no", NULL, -- NULL, NULL, NULL, NULL, -+ "taa-no", NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, --- -2.27.0 - diff --git a/target-i386-Fix-the-RES-memory-inc-which-caused-by-t.patch b/target-i386-Fix-the-RES-memory-inc-which-caused-by-t.patch new file mode 100644 index 0000000000000000000000000000000000000000..ae16318772e2e2e2ff67042f20aebc4467b56c34 --- /dev/null +++ b/target-i386-Fix-the-RES-memory-inc-which-caused-by-t.patch @@ -0,0 +1,30 @@ +From 6e070be26502e171fd5d43a128dea99f1d34429b Mon Sep 17 00:00:00 2001 +From: jiangdongxu +Date: Thu, 10 Feb 2022 21:41:06 +0800 +Subject: [PATCH] target-i386: Fix the RES memory inc which caused by the + coroutine created + +for better performance, change the POOL_BATCH_SIZE from 64 to 128. + +Signed-off-by: caojinhua +Signed-off-by: jiangdongxu +--- + util/qemu-coroutine.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c +index 38fb6d3084..b9586d6929 100644 +--- a/util/qemu-coroutine.c ++++ b/util/qemu-coroutine.c +@@ -21,7 +21,7 @@ + #include "block/aio.h" + + enum { +- POOL_BATCH_SIZE = 64, ++ POOL_BATCH_SIZE = 128, + }; + + /** Free list to speed up creation */ +-- +2.27.0 + diff --git a/target-i386-Introduce-Denverton-CPU-model.patch b/target-i386-Introduce-Denverton-CPU-model.patch deleted file mode 100644 index 3e9debe339e6d1b0f7c0ca0ad019129de668363b..0000000000000000000000000000000000000000 --- a/target-i386-Introduce-Denverton-CPU-model.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 7d602cefa04f4992d913683c1a5826abc4806e41 Mon Sep 17 00:00:00 2001 -From: Tao Xu -Date: Thu, 18 Jul 2019 15:34:05 +0800 -Subject: [PATCH] target/i386: Introduce Denverton CPU model - -Denverton is the Atom Processor of Intel Harrisonville platform. - -For more information: -https://ark.intel.com/content/www/us/en/ark/products/\ -codename/63508/denverton.html - -Signed-off-by: Tao Xu -Message-Id: <20190718073405.28301-1-tao3.xu@intel.com> -Signed-off-by: Eduardo Habkost ---- - target/i386/cpu.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 47 insertions(+) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index 5af4fca350..d3742ef4ac 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -2552,6 +2552,53 @@ static X86CPUDefinition builtin_x86_defs[] = { - .xlevel = 0x80000008, - .model_id = "Intel Xeon Processor (Icelake)", - }, -+ { -+ .name = "Denverton", -+ .level = 21, -+ .vendor = CPUID_VENDOR_INTEL, -+ .family = 6, -+ .model = 95, -+ .stepping = 1, -+ .features[FEAT_1_EDX] = -+ CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | -+ CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | -+ CPUID_SEP | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | -+ CPUID_PAT | CPUID_PSE36 | CPUID_CLFLUSH | CPUID_MMX | CPUID_FXSR | -+ CPUID_SSE | CPUID_SSE2, -+ .features[FEAT_1_ECX] = -+ CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_MONITOR | -+ CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | CPUID_EXT_SSE41 | -+ CPUID_EXT_SSE42 | CPUID_EXT_X2APIC | CPUID_EXT_MOVBE | -+ CPUID_EXT_POPCNT | CPUID_EXT_TSC_DEADLINE_TIMER | -+ CPUID_EXT_AES | CPUID_EXT_XSAVE | CPUID_EXT_RDRAND, -+ .features[FEAT_8000_0001_EDX] = -+ CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | CPUID_EXT2_PDPE1GB | -+ CPUID_EXT2_RDTSCP | CPUID_EXT2_LM, -+ .features[FEAT_8000_0001_ECX] = -+ CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, -+ .features[FEAT_7_0_EBX] = -+ CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_ERMS | -+ CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_SMAP | -+ CPUID_7_0_EBX_CLFLUSHOPT | CPUID_7_0_EBX_SHA_NI, -+ .features[FEAT_7_0_EDX] = -+ CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_ARCH_CAPABILITIES | -+ CPUID_7_0_EDX_SPEC_CTRL_SSBD, -+ /* -+ * Missing: XSAVES (not supported by some Linux versions, -+ * including v4.1 to v4.12). -+ * KVM doesn't yet expose any XSAVES state save component, -+ * and the only one defined in Skylake (processor tracing) -+ * probably will block migration anyway. -+ */ -+ .features[FEAT_XSAVE] = -+ CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | CPUID_XSAVE_XGETBV1, -+ .features[FEAT_6_EAX] = -+ CPUID_6_EAX_ARAT, -+ .features[FEAT_ARCH_CAPABILITIES] = -+ MSR_ARCH_CAP_RDCL_NO | MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY, -+ .xlevel = 0x80000008, -+ .model_id = "Intel Atom Processor (Denverton)", -+ }, - { - .name = "Snowridge", - .level = 27, --- -2.27.0 - diff --git a/target-i386-Modify-the-VM-s-physical-bits-value-set-.patch b/target-i386-Modify-the-VM-s-physical-bits-value-set-.patch new file mode 100644 index 0000000000000000000000000000000000000000..2a490b614796ce0d33f645039c057ca8950187be --- /dev/null +++ b/target-i386-Modify-the-VM-s-physical-bits-value-set-.patch @@ -0,0 +1,116 @@ +From a09c3928b33b0c53831bd9eeb56f8171c26057bc Mon Sep 17 00:00:00 2001 +From: Jiajie Li +Date: Tue, 8 Feb 2022 09:46:53 +0800 +Subject: [PATCH 2/2] target-i386: Modify the VM's physical bits value set + policy. + +To resolve the problem that a VM with large memory capacity fails +to be live migrated, determine whether the VM is a large memory +capacity based on the memory size (4 TB). If yes, set the bus width +of the VM address to 46 bits. If no, set the bus width to 42 bits. + +Signed-off-by: Jinhua Cao +Signed-off-by: Jiajie Li +--- + target/i386/cpu.c | 19 ++++++++++++++++++- + target/i386/cpu.h | 6 ++++++ + target/i386/host-cpu.c | 13 +++++++------ + 3 files changed, 31 insertions(+), 7 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index aa9e636800..868cf3e7e8 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -6678,6 +6678,23 @@ static void x86_cpu_set_pc(CPUState *cs, vaddr value) + cpu->env.eip = value; + } + ++/* At present, we check the vm is *LARGE* or not, i.e. whether ++ * the memory size is more than 4T or not. ++ */ ++const uint64_t large_vm_mem_size = 0x40000000000UL; ++void x86_cpu_adjuest_by_ram_size(ram_addr_t ram_size, X86CPU *cpu) ++{ ++ /* If there is not a large vm, we set the phys_bits to 42 bits, ++ * otherwise, we increase the phys_bits to 46 bits. ++ */ ++ if (ram_size < large_vm_mem_size) { ++ cpu->phys_bits = DEFAULT_VM_CPU_PHYS_BITS; ++ } else { ++ cpu->phys_bits = LARGE_VM_CPU_PHYS_BITS; ++ cpu->fill_mtrr_mask = true; ++ } ++} ++ + int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request) + { + X86CPU *cpu = X86_CPU(cs); +@@ -6862,7 +6879,7 @@ static Property x86_cpu_properties[] = { + DEFINE_PROP_UINT32("phys-bits", X86CPU, phys_bits, 0), + DEFINE_PROP_BOOL("host-phys-bits", X86CPU, host_phys_bits, false), + DEFINE_PROP_UINT8("host-phys-bits-limit", X86CPU, host_phys_bits_limit, 0), +- DEFINE_PROP_BOOL("fill-mtrr-mask", X86CPU, fill_mtrr_mask, true), ++ DEFINE_PROP_BOOL("fill-mtrr-mask", X86CPU, fill_mtrr_mask, false), + DEFINE_PROP_UINT32("level-func7", X86CPU, env.cpuid_level_func7, + UINT32_MAX), + DEFINE_PROP_UINT32("level", X86CPU, env.cpuid_level, UINT32_MAX), +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 04f2b790c9..6f777fd6ca 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -24,6 +24,7 @@ + #include "cpu-qom.h" + #include "kvm/hyperv-proto.h" + #include "exec/cpu-defs.h" ++#include "exec/cpu-common.h" + #include "qapi/qapi-types-common.h" + + /* The x86 has a strong memory model with some store-after-load re-ordering */ +@@ -1841,6 +1842,11 @@ struct X86CPU { + extern const VMStateDescription vmstate_x86_cpu; + #endif + ++#define DEFAULT_VM_CPU_PHYS_BITS 42 ++#define LARGE_VM_CPU_PHYS_BITS 46 ++ ++void x86_cpu_adjuest_by_ram_size(ram_addr_t ram_size, X86CPU *cpu); ++ + int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request); + + int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu, +diff --git a/target/i386/host-cpu.c b/target/i386/host-cpu.c +index 10f8aba86e..5a1bbefa36 100644 +--- a/target/i386/host-cpu.c ++++ b/target/i386/host-cpu.c +@@ -12,6 +12,7 @@ + #include "host-cpu.h" + #include "qapi/error.h" + #include "sysemu/sysemu.h" ++#include "hw/boards.h" + + /* Note: Only safe for use on x86(-64) hosts */ + static uint32_t host_cpu_phys_bits(void) +@@ -56,14 +57,14 @@ static uint32_t host_cpu_adjust_phys_bits(X86CPU *cpu) + uint32_t phys_bits = cpu->phys_bits; + static bool warned; + +- /* +- * Print a warning if the user set it to a value that's not the +- * host value. +- */ +- if (phys_bits != host_phys_bits && phys_bits != 0 && ++ /* adjust x86 cpu phys_bits according to ram_size. */ ++ x86_cpu_adjuest_by_ram_size(current_machine->ram_size, cpu); ++ ++ /* Print a warning if the host value less than the user set. */ ++ if (phys_bits > host_phys_bits && phys_bits != 0 && + !warned) { + warn_report("Host physical bits (%u)" +- " does not match phys-bits property (%u)", ++ " less than phys-bits property (%u)", + host_phys_bits, phys_bits); + warned = true; + } +-- +2.27.0 + diff --git a/target-i386-add-PSCHANGE_NO-bit-for-the-ARCH_CAPABIL.patch b/target-i386-add-PSCHANGE_NO-bit-for-the-ARCH_CAPABIL.patch deleted file mode 100644 index 6cba87b020b3f5a01fbc2f74958d8e9c03a9d1a2..0000000000000000000000000000000000000000 --- a/target-i386-add-PSCHANGE_NO-bit-for-the-ARCH_CAPABIL.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 4372535d5f2f50b24d14ec8a3393aebec938fb61 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Wed, 13 Nov 2019 15:54:35 +0100 -Subject: [PATCH] target/i386: add PSCHANGE_NO bit for the ARCH_CAPABILITIES - MSR - -This is required to disable ITLB multihit mitigations in nested -hypervisors. - -Signed-off-by: Paolo Bonzini - -Signed-off-by: Jingyi Wang ---- - 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 50d6ef9de4..29836cb2a5 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -1208,7 +1208,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { - .type = MSR_FEATURE_WORD, - .feat_names = { - "rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry", -- "ssb-no", "mds-no", NULL, NULL, -+ "ssb-no", "mds-no", "pschange-mc-no", NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, --- -2.27.0 - diff --git a/target-i386-add-VMX-definitions.patch b/target-i386-add-VMX-definitions.patch deleted file mode 100644 index 4365e3a7a1082abf15b5e9c51a7c3801e27ee806..0000000000000000000000000000000000000000 --- a/target-i386-add-VMX-definitions.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 9fb16fc548fca297086be0efe20345160660f340 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 1 Jul 2019 18:24:52 +0200 -Subject: [PATCH] target/i386: add VMX definitions - -These will be used to compile the list of VMX features for named -CPU models, and/or by the code that sets up the VMX MSRs. - -Signed-off-by: Paolo Bonzini ---- - target/i386/cpu.h | 130 ++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 130 insertions(+) - -diff --git a/target/i386/cpu.h b/target/i386/cpu.h -index 9a105b2251..b4be6ffb1f 100644 ---- a/target/i386/cpu.h -+++ b/target/i386/cpu.h -@@ -452,6 +452,25 @@ typedef enum X86Seg { - #define MSR_IA32_BNDCFGS 0x00000d90 - #define MSR_IA32_XSS 0x00000da0 - -+#define MSR_IA32_VMX_BASIC 0x00000480 -+#define MSR_IA32_VMX_PINBASED_CTLS 0x00000481 -+#define MSR_IA32_VMX_PROCBASED_CTLS 0x00000482 -+#define MSR_IA32_VMX_EXIT_CTLS 0x00000483 -+#define MSR_IA32_VMX_ENTRY_CTLS 0x00000484 -+#define MSR_IA32_VMX_MISC 0x00000485 -+#define MSR_IA32_VMX_CR0_FIXED0 0x00000486 -+#define MSR_IA32_VMX_CR0_FIXED1 0x00000487 -+#define MSR_IA32_VMX_CR4_FIXED0 0x00000488 -+#define MSR_IA32_VMX_CR4_FIXED1 0x00000489 -+#define MSR_IA32_VMX_VMCS_ENUM 0x0000048a -+#define MSR_IA32_VMX_PROCBASED_CTLS2 0x0000048b -+#define MSR_IA32_VMX_EPT_VPID_CAP 0x0000048c -+#define MSR_IA32_VMX_TRUE_PINBASED_CTLS 0x0000048d -+#define MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x0000048e -+#define MSR_IA32_VMX_TRUE_EXIT_CTLS 0x0000048f -+#define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x00000490 -+#define MSR_IA32_VMX_VMFUNC 0x00000491 -+ - #define XSTATE_FP_BIT 0 - #define XSTATE_SSE_BIT 1 - #define XSTATE_YMM_BIT 2 -@@ -757,6 +776,117 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; - - #define MSR_CORE_CAP_SPLIT_LOCK_DETECT (1U << 5) - -+/* VMX MSR features */ -+#define MSR_VMX_BASIC_VMCS_REVISION_MASK 0x7FFFFFFFull -+#define MSR_VMX_BASIC_VMXON_REGION_SIZE_MASK (0x00001FFFull << 32) -+#define MSR_VMX_BASIC_VMCS_MEM_TYPE_MASK (0x003C0000ull << 32) -+#define MSR_VMX_BASIC_DUAL_MONITOR (1ULL << 49) -+#define MSR_VMX_BASIC_INS_OUTS (1ULL << 54) -+#define MSR_VMX_BASIC_TRUE_CTLS (1ULL << 55) -+ -+#define MSR_VMX_MISC_PREEMPTION_TIMER_SHIFT_MASK 0x1Full -+#define MSR_VMX_MISC_STORE_LMA (1ULL << 5) -+#define MSR_VMX_MISC_ACTIVITY_HLT (1ULL << 6) -+#define MSR_VMX_MISC_ACTIVITY_SHUTDOWN (1ULL << 7) -+#define MSR_VMX_MISC_ACTIVITY_WAIT_SIPI (1ULL << 8) -+#define MSR_VMX_MISC_MAX_MSR_LIST_SIZE_MASK 0x0E000000ull -+#define MSR_VMX_MISC_VMWRITE_VMEXIT (1ULL << 29) -+#define MSR_VMX_MISC_ZERO_LEN_INJECT (1ULL << 30) -+ -+#define MSR_VMX_EPT_EXECONLY (1ULL << 0) -+#define MSR_VMX_EPT_PAGE_WALK_LENGTH_4 (1ULL << 6) -+#define MSR_VMX_EPT_PAGE_WALK_LENGTH_5 (1ULL << 7) -+#define MSR_VMX_EPT_UC (1ULL << 8) -+#define MSR_VMX_EPT_WB (1ULL << 14) -+#define MSR_VMX_EPT_2MB (1ULL << 16) -+#define MSR_VMX_EPT_1GB (1ULL << 17) -+#define MSR_VMX_EPT_INVEPT (1ULL << 20) -+#define MSR_VMX_EPT_AD_BITS (1ULL << 21) -+#define MSR_VMX_EPT_ADVANCED_VMEXIT_INFO (1ULL << 22) -+#define MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT (1ULL << 25) -+#define MSR_VMX_EPT_INVEPT_ALL_CONTEXT (1ULL << 26) -+#define MSR_VMX_EPT_INVVPID (1ULL << 32) -+#define MSR_VMX_EPT_INVVPID_SINGLE_ADDR (1ULL << 40) -+#define MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT (1ULL << 41) -+#define MSR_VMX_EPT_INVVPID_ALL_CONTEXT (1ULL << 42) -+#define MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS (1ULL << 43) -+ -+#define MSR_VMX_VMFUNC_EPT_SWITCHING (1ULL << 0) -+ -+ -+/* VMX controls */ -+#define VMX_CPU_BASED_VIRTUAL_INTR_PENDING 0x00000004 -+#define VMX_CPU_BASED_USE_TSC_OFFSETING 0x00000008 -+#define VMX_CPU_BASED_HLT_EXITING 0x00000080 -+#define VMX_CPU_BASED_INVLPG_EXITING 0x00000200 -+#define VMX_CPU_BASED_MWAIT_EXITING 0x00000400 -+#define VMX_CPU_BASED_RDPMC_EXITING 0x00000800 -+#define VMX_CPU_BASED_RDTSC_EXITING 0x00001000 -+#define VMX_CPU_BASED_CR3_LOAD_EXITING 0x00008000 -+#define VMX_CPU_BASED_CR3_STORE_EXITING 0x00010000 -+#define VMX_CPU_BASED_CR8_LOAD_EXITING 0x00080000 -+#define VMX_CPU_BASED_CR8_STORE_EXITING 0x00100000 -+#define VMX_CPU_BASED_TPR_SHADOW 0x00200000 -+#define VMX_CPU_BASED_VIRTUAL_NMI_PENDING 0x00400000 -+#define VMX_CPU_BASED_MOV_DR_EXITING 0x00800000 -+#define VMX_CPU_BASED_UNCOND_IO_EXITING 0x01000000 -+#define VMX_CPU_BASED_USE_IO_BITMAPS 0x02000000 -+#define VMX_CPU_BASED_MONITOR_TRAP_FLAG 0x08000000 -+#define VMX_CPU_BASED_USE_MSR_BITMAPS 0x10000000 -+#define VMX_CPU_BASED_MONITOR_EXITING 0x20000000 -+#define VMX_CPU_BASED_PAUSE_EXITING 0x40000000 -+#define VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS 0x80000000 -+ -+#define VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001 -+#define VMX_SECONDARY_EXEC_ENABLE_EPT 0x00000002 -+#define VMX_SECONDARY_EXEC_DESC 0x00000004 -+#define VMX_SECONDARY_EXEC_RDTSCP 0x00000008 -+#define VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE 0x00000010 -+#define VMX_SECONDARY_EXEC_ENABLE_VPID 0x00000020 -+#define VMX_SECONDARY_EXEC_WBINVD_EXITING 0x00000040 -+#define VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080 -+#define VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT 0x00000100 -+#define VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY 0x00000200 -+#define VMX_SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400 -+#define VMX_SECONDARY_EXEC_RDRAND_EXITING 0x00000800 -+#define VMX_SECONDARY_EXEC_ENABLE_INVPCID 0x00001000 -+#define VMX_SECONDARY_EXEC_ENABLE_VMFUNC 0x00002000 -+#define VMX_SECONDARY_EXEC_SHADOW_VMCS 0x00004000 -+#define VMX_SECONDARY_EXEC_ENCLS_EXITING 0x00008000 -+#define VMX_SECONDARY_EXEC_RDSEED_EXITING 0x00010000 -+#define VMX_SECONDARY_EXEC_ENABLE_PML 0x00020000 -+#define VMX_SECONDARY_EXEC_XSAVES 0x00100000 -+ -+#define VMX_PIN_BASED_EXT_INTR_MASK 0x00000001 -+#define VMX_PIN_BASED_NMI_EXITING 0x00000008 -+#define VMX_PIN_BASED_VIRTUAL_NMIS 0x00000020 -+#define VMX_PIN_BASED_VMX_PREEMPTION_TIMER 0x00000040 -+#define VMX_PIN_BASED_POSTED_INTR 0x00000080 -+ -+#define VMX_VM_EXIT_SAVE_DEBUG_CONTROLS 0x00000004 -+#define VMX_VM_EXIT_HOST_ADDR_SPACE_SIZE 0x00000200 -+#define VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL 0x00001000 -+#define VMX_VM_EXIT_ACK_INTR_ON_EXIT 0x00008000 -+#define VMX_VM_EXIT_SAVE_IA32_PAT 0x00040000 -+#define VMX_VM_EXIT_LOAD_IA32_PAT 0x00080000 -+#define VMX_VM_EXIT_SAVE_IA32_EFER 0x00100000 -+#define VMX_VM_EXIT_LOAD_IA32_EFER 0x00200000 -+#define VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER 0x00400000 -+#define VMX_VM_EXIT_CLEAR_BNDCFGS 0x00800000 -+#define VMX_VM_EXIT_PT_CONCEAL_PIP 0x01000000 -+#define VMX_VM_EXIT_CLEAR_IA32_RTIT_CTL 0x02000000 -+ -+#define VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS 0x00000004 -+#define VMX_VM_ENTRY_IA32E_MODE 0x00000200 -+#define VMX_VM_ENTRY_SMM 0x00000400 -+#define VMX_VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800 -+#define VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL 0x00002000 -+#define VMX_VM_ENTRY_LOAD_IA32_PAT 0x00004000 -+#define VMX_VM_ENTRY_LOAD_IA32_EFER 0x00008000 -+#define VMX_VM_ENTRY_LOAD_BNDCFGS 0x00010000 -+#define VMX_VM_ENTRY_PT_CONCEAL_PIP 0x00020000 -+#define VMX_VM_ENTRY_LOAD_IA32_RTIT_CTL 0x00040000 -+ - /* Supported Hyper-V Enlightenments */ - #define HYPERV_FEAT_RELAXED 0 - #define HYPERV_FEAT_VAPIC 1 --- -2.27.0 - diff --git a/target-i386-add-VMX-features-to-named-CPU-models.patch b/target-i386-add-VMX-features-to-named-CPU-models.patch deleted file mode 100644 index ab42b83785e5e5fd463f64415611b98ebe06066b..0000000000000000000000000000000000000000 --- a/target-i386-add-VMX-features-to-named-CPU-models.patch +++ /dev/null @@ -1,980 +0,0 @@ -From 5a63a16d709c89b25a0a9c3c7fdf765f26dac312 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Wed, 20 Nov 2019 18:37:53 +0100 -Subject: [PATCH] target/i386: add VMX features to named CPU models - -This allows using "-cpu Haswell,+vmx", which we did not really want to -support in QEMU but was produced by Libvirt when using the "host-model" -CPU model. Without this patch, no VMX feature is _actually_ supported -(only the basic instruction set extensions are) and KVM fails to load -in the guest. - -This was produced from the output of scripts/kvm/vmxcap using the following -very ugly Python script: - - bits = { - 'INS/OUTS instruction information': ['FEAT_VMX_BASIC', 'MSR_VMX_BASIC_INS_OUTS'], - 'IA32_VMX_TRUE_*_CTLS support': ['FEAT_VMX_BASIC', 'MSR_VMX_BASIC_TRUE_CTLS'], - 'External interrupt exiting': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_EXT_INTR_MASK'], - 'NMI exiting': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_NMI_EXITING'], - 'Virtual NMIs': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_VIRTUAL_NMIS'], - 'Activate VMX-preemption timer': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_VMX_PREEMPTION_TIMER'], - 'Process posted interrupts': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_POSTED_INTR'], - 'Interrupt window exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_VIRTUAL_INTR_PENDING'], - 'Use TSC offsetting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_USE_TSC_OFFSETING'], - 'HLT exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_HLT_EXITING'], - 'INVLPG exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_INVLPG_EXITING'], - 'MWAIT exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_MWAIT_EXITING'], - 'RDPMC exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_RDPMC_EXITING'], - 'RDTSC exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_RDTSC_EXITING'], - 'CR3-load exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_CR3_LOAD_EXITING'], - 'CR3-store exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_CR3_STORE_EXITING'], - 'CR8-load exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_CR8_LOAD_EXITING'], - 'CR8-store exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_CR8_STORE_EXITING'], - 'Use TPR shadow': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_TPR_SHADOW'], - 'NMI-window exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_VIRTUAL_NMI_PENDING'], - 'MOV-DR exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_MOV_DR_EXITING'], - 'Unconditional I/O exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_UNCOND_IO_EXITING'], - 'Use I/O bitmaps': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_USE_IO_BITMAPS'], - 'Monitor trap flag': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_MONITOR_TRAP_FLAG'], - 'Use MSR bitmaps': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_USE_MSR_BITMAPS'], - 'MONITOR exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_MONITOR_EXITING'], - 'PAUSE exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_PAUSE_EXITING'], - 'Activate secondary control': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS'], - 'Virtualize APIC accesses': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES'], - 'Enable EPT': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_EPT'], - 'Descriptor-table exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_DESC'], - 'Enable RDTSCP': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_RDTSCP'], - 'Virtualize x2APIC mode': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE'], - 'Enable VPID': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_VPID'], - 'WBINVD exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_WBINVD_EXITING'], - 'Unrestricted guest': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST'], - 'APIC register emulation': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT'], - 'Virtual interrupt delivery': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY'], - 'PAUSE-loop exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_PAUSE_LOOP_EXITING'], - 'RDRAND exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_RDRAND_EXITING'], - 'Enable INVPCID': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_INVPCID'], - 'Enable VM functions': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_VMFUNC'], - 'VMCS shadowing': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_SHADOW_VMCS'], - 'RDSEED exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_RDSEED_EXITING'], - 'Enable PML': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_PML'], - 'Enable XSAVES/XRSTORS': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_XSAVES'], - 'Save debug controls': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_SAVE_DEBUG_CONTROLS'], - 'Load IA32_PERF_GLOBAL_CTRL': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL'], - 'Acknowledge interrupt on exit': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_ACK_INTR_ON_EXIT'], - 'Save IA32_PAT': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_SAVE_IA32_PAT'], - 'Load IA32_PAT': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_LOAD_IA32_PAT'], - 'Save IA32_EFER': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_SAVE_IA32_EFER'], - 'Load IA32_EFER': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_LOAD_IA32_EFER'], - 'Save VMX-preemption timer value': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER'], - 'Clear IA32_BNDCFGS': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_CLEAR_BNDCFGS'], - 'Load debug controls': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS'], - 'IA-32e mode guest': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_IA32E_MODE'], - 'Load IA32_PERF_GLOBAL_CTRL': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL'], - 'Load IA32_PAT': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_IA32_PAT'], - 'Load IA32_EFER': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_IA32_EFER'], - 'Load IA32_BNDCFGS': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_BNDCFGS'], - 'Store EFER.LMA into IA-32e mode guest control': ['FEAT_VMX_MISC', 'MSR_VMX_MISC_STORE_LMA'], - 'HLT activity state': ['FEAT_VMX_MISC', 'MSR_VMX_MISC_ACTIVITY_HLT'], - 'VMWRITE to VM-exit information fields': ['FEAT_VMX_MISC', 'MSR_VMX_MISC_VMWRITE_VMEXIT'], - 'Inject event with insn length=0': ['FEAT_VMX_MISC', 'MSR_VMX_MISC_ZERO_LEN_INJECT'], - 'Execute-only EPT translations': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_EXECONLY'], - 'Page-walk length 4': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_PAGE_WALK_LENGTH_4'], - 'Paging-structure memory type WB': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_WB'], - '2MB EPT pages': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_2MB | MSR_VMX_EPT_1GB'], - 'INVEPT supported': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVEPT'], - 'EPT accessed and dirty flags': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_AD_BITS'], - 'Single-context INVEPT': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT'], - 'All-context INVEPT': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVEPT_ALL_CONTEXT'], - 'INVVPID supported': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID'], - 'Individual-address INVVPID': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID_SINGLE_ADDR'], - 'Single-context INVVPID': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT'], - 'All-context INVVPID': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID_ALL_CONTEXT'], - 'Single-context-retaining-globals INVVPID': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS'], - 'EPTP Switching': ['FEAT_VMX_VMFUNC', 'MSR_VMX_VMFUNC_EPT_SWITCHING'] - } - - import sys - import textwrap - - out = {} - for l in sys.stdin.readlines(): - l = l.rstrip() - if l.endswith('!!'): - l = l[:-2].rstrip() - if l.startswith(' ') and (l.endswith('default') or l.endswith('yes')): - l = l[4:] - for key, value in bits.items(): - if l.startswith(key): - ctl, bit = value - if ctl in out: - out[ctl] = out[ctl] + ' | ' - else: - out[ctl] = ' [%s] = ' % ctl - out[ctl] = out[ctl] + bit - - for x in sorted(out.keys()): - print("\n ".join(textwrap.wrap(out[x] + ","))) - -Note that the script has a bug in that some keys apply to both VM entry -and VM exit controls ("load IA32_PERF_GLOBAL_CTRL", "load IA32_EFER", -"load IA32_PAT". Those have to be fixed by hand. - -Reviewed-by: Eduardo Habkost -Signed-off-by: Paolo Bonzini ---- - target/i386/cpu.c | 705 ++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 705 insertions(+) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index fd248a78db..2f32d67aa5 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -1799,6 +1799,34 @@ static CPUCaches epyc_cache_info = { - }, - }; - -+/* The following VMX features are not supported by KVM and are left out in the -+ * CPU definitions: -+ * -+ * Dual-monitor support (all processors) -+ * Entry to SMM -+ * Deactivate dual-monitor treatment -+ * Number of CR3-target values -+ * Shutdown activity state -+ * Wait-for-SIPI activity state -+ * PAUSE-loop exiting (Westmere and newer) -+ * EPT-violation #VE (Broadwell and newer) -+ * Inject event with insn length=0 (Skylake and newer) -+ * Conceal non-root operation from PT -+ * Conceal VM exits from PT -+ * Conceal VM entries from PT -+ * Enable ENCLS exiting -+ * Mode-based execute control (XS/XU) -+ s TSC scaling (Skylake Server and newer) -+ * GPA translation for PT (IceLake and newer) -+ * User wait and pause -+ * ENCLV exiting -+ * Load IA32_RTIT_CTL -+ * Clear IA32_RTIT_CTL -+ * Advanced VM-exit information for EPT violations -+ * Sub-page write permissions -+ * PT in VMX operation -+ */ -+ - static X86CPUDefinition builtin_x86_defs[] = { - { - .name = "qemu64", -@@ -1873,6 +1901,24 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_LAHF_LM, -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, -+ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES, - .xlevel = 0x80000008, - .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz", - }, -@@ -1900,6 +1946,20 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */ - .features[FEAT_8000_0001_ECX] = - 0, -+ /* VMX features from Cedar Mill/Prescott */ -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, -+ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING, - .xlevel = 0x80000008, - .model_id = "Common KVM processor" - }, -@@ -1931,6 +1991,19 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_EXT_SSE3, - .features[FEAT_8000_0001_ECX] = - 0, -+ /* VMX features from Yonah */ -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, -+ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_MOV_DR_EXITING | VMX_CPU_BASED_UNCOND_IO_EXITING | -+ VMX_CPU_BASED_USE_IO_BITMAPS | VMX_CPU_BASED_MONITOR_EXITING | -+ VMX_CPU_BASED_PAUSE_EXITING | VMX_CPU_BASED_USE_MSR_BITMAPS, - .xlevel = 0x80000008, - .model_id = "Common 32-bit KVM processor" - }, -@@ -1952,6 +2025,18 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_EXT_SSE3 | CPUID_EXT_MONITOR, - .features[FEAT_8000_0001_EDX] = - CPUID_EXT2_NX, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, -+ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_MOV_DR_EXITING | VMX_CPU_BASED_UNCOND_IO_EXITING | -+ VMX_CPU_BASED_USE_IO_BITMAPS | VMX_CPU_BASED_MONITOR_EXITING | -+ VMX_CPU_BASED_PAUSE_EXITING | VMX_CPU_BASED_USE_MSR_BITMAPS, - .xlevel = 0x80000008, - .model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz", - }, -@@ -2062,6 +2147,24 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_LAHF_LM, -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, -+ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES, - .xlevel = 0x80000008, - .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)", - }, -@@ -2085,6 +2188,27 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_LAHF_LM, -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | -+ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL, -+ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT | -+ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | -+ VMX_SECONDARY_EXEC_WBINVD_EXITING, - .xlevel = 0x80000008, - .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)", - }, -@@ -2108,6 +2232,46 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, - .features[FEAT_8000_0001_ECX] = - CPUID_EXT3_LAHF_LM, -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | -+ MSR_VMX_BASIC_TRUE_CTLS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | -+ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | -+ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, -+ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | -+ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | -+ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | -+ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, -+ .features[FEAT_VMX_EXIT_CTLS] = -+ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | -+ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | -+ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | -+ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | -+ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | -+ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | -+ VMX_CPU_BASED_MONITOR_TRAP_FLAG | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | -+ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | -+ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | -+ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | -+ VMX_SECONDARY_EXEC_ENABLE_VPID, - .xlevel = 0x80000008, - .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)", - .versions = (X86CPUVersionDefinition[]) { -@@ -2148,6 +2312,47 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_EXT3_LAHF_LM, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | -+ MSR_VMX_BASIC_TRUE_CTLS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | -+ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | -+ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, -+ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | -+ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | -+ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | -+ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, -+ .features[FEAT_VMX_EXIT_CTLS] = -+ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | -+ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | -+ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | -+ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | -+ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | -+ MSR_VMX_MISC_STORE_LMA, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | -+ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | -+ VMX_CPU_BASED_MONITOR_TRAP_FLAG | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | -+ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | -+ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | -+ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | -+ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST, - .xlevel = 0x80000008, - .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)", - .versions = (X86CPUVersionDefinition[]) { -@@ -2193,6 +2398,47 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_XSAVE_XSAVEOPT, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | -+ MSR_VMX_BASIC_TRUE_CTLS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | -+ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | -+ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, -+ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | -+ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | -+ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | -+ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, -+ .features[FEAT_VMX_EXIT_CTLS] = -+ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | -+ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | -+ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | -+ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | -+ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | -+ MSR_VMX_MISC_STORE_LMA, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | -+ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | -+ VMX_CPU_BASED_MONITOR_TRAP_FLAG | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | -+ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | -+ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | -+ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | -+ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST, - .xlevel = 0x80000008, - .model_id = "Intel Xeon E312xx (Sandy Bridge)", - .versions = (X86CPUVersionDefinition[]) { -@@ -2241,6 +2487,50 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_XSAVE_XSAVEOPT, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | -+ MSR_VMX_BASIC_TRUE_CTLS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | -+ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | -+ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, -+ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | -+ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | -+ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | -+ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, -+ .features[FEAT_VMX_EXIT_CTLS] = -+ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | -+ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | -+ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | -+ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | -+ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | -+ MSR_VMX_MISC_STORE_LMA, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | -+ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | -+ VMX_CPU_BASED_MONITOR_TRAP_FLAG | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | -+ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | -+ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | -+ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | -+ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | -+ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | -+ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | -+ VMX_SECONDARY_EXEC_RDRAND_EXITING, - .xlevel = 0x80000008, - .model_id = "Intel Xeon E3-12xx v2 (Ivy Bridge)", - .versions = (X86CPUVersionDefinition[]) { -@@ -2292,6 +2582,52 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_XSAVE_XSAVEOPT, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | -+ MSR_VMX_BASIC_TRUE_CTLS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | -+ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | -+ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, -+ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | -+ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | -+ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | -+ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, -+ .features[FEAT_VMX_EXIT_CTLS] = -+ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | -+ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | -+ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | -+ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | -+ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | -+ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | -+ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | -+ VMX_CPU_BASED_MONITOR_TRAP_FLAG | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | -+ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | -+ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | -+ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | -+ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | -+ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | -+ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | -+ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | -+ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, -+ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, - .xlevel = 0x80000008, - .model_id = "Intel Core Processor (Haswell)", - .versions = (X86CPUVersionDefinition[]) { -@@ -2376,6 +2712,53 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_XSAVE_XSAVEOPT, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | -+ MSR_VMX_BASIC_TRUE_CTLS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | -+ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | -+ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, -+ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | -+ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | -+ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | -+ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, -+ .features[FEAT_VMX_EXIT_CTLS] = -+ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | -+ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | -+ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | -+ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | -+ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | -+ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | -+ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | -+ VMX_CPU_BASED_MONITOR_TRAP_FLAG | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | -+ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | -+ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | -+ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | -+ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | -+ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | -+ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | -+ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | -+ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | -+ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, -+ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, - .xlevel = 0x80000008, - .model_id = "Intel Core Processor (Broadwell)", - .versions = (X86CPUVersionDefinition[]) { -@@ -2460,6 +2843,51 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_XSAVE_XGETBV1, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, -+ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | -+ MSR_VMX_BASIC_TRUE_CTLS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | -+ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | -+ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, -+ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | -+ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | -+ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | -+ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, -+ .features[FEAT_VMX_EXIT_CTLS] = -+ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | -+ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | -+ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | -+ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | -+ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | -+ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | -+ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | -+ VMX_CPU_BASED_MONITOR_TRAP_FLAG | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | -+ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | -+ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | -+ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | -+ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | -+ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | -+ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, -+ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, - .xlevel = 0x80000008, - .model_id = "Intel Core Processor (Skylake)", - .versions = (X86CPUVersionDefinition[]) { -@@ -2524,6 +2952,52 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_XSAVE_XGETBV1, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, -+ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | -+ MSR_VMX_BASIC_TRUE_CTLS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | -+ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | -+ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, -+ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | -+ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | -+ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | -+ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, -+ .features[FEAT_VMX_EXIT_CTLS] = -+ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | -+ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | -+ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | -+ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | -+ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | -+ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | -+ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | -+ VMX_CPU_BASED_MONITOR_TRAP_FLAG | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | -+ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | -+ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | -+ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | -+ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | -+ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | -+ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | -+ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | -+ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, - .xlevel = 0x80000008, - .model_id = "Intel Xeon Processor (Skylake)", - .versions = (X86CPUVersionDefinition[]) { -@@ -2594,6 +3068,52 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_XSAVE_XGETBV1, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, -+ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | -+ MSR_VMX_BASIC_TRUE_CTLS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | -+ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | -+ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, -+ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | -+ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | -+ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | -+ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, -+ .features[FEAT_VMX_EXIT_CTLS] = -+ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | -+ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | -+ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | -+ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | -+ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | -+ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | -+ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | -+ VMX_CPU_BASED_MONITOR_TRAP_FLAG | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | -+ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | -+ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | -+ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | -+ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | -+ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | -+ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | -+ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | -+ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, - .xlevel = 0x80000008, - .model_id = "Intel Xeon Processor (Cascadelake)", - .versions = (X86CPUVersionDefinition[]) { -@@ -2724,6 +3244,51 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_XSAVE_XGETBV1, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, -+ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | -+ MSR_VMX_BASIC_TRUE_CTLS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | -+ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | -+ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, -+ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | -+ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | -+ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | -+ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, -+ .features[FEAT_VMX_EXIT_CTLS] = -+ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | -+ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | -+ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | -+ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | -+ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | -+ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | -+ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | -+ VMX_CPU_BASED_MONITOR_TRAP_FLAG | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | -+ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | -+ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | -+ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | -+ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | -+ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | -+ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, -+ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, - .xlevel = 0x80000008, - .model_id = "Intel Core Processor (Icelake)", - }, -@@ -2782,6 +3347,52 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_XSAVE_XGETBV1, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, -+ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | -+ MSR_VMX_BASIC_TRUE_CTLS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | -+ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | -+ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, -+ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | -+ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | -+ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | -+ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, -+ .features[FEAT_VMX_EXIT_CTLS] = -+ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | -+ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | -+ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | -+ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | -+ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | -+ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | -+ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | -+ VMX_CPU_BASED_MONITOR_TRAP_FLAG | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | -+ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | -+ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | -+ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | -+ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | -+ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | -+ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | -+ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | -+ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, - .xlevel = 0x80000008, - .model_id = "Intel Xeon Processor (Icelake)", - }, -@@ -2829,6 +3440,53 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_6_EAX_ARAT, - .features[FEAT_ARCH_CAPABILITIES] = - MSR_ARCH_CAP_RDCL_NO | MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY, -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | -+ MSR_VMX_BASIC_TRUE_CTLS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | -+ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | -+ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, -+ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | -+ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | -+ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | -+ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, -+ .features[FEAT_VMX_EXIT_CTLS] = -+ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | -+ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | -+ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | -+ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | -+ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | -+ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | -+ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | -+ VMX_CPU_BASED_MONITOR_TRAP_FLAG | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | -+ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | -+ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | -+ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | -+ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | -+ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | -+ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | -+ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | -+ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | -+ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, -+ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, - .xlevel = 0x80000008, - .model_id = "Intel Atom Processor (Denverton)", - }, -@@ -2899,6 +3557,53 @@ static X86CPUDefinition builtin_x86_defs[] = { - CPUID_XSAVE_XGETBV1, - .features[FEAT_6_EAX] = - CPUID_6_EAX_ARAT, -+ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | -+ MSR_VMX_BASIC_TRUE_CTLS, -+ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | -+ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | -+ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, -+ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | -+ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | -+ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | -+ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | -+ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, -+ .features[FEAT_VMX_EXIT_CTLS] = -+ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | -+ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | -+ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | -+ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | -+ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, -+ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | -+ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, -+ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | -+ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | -+ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, -+ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | -+ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | -+ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | -+ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | -+ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | -+ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | -+ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | -+ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | -+ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | -+ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | -+ VMX_CPU_BASED_MONITOR_TRAP_FLAG | -+ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, -+ .features[FEAT_VMX_SECONDARY_CTLS] = -+ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | -+ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | -+ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | -+ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | -+ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | -+ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | -+ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | -+ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | -+ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | -+ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, -+ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, - .xlevel = 0x80000008, - .model_id = "Intel Atom Processor (SnowRidge)", - .versions = (X86CPUVersionDefinition[]) { --- -2.27.0 - diff --git a/target-i386-add-VMX-features.patch b/target-i386-add-VMX-features.patch deleted file mode 100644 index 50457d7f2125e4db535a18c4798e6bab48d68393..0000000000000000000000000000000000000000 --- a/target-i386-add-VMX-features.patch +++ /dev/null @@ -1,492 +0,0 @@ -From 290ed17e639a67a9faf4a18b1b5973f9535bace4 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 1 Jul 2019 18:32:17 +0200 -Subject: [PATCH] target/i386: add VMX features - -Add code to convert the VMX feature words back into MSR values, -allowing the user to enable/disable VMX features as they wish. The same -infrastructure enables support for limiting VMX features in named -CPU models. - -Signed-off-by: Paolo Bonzini ---- - target/i386/cpu.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++ - target/i386/cpu.h | 9 ++ - target/i386/kvm.c | 162 ++++++++++++++++++++++++++++++++- - 3 files changed, 394 insertions(+), 2 deletions(-) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index 3d6541c4a8..fd248a78db 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -1232,6 +1232,163 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { - .index = MSR_IA32_CORE_CAPABILITY, - }, - }, -+ -+ [FEAT_VMX_PROCBASED_CTLS] = { -+ .type = MSR_FEATURE_WORD, -+ .feat_names = { -+ NULL, NULL, "vmx-vintr-pending", "vmx-tsc-offset", -+ NULL, NULL, NULL, "vmx-hlt-exit", -+ NULL, "vmx-invlpg-exit", "vmx-mwait-exit", "vmx-rdpmc-exit", -+ "vmx-rdtsc-exit", NULL, NULL, "vmx-cr3-load-noexit", -+ "vmx-cr3-store-noexit", NULL, NULL, "vmx-cr8-load-exit", -+ "vmx-cr8-store-exit", "vmx-flexpriority", "vmx-vnmi-pending", "vmx-movdr-exit", -+ "vmx-io-exit", "vmx-io-bitmap", NULL, "vmx-mtf", -+ "vmx-msr-bitmap", "vmx-monitor-exit", "vmx-pause-exit", "vmx-secondary-ctls", -+ }, -+ .msr = { -+ .index = MSR_IA32_VMX_TRUE_PROCBASED_CTLS, -+ } -+ }, -+ -+ [FEAT_VMX_SECONDARY_CTLS] = { -+ .type = MSR_FEATURE_WORD, -+ .feat_names = { -+ "vmx-apicv-xapic", "vmx-ept", "vmx-desc-exit", "vmx-rdtscp-exit", -+ "vmx-apicv-x2apic", "vmx-vpid", "vmx-wbinvd-exit", "vmx-unrestricted-guest", -+ "vmx-apicv-register", "vmx-apicv-vid", "vmx-ple", "vmx-rdrand-exit", -+ "vmx-invpcid-exit", "vmx-vmfunc", "vmx-shadow-vmcs", "vmx-encls-exit", -+ "vmx-rdseed-exit", "vmx-pml", NULL, NULL, -+ "vmx-xsaves", NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ }, -+ .msr = { -+ .index = MSR_IA32_VMX_PROCBASED_CTLS2, -+ } -+ }, -+ -+ [FEAT_VMX_PINBASED_CTLS] = { -+ .type = MSR_FEATURE_WORD, -+ .feat_names = { -+ "vmx-intr-exit", NULL, NULL, "vmx-nmi-exit", -+ NULL, "vmx-vnmi", "vmx-preemption-timer", "vmx-posted-intr", -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ }, -+ .msr = { -+ .index = MSR_IA32_VMX_TRUE_PINBASED_CTLS, -+ } -+ }, -+ -+ [FEAT_VMX_EXIT_CTLS] = { -+ .type = MSR_FEATURE_WORD, -+ /* -+ * VMX_VM_EXIT_HOST_ADDR_SPACE_SIZE is copied from -+ * the LM CPUID bit. -+ */ -+ .feat_names = { -+ NULL, NULL, "vmx-exit-nosave-debugctl", NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL /* vmx-exit-host-addr-space-size */, NULL, NULL, -+ "vmx-exit-load-perf-global-ctrl", NULL, NULL, "vmx-exit-ack-intr", -+ NULL, NULL, "vmx-exit-save-pat", "vmx-exit-load-pat", -+ "vmx-exit-save-efer", "vmx-exit-load-efer", -+ "vmx-exit-save-preemption-timer", "vmx-exit-clear-bndcfgs", -+ NULL, "vmx-exit-clear-rtit-ctl", NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ }, -+ .msr = { -+ .index = MSR_IA32_VMX_TRUE_EXIT_CTLS, -+ } -+ }, -+ -+ [FEAT_VMX_ENTRY_CTLS] = { -+ .type = MSR_FEATURE_WORD, -+ .feat_names = { -+ NULL, NULL, "vmx-entry-noload-debugctl", NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, "vmx-entry-ia32e-mode", NULL, NULL, -+ NULL, "vmx-entry-load-perf-global-ctrl", "vmx-entry-load-pat", "vmx-entry-load-efer", -+ "vmx-entry-load-bndcfgs", NULL, "vmx-entry-load-rtit-ctl", NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ }, -+ .msr = { -+ .index = MSR_IA32_VMX_TRUE_ENTRY_CTLS, -+ } -+ }, -+ -+ [FEAT_VMX_MISC] = { -+ .type = MSR_FEATURE_WORD, -+ .feat_names = { -+ NULL, NULL, NULL, NULL, -+ NULL, "vmx-store-lma", "vmx-activity-hlt", "vmx-activity-shutdown", -+ "vmx-activity-wait-sipi", NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, "vmx-vmwrite-vmexit-fields", "vmx-zero-len-inject", NULL, -+ }, -+ .msr = { -+ .index = MSR_IA32_VMX_MISC, -+ } -+ }, -+ -+ [FEAT_VMX_EPT_VPID_CAPS] = { -+ .type = MSR_FEATURE_WORD, -+ .feat_names = { -+ "vmx-ept-execonly", NULL, NULL, NULL, -+ NULL, NULL, "vmx-page-walk-4", "vmx-page-walk-5", -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ "vmx-ept-2mb", "vmx-ept-1gb", NULL, NULL, -+ "vmx-invept", "vmx-eptad", "vmx-ept-advanced-exitinfo", NULL, -+ NULL, "vmx-invept-single-context", "vmx-invept-all-context", NULL, -+ NULL, NULL, NULL, NULL, -+ "vmx-invvpid", NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ "vmx-invvpid-single-addr", "vmx-invept-single-context", -+ "vmx-invvpid-all-context", "vmx-invept-single-context-noglobals", -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ }, -+ .msr = { -+ .index = MSR_IA32_VMX_EPT_VPID_CAP, -+ } -+ }, -+ -+ [FEAT_VMX_BASIC] = { -+ .type = MSR_FEATURE_WORD, -+ .feat_names = { -+ [54] = "vmx-ins-outs", -+ [55] = "vmx-true-ctls", -+ }, -+ .msr = { -+ .index = MSR_IA32_VMX_BASIC, -+ }, -+ /* Just to be safe - we don't support setting the MSEG version field. */ -+ .no_autoenable_flags = MSR_VMX_BASIC_DUAL_MONITOR, -+ }, -+ -+ [FEAT_VMX_VMFUNC] = { -+ .type = MSR_FEATURE_WORD, -+ .feat_names = { -+ [0] = "vmx-eptp-switching", -+ }, -+ .msr = { -+ .index = MSR_IA32_VMX_VMFUNC, -+ } -+ }, -+ - }; - - typedef struct FeatureMask { -@@ -1252,6 +1409,74 @@ static FeatureDep feature_dependencies[] = { - .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY }, - .to = { FEAT_CORE_CAPABILITY, ~0ull }, - }, -+ { -+ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, -+ .to = { FEAT_VMX_PROCBASED_CTLS, ~0ull }, -+ }, -+ { -+ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, -+ .to = { FEAT_VMX_PINBASED_CTLS, ~0ull }, -+ }, -+ { -+ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, -+ .to = { FEAT_VMX_EXIT_CTLS, ~0ull }, -+ }, -+ { -+ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, -+ .to = { FEAT_VMX_ENTRY_CTLS, ~0ull }, -+ }, -+ { -+ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, -+ .to = { FEAT_VMX_MISC, ~0ull }, -+ }, -+ { -+ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, -+ .to = { FEAT_VMX_BASIC, ~0ull }, -+ }, -+ { -+ .from = { FEAT_8000_0001_EDX, CPUID_EXT2_LM }, -+ .to = { FEAT_VMX_ENTRY_CTLS, VMX_VM_ENTRY_IA32E_MODE }, -+ }, -+ { -+ .from = { FEAT_VMX_PROCBASED_CTLS, VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS }, -+ .to = { FEAT_VMX_SECONDARY_CTLS, ~0ull }, -+ }, -+ { -+ .from = { FEAT_XSAVE, CPUID_XSAVE_XSAVES }, -+ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_XSAVES }, -+ }, -+ { -+ .from = { FEAT_1_ECX, CPUID_EXT_RDRAND }, -+ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_RDRAND_EXITING }, -+ }, -+ { -+ .from = { FEAT_7_0_EBX, CPUID_7_0_EBX_INVPCID }, -+ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_INVPCID }, -+ }, -+ { -+ .from = { FEAT_7_0_EBX, CPUID_7_0_EBX_RDSEED }, -+ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_RDSEED_EXITING }, -+ }, -+ { -+ .from = { FEAT_8000_0001_EDX, CPUID_EXT2_RDTSCP }, -+ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_RDTSCP }, -+ }, -+ { -+ .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_EPT }, -+ .to = { FEAT_VMX_EPT_VPID_CAPS, 0xffffffffull }, -+ }, -+ { -+ .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_EPT }, -+ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST }, -+ }, -+ { -+ .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_VPID }, -+ .to = { FEAT_VMX_EPT_VPID_CAPS, 0xffffffffull << 32 }, -+ }, -+ { -+ .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_VMFUNC }, -+ .to = { FEAT_VMX_VMFUNC, ~0ull }, -+ }, - }; - - typedef struct X86RegisterInfo32 { -diff --git a/target/i386/cpu.h b/target/i386/cpu.h -index b4be6ffb1f..0b57b915af 100644 ---- a/target/i386/cpu.h -+++ b/target/i386/cpu.h -@@ -518,6 +518,15 @@ typedef enum FeatureWord { - FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ - FEAT_ARCH_CAPABILITIES, - FEAT_CORE_CAPABILITY, -+ FEAT_VMX_PROCBASED_CTLS, -+ FEAT_VMX_SECONDARY_CTLS, -+ FEAT_VMX_PINBASED_CTLS, -+ FEAT_VMX_EXIT_CTLS, -+ FEAT_VMX_ENTRY_CTLS, -+ FEAT_VMX_MISC, -+ FEAT_VMX_EPT_VPID_CAPS, -+ FEAT_VMX_BASIC, -+ FEAT_VMX_VMFUNC, - FEATURE_WORDS, - } FeatureWord; - -diff --git a/target/i386/kvm.c b/target/i386/kvm.c -index e9a6293ab2..fafb9fb26d 100644 ---- a/target/i386/kvm.c -+++ b/target/i386/kvm.c -@@ -96,6 +96,7 @@ static bool has_msr_virt_ssbd; - static bool has_msr_smi_count; - static bool has_msr_arch_capabs; - static bool has_msr_core_capabs; -+static bool has_msr_vmx_vmfunc; - - static uint32_t has_architectural_pmu_version; - static uint32_t num_architectural_pmu_gp_counters; -@@ -443,7 +444,8 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) - struct kvm_msrs info; - struct kvm_msr_entry entries[1]; - } msr_data; -- uint32_t ret; -+ uint64_t value; -+ uint32_t ret, can_be_one, must_be_one; - - if (kvm_feature_msrs == NULL) { /* Host doesn't support feature MSRs */ - return 0; -@@ -469,7 +471,25 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) - exit(1); - } - -- return msr_data.entries[0].data; -+ value = msr_data.entries[0].data; -+ switch (index) { -+ case MSR_IA32_VMX_PROCBASED_CTLS2: -+ case MSR_IA32_VMX_TRUE_PINBASED_CTLS: -+ case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: -+ case MSR_IA32_VMX_TRUE_ENTRY_CTLS: -+ case MSR_IA32_VMX_TRUE_EXIT_CTLS: -+ /* -+ * Return true for bits that can be one, but do not have to be one. -+ * The SDM tells us which bits could have a "must be one" setting, -+ * so we can do the opposite transformation in make_vmx_msr_value. -+ */ -+ must_be_one = (uint32_t)value; -+ can_be_one = (uint32_t)(value >> 32); -+ return can_be_one & ~must_be_one; -+ -+ default: -+ return value; -+ } - } - - -@@ -1933,6 +1953,9 @@ static int kvm_get_supported_msrs(KVMState *s) - case MSR_IA32_CORE_CAPABILITY: - has_msr_core_capabs = true; - break; -+ case MSR_IA32_VMX_VMFUNC: -+ has_msr_vmx_vmfunc = true; -+ break; - } - } - } -@@ -2407,6 +2430,132 @@ static int kvm_put_msr_feature_control(X86CPU *cpu) - return 0; - } - -+static uint64_t make_vmx_msr_value(uint32_t index, uint32_t features) -+{ -+ uint32_t default1, can_be_one, can_be_zero; -+ uint32_t must_be_one; -+ -+ switch (index) { -+ case MSR_IA32_VMX_TRUE_PINBASED_CTLS: -+ default1 = 0x00000016; -+ break; -+ case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: -+ default1 = 0x0401e172; -+ break; -+ case MSR_IA32_VMX_TRUE_ENTRY_CTLS: -+ default1 = 0x000011ff; -+ break; -+ case MSR_IA32_VMX_TRUE_EXIT_CTLS: -+ default1 = 0x00036dff; -+ break; -+ case MSR_IA32_VMX_PROCBASED_CTLS2: -+ default1 = 0; -+ break; -+ default: -+ abort(); -+ } -+ -+ /* If a feature bit is set, the control can be either set or clear. -+ * Otherwise the value is limited to either 0 or 1 by default1. -+ */ -+ can_be_one = features | default1; -+ can_be_zero = features | ~default1; -+ must_be_one = ~can_be_zero; -+ -+ /* -+ * Bit 0:31 -> 0 if the control bit can be zero (i.e. 1 if it must be one). -+ * Bit 32:63 -> 1 if the control bit can be one. -+ */ -+ return must_be_one | (((uint64_t)can_be_one) << 32); -+} -+ -+#define VMCS12_MAX_FIELD_INDEX (0x17) -+ -+static void kvm_msr_entry_add_vmx(X86CPU *cpu, FeatureWordArray f) -+{ -+ uint64_t kvm_vmx_basic = -+ kvm_arch_get_supported_msr_feature(kvm_state, -+ MSR_IA32_VMX_BASIC); -+ uint64_t kvm_vmx_misc = -+ kvm_arch_get_supported_msr_feature(kvm_state, -+ MSR_IA32_VMX_MISC); -+ uint64_t kvm_vmx_ept_vpid = -+ kvm_arch_get_supported_msr_feature(kvm_state, -+ MSR_IA32_VMX_EPT_VPID_CAP); -+ -+ /* -+ * If the guest is 64-bit, a value of 1 is allowed for the host address -+ * space size vmexit control. -+ */ -+ uint64_t fixed_vmx_exit = f[FEAT_8000_0001_EDX] & CPUID_EXT2_LM -+ ? (uint64_t)VMX_VM_EXIT_HOST_ADDR_SPACE_SIZE << 32 : 0; -+ -+ /* -+ * Bits 0-30, 32-44 and 50-53 come from the host. KVM should -+ * not change them for backwards compatibility. -+ */ -+ uint64_t fixed_vmx_basic = kvm_vmx_basic & -+ (MSR_VMX_BASIC_VMCS_REVISION_MASK | -+ MSR_VMX_BASIC_VMXON_REGION_SIZE_MASK | -+ MSR_VMX_BASIC_VMCS_MEM_TYPE_MASK); -+ -+ /* -+ * Same for bits 0-4 and 25-27. Bits 16-24 (CR3 target count) can -+ * change in the future but are always zero for now, clear them to be -+ * future proof. Bits 32-63 in theory could change, though KVM does -+ * not support dual-monitor treatment and probably never will; mask -+ * them out as well. -+ */ -+ uint64_t fixed_vmx_misc = kvm_vmx_misc & -+ (MSR_VMX_MISC_PREEMPTION_TIMER_SHIFT_MASK | -+ MSR_VMX_MISC_MAX_MSR_LIST_SIZE_MASK); -+ -+ /* -+ * EPT memory types should not change either, so we do not bother -+ * adding features for them. -+ */ -+ uint64_t fixed_vmx_ept_mask = -+ (f[FEAT_VMX_SECONDARY_CTLS] & VMX_SECONDARY_EXEC_ENABLE_EPT ? -+ MSR_VMX_EPT_UC | MSR_VMX_EPT_WB : 0); -+ uint64_t fixed_vmx_ept_vpid = kvm_vmx_ept_vpid & fixed_vmx_ept_mask; -+ -+ kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS, -+ make_vmx_msr_value(MSR_IA32_VMX_TRUE_PROCBASED_CTLS, -+ f[FEAT_VMX_PROCBASED_CTLS])); -+ kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_PINBASED_CTLS, -+ make_vmx_msr_value(MSR_IA32_VMX_TRUE_PINBASED_CTLS, -+ f[FEAT_VMX_PINBASED_CTLS])); -+ kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_EXIT_CTLS, -+ make_vmx_msr_value(MSR_IA32_VMX_TRUE_EXIT_CTLS, -+ f[FEAT_VMX_EXIT_CTLS]) | fixed_vmx_exit); -+ kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_ENTRY_CTLS, -+ make_vmx_msr_value(MSR_IA32_VMX_TRUE_ENTRY_CTLS, -+ f[FEAT_VMX_ENTRY_CTLS])); -+ kvm_msr_entry_add(cpu, MSR_IA32_VMX_PROCBASED_CTLS2, -+ make_vmx_msr_value(MSR_IA32_VMX_PROCBASED_CTLS2, -+ f[FEAT_VMX_SECONDARY_CTLS])); -+ kvm_msr_entry_add(cpu, MSR_IA32_VMX_EPT_VPID_CAP, -+ f[FEAT_VMX_EPT_VPID_CAPS] | fixed_vmx_ept_vpid); -+ kvm_msr_entry_add(cpu, MSR_IA32_VMX_BASIC, -+ f[FEAT_VMX_BASIC] | fixed_vmx_basic); -+ kvm_msr_entry_add(cpu, MSR_IA32_VMX_MISC, -+ f[FEAT_VMX_MISC] | fixed_vmx_misc); -+ if (has_msr_vmx_vmfunc) { -+ kvm_msr_entry_add(cpu, MSR_IA32_VMX_VMFUNC, f[FEAT_VMX_VMFUNC]); -+ } -+ -+ /* -+ * Just to be safe, write these with constant values. The CRn_FIXED1 -+ * MSRs are generated by KVM based on the vCPU's CPUID. -+ */ -+ kvm_msr_entry_add(cpu, MSR_IA32_VMX_CR0_FIXED0, -+ CR0_PE_MASK | CR0_PG_MASK | CR0_NE_MASK); -+ kvm_msr_entry_add(cpu, MSR_IA32_VMX_CR4_FIXED0, -+ CR4_VMXE_MASK); -+ kvm_msr_entry_add(cpu, MSR_IA32_VMX_VMCS_ENUM, -+ VMCS12_MAX_FIELD_INDEX << 1); -+} -+ - static int kvm_put_msrs(X86CPU *cpu, int level) - { - CPUX86State *env = &cpu->env; -@@ -2646,7 +2795,16 @@ static int kvm_put_msrs(X86CPU *cpu, int level) - - /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see - * kvm_put_msr_feature_control. */ -+ -+ /* -+ * Older kernels do not include VMX MSRs in KVM_GET_MSR_INDEX_LIST, but -+ * all kernels with MSR features should have them. -+ */ -+ if (kvm_feature_msrs && cpu_has_vmx(env)) { -+ kvm_msr_entry_add_vmx(cpu, env->features); -+ } - } -+ - if (env->mcg_cap) { - int i; - --- -2.27.0 - diff --git a/target-i386-add-a-ucode-rev-property.patch b/target-i386-add-a-ucode-rev-property.patch deleted file mode 100644 index 8a3ff6fd91f67dc93e12e75f9c84ce30dd7725f1..0000000000000000000000000000000000000000 --- a/target-i386-add-a-ucode-rev-property.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 9b3b22bfe87be7eec126056b96f7cea7e3ab9257 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 17 Feb 2020 16:23:12 +0000 -Subject: [PATCH] target/i386: add a ucode-rev property - -RH-Author: Paolo Bonzini -Message-id: <20200217162316.2464-3-pbonzini@redhat.com> -Patchwork-id: 93909 -O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH 2/6] target/i386: add a ucode-rev property -Bugzilla: 1791648 -RH-Acked-by: Eduardo Habkost -RH-Acked-by: Maxim Levitsky -RH-Acked-by: Dr. David Alan Gilbert - -Add the property and plumb it in TCG and HVF (the latter of which -tried to support returning a constant value but used the wrong MSR). - -Signed-off-by: Paolo Bonzini -Message-Id: <1579544504-3616-3-git-send-email-pbonzini@redhat.com> -Signed-off-by: Paolo Bonzini -(cherry picked from commit 4e45aff398cd1542c2a384a2a3b8600f23337d86) -Signed-off-by: Danilo C. L. de Paula ---- - target/i386/cpu.c | 10 ++++++++++ - target/i386/cpu.h | 3 +++ - target/i386/hvf/x86_emu.c | 4 +--- - target/i386/misc_helper.c | 4 ++++ - 4 files changed, 18 insertions(+), 3 deletions(-) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index 35a33db39a..ec8bc9957e 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -6332,6 +6332,15 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) - } - } - -+ if (cpu->ucode_rev == 0) { -+ /* The default is the same as KVM's. */ -+ if (IS_AMD_CPU(env)) { -+ cpu->ucode_rev = 0x01000065; -+ } else { -+ cpu->ucode_rev = 0x100000000ULL; -+ } -+ } -+ - /* mwait extended info: needed for Core compatibility */ - /* We always wake on interrupt even if host does not have the capability */ - cpu->mwait.ecx |= CPUID_MWAIT_EMX | CPUID_MWAIT_IBE; -@@ -7011,6 +7020,7 @@ static Property x86_cpu_properties[] = { - DEFINE_PROP_UINT32("min-level", X86CPU, env.cpuid_min_level, 0), - DEFINE_PROP_UINT32("min-xlevel", X86CPU, env.cpuid_min_xlevel, 0), - DEFINE_PROP_UINT32("min-xlevel2", X86CPU, env.cpuid_min_xlevel2, 0), -+ DEFINE_PROP_UINT64("ucode-rev", X86CPU, ucode_rev, 0), - DEFINE_PROP_BOOL("full-cpuid-auto-level", X86CPU, full_cpuid_auto_level, true), - DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor_id), - DEFINE_PROP_BOOL("cpuid-0xb", X86CPU, enable_cpuid_0xb, true), -diff --git a/target/i386/cpu.h b/target/i386/cpu.h -index 0b57b915af..ca7de143af 100644 ---- a/target/i386/cpu.h -+++ b/target/i386/cpu.h -@@ -345,6 +345,7 @@ typedef enum X86Seg { - #define MSR_IA32_SPEC_CTRL 0x48 - #define MSR_VIRT_SSBD 0xc001011f - #define MSR_IA32_PRED_CMD 0x49 -+#define MSR_IA32_UCODE_REV 0x8b - #define MSR_IA32_CORE_CAPABILITY 0xcf - #define MSR_IA32_ARCH_CAPABILITIES 0x10a - #define MSR_IA32_TSCDEADLINE 0x6e0 -@@ -1562,6 +1563,8 @@ struct X86CPU { - CPUNegativeOffsetState neg; - CPUX86State env; - -+ uint64_t ucode_rev; -+ - uint32_t hyperv_spinlock_attempts; - char *hyperv_vendor_id; - bool hyperv_synic_kvm_only; -diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c -index 1b04bd7e94..cd40520c16 100644 ---- a/target/i386/hvf/x86_emu.c -+++ b/target/i386/hvf/x86_emu.c -@@ -664,8 +664,6 @@ static void exec_lods(struct CPUX86State *env, struct x86_decode *decode) - RIP(env) += decode->len; - } - --#define MSR_IA32_UCODE_REV 0x00000017 -- - void simulate_rdmsr(struct CPUState *cpu) - { - X86CPU *x86_cpu = X86_CPU(cpu); -@@ -681,7 +679,7 @@ void simulate_rdmsr(struct CPUState *cpu) - val = cpu_get_apic_base(X86_CPU(cpu)->apic_state); - break; - case MSR_IA32_UCODE_REV: -- val = (0x100000000ULL << 32) | 0x100000000ULL; -+ val = x86_cpu->ucode_rev; - break; - case MSR_EFER: - val = rvmcs(cpu->hvf_fd, VMCS_GUEST_IA32_EFER); -diff --git a/target/i386/misc_helper.c b/target/i386/misc_helper.c -index 3eff6885f8..aed16fe3f0 100644 ---- a/target/i386/misc_helper.c -+++ b/target/i386/misc_helper.c -@@ -229,6 +229,7 @@ void helper_rdmsr(CPUX86State *env) - #else - void helper_wrmsr(CPUX86State *env) - { -+ X86CPU *x86_cpu = env_archcpu(env); - uint64_t val; - - cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC()); -@@ -371,6 +372,9 @@ void helper_wrmsr(CPUX86State *env) - env->msr_bndcfgs = val; - cpu_sync_bndcs_hflags(env); - break; -+ case MSR_IA32_UCODE_REV: -+ val = x86_cpu->ucode_rev; -+ break; - default: - if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL - && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL + --- -2.27.0 - diff --git a/target-i386-add-two-missing-VMX-features-for-Skylake.patch b/target-i386-add-two-missing-VMX-features-for-Skylake.patch deleted file mode 100644 index fa3c6d8f39ad28cb75995e142697bee2bf48e97a..0000000000000000000000000000000000000000 --- a/target-i386-add-two-missing-VMX-features-for-Skylake.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 1faa48f4de44c123143d43e67cd5a478628a45a4 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 25 Nov 2019 19:12:16 +0100 -Subject: [PATCH] target/i386: add two missing VMX features for Skylake and - CascadeLake Server - -They are present in client (Core) Skylake but pasted wrong into the server -SKUs. - -Reported-by: Dr. David Alan Gilbert -Signed-off-by: Paolo Bonzini ---- - target/i386/cpu.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index 2f32d67aa5..6f27a5170a 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -2997,7 +2997,8 @@ static X86CPUDefinition builtin_x86_defs[] = { - VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | - VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | - VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | -- VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, -+ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | -+ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, - .xlevel = 0x80000008, - .model_id = "Intel Xeon Processor (Skylake)", - .versions = (X86CPUVersionDefinition[]) { -@@ -3113,7 +3114,8 @@ static X86CPUDefinition builtin_x86_defs[] = { - VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | - VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | - VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | -- VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, -+ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | -+ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, - .xlevel = 0x80000008, - .model_id = "Intel Xeon Processor (Cascadelake)", - .versions = (X86CPUVersionDefinition[]) { --- -2.27.0 - diff --git a/target-i386-check-for-availability-of-MSR_IA32_UCODE.patch b/target-i386-check-for-availability-of-MSR_IA32_UCODE.patch deleted file mode 100644 index 377226a4cbff7b6a4c83d410f8f78ff18bc97190..0000000000000000000000000000000000000000 --- a/target-i386-check-for-availability-of-MSR_IA32_UCODE.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0633e7684b4f4da858a3739d68cb57a1d49bdf01 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Tue, 11 Feb 2020 18:55:16 +0100 -Subject: [PATCH] target/i386: check for availability of MSR_IA32_UCODE_REV as - an emulated MSR - -Even though MSR_IA32_UCODE_REV has been available long before Linux 5.6, -which added it to the emulated MSR list, a bug caused the microcode -version to revert to 0x100000000 on INIT. As a result, processors other -than the bootstrap processor would not see the host microcode revision; -some Windows version complain loudly about this and crash with a -fairly explicit MICROCODE REVISION MISMATCH error. - -[If running 5.6 prereleases, the kernel fix "KVM: x86: do not reset - microcode version on INIT or RESET" should also be applied.] - -Reported-by: Alex Williamson -Message-id: <20200211175516.10716-1-pbonzini@redhat.com> -Signed-off-by: Paolo Bonzini ---- - target/i386/kvm.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/target/i386/kvm.c b/target/i386/kvm.c -index 7437f86130..e49a2d2585 100644 ---- a/target/i386/kvm.c -+++ b/target/i386/kvm.c -@@ -99,6 +99,7 @@ static bool has_msr_smi_count; - static bool has_msr_arch_capabs; - static bool has_msr_core_capabs; - static bool has_msr_vmx_vmfunc; -+static bool has_msr_ucode_rev; - static bool has_msr_vmx_procbased_ctls2; - - static uint32_t has_architectural_pmu_version; -@@ -1985,6 +1986,9 @@ static int kvm_get_supported_msrs(KVMState *s) - case MSR_IA32_VMX_VMFUNC: - has_msr_vmx_vmfunc = true; - break; -+ case MSR_IA32_UCODE_REV: -+ has_msr_ucode_rev = true; -+ break; - case MSR_IA32_VMX_PROCBASED_CTLS2: - has_msr_vmx_procbased_ctls2 = true; - break; -@@ -2628,8 +2632,7 @@ static void kvm_init_msrs(X86CPU *cpu) - env->features[FEAT_CORE_CAPABILITY]); - } - -- if (kvm_arch_get_supported_msr_feature(kvm_state, -- MSR_IA32_UCODE_REV)) { -+ if (has_msr_ucode_rev) { - kvm_msr_entry_add(cpu, MSR_IA32_UCODE_REV, cpu->ucode_rev); - } - --- -2.27.0 - diff --git a/target-i386-disable-VMX-features-if-nested-0.patch b/target-i386-disable-VMX-features-if-nested-0.patch deleted file mode 100644 index fa7edfdb2a7296a0039a44e2c4c1af9b5b324951..0000000000000000000000000000000000000000 --- a/target-i386-disable-VMX-features-if-nested-0.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 26f01427d155510edcab07e312a72f5bacddafb2 Mon Sep 17 00:00:00 2001 -From: Yang Zhong -Date: Fri, 6 Dec 2019 15:11:11 +0800 -Subject: [PATCH] target/i386: disable VMX features if nested=0 - -If kvm does not support VMX feature by nested=0, the kvm_vmx_basic -can't get the right value from MSR_IA32_VMX_BASIC register, which -make qemu coredump when qemu do KVM_SET_MSRS. - -The coredump info: -error: failed to set MSR 0x480 to 0x0 -kvm_put_msrs: Assertion `ret == cpu->kvm_msr_buf->nmsrs' failed. - -Signed-off-by: Yang Zhong -Message-Id: <20191206071111.12128-1-yang.zhong@intel.com> -Reported-by: Catherine Ho -Signed-off-by: Paolo Bonzini ---- - target/i386/kvm.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/target/i386/kvm.c b/target/i386/kvm.c -index b97f40df6b..5ee0c50d7c 100644 ---- a/target/i386/kvm.c -+++ b/target/i386/kvm.c -@@ -2493,6 +2493,14 @@ static void kvm_msr_entry_add_vmx(X86CPU *cpu, FeatureWordArray f) - uint64_t kvm_vmx_basic = - kvm_arch_get_supported_msr_feature(kvm_state, - MSR_IA32_VMX_BASIC); -+ -+ if (!kvm_vmx_basic) { -+ /* If the kernel doesn't support VMX feature (kvm_intel.nested=0), -+ * then kvm_vmx_basic will be 0 and KVM_SET_MSR will fail. -+ */ -+ return; -+ } -+ - uint64_t kvm_vmx_misc = - kvm_arch_get_supported_msr_feature(kvm_state, - MSR_IA32_VMX_MISC); --- -2.27.0 - diff --git a/target-i386-do-not-set-unsupported-VMX-secondary-exe.patch b/target-i386-do-not-set-unsupported-VMX-secondary-exe.patch deleted file mode 100644 index 8eda458156b202ba7c5405bf1e261e56a7aa1771..0000000000000000000000000000000000000000 --- a/target-i386-do-not-set-unsupported-VMX-secondary-exe.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 472ccc3e48cab962ec9acf3f31e4467544b51705 Mon Sep 17 00:00:00 2001 -From: Vitaly Kuznetsov -Date: Tue, 31 Mar 2020 18:27:52 +0200 -Subject: [PATCH] target/i386: do not set unsupported VMX secondary execution - controls - -Commit 048c95163b4 ("target/i386: work around KVM_GET_MSRS bug for -secondary execution controls") added a workaround for KVM pre-dating -commit 6defc591846d ("KVM: nVMX: include conditional controls in /dev/kvm -KVM_GET_MSRS") which wasn't setting certain available controls. The -workaround uses generic CPUID feature bits to set missing VMX controls. - -It was found that in some cases it is possible to observe hosts which -have certain CPUID features but lack the corresponding VMX control. - -In particular, it was reported that Azure VMs have RDSEED but lack -VMX_SECONDARY_EXEC_RDSEED_EXITING; attempts to enable this feature -bit result in QEMU abort. - -Resolve the issue but not applying the workaround when we don't have -to. As there is no good way to find out if KVM has the fix itself, use -95c5c7c77c ("KVM: nVMX: list VMX MSRs in KVM_GET_MSR_INDEX_LIST") instead -as these [are supposed to] come together. - -Fixes: 048c95163b4 ("target/i386: work around KVM_GET_MSRS bug for secondary execution controls") -Suggested-by: Paolo Bonzini -Signed-off-by: Vitaly Kuznetsov -Message-Id: <20200331162752.1209928-1-vkuznets@redhat.com> -Signed-off-by: Paolo Bonzini ---- - target/i386/kvm.c | 41 ++++++++++++++++++++++++++--------------- - 1 file changed, 26 insertions(+), 15 deletions(-) - -diff --git a/target/i386/kvm.c b/target/i386/kvm.c -index 5ee0c50d7c..7328746d92 100644 ---- a/target/i386/kvm.c -+++ b/target/i386/kvm.c -@@ -97,6 +97,7 @@ static bool has_msr_smi_count; - static bool has_msr_arch_capabs; - static bool has_msr_core_capabs; - static bool has_msr_vmx_vmfunc; -+static bool has_msr_vmx_procbased_ctls2; - - static uint32_t has_architectural_pmu_version; - static uint32_t num_architectural_pmu_gp_counters; -@@ -474,21 +475,28 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) - value = msr_data.entries[0].data; - switch (index) { - case MSR_IA32_VMX_PROCBASED_CTLS2: -- /* KVM forgot to add these bits for some time, do this ourselves. */ -- if (kvm_arch_get_supported_cpuid(s, 0xD, 1, R_ECX) & CPUID_XSAVE_XSAVES) { -- value |= (uint64_t)VMX_SECONDARY_EXEC_XSAVES << 32; -- } -- if (kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX) & CPUID_EXT_RDRAND) { -- value |= (uint64_t)VMX_SECONDARY_EXEC_RDRAND_EXITING << 32; -- } -- if (kvm_arch_get_supported_cpuid(s, 7, 0, R_EBX) & CPUID_7_0_EBX_INVPCID) { -- value |= (uint64_t)VMX_SECONDARY_EXEC_ENABLE_INVPCID << 32; -- } -- if (kvm_arch_get_supported_cpuid(s, 7, 0, R_EBX) & CPUID_7_0_EBX_RDSEED) { -- value |= (uint64_t)VMX_SECONDARY_EXEC_RDSEED_EXITING << 32; -- } -- if (kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX) & CPUID_EXT2_RDTSCP) { -- value |= (uint64_t)VMX_SECONDARY_EXEC_RDTSCP << 32; -+ if (!has_msr_vmx_procbased_ctls2) { -+ /* KVM forgot to add these bits for some time, do this ourselves. */ -+ if (kvm_arch_get_supported_cpuid(s, 0xD, 1, R_ECX) & -+ CPUID_XSAVE_XSAVES) { -+ value |= (uint64_t)VMX_SECONDARY_EXEC_XSAVES << 32; -+ } -+ if (kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX) & -+ CPUID_EXT_RDRAND) { -+ value |= (uint64_t)VMX_SECONDARY_EXEC_RDRAND_EXITING << 32; -+ } -+ if (kvm_arch_get_supported_cpuid(s, 7, 0, R_EBX) & -+ CPUID_7_0_EBX_INVPCID) { -+ value |= (uint64_t)VMX_SECONDARY_EXEC_ENABLE_INVPCID << 32; -+ } -+ if (kvm_arch_get_supported_cpuid(s, 7, 0, R_EBX) & -+ CPUID_7_0_EBX_RDSEED) { -+ value |= (uint64_t)VMX_SECONDARY_EXEC_RDSEED_EXITING << 32; -+ } -+ if (kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX) & -+ CPUID_EXT2_RDTSCP) { -+ value |= (uint64_t)VMX_SECONDARY_EXEC_RDTSCP << 32; -+ } - } - /* fall through */ - case MSR_IA32_VMX_TRUE_PINBASED_CTLS: -@@ -1973,6 +1981,9 @@ static int kvm_get_supported_msrs(KVMState *s) - case MSR_IA32_VMX_VMFUNC: - has_msr_vmx_vmfunc = true; - break; -+ case MSR_IA32_VMX_PROCBASED_CTLS2: -+ has_msr_vmx_procbased_ctls2 = true; -+ break; - } - } - } --- -2.27.0 - diff --git a/target-i386-enable-monitor-and-ucode-revision-with-c.patch b/target-i386-enable-monitor-and-ucode-revision-with-c.patch deleted file mode 100644 index 398a79d1648aa2d595ad39098a49c00b7b8ab95a..0000000000000000000000000000000000000000 --- a/target-i386-enable-monitor-and-ucode-revision-with-c.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 8470399d9508b3b56d625866ea235c2a5b4cb39a Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 17 Feb 2020 16:23:16 +0000 -Subject: [PATCH] target/i386: enable monitor and ucode revision with -cpu max -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -RH-Author: Paolo Bonzini -Message-id: <20200217162316.2464-7-pbonzini@redhat.com> -Patchwork-id: 93910 -O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH 6/6] target/i386: enable monitor and ucode revision with -cpu max -Bugzilla: 1791648 -RH-Acked-by: Philippe Mathieu-Daudé -RH-Acked-by: Maxim Levitsky -RH-Acked-by: Dr. David Alan Gilbert - -These two features were incorrectly tied to host_cpuid_required rather than -cpu->max_features. As a result, -cpu max was not enabling either MONITOR -features or ucode revision. - -Signed-off-by: Paolo Bonzini -(cherry picked from commit be02cda3afde60d219786e23c3f8edb53aec8e17) - -[RHEL7: context, upstream uses g_autofree] - -Signed-off-by: Danilo C. L. de Paula ---- - target/i386/cpu.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index 22e0e89718..6147cd419a 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -6317,7 +6317,9 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) - g_free(name); - goto out; - } -+ } - -+ if (cpu->max_features && accel_uses_host_cpuid()) { - if (enable_cpu_pm) { - host_cpuid(5, 0, &cpu->mwait.eax, &cpu->mwait.ebx, - &cpu->mwait.ecx, &cpu->mwait.edx); --- -2.27.0 - diff --git a/target-i386-expand-feature-words-to-64-bits.patch b/target-i386-expand-feature-words-to-64-bits.patch deleted file mode 100644 index e4a06e5954aec3ec8d30e29c61234612ed36d0c7..0000000000000000000000000000000000000000 --- a/target-i386-expand-feature-words-to-64-bits.patch +++ /dev/null @@ -1,295 +0,0 @@ -From bec2d75a3d3c6405d0afe59c343d23199b009666 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 1 Jul 2019 17:38:54 +0200 -Subject: [PATCH] target/i386: expand feature words to 64 bits - -VMX requires 64-bit feature words for the IA32_VMX_EPT_VPID_CAP -and IA32_VMX_BASIC MSRs. (The VMX control MSRs are 64-bit wide but -actually have only 32 bits of information). - -Signed-off-by: Paolo Bonzini ---- - include/sysemu/kvm.h | 2 +- - target/i386/cpu.c | 71 +++++++++++++++++++++++--------------------- - target/i386/cpu.h | 2 +- - target/i386/kvm.c | 2 +- - 4 files changed, 40 insertions(+), 37 deletions(-) - -diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h -index 565adb4e2c..875b2bf10d 100644 ---- a/include/sysemu/kvm.h -+++ b/include/sysemu/kvm.h -@@ -464,7 +464,7 @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension); - - uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, - uint32_t index, int reg); --uint32_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index); -+uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index); - - - void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len); -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index d4a435ba96..3d6541c4a8 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -789,7 +789,7 @@ typedef struct FeatureWordInfo { - * In cases of disagreement between feature naming conventions, - * aliases may be added. - */ -- const char *feat_names[32]; -+ const char *feat_names[64]; - union { - /* If type==CPUID_FEATURE_WORD */ - struct { -@@ -803,11 +803,11 @@ typedef struct FeatureWordInfo { - uint32_t index; - } msr; - }; -- uint32_t tcg_features; /* Feature flags supported by TCG */ -- uint32_t unmigratable_flags; /* Feature flags known to be unmigratable */ -- uint32_t migratable_flags; /* Feature flags known to be migratable */ -+ uint64_t tcg_features; /* Feature flags supported by TCG */ -+ uint64_t unmigratable_flags; /* Feature flags known to be unmigratable */ -+ uint64_t migratable_flags; /* Feature flags known to be migratable */ - /* Features that shouldn't be auto-enabled by "-cpu host" */ -- uint32_t no_autoenable_flags; -+ uint64_t no_autoenable_flags; - } FeatureWordInfo; - - static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { -@@ -1236,7 +1236,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { - - typedef struct FeatureMask { - FeatureWord index; -- uint32_t mask; -+ uint64_t mask; - } FeatureMask; - - typedef struct FeatureDep { -@@ -1246,11 +1246,11 @@ typedef struct FeatureDep { - static FeatureDep feature_dependencies[] = { - { - .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_ARCH_CAPABILITIES }, -- .to = { FEAT_ARCH_CAPABILITIES, ~0u }, -+ .to = { FEAT_ARCH_CAPABILITIES, ~0ull }, - }, - { - .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY }, -- .to = { FEAT_CORE_CAPABILITY, ~0u }, -+ .to = { FEAT_CORE_CAPABILITY, ~0ull }, - }, - }; - -@@ -1362,14 +1362,14 @@ const char *get_register_name_32(unsigned int reg) - * Returns the set of feature flags that are supported and migratable by - * QEMU, for a given FeatureWord. - */ --static uint32_t x86_cpu_get_migratable_flags(FeatureWord w) -+static uint64_t x86_cpu_get_migratable_flags(FeatureWord w) - { - FeatureWordInfo *wi = &feature_word_info[w]; -- uint32_t r = 0; -+ uint64_t r = 0; - int i; - -- for (i = 0; i < 32; i++) { -- uint32_t f = 1U << i; -+ for (i = 0; i < 64; i++) { -+ uint64_t f = 1ULL << i; - - /* If the feature name is known, it is implicitly considered migratable, - * unless it is explicitly set in unmigratable_flags */ -@@ -3051,7 +3051,7 @@ void x86_cpu_change_kvm_default(const char *prop, const char *value) - assert(pv->prop); - } - --static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, -+static uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, - bool migratable_only); - - static bool lmce_supported(void) -@@ -3237,7 +3237,7 @@ static bool x86_cpu_have_filtered_features(X86CPU *cpu) - return false; - } - --static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint32_t mask, -+static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint64_t mask, - const char *verbose_prefix) - { - CPUX86State *env = &cpu->env; -@@ -3254,8 +3254,8 @@ static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint32_t mask, - return; - } - -- for (i = 0; i < 32; ++i) { -- if ((1UL << i) & mask) { -+ for (i = 0; i < 64; ++i) { -+ if ((1ULL << i) & mask) { - feat_word_str = feature_word_description(f, i); - warn_report("%s: %s%s%s [bit %d]", - verbose_prefix, -@@ -3498,7 +3498,7 @@ static void x86_cpu_get_feature_words(Object *obj, Visitor *v, - const char *name, void *opaque, - Error **errp) - { -- uint32_t *array = (uint32_t *)opaque; -+ uint64_t *array = (uint64_t *)opaque; - FeatureWord w; - X86CPUFeatureWordInfo word_infos[FEATURE_WORDS] = { }; - X86CPUFeatureWordInfoList list_entries[FEATURE_WORDS] = { }; -@@ -3542,6 +3542,7 @@ static inline void feat2prop(char *s) - /* Return the feature property name for a feature flag bit */ - static const char *x86_cpu_feature_name(FeatureWord w, int bitnr) - { -+ const char *name; - /* XSAVE components are automatically enabled by other features, - * so return the original feature name instead - */ -@@ -3555,9 +3556,11 @@ static const char *x86_cpu_feature_name(FeatureWord w, int bitnr) - } - } - -- assert(bitnr < 32); -+ assert(bitnr < 64); - assert(w < FEATURE_WORDS); -- return feature_word_info[w].feat_names[bitnr]; -+ name = feature_word_info[w].feat_names[bitnr]; -+ assert(bitnr < 32 || !(name && feature_word_info[w].type == CPUID_FEATURE_WORD)); -+ return name; - } - - /* Compatibily hack to maintain legacy +-feat semantic, -@@ -3673,10 +3676,10 @@ static void x86_cpu_list_feature_names(FeatureWordArray features, - strList **next = feat_names; - - for (w = 0; w < FEATURE_WORDS; w++) { -- uint32_t filtered = features[w]; -+ uint64_t filtered = features[w]; - int i; -- for (i = 0; i < 32; i++) { -- if (filtered & (1UL << i)) { -+ for (i = 0; i < 64; i++) { -+ if (filtered & (1ULL << i)) { - strList *new = g_new0(strList, 1); - new->value = g_strdup(x86_cpu_feature_name(w, i)); - *next = new; -@@ -3845,7 +3848,7 @@ void x86_cpu_list(void) - names = NULL; - for (i = 0; i < ARRAY_SIZE(feature_word_info); i++) { - FeatureWordInfo *fw = &feature_word_info[i]; -- for (j = 0; j < 32; j++) { -+ for (j = 0; j < 64; j++) { - if (fw->feat_names[j]) { - names = g_list_append(names, (gpointer)fw->feat_names[j]); - } -@@ -3900,11 +3903,11 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) - return cpu_list; - } - --static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, -+static uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, - bool migratable_only) - { - FeatureWordInfo *wi = &feature_word_info[w]; -- uint32_t r = 0; -+ uint64_t r = 0; - - if (kvm_enabled()) { - switch (wi->type) { -@@ -4075,7 +4078,7 @@ static QDict *x86_cpu_static_props(void) - for (w = 0; w < FEATURE_WORDS; w++) { - FeatureWordInfo *fi = &feature_word_info[w]; - int bit; -- for (bit = 0; bit < 32; bit++) { -+ for (bit = 0; bit < 64; bit++) { - if (!fi->feat_names[bit]) { - continue; - } -@@ -5231,7 +5234,7 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) - for (i = 0; i < ARRAY_SIZE(feature_dependencies); i++) { - FeatureDep *d = &feature_dependencies[i]; - if (!(env->features[d->from.index] & d->from.mask)) { -- uint32_t unavailable_features = env->features[d->to.index] & d->to.mask; -+ uint64_t unavailable_features = env->features[d->to.index] & d->to.mask; - - /* Not an error unless the dependent feature was added explicitly. */ - mark_unavailable_features(cpu, d->to.index, -@@ -5326,10 +5329,10 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool verbose) - } - - for (w = 0; w < FEATURE_WORDS; w++) { -- uint32_t host_feat = -+ uint64_t host_feat = - x86_cpu_get_supported_feature_word(w, false); -- uint32_t requested_features = env->features[w]; -- uint32_t unavailable_features = requested_features & ~host_feat; -+ uint64_t requested_features = env->features[w]; -+ uint64_t unavailable_features = requested_features & ~host_feat; - mark_unavailable_features(cpu, w, unavailable_features, prefix); - } - -@@ -5626,7 +5629,7 @@ static void x86_cpu_unrealizefn(DeviceState *dev, Error **errp) - - typedef struct BitProperty { - FeatureWord w; -- uint32_t mask; -+ uint64_t mask; - } BitProperty; - - static void x86_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name, -@@ -5634,7 +5637,7 @@ static void x86_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name, - { - X86CPU *cpu = X86_CPU(obj); - BitProperty *fp = opaque; -- uint32_t f = cpu->env.features[fp->w]; -+ uint64_t f = cpu->env.features[fp->w]; - bool value = (f & fp->mask) == fp->mask; - visit_type_bool(v, name, &value, errp); - } -@@ -5687,7 +5690,7 @@ static void x86_cpu_register_bit_prop(X86CPU *cpu, - { - BitProperty *fp; - ObjectProperty *op; -- uint32_t mask = (1UL << bitnr); -+ uint64_t mask = (1ULL << bitnr); - - op = object_property_find(OBJECT(cpu), prop_name, NULL); - if (op) { -@@ -5821,7 +5824,7 @@ static void x86_cpu_initfn(Object *obj) - for (w = 0; w < FEATURE_WORDS; w++) { - int bitnr; - -- for (bitnr = 0; bitnr < 32; bitnr++) { -+ for (bitnr = 0; bitnr < 64; bitnr++) { - x86_cpu_register_feature_bit_props(cpu, w, bitnr); - } - } -diff --git a/target/i386/cpu.h b/target/i386/cpu.h -index 24d489db0f..9a105b2251 100644 ---- a/target/i386/cpu.h -+++ b/target/i386/cpu.h -@@ -502,7 +502,7 @@ typedef enum FeatureWord { - FEATURE_WORDS, - } FeatureWord; - --typedef uint32_t FeatureWordArray[FEATURE_WORDS]; -+typedef uint64_t FeatureWordArray[FEATURE_WORDS]; - - /* cpuid_features bits */ - #define CPUID_FP87 (1U << 0) -diff --git a/target/i386/kvm.c b/target/i386/kvm.c -index f55d4b4b97..e9a6293ab2 100644 ---- a/target/i386/kvm.c -+++ b/target/i386/kvm.c -@@ -437,7 +437,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, - return ret; - } - --uint32_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) -+uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) - { - struct { - struct kvm_msrs info; --- -2.27.0 - diff --git a/target-i386-handle-filtered_features-in-a-new-functi.patch b/target-i386-handle-filtered_features-in-a-new-functi.patch deleted file mode 100644 index ba35948dd1e1c10f566c327750026c22b626a5f2..0000000000000000000000000000000000000000 --- a/target-i386-handle-filtered_features-in-a-new-functi.patch +++ /dev/null @@ -1,176 +0,0 @@ -From b9d29966103ca671718ef1eb5b68067b05fad340 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Tue, 2 Jul 2019 15:32:41 +0200 -Subject: [PATCH] target/i386: handle filtered_features in a new function - mark_unavailable_features - -The next patch will add a different reason for filtering features, unrelated -to host feature support. Extract a new function that takes care of disabling -the features and optionally reporting them. - -Signed-off-by: Paolo Bonzini ---- - target/i386/cpu.c | 87 ++++++++++++++++++++++++++--------------------- - 1 file changed, 48 insertions(+), 39 deletions(-) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index e65f372f25..8798cafc7a 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -3216,17 +3216,41 @@ static char *feature_word_description(FeatureWordInfo *f, uint32_t bit) - return NULL; - } - --static void report_unavailable_features(FeatureWord w, uint32_t mask) -+static bool x86_cpu_have_filtered_features(X86CPU *cpu) - { -+ FeatureWord w; -+ -+ for (w = 0; w < FEATURE_WORDS; w++) { -+ if (cpu->filtered_features[w]) { -+ return true; -+ } -+ } -+ -+ return false; -+} -+ -+static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint32_t mask, -+ const char *verbose_prefix) -+{ -+ CPUX86State *env = &cpu->env; - FeatureWordInfo *f = &feature_word_info[w]; - int i; - char *feat_word_str; - -+ if (!cpu->force_features) { -+ env->features[w] &= ~mask; -+ } -+ cpu->filtered_features[w] |= mask; -+ -+ if (!verbose_prefix) { -+ return; -+ } -+ - for (i = 0; i < 32; ++i) { - if ((1UL << i) & mask) { - feat_word_str = feature_word_description(f, i); -- warn_report("%s doesn't support requested feature: %s%s%s [bit %d]", -- accel_uses_host_cpuid() ? "host" : "TCG", -+ warn_report("%s: %s%s%s [bit %d]", -+ verbose_prefix, - feat_word_str, - f->feat_names[i] ? "." : "", - f->feat_names[i] ? f->feat_names[i] : "", i); -@@ -3631,7 +3655,7 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features, - } - - static void x86_cpu_expand_features(X86CPU *cpu, Error **errp); --static int x86_cpu_filter_features(X86CPU *cpu); -+static void x86_cpu_filter_features(X86CPU *cpu, bool verbose); - - /* Build a list with the name of all features on a feature word array */ - static void x86_cpu_list_feature_names(FeatureWordArray features, -@@ -3696,7 +3720,7 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc, - next = &new->next; - } - -- x86_cpu_filter_features(xc); -+ x86_cpu_filter_features(xc, false); - - x86_cpu_list_feature_names(xc->filtered_features, next); - -@@ -3904,15 +3928,6 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, - return r; - } - --static void x86_cpu_report_filtered_features(X86CPU *cpu) --{ -- FeatureWord w; -- -- for (w = 0; w < FEATURE_WORDS; w++) { -- report_unavailable_features(w, cpu->filtered_features[w]); -- } --} -- - static void x86_cpu_apply_props(X86CPU *cpu, PropValue *props) - { - PropValue *pv; -@@ -5274,24 +5289,24 @@ out: - * - * Returns: 0 if all flags are supported by the host, non-zero otherwise. - */ --static int x86_cpu_filter_features(X86CPU *cpu) -+static void x86_cpu_filter_features(X86CPU *cpu, bool verbose) - { - CPUX86State *env = &cpu->env; - FeatureWord w; -- int rv = 0; -+ const char *prefix = NULL; -+ -+ if (verbose) { -+ prefix = accel_uses_host_cpuid() -+ ? "host doesn't support requested feature" -+ : "TCG doesn't support requested feature"; -+ } - - for (w = 0; w < FEATURE_WORDS; w++) { - uint32_t host_feat = - x86_cpu_get_supported_feature_word(w, false); - uint32_t requested_features = env->features[w]; -- uint32_t available_features = requested_features & host_feat; -- if (!cpu->force_features) { -- env->features[w] = available_features; -- } -- cpu->filtered_features[w] = requested_features & ~available_features; -- if (cpu->filtered_features[w]) { -- rv = 1; -- } -+ uint32_t unavailable_features = requested_features & ~host_feat; -+ mark_unavailable_features(cpu, w, unavailable_features, prefix); - } - - if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) && -@@ -5317,13 +5332,9 @@ static int x86_cpu_filter_features(X86CPU *cpu) - * host can't emulate the capabilities we report on - * cpu_x86_cpuid(), intel-pt can't be enabled on the current host. - */ -- env->features[FEAT_7_0_EBX] &= ~CPUID_7_0_EBX_INTEL_PT; -- cpu->filtered_features[FEAT_7_0_EBX] |= CPUID_7_0_EBX_INTEL_PT; -- rv = 1; -+ mark_unavailable_features(cpu, FEAT_7_0_EBX, CPUID_7_0_EBX_INTEL_PT, prefix); - } - } -- -- return rv; - } - - static void x86_cpu_realizefn(DeviceState *dev, Error **errp) -@@ -5364,16 +5375,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) - goto out; - } - -- if (x86_cpu_filter_features(cpu) && -- (cpu->check_cpuid || cpu->enforce_cpuid)) { -- x86_cpu_report_filtered_features(cpu); -- if (cpu->enforce_cpuid) { -- error_setg(&local_err, -- accel_uses_host_cpuid() ? -- "Host doesn't support requested features" : -- "TCG doesn't support requested features"); -- goto out; -- } -+ x86_cpu_filter_features(cpu, cpu->check_cpuid || cpu->enforce_cpuid); -+ -+ if (cpu->enforce_cpuid && x86_cpu_have_filtered_features(cpu)) { -+ error_setg(&local_err, -+ accel_uses_host_cpuid() ? -+ "Host doesn't support requested features" : -+ "TCG doesn't support requested features"); -+ goto out; - } - - /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on --- -2.27.0 - diff --git a/target-i386-introduce-generic-feature-dependency-mec.patch b/target-i386-introduce-generic-feature-dependency-mec.patch deleted file mode 100644 index da374c58652d5559993c9a584d7c83377d6669cd..0000000000000000000000000000000000000000 --- a/target-i386-introduce-generic-feature-dependency-mec.patch +++ /dev/null @@ -1,146 +0,0 @@ -From ed8fa9d895a0e06434b4163405aeaacbe65bcf44 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 1 Jul 2019 17:26:45 +0200 -Subject: [PATCH] target/i386: introduce generic feature dependency mechanism - -Sometimes a CPU feature does not make sense unless another is -present. In the case of VMX features, KVM does not even allow -setting the VMX controls to some invalid combinations. - -Therefore, this patch adds a generic mechanism that looks for bits -that the user explicitly cleared, and uses them to remove other bits -from the expanded CPU definition. If these dependent bits were also -explicitly *set* by the user, this will be a warning for "-cpu check" -and an error for "-cpu enforce". If not, then the dependent bits are -cleared silently, for convenience. - -With VMX features, this will be used so that for example -"-cpu host,-rdrand" will also hide support for RDRAND exiting. - -Signed-off-by: Paolo Bonzini ---- - target/i386/cpu.c | 72 +++++++++++++++++++++++++++++++---------------- - 1 file changed, 48 insertions(+), 24 deletions(-) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index 8798cafc7a..d4a435ba96 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -801,10 +801,6 @@ typedef struct FeatureWordInfo { - /* If type==MSR_FEATURE_WORD */ - struct { - uint32_t index; -- struct { /*CPUID that enumerate this MSR*/ -- FeatureWord cpuid_class; -- uint32_t cpuid_flag; -- } cpuid_dep; - } msr; - }; - uint32_t tcg_features; /* Feature flags supported by TCG */ -@@ -1218,10 +1214,6 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { - }, - .msr = { - .index = MSR_IA32_ARCH_CAPABILITIES, -- .cpuid_dep = { -- FEAT_7_0_EDX, -- CPUID_7_0_EDX_ARCH_CAPABILITIES -- } - }, - }, - [FEAT_CORE_CAPABILITY] = { -@@ -1238,14 +1230,30 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { - }, - .msr = { - .index = MSR_IA32_CORE_CAPABILITY, -- .cpuid_dep = { -- FEAT_7_0_EDX, -- CPUID_7_0_EDX_CORE_CAPABILITY, -- }, - }, - }, - }; - -+typedef struct FeatureMask { -+ FeatureWord index; -+ uint32_t mask; -+} FeatureMask; -+ -+typedef struct FeatureDep { -+ FeatureMask from, to; -+} FeatureDep; -+ -+static FeatureDep feature_dependencies[] = { -+ { -+ .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_ARCH_CAPABILITIES }, -+ .to = { FEAT_ARCH_CAPABILITIES, ~0u }, -+ }, -+ { -+ .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY }, -+ .to = { FEAT_CORE_CAPABILITY, ~0u }, -+ }, -+}; -+ - typedef struct X86RegisterInfo32 { - /* Name of register */ - const char *name; -@@ -5183,9 +5191,26 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) - { - CPUX86State *env = &cpu->env; - FeatureWord w; -+ int i; - GList *l; - Error *local_err = NULL; - -+ for (l = plus_features; l; l = l->next) { -+ const char *prop = l->data; -+ object_property_set_bool(OBJECT(cpu), true, prop, &local_err); -+ if (local_err) { -+ goto out; -+ } -+ } -+ -+ for (l = minus_features; l; l = l->next) { -+ const char *prop = l->data; -+ object_property_set_bool(OBJECT(cpu), false, prop, &local_err); -+ if (local_err) { -+ goto out; -+ } -+ } -+ - /*TODO: Now cpu->max_features doesn't overwrite features - * set using QOM properties, and we can convert - * plus_features & minus_features to global properties -@@ -5203,19 +5228,18 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) - } - } - -- for (l = plus_features; l; l = l->next) { -- const char *prop = l->data; -- object_property_set_bool(OBJECT(cpu), true, prop, &local_err); -- if (local_err) { -- goto out; -- } -- } -+ for (i = 0; i < ARRAY_SIZE(feature_dependencies); i++) { -+ FeatureDep *d = &feature_dependencies[i]; -+ if (!(env->features[d->from.index] & d->from.mask)) { -+ uint32_t unavailable_features = env->features[d->to.index] & d->to.mask; - -- for (l = minus_features; l; l = l->next) { -- const char *prop = l->data; -- object_property_set_bool(OBJECT(cpu), false, prop, &local_err); -- if (local_err) { -- goto out; -+ /* Not an error unless the dependent feature was added explicitly. */ -+ mark_unavailable_features(cpu, d->to.index, -+ unavailable_features & env->user_features[d->to.index], -+ "This feature depends on other features that were not requested"); -+ -+ env->user_features[d->to.index] |= unavailable_features; -+ env->features[d->to.index] &= ~unavailable_features; - } - } - --- -2.27.0 - diff --git a/target-i386-kvm-initialize-feature-MSRs-very-early.patch b/target-i386-kvm-initialize-feature-MSRs-very-early.patch deleted file mode 100644 index 90b6f6fa4ba76fb4dde12567fcf3aee236236bde..0000000000000000000000000000000000000000 --- a/target-i386-kvm-initialize-feature-MSRs-very-early.patch +++ /dev/null @@ -1,178 +0,0 @@ -From c222711e37196e4be1776a084a1acb3c5a1f7283 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 17 Feb 2020 16:23:11 +0000 -Subject: [PATCH] target/i386: kvm: initialize feature MSRs very early -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -RH-Author: Paolo Bonzini -Message-id: <20200217162316.2464-2-pbonzini@redhat.com> -Patchwork-id: 93899 -O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH 1/6] target/i386: kvm: initialize feature MSRs very early -Bugzilla: 1791648 -RH-Acked-by: Philippe Mathieu-Daudé -RH-Acked-by: Maxim Levitsky -RH-Acked-by: Dr. David Alan Gilbert - -Some read-only MSRs affect the behavior of ioctls such as -KVM_SET_NESTED_STATE. We can initialize them once and for all -right after the CPU is realized, since they will never be modified -by the guest. - -Reported-by: Qingua Cheng -Cc: qemu-stable@nongnu.org -Signed-off-by: Paolo Bonzini -Message-Id: <1579544504-3616-2-git-send-email-pbonzini@redhat.com> -Signed-off-by: Paolo Bonzini -(cherry picked from commit 420ae1fc51c99abfd03b1c590f55617edd2a2bed) -Signed-off-by: Danilo C. L. de Paula ---- - target/i386/kvm.c | 81 +++++++++++++++++++++++++----------------- - target/i386/kvm_i386.h | 1 + - 2 files changed, 49 insertions(+), 33 deletions(-) - -diff --git a/target/i386/kvm.c b/target/i386/kvm.c -index 7328746d92..60060087fd 100644 ---- a/target/i386/kvm.c -+++ b/target/i386/kvm.c -@@ -63,6 +63,8 @@ - * 255 kvm_msr_entry structs */ - #define MSR_BUF_SIZE 4096 - -+static void kvm_init_msrs(X86CPU *cpu); -+ - const KVMCapabilityInfo kvm_arch_required_capabilities[] = { - KVM_CAP_INFO(SET_TSS_ADDR), - KVM_CAP_INFO(EXT_CPUID), -@@ -1777,6 +1779,8 @@ int kvm_arch_init_vcpu(CPUState *cs) - has_msr_tsc_aux = false; - } - -+ kvm_init_msrs(cpu); -+ - r = hyperv_init_vcpu(cpu); - if (r) { - goto fail; -@@ -2592,11 +2596,53 @@ static void kvm_msr_entry_add_vmx(X86CPU *cpu, FeatureWordArray f) - VMCS12_MAX_FIELD_INDEX << 1); - } - -+static int kvm_buf_set_msrs(X86CPU *cpu) -+{ -+ int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf); -+ if (ret < 0) { -+ return ret; -+ } -+ -+ if (ret < cpu->kvm_msr_buf->nmsrs) { -+ struct kvm_msr_entry *e = &cpu->kvm_msr_buf->entries[ret]; -+ error_report("error: failed to set MSR 0x%" PRIx32 " to 0x%" PRIx64, -+ (uint32_t)e->index, (uint64_t)e->data); -+ } -+ -+ assert(ret == cpu->kvm_msr_buf->nmsrs); -+ return 0; -+} -+ -+static void kvm_init_msrs(X86CPU *cpu) -+{ -+ CPUX86State *env = &cpu->env; -+ -+ kvm_msr_buf_reset(cpu); -+ if (has_msr_arch_capabs) { -+ kvm_msr_entry_add(cpu, MSR_IA32_ARCH_CAPABILITIES, -+ env->features[FEAT_ARCH_CAPABILITIES]); -+ } -+ -+ if (has_msr_core_capabs) { -+ kvm_msr_entry_add(cpu, MSR_IA32_CORE_CAPABILITY, -+ env->features[FEAT_CORE_CAPABILITY]); -+ } -+ -+ /* -+ * Older kernels do not include VMX MSRs in KVM_GET_MSR_INDEX_LIST, but -+ * all kernels with MSR features should have them. -+ */ -+ if (kvm_feature_msrs && cpu_has_vmx(env)) { -+ kvm_msr_entry_add_vmx(cpu, env->features); -+ } -+ -+ assert(kvm_buf_set_msrs(cpu) == 0); -+} -+ - static int kvm_put_msrs(X86CPU *cpu, int level) - { - CPUX86State *env = &cpu->env; - int i; -- int ret; - - kvm_msr_buf_reset(cpu); - -@@ -2648,17 +2694,6 @@ static int kvm_put_msrs(X86CPU *cpu, int level) - } - #endif - -- /* If host supports feature MSR, write down. */ -- if (has_msr_arch_capabs) { -- kvm_msr_entry_add(cpu, MSR_IA32_ARCH_CAPABILITIES, -- env->features[FEAT_ARCH_CAPABILITIES]); -- } -- -- if (has_msr_core_capabs) { -- kvm_msr_entry_add(cpu, MSR_IA32_CORE_CAPABILITY, -- env->features[FEAT_CORE_CAPABILITY]); -- } -- - /* - * The following MSRs have side effects on the guest or are too heavy - * for normal writeback. Limit them to reset or full state updates. -@@ -2831,14 +2866,6 @@ static int kvm_put_msrs(X86CPU *cpu, int level) - - /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see - * kvm_put_msr_feature_control. */ -- -- /* -- * Older kernels do not include VMX MSRs in KVM_GET_MSR_INDEX_LIST, but -- * all kernels with MSR features should have them. -- */ -- if (kvm_feature_msrs && cpu_has_vmx(env)) { -- kvm_msr_entry_add_vmx(cpu, env->features); -- } - } - - if (env->mcg_cap) { -@@ -2854,19 +2881,7 @@ static int kvm_put_msrs(X86CPU *cpu, int level) - } - } - -- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf); -- if (ret < 0) { -- return ret; -- } -- -- if (ret < cpu->kvm_msr_buf->nmsrs) { -- struct kvm_msr_entry *e = &cpu->kvm_msr_buf->entries[ret]; -- error_report("error: failed to set MSR 0x%" PRIx32 " to 0x%" PRIx64, -- (uint32_t)e->index, (uint64_t)e->data); -- } -- -- assert(ret == cpu->kvm_msr_buf->nmsrs); -- return 0; -+ return kvm_buf_set_msrs(cpu); - } - - -diff --git a/target/i386/kvm_i386.h b/target/i386/kvm_i386.h -index 06fe06bdb3..d98c6f69d0 100644 ---- a/target/i386/kvm_i386.h -+++ b/target/i386/kvm_i386.h -@@ -66,4 +66,5 @@ bool kvm_enable_x2apic(void); - bool kvm_has_x2apic_api(void); - - bool kvm_hv_vpindex_settable(void); -+ - #endif --- -2.27.0 - diff --git a/target-i386-kvm-initialize-microcode-revision-from-K.patch b/target-i386-kvm-initialize-microcode-revision-from-K.patch deleted file mode 100644 index 5c15a47a5c025cc76e9f0fb2d9ade102a6cee294..0000000000000000000000000000000000000000 --- a/target-i386-kvm-initialize-microcode-revision-from-K.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 8664cd20e4cdb8594076a26dacef592a4b4816b2 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 20 Jan 2020 19:21:44 +0100 -Subject: [PATCH] target/i386: kvm: initialize microcode revision from KVM - -KVM can return the host microcode revision as a feature MSR. -Use it as the default value for -cpu host. - -Signed-off-by: Paolo Bonzini -Message-Id: <1579544504-3616-4-git-send-email-pbonzini@redhat.com> -Signed-off-by: Paolo Bonzini ---- - target/i386/cpu.c | 4 ++++ - target/i386/kvm.c | 5 +++++ - 2 files changed, 9 insertions(+) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index ec8bc9957e..1962f00c77 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -6330,6 +6330,10 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) - &cpu->mwait.ecx, &cpu->mwait.edx); - env->features[FEAT_1_ECX] |= CPUID_EXT_MONITOR; - } -+ if (kvm_enabled() && cpu->ucode_rev == 0) { -+ cpu->ucode_rev = kvm_arch_get_supported_msr_feature(kvm_state, -+ MSR_IA32_UCODE_REV); -+ } - } - - if (cpu->ucode_rev == 0) { -diff --git a/target/i386/kvm.c b/target/i386/kvm.c -index 60060087fd..7437f86130 100644 ---- a/target/i386/kvm.c -+++ b/target/i386/kvm.c -@@ -2628,6 +2628,11 @@ static void kvm_init_msrs(X86CPU *cpu) - env->features[FEAT_CORE_CAPABILITY]); - } - -+ if (kvm_arch_get_supported_msr_feature(kvm_state, -+ MSR_IA32_UCODE_REV)) { -+ kvm_msr_entry_add(cpu, MSR_IA32_UCODE_REV, cpu->ucode_rev); -+ } -+ - /* - * Older kernels do not include VMX MSRs in KVM_GET_MSR_INDEX_LIST, but - * all kernels with MSR features should have them. --- -2.27.0 - diff --git a/target-i386-set-the-CPUID-level-to-0x14-on-old-machi.patch b/target-i386-set-the-CPUID-level-to-0x14-on-old-machi.patch deleted file mode 100644 index 462768e0318844720a338f553914e6bfbcdb0c8c..0000000000000000000000000000000000000000 --- a/target-i386-set-the-CPUID-level-to-0x14-on-old-machi.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 3b172cd5a6e62be725c778b8397310462fe0a890 Mon Sep 17 00:00:00 2001 -From: "plai@redhat.com" -Date: Thu, 7 May 2020 22:09:23 +0100 -Subject: [PATCH] target/i386: set the CPUID level to 0x14 on old machine-type - -RH-Author: plai@redhat.com -Message-id: <20200507220923.13723-1-plai@redhat.com> -Patchwork-id: 96347 -O-Subject: [RHEL8.2.1 AV qemu-kvm PATCH RESEND] target/i386: set the CPUID level to 0x14 on old machine-type -Bugzilla: 1513681 -RH-Acked-by: Eduardo Habkost -RH-Acked-by: Igor Mammedov -RH-Acked-by: Danilo de Paula - -From: Luwei Kang - -BZ https://bugzilla.redhat.com/show_bug.cgi?id=1513681 -Brew: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=28146304 -Branch: rhel-av-8.2.1 - -Tested on intel-icelake-y-01.ml3.eng.bos.redhat.com. - -The CPUID level need to be set to 0x14 manually on old -machine-type if Intel PT is enabled in guest. E.g. the -CPUID[0].EAX(level)=7 and CPUID[7].EBX[25](intel-pt)=1 when the -Qemu with "-machine pc-i440fx-3.1 -cpu qemu64,+intel-pt" parameter. - -Some Intel PT capabilities are exposed by leaf 0x14 and the -missing capabilities will cause some MSRs access failed. -This patch add a warning message to inform the user to extend -the CPUID level. - -Suggested-by: Eduardo Habkost -Signed-off-by: Luwei Kang -Message-Id: <1584031686-16444-1-git-send-email-luwei.kang@intel.com> -Signed-off-by: Eduardo Habkost -(cherry picked from commit ddc2fc9e4e42ebce48b088963dc7fbd1c08d5f33) -Signed-off-by: Paul Lai -Signed-off-by: Danilo C. L. de Paula ---- - target/i386/cpu.c | 11 ++++++++--- - 1 file changed, 8 insertions(+), 3 deletions(-) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index 6147cd419a..35a33db39a 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -6206,9 +6206,14 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) - x86_cpu_adjust_feat_level(cpu, FEAT_XSAVE); - - /* Intel Processor Trace requires CPUID[0x14] */ -- if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) && -- kvm_enabled() && cpu->intel_pt_auto_level) { -- x86_cpu_adjust_level(cpu, &cpu->env.cpuid_min_level, 0x14); -+ if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT)) { -+ if (cpu->intel_pt_auto_level) { -+ x86_cpu_adjust_level(cpu, &cpu->env.cpuid_min_level, 0x14); -+ } else if (cpu->env.cpuid_min_level < 0x14) { -+ mark_unavailable_features(cpu, FEAT_7_0_EBX, -+ CPUID_7_0_EBX_INTEL_PT, -+ "Intel PT need CPUID leaf 0x14, please set by \"-cpu ...,+intel-pt,level=0x14\""); -+ } - } - - /* CPU topology with multi-dies support requires CPUID[0x1F] */ --- -2.27.0 - diff --git a/target-i386-work-around-KVM_GET_MSRS-bug-for-seconda.patch b/target-i386-work-around-KVM_GET_MSRS-bug-for-seconda.patch deleted file mode 100644 index b4156952cf7fca7359fb38c8db086837b8ba3651..0000000000000000000000000000000000000000 --- a/target-i386-work-around-KVM_GET_MSRS-bug-for-seconda.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 70e4d278b89e04d7f9397ea25163feb6a7dbaa2d Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Tue, 2 Jul 2019 14:58:48 +0200 -Subject: [PATCH] target/i386: work around KVM_GET_MSRS bug for secondary - execution controls - -Some secondary controls are automatically enabled/disabled based on the CPUID -values that are set for the guest. However, they are still available at a -global level and therefore should be present when KVM_GET_MSRS is sent to -/dev/kvm. - -Unfortunately KVM forgot to include those, so fix that. - -Signed-off-by: Paolo Bonzini ---- - target/i386/kvm.c | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/target/i386/kvm.c b/target/i386/kvm.c -index fafb9fb26d..b97f40df6b 100644 ---- a/target/i386/kvm.c -+++ b/target/i386/kvm.c -@@ -474,6 +474,23 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) - value = msr_data.entries[0].data; - switch (index) { - case MSR_IA32_VMX_PROCBASED_CTLS2: -+ /* KVM forgot to add these bits for some time, do this ourselves. */ -+ if (kvm_arch_get_supported_cpuid(s, 0xD, 1, R_ECX) & CPUID_XSAVE_XSAVES) { -+ value |= (uint64_t)VMX_SECONDARY_EXEC_XSAVES << 32; -+ } -+ if (kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX) & CPUID_EXT_RDRAND) { -+ value |= (uint64_t)VMX_SECONDARY_EXEC_RDRAND_EXITING << 32; -+ } -+ if (kvm_arch_get_supported_cpuid(s, 7, 0, R_EBX) & CPUID_7_0_EBX_INVPCID) { -+ value |= (uint64_t)VMX_SECONDARY_EXEC_ENABLE_INVPCID << 32; -+ } -+ if (kvm_arch_get_supported_cpuid(s, 7, 0, R_EBX) & CPUID_7_0_EBX_RDSEED) { -+ value |= (uint64_t)VMX_SECONDARY_EXEC_RDSEED_EXITING << 32; -+ } -+ if (kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX) & CPUID_EXT2_RDTSCP) { -+ value |= (uint64_t)VMX_SECONDARY_EXEC_RDTSCP << 32; -+ } -+ /* fall through */ - case MSR_IA32_VMX_TRUE_PINBASED_CTLS: - case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: - case MSR_IA32_VMX_TRUE_ENTRY_CTLS: --- -2.27.0 - diff --git a/tcp_emu-Fix-oob-access.patch b/tcp_emu-Fix-oob-access.patch deleted file mode 100644 index 807dfef08e28fe33a65fede676bbb076f5d9e393..0000000000000000000000000000000000000000 --- a/tcp_emu-Fix-oob-access.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 585634894f511bc1821cef54494bf2d9abc109c9 Mon Sep 17 00:00:00 2001 -From: Samuel Thibault -Date: Tue, 14 Apr 2020 18:04:33 +0800 -Subject: [PATCH] tcp_emu: Fix oob access - -The main loop only checks for one available byte, while we sometimes -need two bytes. ---- - slirp/src/tcp_subr.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/slirp/src/tcp_subr.c b/slirp/src/tcp_subr.c -index d6dd133a..9c94c03a 100644 ---- a/slirp/src/tcp_subr.c -+++ b/slirp/src/tcp_subr.c -@@ -886,6 +886,9 @@ int tcp_emu(struct socket *so, struct mbuf *m) - break; - - case 5: -+ if (bptr == m->m_data + m->m_len - 1) -+ return 1; /* We need two bytes */ -+ - /* - * The difference between versions 1.0 and - * 2.0 is here. For future versions of -@@ -901,6 +904,9 @@ int tcp_emu(struct socket *so, struct mbuf *m) - /* This is the field containing the port - * number that RA-player is listening to. - */ -+ if (bptr == m->m_data + m->m_len - 1) -+ return 1; /* We need two bytes */ -+ - lport = (((uint8_t *)bptr)[0] << 8) + ((uint8_t *)bptr)[1]; - if (lport < 6970) - lport += 256; /* don't know why */ --- -2.23.0 diff --git a/tcp_emu-fix-unsafe-snprintf-usages.patch b/tcp_emu-fix-unsafe-snprintf-usages.patch deleted file mode 100644 index 2f6850a60c2fb942ecc7ef15030686d3dd94aa9c..0000000000000000000000000000000000000000 --- a/tcp_emu-fix-unsafe-snprintf-usages.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 220a52fda279038d46c25d39a372154ff9b024d2 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureauls?= -Date: Tue, 14 Apr 2020 19:06:35 +0800 -Subject: [PATCH] tcp_emu: fix unsafe snprintf() usages -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Various calls to snprintf() assume that snprintf() returns "only" the -number of bytes written (excluding terminating NUL). - -https://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html#tag_16_159_04 - -"Upon successful completion, the snprintf() function shall return the -number of bytes that would be written to s had n been sufficiently -large excluding the terminating null byte." - -Before patch ce131029, if there isn't enough room in "m_data" for the -"DCC ..." message, we overflow "m_data". - -After the patch, if there isn't enough room for the same, we don't -overflow "m_data", but we set "m_len" out-of-bounds. The next time an -access is bounded by "m_len", we'll have a buffer overflow then. - -Use slirp_fmt*() to fix potential OOB memory access. -Reported-by: default avatarLaszlo Ersek -Signed-off-by: default avatarMarc-André Lureau -Reviewed-by: Samuel Thibault's avatarSamuel Thibault -Message-Id: <20200127092414.169796-7-marcandre.lureau@redhat.com> ---- - slirp/src/tcp_subr.c | 15 +++++++-------- - 1 file changed, 7 insertions(+), 8 deletions(-) - -diff --git a/slirp/src/tcp_subr.c b/slirp/src/tcp_subr.c -index 019b637a..6c1b17bd 100644 ---- a/slirp/src/tcp_subr.c -+++ b/slirp/src/tcp_subr.c -@@ -655,8 +655,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) - NTOHS(n1); - NTOHS(n2); - m_inc(m, snprintf(NULL, 0, "%d,%d\r\n", n1, n2) + 1); -- m->m_len = snprintf(m->m_data, M_ROOM(m), "%d,%d\r\n", n1, n2); -- assert(m->m_len < M_ROOM(m)); -+ m->m_len = slirp_fmt(m->m_data, M_ROOM(m), "%d,%d\r\n", n1, n2); - } else { - *eol = '\r'; - } -@@ -696,7 +695,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) - n4 = (laddr & 0xff); - - m->m_len = bptr - m->m_data; /* Adjust length */ -- m->m_len += snprintf(bptr, M_FREEROOM(m), -+ m->m_len += slirp_fmt(bptr, M_FREEROOM(m), - "ORT %d,%d,%d,%d,%d,%d\r\n%s", n1, n2, n3, n4, - n5, n6, x == 7 ? buff : ""); - return 1; -@@ -732,7 +731,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) - - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += -- snprintf(bptr, M_FREEROOM(m), -+ slirp_fmt(bptr, M_FREEROOM(m), - "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s", - n1, n2, n3, n4, n5, n6, x == 7 ? buff : ""); - -@@ -759,7 +758,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) - (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr, - htons(lport), SS_FACCEPTONCE)) != NULL) - m->m_len = -- snprintf(m->m_data, M_ROOM(m), -+ slirp_fmt0(m->m_data, M_ROOM(m), - "%d", ntohs(so->so_fport)) + 1; - return 1; - -@@ -779,7 +778,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) - return 1; - } - m->m_len = bptr - m->m_data; /* Adjust length */ -- m->m_len += snprintf(bptr, M_FREEROOM(m), -+ m->m_len += slirp_fmt(bptr, M_FREEROOM(m), - "DCC CHAT chat %lu %u%c\n", - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), 1); -@@ -791,7 +790,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) - } - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += -- snprintf(bptr, M_FREEROOM(m), -+ slirp_fmt(bptr, M_FREEROOM(m), - "DCC SEND %s %lu %u %u%c\n", buff, - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), n1, 1); -@@ -803,7 +802,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) - } - m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += -- snprintf(bptr, M_FREEROOM(m), -+ slirp_fmt(bptr, M_FREEROOM(m), - "DCC MOVE %s %lu %u %u%c\n", buff, - (unsigned long)ntohl(so->so_faddr.s_addr), - ntohs(so->so_fport), n1, 1); --- -2.23.0 diff --git a/test-numa-Adjust-aarch64-numa-test.patch b/test-numa-Adjust-aarch64-numa-test.patch index 24145937724385b1ff8dd0bd280e5e62341ad659..cb3331439de9a93efc720dd38dd5dac9e67caae1 100644 --- a/test-numa-Adjust-aarch64-numa-test.patch +++ b/test-numa-Adjust-aarch64-numa-test.patch @@ -1,4 +1,4 @@ -From 3ef97cc418d1061fc0ec70098270ce2d76005cc1 Mon Sep 17 00:00:00 2001 +From 1a347bf3f8e7e31cdaed265af22853d66c202090 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Thu, 23 Apr 2020 20:54:18 +0800 Subject: [PATCH] test/numa: Adjust aarch64 numa test @@ -8,20 +8,20 @@ changes the meaning of "thread-id", so we must modify test case. Signed-off-by: Keqian Zhu --- - tests/numa-test.c | 16 ++++++++-------- + tests/qtest/numa-test.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) -diff --git a/tests/numa-test.c b/tests/numa-test.c -index 8de8581231..71cdd7b4f7 100644 ---- a/tests/numa-test.c -+++ b/tests/numa-test.c -@@ -231,17 +231,17 @@ static void aarch64_numa_cpu(const void *data) - QObject *e; +diff --git a/tests/qtest/numa-test.c b/tests/qtest/numa-test.c +index 90bf68a5b3..08f28012c8 100644 +--- a/tests/qtest/numa-test.c ++++ b/tests/qtest/numa-test.c +@@ -223,17 +223,17 @@ static void aarch64_numa_cpu(const void *data) QTestState *qts; - -- cli = make_cli(data, "-smp 2 " -+ cli = make_cli(data, "-smp 2,cores=2 " - "-numa node,nodeid=0 -numa node,nodeid=1 " + g_autofree char *cli = NULL; + +- cli = make_cli(data, "-machine smp.cpus=2 " ++ cli = make_cli(data, "-machine smp.cpus=2,smp.cores=2 " + "-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 " - "-numa cpu,node-id=1,thread-id=0 " - "-numa cpu,node-id=0,thread-id=1"); + "-numa cpu,node-id=1,core-id=0 " @@ -29,23 +29,23 @@ index 8de8581231..71cdd7b4f7 100644 qts = qtest_init(cli); cpus = get_cpus(qts, &resp); g_assert(cpus); - + while ((e = qlist_pop(cpus))) { QDict *cpu, *props; - int64_t thread, node; + int64_t core, node; - + cpu = qobject_to(QDict, e); g_assert(qdict_haskey(cpu, "props")); -@@ -249,12 +249,12 @@ static void aarch64_numa_cpu(const void *data) - +@@ -241,12 +241,12 @@ static void aarch64_numa_cpu(const void *data) + g_assert(qdict_haskey(props, "node-id")); node = qdict_get_int(props, "node-id"); - g_assert(qdict_haskey(props, "thread-id")); - thread = qdict_get_int(props, "thread-id"); + g_assert(qdict_haskey(props, "core-id")); + core = qdict_get_int(props, "core-id"); - + - if (thread == 0) { + if (core == 0) { g_assert_cmpint(node, ==, 1); @@ -54,5 +54,6 @@ index 8de8581231..71cdd7b4f7 100644 g_assert_cmpint(node, ==, 0); } else { g_assert(false); --- -2.19.1 +-- +2.27.0 + diff --git a/test-tpm-pass-optional-machine-options-to-swtpm-test.patch b/test-tpm-pass-optional-machine-options-to-swtpm-test.patch deleted file mode 100644 index fe7fd4ac907813d676cdf0c2a713e31279c29685..0000000000000000000000000000000000000000 --- a/test-tpm-pass-optional-machine-options-to-swtpm-test.patch +++ /dev/null @@ -1,187 +0,0 @@ -From c06a3ceacc1793bc1cfe5c2a6ed510c9aea8253d Mon Sep 17 00:00:00 2001 -From: jiangfangjie -Date: Thu, 13 Aug 2020 20:28:25 +0800 -Subject: [PATCH 17/19] test: tpm: pass optional machine options to swtpm test - functions - -We plan to use swtpm test functions on ARM for testing the -sysbus TPM-TIS device. However on ARM there is no default machine -type. So we need to explictly pass some machine options on startup. -Let's allow this by adding a new parameter to both swtpm test -functions and update all call sites. - -Signed-off-by: Eric Auger -Reviewed-by: Stefan Berger -Message-id: 20200305165149.618-9-eric.auger@redhat.com -Signed-off-by: Stefan Berger -Signed-off-by: jiangfangjie ---- - tests/tpm-crb-swtpm-test.c | 5 +++-- - tests/tpm-tests.c | 10 ++++++---- - tests/tpm-tests.h | 5 +++-- - tests/tpm-tis-swtpm-test.c | 5 +++-- - tests/tpm-util.c | 8 ++++++-- - tests/tpm-util.h | 3 ++- - 6 files changed, 23 insertions(+), 13 deletions(-) - -diff --git a/tests/tpm-crb-swtpm-test.c b/tests/tpm-crb-swtpm-test.c -index 2c4fb8ae..5228cb7a 100644 ---- a/tests/tpm-crb-swtpm-test.c -+++ b/tests/tpm-crb-swtpm-test.c -@@ -29,7 +29,8 @@ static void tpm_crb_swtpm_test(const void *data) - { - const TestState *ts = data; - -- tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_crb_transfer, "tpm-crb"); -+ tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_crb_transfer, -+ "tpm-crb", NULL); - } - - static void tpm_crb_swtpm_migration_test(const void *data) -@@ -37,7 +38,7 @@ static void tpm_crb_swtpm_migration_test(const void *data) - const TestState *ts = data; - - tpm_test_swtpm_migration_test(ts->src_tpm_path, ts->dst_tpm_path, ts->uri, -- tpm_util_crb_transfer, "tpm-crb"); -+ tpm_util_crb_transfer, "tpm-crb", NULL); - } - - int main(int argc, char **argv) -diff --git a/tests/tpm-tests.c b/tests/tpm-tests.c -index e640777a..d823bda8 100644 ---- a/tests/tpm-tests.c -+++ b/tests/tpm-tests.c -@@ -30,7 +30,7 @@ tpm_test_swtpm_skip(void) - } - - void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx, -- const char *ifmodel) -+ const char *ifmodel, const char *machine_options) - { - char *args = NULL; - QTestState *s; -@@ -47,10 +47,11 @@ void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx, - g_assert_true(succ); - - args = g_strdup_printf( -+ "%s " - "-chardev socket,id=chr,path=%s " - "-tpmdev emulator,id=dev,chardev=chr " - "-device %s,tpmdev=dev", -- addr->u.q_unix.path, ifmodel); -+ machine_options ? : "", addr->u.q_unix.path, ifmodel); - - s = qtest_start(args); - g_free(args); -@@ -78,7 +79,8 @@ void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx, - void tpm_test_swtpm_migration_test(const char *src_tpm_path, - const char *dst_tpm_path, - const char *uri, tx_func *tx, -- const char *ifmodel) -+ const char *ifmodel, -+ const char *machine_options) - { - gboolean succ; - GPid src_tpm_pid, dst_tpm_pid; -@@ -100,7 +102,7 @@ void tpm_test_swtpm_migration_test(const char *src_tpm_path, - - tpm_util_migration_start_qemu(&src_qemu, &dst_qemu, - src_tpm_addr, dst_tpm_addr, uri, -- ifmodel); -+ ifmodel, machine_options); - - tpm_util_startup(src_qemu, tx); - tpm_util_pcrextend(src_qemu, tx); -diff --git a/tests/tpm-tests.h b/tests/tpm-tests.h -index b97688fe..a5df35ab 100644 ---- a/tests/tpm-tests.h -+++ b/tests/tpm-tests.h -@@ -16,11 +16,12 @@ - #include "tpm-util.h" - - void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx, -- const char *ifmodel); -+ const char *ifmodel, const char *machine_options); - - void tpm_test_swtpm_migration_test(const char *src_tpm_path, - const char *dst_tpm_path, - const char *uri, tx_func *tx, -- const char *ifmodel); -+ const char *ifmodel, -+ const char *machine_options); - - #endif /* TESTS_TPM_TESTS_H */ -diff --git a/tests/tpm-tis-swtpm-test.c b/tests/tpm-tis-swtpm-test.c -index 9f58a3a9..9470f157 100644 ---- a/tests/tpm-tis-swtpm-test.c -+++ b/tests/tpm-tis-swtpm-test.c -@@ -29,7 +29,8 @@ static void tpm_tis_swtpm_test(const void *data) - { - const TestState *ts = data; - -- tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_tis_transfer, "tpm-tis"); -+ tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_tis_transfer, -+ "tpm-tis", NULL); - } - - static void tpm_tis_swtpm_migration_test(const void *data) -@@ -37,7 +38,7 @@ static void tpm_tis_swtpm_migration_test(const void *data) - const TestState *ts = data; - - tpm_test_swtpm_migration_test(ts->src_tpm_path, ts->dst_tpm_path, ts->uri, -- tpm_util_tis_transfer, "tpm-tis"); -+ tpm_util_tis_transfer, "tpm-tis", NULL); - } - - int main(int argc, char **argv) -diff --git a/tests/tpm-util.c b/tests/tpm-util.c -index e08b1376..7ecdae2f 100644 ---- a/tests/tpm-util.c -+++ b/tests/tpm-util.c -@@ -258,23 +258,27 @@ void tpm_util_migration_start_qemu(QTestState **src_qemu, - SocketAddress *src_tpm_addr, - SocketAddress *dst_tpm_addr, - const char *miguri, -- const char *ifmodel) -+ const char *ifmodel, -+ const char *machine_options) - { - char *src_qemu_args, *dst_qemu_args; - - src_qemu_args = g_strdup_printf( -+ "%s " - "-chardev socket,id=chr,path=%s " - "-tpmdev emulator,id=dev,chardev=chr " - "-device %s,tpmdev=dev ", -- src_tpm_addr->u.q_unix.path, ifmodel); -+ machine_options ? : "", src_tpm_addr->u.q_unix.path, ifmodel); - - *src_qemu = qtest_init(src_qemu_args); - - dst_qemu_args = g_strdup_printf( -+ "%s " - "-chardev socket,id=chr,path=%s " - "-tpmdev emulator,id=dev,chardev=chr " - "-device %s,tpmdev=dev " - "-incoming %s", -+ machine_options ? : "", - dst_tpm_addr->u.q_unix.path, - ifmodel, miguri); - -diff --git a/tests/tpm-util.h b/tests/tpm-util.h -index 5755698a..15e39249 100644 ---- a/tests/tpm-util.h -+++ b/tests/tpm-util.h -@@ -44,7 +44,8 @@ void tpm_util_migration_start_qemu(QTestState **src_qemu, - SocketAddress *src_tpm_addr, - SocketAddress *dst_tpm_addr, - const char *miguri, -- const char *ifmodel); -+ const char *ifmodel, -+ const char *machine_options); - - void tpm_util_wait_for_migration_complete(QTestState *who); - --- -2.23.0 - diff --git a/test-tpm-tis-Add-Sysbus-TPM-TIS-device-test.patch b/test-tpm-tis-Add-Sysbus-TPM-TIS-device-test.patch deleted file mode 100644 index fe33c8f4bd99eba304dc696d70a5126c559cd052..0000000000000000000000000000000000000000 --- a/test-tpm-tis-Add-Sysbus-TPM-TIS-device-test.patch +++ /dev/null @@ -1,226 +0,0 @@ -From 2d28c0edddeaee5e4aa6e8c6b109776cddc1c4e4 Mon Sep 17 00:00:00 2001 -From: jiangfangjie -Date: Thu, 13 Aug 2020 21:37:23 +0800 -Subject: [PATCH 19/19] test: tpm-tis: Add Sysbus TPM-TIS device test - -The tests themselves are the same as the ISA device ones. -Only the main() changes as the tpm-tis-device device gets -instantiated. Also the base address of the device is not -0xFED40000 anymore but matches the base address of the -ARM virt platform bus. - -Signed-off-by: Eric Auger -Reviewed-by: Stefan Berger -Message-id: 20200305165149.618-11-eric.auger@redhat.com -Signed-off-by: Stefan Berger -Signed-off-by: jiangfangjie ---- - tests/Makefile.include | 5 ++ - tests/tpm-tis-device-swtpm-test.c | 76 +++++++++++++++++++++++++++ - tests/tpm-tis-device-test.c | 87 +++++++++++++++++++++++++++++++ - 3 files changed, 168 insertions(+) - create mode 100644 tests/tpm-tis-device-swtpm-test.c - create mode 100644 tests/tpm-tis-device-test.c - -diff --git a/tests/Makefile.include b/tests/Makefile.include -index 950b32a2..d6de4e10 100644 ---- a/tests/Makefile.include -+++ b/tests/Makefile.include -@@ -263,6 +263,8 @@ check-qtest-arm-y += tests/boot-serial-test$(EXESUF) - check-qtest-arm-y += tests/hexloader-test$(EXESUF) - check-qtest-arm-$(CONFIG_PFLASH_CFI02) += tests/pflash-cfi02-test$(EXESUF) - -+check-qtest-aarch64-$(CONFIG_TPM_TIS_SYSBUS) += tpm-tis-device-test -+check-qtest-aarch64-$(CONFIG_TPM_TIS_SYSBUS) += tpm-tis-device-swtpm-test - check-qtest-aarch64-y = tests/numa-test$(EXESUF) - check-qtest-aarch64-y += tests/boot-serial-test$(EXESUF) - check-qtest-aarch64-y += tests/migration-test$(EXESUF) -@@ -667,7 +669,10 @@ tests/tpm-crb-swtpm-test$(EXESUF): tests/tpm-crb-swtpm-test.o tests/tpm-emu.o \ - tests/tpm-crb-test$(EXESUF): tests/tpm-crb-test.o tests/tpm-emu.o $(test-io-obj-y) - tests/tpm-tis-swtpm-test$(EXESUF): tests/tpm-tis-swtpm-test.o tests/tpm-emu.o \ - tests/tpm-util.o tests/tpm-tests.o $(test-io-obj-y) -+tests/tpm-tis-device-swtpm-test$(EXESUF): tests/tpm-tis-device-swtpm-test.o tests/tpm-emu.o \ -+ tests/tpm-util.o tests/tpm-tests.o $(test-io-obj-y) - tests/tpm-tis-test$(EXESUF): tests/tpm-tis-test.o tests/tpm-tis-util.o tests/tpm-emu.o $(test-io-obj-y) -+tests/tpm-tis-device-test$(EXESUF): tests/tpm-tis-device-test.o tests/tpm-tis-util.o tests/tpm-emu.o $(test-io-obj-y) - tests/test-io-channel-file$(EXESUF): tests/test-io-channel-file.o \ - tests/io-channel-helpers.o $(test-io-obj-y) - tests/test-io-channel-tls$(EXESUF): tests/test-io-channel-tls.o \ -diff --git a/tests/tpm-tis-device-swtpm-test.c b/tests/tpm-tis-device-swtpm-test.c -new file mode 100644 -index 00000000..7b200351 ---- /dev/null -+++ b/tests/tpm-tis-device-swtpm-test.c -@@ -0,0 +1,76 @@ -+/* -+ * QTest testcase for Sysbus TPM TIS talking to external swtpm and swtpm -+ * migration -+ * -+ * Copyright (c) 2018 IBM Corporation -+ * with parts borrowed from migration-test.c that is: -+ * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates -+ * -+ * Authors: -+ * Stefan Berger -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#include "qemu/osdep.h" -+#include -+ -+#include "libqtest.h" -+#include "qemu/module.h" -+#include "tpm-tests.h" -+#include "hw/acpi/tpm.h" -+ -+uint64_t tpm_tis_base_addr = 0xc000000; -+#define MACHINE_OPTIONS "-machine virt,gic-version=max -accel tcg" -+ -+typedef struct TestState { -+ char *src_tpm_path; -+ char *dst_tpm_path; -+ char *uri; -+} TestState; -+ -+static void tpm_tis_swtpm_test(const void *data) -+{ -+ const TestState *ts = data; -+ -+ tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_tis_transfer, -+ "tpm-tis-device", MACHINE_OPTIONS); -+} -+ -+static void tpm_tis_swtpm_migration_test(const void *data) -+{ -+ const TestState *ts = data; -+ -+ tpm_test_swtpm_migration_test(ts->src_tpm_path, ts->dst_tpm_path, ts->uri, -+ tpm_util_tis_transfer, "tpm-tis-device", -+ MACHINE_OPTIONS); -+} -+ -+int main(int argc, char **argv) -+{ -+ int ret; -+ TestState ts = { 0 }; -+ -+ ts.src_tpm_path = g_dir_make_tmp("qemu-tpm-tis-device-swtpm-test.XXXXXX", -+ NULL); -+ ts.dst_tpm_path = g_dir_make_tmp("qemu-tpm-tis-device-swtpm-test.XXXXXX", -+ NULL); -+ ts.uri = g_strdup_printf("unix:%s/migsocket", ts.src_tpm_path); -+ -+ module_call_init(MODULE_INIT_QOM); -+ g_test_init(&argc, &argv, NULL); -+ -+ qtest_add_data_func("/tpm/tis-swtpm/test", &ts, tpm_tis_swtpm_test); -+ qtest_add_data_func("/tpm/tis-swtpm-migration/test", &ts, -+ tpm_tis_swtpm_migration_test); -+ ret = g_test_run(); -+ -+ g_rmdir(ts.dst_tpm_path); -+ g_free(ts.dst_tpm_path); -+ g_rmdir(ts.src_tpm_path); -+ g_free(ts.src_tpm_path); -+ g_free(ts.uri); -+ -+ return ret; -+} -diff --git a/tests/tpm-tis-device-test.c b/tests/tpm-tis-device-test.c -new file mode 100644 -index 00000000..63ed3644 ---- /dev/null -+++ b/tests/tpm-tis-device-test.c -@@ -0,0 +1,87 @@ -+/* -+ * QTest testcase for SYSBUS TPM TIS -+ * -+ * Copyright (c) 2018 Red Hat, Inc. -+ * Copyright (c) 2018 IBM Corporation -+ * -+ * Authors: -+ * Marc-André Lureau -+ * Stefan Berger -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#include "qemu/osdep.h" -+#include -+ -+#include "io/channel-socket.h" -+#include "libqtest-single.h" -+#include "qemu/module.h" -+#include "tpm-emu.h" -+#include "tpm-util.h" -+#include "tpm-tis-util.h" -+ -+/* -+ * As the Sysbus tpm-tis-device is instantiated on the ARM virt -+ * platform bus and it is the only sysbus device dynamically -+ * instantiated, it gets plugged at its base address -+ */ -+uint64_t tpm_tis_base_addr = 0xc000000; -+ -+int main(int argc, char **argv) -+{ -+ char *tmp_path = g_dir_make_tmp("qemu-tpm-tis-device-test.XXXXXX", NULL); -+ GThread *thread; -+ TestState test; -+ char *args; -+ int ret; -+ -+ module_call_init(MODULE_INIT_QOM); -+ g_test_init(&argc, &argv, NULL); -+ -+ test.addr = g_new0(SocketAddress, 1); -+ test.addr->type = SOCKET_ADDRESS_TYPE_UNIX; -+ test.addr->u.q_unix.path = g_build_filename(tmp_path, "sock", NULL); -+ g_mutex_init(&test.data_mutex); -+ g_cond_init(&test.data_cond); -+ test.data_cond_signal = false; -+ -+ thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test); -+ tpm_emu_test_wait_cond(&test); -+ -+ args = g_strdup_printf( -+ "-machine virt,gic-version=max -accel tcg " -+ "-chardev socket,id=chr,path=%s " -+ "-tpmdev emulator,id=dev,chardev=chr " -+ "-device tpm-tis-device,tpmdev=dev", -+ test.addr->u.q_unix.path); -+ qtest_start(args); -+ -+ qtest_add_data_func("/tpm-tis/test_check_localities", &test, -+ tpm_tis_test_check_localities); -+ -+ qtest_add_data_func("/tpm-tis/test_check_access_reg", &test, -+ tpm_tis_test_check_access_reg); -+ -+ qtest_add_data_func("/tpm-tis/test_check_access_reg_seize", &test, -+ tpm_tis_test_check_access_reg_seize); -+ -+ qtest_add_data_func("/tpm-tis/test_check_access_reg_release", &test, -+ tpm_tis_test_check_access_reg_release); -+ -+ qtest_add_data_func("/tpm-tis/test_check_transmit", &test, -+ tpm_tis_test_check_transmit); -+ -+ ret = g_test_run(); -+ -+ qtest_end(); -+ -+ g_thread_join(thread); -+ g_unlink(test.addr->u.q_unix.path); -+ qapi_free_SocketAddress(test.addr); -+ g_rmdir(tmp_path); -+ g_free(tmp_path); -+ g_free(args); -+ return ret; -+} --- -2.23.0 - diff --git a/test-tpm-tis-Get-prepared-to-share-tests-between-ISA.patch b/test-tpm-tis-Get-prepared-to-share-tests-between-ISA.patch deleted file mode 100644 index 4c7be00a5f1d015d5da4fcf4791e6a175f0ff9c7..0000000000000000000000000000000000000000 --- a/test-tpm-tis-Get-prepared-to-share-tests-between-ISA.patch +++ /dev/null @@ -1,1044 +0,0 @@ -From c8ed2a1fbe306ecbfb5c7d4156ae81c029829d95 Mon Sep 17 00:00:00 2001 -From: jiangfangjie -Date: Thu, 13 Aug 2020 20:56:54 +0800 -Subject: [PATCH 18/19] test: tpm-tis: Get prepared to share tests between ISA - and sysbus devices - -ISA and sysbus TPM-TIS devices will share their tests. Only -the main() will change (instantiation option is different). -Also the base address of the TPM-TIS device is going to be -different. on x86 it is located at 0xFED40000 while on ARM -it can be located at any location, discovered through the -device tree description. - -So we put shared test functions in a new object module. -Each test needs to set tpm_tis_base_addr global variable. - -Also take benefit of this move to fix "block comments using -a leading */ on a separate line" checkpatch warnings. - -Signed-off-by: Eric Auger -Reviewed-by: Stefan Berger -Message-id: 20200305165149.618-10-eric.auger@redhat.com -Signed-off-by: Stefan Berger -Signed-off-by: jiangfangjie ---- - tests/Makefile.include | 2 +- - tests/tpm-crb-swtpm-test.c | 4 + - tests/tpm-crb-test.c | 3 + - tests/tpm-tis-swtpm-test.c | 3 + - tests/tpm-tis-test.c | 414 +--------------------------------- - tests/tpm-tis-util.c | 451 +++++++++++++++++++++++++++++++++++++ - tests/tpm-tis-util.h | 23 ++ - tests/tpm-util.c | 3 - - tests/tpm-util.h | 5 + - 9 files changed, 493 insertions(+), 415 deletions(-) - create mode 100644 tests/tpm-tis-util.c - create mode 100644 tests/tpm-tis-util.h - -diff --git a/tests/Makefile.include b/tests/Makefile.include -index c151de64..950b32a2 100644 ---- a/tests/Makefile.include -+++ b/tests/Makefile.include -@@ -667,7 +667,7 @@ tests/tpm-crb-swtpm-test$(EXESUF): tests/tpm-crb-swtpm-test.o tests/tpm-emu.o \ - tests/tpm-crb-test$(EXESUF): tests/tpm-crb-test.o tests/tpm-emu.o $(test-io-obj-y) - tests/tpm-tis-swtpm-test$(EXESUF): tests/tpm-tis-swtpm-test.o tests/tpm-emu.o \ - tests/tpm-util.o tests/tpm-tests.o $(test-io-obj-y) --tests/tpm-tis-test$(EXESUF): tests/tpm-tis-test.o tests/tpm-emu.o $(test-io-obj-y) -+tests/tpm-tis-test$(EXESUF): tests/tpm-tis-test.o tests/tpm-tis-util.o tests/tpm-emu.o $(test-io-obj-y) - tests/test-io-channel-file$(EXESUF): tests/test-io-channel-file.o \ - tests/io-channel-helpers.o $(test-io-obj-y) - tests/test-io-channel-tls$(EXESUF): tests/test-io-channel-tls.o \ -diff --git a/tests/tpm-crb-swtpm-test.c b/tests/tpm-crb-swtpm-test.c -index 5228cb7a..55fdb565 100644 ---- a/tests/tpm-crb-swtpm-test.c -+++ b/tests/tpm-crb-swtpm-test.c -@@ -18,6 +18,10 @@ - #include "libqtest.h" - #include "qemu/module.h" - #include "tpm-tests.h" -+#include "hw/acpi/tpm.h" -+ -+/* Not used but needed for linking */ -+uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; - - typedef struct TestState { - char *src_tpm_path; -diff --git a/tests/tpm-crb-test.c b/tests/tpm-crb-test.c -index a139caa5..32695810 100644 ---- a/tests/tpm-crb-test.c -+++ b/tests/tpm-crb-test.c -@@ -19,6 +19,9 @@ - #include "qemu/module.h" - #include "tpm-emu.h" - -+/* Not used but needed for linking */ -+uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; -+ - #define TPM_CMD "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00" - - static void tpm_crb_test(const void *data) -diff --git a/tests/tpm-tis-swtpm-test.c b/tests/tpm-tis-swtpm-test.c -index 9470f157..90131cb3 100644 ---- a/tests/tpm-tis-swtpm-test.c -+++ b/tests/tpm-tis-swtpm-test.c -@@ -18,6 +18,9 @@ - #include "libqtest.h" - #include "qemu/module.h" - #include "tpm-tests.h" -+#include "hw/acpi/tpm.h" -+ -+uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; - - typedef struct TestState { - char *src_tpm_path; -diff --git a/tests/tpm-tis-test.c b/tests/tpm-tis-test.c -index 92a7e95a..8042de13 100644 ---- a/tests/tpm-tis-test.c -+++ b/tests/tpm-tis-test.c -@@ -1,5 +1,5 @@ - /* -- * QTest testcase for TPM TIS -+ * QTest testcase for ISA TPM TIS - * - * Copyright (c) 2018 Red Hat, Inc. - * Copyright (c) 2018 IBM Corporation -@@ -20,417 +20,9 @@ - #include "libqtest.h" - #include "qemu/module.h" - #include "tpm-emu.h" -+#include "tpm-tis-util.h" - --#define TIS_REG(LOCTY, REG) \ -- (TPM_TIS_ADDR_BASE + ((LOCTY) << 12) + REG) -- --#define DEBUG_TIS_TEST 0 -- --#define DPRINTF(fmt, ...) do { \ -- if (DEBUG_TIS_TEST) { \ -- printf(fmt, ## __VA_ARGS__); \ -- } \ --} while (0) -- --#define DPRINTF_ACCESS \ -- DPRINTF("%s: %d: locty=%d l=%d access=0x%02x pending_request_flag=0x%x\n", \ -- __func__, __LINE__, locty, l, access, pending_request_flag) -- --#define DPRINTF_STS \ -- DPRINTF("%s: %d: sts = 0x%08x\n", __func__, __LINE__, sts) -- --static const uint8_t TPM_CMD[12] = -- "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00"; -- --static void tpm_tis_test_check_localities(const void *data) --{ -- uint8_t locty; -- uint8_t access; -- uint32_t ifaceid; -- uint32_t capability; -- uint32_t didvid; -- uint32_t rid; -- -- for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) { -- access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- capability = readl(TIS_REG(locty, TPM_TIS_REG_INTF_CAPABILITY)); -- g_assert_cmpint(capability, ==, TPM_TIS_CAPABILITIES_SUPPORTED2_0); -- -- ifaceid = readl(TIS_REG(locty, TPM_TIS_REG_INTERFACE_ID)); -- g_assert_cmpint(ifaceid, ==, TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0); -- -- didvid = readl(TIS_REG(locty, TPM_TIS_REG_DID_VID)); -- g_assert_cmpint(didvid, !=, 0); -- g_assert_cmpint(didvid, !=, 0xffffffff); -- -- rid = readl(TIS_REG(locty, TPM_TIS_REG_RID)); -- g_assert_cmpint(rid, !=, 0); -- g_assert_cmpint(rid, !=, 0xffffffff); -- } --} -- --static void tpm_tis_test_check_access_reg(const void *data) --{ -- uint8_t locty; -- uint8_t access; -- -- /* do not test locality 4 (hw only) */ -- for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { -- access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* request use of locality */ -- writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); -- -- access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_ACTIVE_LOCALITY | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* release access */ -- writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), -- TPM_TIS_ACCESS_ACTIVE_LOCALITY); -- access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- } --} -- --/* -- * Test case for seizing access by a higher number locality -- */ --static void tpm_tis_test_check_access_reg_seize(const void *data) --{ -- int locty, l; -- uint8_t access; -- uint8_t pending_request_flag; -- -- /* do not test locality 4 (hw only) */ -- for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { -- pending_request_flag = 0; -- -- access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* request use of locality */ -- writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); -- access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_ACTIVE_LOCALITY | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* lower localities cannot seize access */ -- for (l = 0; l < locty; l++) { -- /* lower locality is not active */ -- access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -- DPRINTF_ACCESS; -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- pending_request_flag | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* try to request use from 'l' */ -- writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); -- -- /* requesting use from 'l' was not possible; -- we must see REQUEST_USE and possibly PENDING_REQUEST */ -- access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -- DPRINTF_ACCESS; -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_REQUEST_USE | -- pending_request_flag | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* locality 'locty' must be unchanged; -- we must see PENDING_REQUEST */ -- access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_ACTIVE_LOCALITY | -- TPM_TIS_ACCESS_PENDING_REQUEST | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* try to seize from 'l' */ -- writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE); -- /* seize from 'l' was not possible */ -- access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -- DPRINTF_ACCESS; -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_REQUEST_USE | -- pending_request_flag | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* locality 'locty' must be unchanged */ -- access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_ACTIVE_LOCALITY | -- TPM_TIS_ACCESS_PENDING_REQUEST | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* on the next loop we will have a PENDING_REQUEST flag -- set for locality 'l' */ -- pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; -- } -- -- /* higher localities can 'seize' access but not 'request use'; -- note: this will activate first l+1, then l+2 etc. */ -- for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { -- /* try to 'request use' from 'l' */ -- writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); -- -- /* requesting use from 'l' was not possible; we should see -- REQUEST_USE and may see PENDING_REQUEST */ -- access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -- DPRINTF_ACCESS; -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_REQUEST_USE | -- pending_request_flag | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* locality 'l-1' must be unchanged; we should always -- see PENDING_REQUEST from 'l' requesting access */ -- access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); -- DPRINTF_ACCESS; -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_ACTIVE_LOCALITY | -- TPM_TIS_ACCESS_PENDING_REQUEST | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* try to seize from 'l' */ -- writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE); -- -- /* seize from 'l' was possible */ -- access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -- DPRINTF_ACCESS; -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_ACTIVE_LOCALITY | -- pending_request_flag | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* l - 1 should show that it has BEEN_SEIZED */ -- access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); -- DPRINTF_ACCESS; -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_BEEN_SEIZED | -- pending_request_flag | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* clear the BEEN_SEIZED flag and make sure it's gone */ -- writeb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS), -- TPM_TIS_ACCESS_BEEN_SEIZED); -- -- access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- pending_request_flag | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- } -- -- /* PENDING_REQUEST will not be set if locty = 0 since all localities -- were active; in case of locty = 1, locality 0 will be active -- but no PENDING_REQUEST anywhere */ -- if (locty <= 1) { -- pending_request_flag = 0; -- } -- -- /* release access from l - 1; this activates locty - 1 */ -- l--; -- -- access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -- DPRINTF_ACCESS; -- -- DPRINTF("%s: %d: relinquishing control on l = %d\n", -- __func__, __LINE__, l); -- writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), -- TPM_TIS_ACCESS_ACTIVE_LOCALITY); -- -- access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -- DPRINTF_ACCESS; -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- pending_request_flag | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- for (l = locty - 1; l >= 0; l--) { -- access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -- DPRINTF_ACCESS; -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_ACTIVE_LOCALITY | -- pending_request_flag | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* release this locality */ -- writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), -- TPM_TIS_ACCESS_ACTIVE_LOCALITY); -- -- if (l == 1) { -- pending_request_flag = 0; -- } -- } -- -- /* no locality may be active now */ -- for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { -- access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -- DPRINTF_ACCESS; -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- } -- } --} -- --/* -- * Test case for getting access when higher number locality relinquishes access -- */ --static void tpm_tis_test_check_access_reg_release(const void *data) --{ -- int locty, l; -- uint8_t access; -- uint8_t pending_request_flag; -- -- /* do not test locality 4 (hw only) */ -- for (locty = TPM_TIS_NUM_LOCALITIES - 2; locty >= 0; locty--) { -- pending_request_flag = 0; -- -- access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* request use of locality */ -- writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); -- access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_ACTIVE_LOCALITY | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- /* request use of all other localities */ -- for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { -- if (l == locty) { -- continue; -- } -- /* request use of locality 'l' -- we MUST see REQUEST USE and -- may see PENDING_REQUEST */ -- writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); -- access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -- DPRINTF_ACCESS; -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_REQUEST_USE | -- pending_request_flag | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; -- } -- /* release locality 'locty' */ -- writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), -- TPM_TIS_ACCESS_ACTIVE_LOCALITY); -- /* highest locality should now be active; release it and make sure the -- next higest locality is active afterwards */ -- for (l = TPM_TIS_NUM_LOCALITIES - 2; l >= 0; l--) { -- if (l == locty) { -- continue; -- } -- /* 'l' should be active now */ -- access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -- DPRINTF_ACCESS; -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_ACTIVE_LOCALITY | -- pending_request_flag | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- /* 'l' relinquishes access */ -- writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), -- TPM_TIS_ACCESS_ACTIVE_LOCALITY); -- access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -- DPRINTF_ACCESS; -- if (l == 1 || (locty <= 1 && l == 2)) { -- pending_request_flag = 0; -- } -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- pending_request_flag | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- } -- } --} -- --/* -- * Test case for transmitting packets -- */ --static void tpm_tis_test_check_transmit(const void *data) --{ -- const TestState *s = data; -- uint8_t access; -- uint32_t sts; -- uint16_t bcount; -- size_t i; -- -- /* request use of locality 0 */ -- writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); -- access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); -- g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -- TPM_TIS_ACCESS_ACTIVE_LOCALITY | -- TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -- -- sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); -- DPRINTF_STS; -- -- g_assert_cmpint(sts & 0xff, ==, 0); -- g_assert_cmpint(sts & TPM_TIS_STS_TPM_FAMILY_MASK, ==, -- TPM_TIS_STS_TPM_FAMILY2_0); -- -- bcount = (sts >> 8) & 0xffff; -- g_assert_cmpint(bcount, >=, 128); -- -- writel(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_COMMAND_READY); -- sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); -- DPRINTF_STS; -- g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_COMMAND_READY); -- -- /* transmit command */ -- for (i = 0; i < sizeof(TPM_CMD); i++) { -- writeb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO), TPM_CMD[i]); -- sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); -- DPRINTF_STS; -- if (i < sizeof(TPM_CMD) - 1) { -- g_assert_cmpint(sts & 0xff, ==, -- TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); -- } else { -- g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_VALID); -- } -- g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); -- } -- /* start processing */ -- writeb(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_TPM_GO); -- -- uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND; -- do { -- sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); -- if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) { -- break; -- } -- } while (g_get_monotonic_time() < end_time); -- -- sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); -- DPRINTF_STS; -- g_assert_cmpint(sts & 0xff, == , -- TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); -- bcount = (sts >> 8) & 0xffff; -- -- /* read response */ -- uint8_t tpm_msg[sizeof(struct tpm_hdr)]; -- g_assert_cmpint(sizeof(tpm_msg), ==, bcount); -- -- for (i = 0; i < sizeof(tpm_msg); i++) { -- tpm_msg[i] = readb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO)); -- sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); -- DPRINTF_STS; -- if (sts & TPM_TIS_STS_DATA_AVAILABLE) { -- g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); -- } -- } -- g_assert_cmpmem(tpm_msg, sizeof(tpm_msg), s->tpm_msg, sizeof(*s->tpm_msg)); -- -- /* relinquish use of locality 0 */ -- writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_ACTIVE_LOCALITY); -- access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); --} -+uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; - - int main(int argc, char **argv) - { -diff --git a/tests/tpm-tis-util.c b/tests/tpm-tis-util.c -new file mode 100644 -index 00000000..9aff503f ---- /dev/null -+++ b/tests/tpm-tis-util.c -@@ -0,0 +1,451 @@ -+/* -+ * QTest testcase for TPM TIS: common test functions used for both -+ * the ISA and SYSBUS devices -+ * -+ * Copyright (c) 2018 Red Hat, Inc. -+ * Copyright (c) 2018 IBM Corporation -+ * -+ * Authors: -+ * Marc-André Lureau -+ * Stefan Berger -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#include "qemu/osdep.h" -+#include -+ -+#include "hw/acpi/tpm.h" -+#include "io/channel-socket.h" -+#include "libqtest.h" -+#include "qemu/module.h" -+#include "tpm-emu.h" -+#include "tpm-util.h" -+#include "tpm-tis-util.h" -+ -+#define DEBUG_TIS_TEST 0 -+ -+#define DPRINTF(fmt, ...) do { \ -+ if (DEBUG_TIS_TEST) { \ -+ printf(fmt, ## __VA_ARGS__); \ -+ } \ -+} while (0) -+ -+#define DPRINTF_ACCESS \ -+ DPRINTF("%s: %d: locty=%d l=%d access=0x%02x pending_request_flag=0x%x\n", \ -+ __func__, __LINE__, locty, l, access, pending_request_flag) -+ -+#define DPRINTF_STS \ -+ DPRINTF("%s: %d: sts = 0x%08x\n", __func__, __LINE__, sts) -+ -+static const uint8_t TPM_CMD[12] = -+ "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00"; -+ -+void tpm_tis_test_check_localities(const void *data) -+{ -+ uint8_t locty; -+ uint8_t access; -+ uint32_t ifaceid; -+ uint32_t capability; -+ uint32_t didvid; -+ uint32_t rid; -+ -+ for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) { -+ access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ capability = readl(TIS_REG(locty, TPM_TIS_REG_INTF_CAPABILITY)); -+ g_assert_cmpint(capability, ==, TPM_TIS_CAPABILITIES_SUPPORTED2_0); -+ -+ ifaceid = readl(TIS_REG(locty, TPM_TIS_REG_INTERFACE_ID)); -+ g_assert_cmpint(ifaceid, ==, TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0); -+ -+ didvid = readl(TIS_REG(locty, TPM_TIS_REG_DID_VID)); -+ g_assert_cmpint(didvid, !=, 0); -+ g_assert_cmpint(didvid, !=, 0xffffffff); -+ -+ rid = readl(TIS_REG(locty, TPM_TIS_REG_RID)); -+ g_assert_cmpint(rid, !=, 0); -+ g_assert_cmpint(rid, !=, 0xffffffff); -+ } -+} -+ -+void tpm_tis_test_check_access_reg(const void *data) -+{ -+ uint8_t locty; -+ uint8_t access; -+ -+ /* do not test locality 4 (hw only) */ -+ for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { -+ access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* request use of locality */ -+ writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); -+ -+ access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* release access */ -+ writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY); -+ access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ } -+} -+ -+/* -+ * Test case for seizing access by a higher number locality -+ */ -+void tpm_tis_test_check_access_reg_seize(const void *data) -+{ -+ int locty, l; -+ uint8_t access; -+ uint8_t pending_request_flag; -+ -+ /* do not test locality 4 (hw only) */ -+ for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { -+ pending_request_flag = 0; -+ -+ access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* request use of locality */ -+ writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); -+ access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* lower localities cannot seize access */ -+ for (l = 0; l < locty; l++) { -+ /* lower locality is not active */ -+ access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -+ DPRINTF_ACCESS; -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ pending_request_flag | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* try to request use from 'l' */ -+ writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); -+ -+ /* -+ * requesting use from 'l' was not possible; -+ * we must see REQUEST_USE and possibly PENDING_REQUEST -+ */ -+ access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -+ DPRINTF_ACCESS; -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_REQUEST_USE | -+ pending_request_flag | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* -+ * locality 'locty' must be unchanged; -+ * we must see PENDING_REQUEST -+ */ -+ access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY | -+ TPM_TIS_ACCESS_PENDING_REQUEST | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* try to seize from 'l' */ -+ writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE); -+ /* seize from 'l' was not possible */ -+ access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -+ DPRINTF_ACCESS; -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_REQUEST_USE | -+ pending_request_flag | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* locality 'locty' must be unchanged */ -+ access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY | -+ TPM_TIS_ACCESS_PENDING_REQUEST | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* -+ * on the next loop we will have a PENDING_REQUEST flag -+ * set for locality 'l' -+ */ -+ pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; -+ } -+ -+ /* -+ * higher localities can 'seize' access but not 'request use'; -+ * note: this will activate first l+1, then l+2 etc. -+ */ -+ for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { -+ /* try to 'request use' from 'l' */ -+ writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); -+ -+ /* -+ * requesting use from 'l' was not possible; we should see -+ * REQUEST_USE and may see PENDING_REQUEST -+ */ -+ access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -+ DPRINTF_ACCESS; -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_REQUEST_USE | -+ pending_request_flag | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* -+ * locality 'l-1' must be unchanged; we should always -+ * see PENDING_REQUEST from 'l' requesting access -+ */ -+ access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); -+ DPRINTF_ACCESS; -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY | -+ TPM_TIS_ACCESS_PENDING_REQUEST | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* try to seize from 'l' */ -+ writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE); -+ -+ /* seize from 'l' was possible */ -+ access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -+ DPRINTF_ACCESS; -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY | -+ pending_request_flag | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* l - 1 should show that it has BEEN_SEIZED */ -+ access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); -+ DPRINTF_ACCESS; -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_BEEN_SEIZED | -+ pending_request_flag | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* clear the BEEN_SEIZED flag and make sure it's gone */ -+ writeb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS), -+ TPM_TIS_ACCESS_BEEN_SEIZED); -+ -+ access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ pending_request_flag | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ } -+ -+ /* -+ * PENDING_REQUEST will not be set if locty = 0 since all localities -+ * were active; in case of locty = 1, locality 0 will be active -+ * but no PENDING_REQUEST anywhere -+ */ -+ if (locty <= 1) { -+ pending_request_flag = 0; -+ } -+ -+ /* release access from l - 1; this activates locty - 1 */ -+ l--; -+ -+ access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -+ DPRINTF_ACCESS; -+ -+ DPRINTF("%s: %d: relinquishing control on l = %d\n", -+ __func__, __LINE__, l); -+ writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY); -+ -+ access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -+ DPRINTF_ACCESS; -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ pending_request_flag | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ for (l = locty - 1; l >= 0; l--) { -+ access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -+ DPRINTF_ACCESS; -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY | -+ pending_request_flag | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* release this locality */ -+ writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY); -+ -+ if (l == 1) { -+ pending_request_flag = 0; -+ } -+ } -+ -+ /* no locality may be active now */ -+ for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { -+ access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -+ DPRINTF_ACCESS; -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ } -+ } -+} -+ -+/* -+ * Test case for getting access when higher number locality relinquishes access -+ */ -+void tpm_tis_test_check_access_reg_release(const void *data) -+{ -+ int locty, l; -+ uint8_t access; -+ uint8_t pending_request_flag; -+ -+ /* do not test locality 4 (hw only) */ -+ for (locty = TPM_TIS_NUM_LOCALITIES - 2; locty >= 0; locty--) { -+ pending_request_flag = 0; -+ -+ access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* request use of locality */ -+ writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); -+ access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ /* request use of all other localities */ -+ for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { -+ if (l == locty) { -+ continue; -+ } -+ /* -+ * request use of locality 'l' -- we MUST see REQUEST USE and -+ * may see PENDING_REQUEST -+ */ -+ writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); -+ access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -+ DPRINTF_ACCESS; -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_REQUEST_USE | -+ pending_request_flag | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; -+ } -+ /* release locality 'locty' */ -+ writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY); -+ /* -+ * highest locality should now be active; release it and make sure the -+ * next higest locality is active afterwards -+ */ -+ for (l = TPM_TIS_NUM_LOCALITIES - 2; l >= 0; l--) { -+ if (l == locty) { -+ continue; -+ } -+ /* 'l' should be active now */ -+ access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -+ DPRINTF_ACCESS; -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY | -+ pending_request_flag | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ /* 'l' relinquishes access */ -+ writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY); -+ access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); -+ DPRINTF_ACCESS; -+ if (l == 1 || (locty <= 1 && l == 2)) { -+ pending_request_flag = 0; -+ } -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ pending_request_flag | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ } -+ } -+} -+ -+/* -+ * Test case for transmitting packets -+ */ -+void tpm_tis_test_check_transmit(const void *data) -+{ -+ const TestState *s = data; -+ uint8_t access; -+ uint32_t sts; -+ uint16_t bcount; -+ size_t i; -+ -+ /* request use of locality 0 */ -+ writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); -+ access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); -+ g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY | -+ TPM_TIS_ACCESS_TPM_ESTABLISHMENT); -+ -+ sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); -+ DPRINTF_STS; -+ -+ g_assert_cmpint(sts & 0xff, ==, 0); -+ g_assert_cmpint(sts & TPM_TIS_STS_TPM_FAMILY_MASK, ==, -+ TPM_TIS_STS_TPM_FAMILY2_0); -+ -+ bcount = (sts >> 8) & 0xffff; -+ g_assert_cmpint(bcount, >=, 128); -+ -+ writel(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_COMMAND_READY); -+ sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); -+ DPRINTF_STS; -+ g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_COMMAND_READY); -+ -+ /* transmit command */ -+ for (i = 0; i < sizeof(TPM_CMD); i++) { -+ writeb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO), TPM_CMD[i]); -+ sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); -+ DPRINTF_STS; -+ if (i < sizeof(TPM_CMD) - 1) { -+ g_assert_cmpint(sts & 0xff, ==, -+ TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); -+ } else { -+ g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_VALID); -+ } -+ g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); -+ } -+ /* start processing */ -+ writeb(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_TPM_GO); -+ -+ uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND; -+ do { -+ sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); -+ if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) { -+ break; -+ } -+ } while (g_get_monotonic_time() < end_time); -+ -+ sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); -+ DPRINTF_STS; -+ g_assert_cmpint(sts & 0xff, == , -+ TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); -+ bcount = (sts >> 8) & 0xffff; -+ -+ /* read response */ -+ uint8_t tpm_msg[sizeof(struct tpm_hdr)]; -+ g_assert_cmpint(sizeof(tpm_msg), ==, bcount); -+ -+ for (i = 0; i < sizeof(tpm_msg); i++) { -+ tpm_msg[i] = readb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO)); -+ sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); -+ DPRINTF_STS; -+ if (sts & TPM_TIS_STS_DATA_AVAILABLE) { -+ g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); -+ } -+ } -+ g_assert_cmpmem(tpm_msg, sizeof(tpm_msg), s->tpm_msg, sizeof(*s->tpm_msg)); -+ -+ /* relinquish use of locality 0 */ -+ writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_ACTIVE_LOCALITY); -+ access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); -+} -diff --git a/tests/tpm-tis-util.h b/tests/tpm-tis-util.h -new file mode 100644 -index 00000000..d10efe86 ---- /dev/null -+++ b/tests/tpm-tis-util.h -@@ -0,0 +1,23 @@ -+/* -+ * QTest TPM TIS: Common test functions used for both the -+ * ISA and SYSBUS devices -+ * -+ * Copyright (c) 2018 IBM Corporation -+ * -+ * Authors: -+ * Stefan Berger -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#ifndef TESTS_TPM_TIS_UTIL_H -+#define TESTS_TPM_TIS_UTIL_H -+ -+void tpm_tis_test_check_localities(const void *data); -+void tpm_tis_test_check_access_reg(const void *data); -+void tpm_tis_test_check_access_reg_seize(const void *data); -+void tpm_tis_test_check_access_reg_release(const void *data); -+void tpm_tis_test_check_transmit(const void *data); -+ -+#endif /* TESTS_TPM_TIS_UTIL_H */ -diff --git a/tests/tpm-util.c b/tests/tpm-util.c -index 7ecdae2f..34efae8f 100644 ---- a/tests/tpm-util.c -+++ b/tests/tpm-util.c -@@ -19,9 +19,6 @@ - #include "tpm-util.h" - #include "qapi/qmp/qdict.h" - --#define TIS_REG(LOCTY, REG) \ -- (TPM_TIS_ADDR_BASE + ((LOCTY) << 12) + REG) -- - void tpm_util_crb_transfer(QTestState *s, - const unsigned char *req, size_t req_size, - unsigned char *rsp, size_t rsp_size) -diff --git a/tests/tpm-util.h b/tests/tpm-util.h -index 15e39249..3b97d690 100644 ---- a/tests/tpm-util.h -+++ b/tests/tpm-util.h -@@ -15,6 +15,11 @@ - - #include "io/channel-socket.h" - -+extern uint64_t tpm_tis_base_addr; -+ -+#define TIS_REG(LOCTY, REG) \ -+ (tpm_tis_base_addr + ((LOCTY) << 12) + REG) -+ - typedef void (tx_func)(QTestState *s, - const unsigned char *req, size_t req_size, - unsigned char *rsp, size_t rsp_size); --- -2.23.0 - diff --git a/tests-Add-bios-tests-to-arm-virt.patch b/tests-Add-bios-tests-to-arm-virt.patch deleted file mode 100644 index 025afb506017f9bc1c6fdb26df35c9534a8f3672..0000000000000000000000000000000000000000 --- a/tests-Add-bios-tests-to-arm-virt.patch +++ /dev/null @@ -1,86 +0,0 @@ -From abbcc35ccb22d81d69a28dc66b5f5d94e673a25e Mon Sep 17 00:00:00 2001 -From: Shameer Kolothum -Date: Wed, 18 Sep 2019 14:06:33 +0100 -Subject: [PATCH] tests: Add bios tests to arm/virt - -This adds numamem and memhp tests for arm/virt platform. - -Signed-off-by: Shameer Kolothum -Reviewed-by: Igor Mammedov -Message-Id: <20190918130633.4872-12-shameerali.kolothum.thodi@huawei.com> -Acked-by: Peter Maydell -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin ---- - tests/bios-tables-test.c | 49 ++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 49 insertions(+) - -diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c -index 53a91a8067..5e177b7155 100644 ---- a/tests/bios-tables-test.c -+++ b/tests/bios-tables-test.c -@@ -874,6 +874,53 @@ static void test_acpi_piix4_tcg_dimm_pxm(void) - test_acpi_tcg_dimm_pxm(MACHINE_PC); - } - -+static void test_acpi_virt_tcg_memhp(void) -+{ -+ test_data data = { -+ .machine = "virt", -+ .accel = "tcg", -+ .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", -+ .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", -+ .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", -+ .ram_start = 0x40000000ULL, -+ .scan_len = 256ULL * 1024 * 1024, -+ }; -+ -+ data.variant = ".memhp"; -+ test_acpi_one(" -cpu cortex-a57" -+ " -m 256M,slots=3,maxmem=1G" -+ " -object memory-backend-ram,id=ram0,size=128M" -+ " -object memory-backend-ram,id=ram1,size=128M" -+ " -numa node,memdev=ram0 -numa node,memdev=ram1" -+ " -numa dist,src=0,dst=1,val=21", -+ &data); -+ -+ free_test_data(&data); -+ -+} -+ -+static void test_acpi_virt_tcg_numamem(void) -+{ -+ test_data data = { -+ .machine = "virt", -+ .accel = "tcg", -+ .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", -+ .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", -+ .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", -+ .ram_start = 0x40000000ULL, -+ .scan_len = 128ULL * 1024 * 1024, -+ }; -+ -+ data.variant = ".numamem"; -+ test_acpi_one(" -cpu cortex-a57" -+ " -object memory-backend-ram,id=ram0,size=128M" -+ " -numa node,memdev=ram0", -+ &data); -+ -+ free_test_data(&data); -+ -+} -+ - static void test_acpi_virt_tcg(void) - { - test_data data = { -@@ -920,6 +967,8 @@ int main(int argc, char *argv[]) - qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm); - } else if (strcmp(arch, "aarch64") == 0) { - qtest_add_func("acpi/virt", test_acpi_virt_tcg); -+ qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem); -+ qtest_add_func("acpi/virt/memhp", test_acpi_virt_tcg_memhp); - } - ret = g_test_run(); - boot_sector_cleanup(disk); --- -2.19.1 diff --git a/tests-Disable-filemonitor-testcase.patch b/tests-Disable-filemonitor-testcase.patch new file mode 100644 index 0000000000000000000000000000000000000000..6d7323635b2164ad0616805fd4eb511f6c3e986e --- /dev/null +++ b/tests-Disable-filemonitor-testcase.patch @@ -0,0 +1,31 @@ +From 4f09a1c2aa855aab666d729defce4c7f0466cb77 Mon Sep 17 00:00:00 2001 +From: Ying Fang +Date: Thu, 10 Feb 2022 17:16:55 +0800 +Subject: [PATCH] tests: Disable filemonitor testcase + +Since filemonitor testcase requires that host kernel being a LTS version, +we cannot guarantee that on OBS system. Lets disable it by default. + +Signed-off-by: Ying Fang +Signed-off-by: Jinhao Gao +--- + tests/unit/meson.build | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/tests/unit/meson.build b/tests/unit/meson.build +index acac3622ed..c21d817874 100644 +--- a/tests/unit/meson.build ++++ b/tests/unit/meson.build +@@ -129,9 +129,6 @@ if have_system + 'test-vmstate': [migration, io], + 'test-yank': ['socket-helpers.c', qom, io, chardev] + } +- if 'CONFIG_INOTIFY1' in config_host +- tests += {'test-util-filemonitor': []} +- endif + + # Some tests: test-char, test-qdev-global-props, and test-qga, + # are not runnable under TSan due to a known issue. +-- +2.27.0 + diff --git a/tests-Disalbe-filemonitor-testcase.patch b/tests-Disalbe-filemonitor-testcase.patch deleted file mode 100644 index b389299e35dd49154f6e660ee3d66237b15ec58b..0000000000000000000000000000000000000000 --- a/tests-Disalbe-filemonitor-testcase.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 4f1eaa63065594276c11958e963377a09668d44b Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Thu, 6 Aug 2020 10:05:00 +0800 -Subject: [PATCH] tests: Disalbe filemonitor testcase - -Since filemonitor testcase requires that host kernel being a LTS version, -we cannot guarantee that on OBS system. Let's disable it by default. - -Signed-of-by: Ying Fang - -diff --git a/tests/Makefile.include b/tests/Makefile.include -index d8cf00c1..f3273ad3 100644 ---- a/tests/Makefile.include -+++ b/tests/Makefile.include -@@ -117,7 +117,6 @@ ifneq (,$(findstring qemu-ga,$(TOOLS))) - check-unit-$(call land,$(CONFIG_LINUX),$(CONFIG_VIRTIO_SERIAL)) += tests/test-qga$(EXESUF) - endif - check-unit-y += tests/test-timed-average$(EXESUF) --check-unit-$(CONFIG_INOTIFY1) += tests/test-util-filemonitor$(EXESUF) - check-unit-y += tests/test-util-sockets$(EXESUF) - check-unit-$(CONFIG_BLOCK) += tests/test-authz-simple$(EXESUF) - check-unit-$(CONFIG_BLOCK) += tests/test-authz-list$(EXESUF) -@@ -654,8 +653,6 @@ tests/test-crypto-tlssession$(EXESUF): tests/test-crypto-tlssession.o \ - tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o \ - tests/crypto-tls-psk-helpers.o \ - $(test-crypto-obj-y) --tests/test-util-filemonitor$(EXESUF): tests/test-util-filemonitor.o \ -- $(test-util-obj-y) - tests/test-util-sockets$(EXESUF): tests/test-util-sockets.o \ - tests/socket-helpers.o $(test-util-obj-y) - tests/test-authz-simple$(EXESUF): tests/test-authz-simple.o $(test-authz-obj-y) --- -2.23.0 - diff --git a/tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch b/tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch deleted file mode 100644 index e739883feb04d14f33a97a2a0b6690ac6c5ccc24..0000000000000000000000000000000000000000 --- a/tests-Update-ACPI-tables-list-for-upcoming-arm-virt-.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 27e2533e43f0ab2b8a60f1902f58f8752581ea9f Mon Sep 17 00:00:00 2001 -From: Shameer Kolothum -Date: Wed, 18 Sep 2019 14:06:32 +0100 -Subject: [PATCH] tests: Update ACPI tables list for upcoming arm/virt tests - -This is in preparation to add numamem and memhp tests to -arm/virt platform. The bios-tables-test-allowed-diff.h -is updated with a list of expected ACPI tables that needs to be -present in tests/data/acpi/virt folder. - -Signed-off-by: Shameer Kolothum -Message-Id: <20190918130633.4872-11-shameerali.kolothum.thodi@huawei.com> -Acked-by: Peter Maydell -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Reviewed-by: Igor Mammedov ---- - tests/bios-tables-test-allowed-diff.h | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/tests/bios-tables-test-allowed-diff.h b/tests/bios-tables-test-allowed-diff.h -index 32a401ae35..3776dd2f3d 100644 ---- a/tests/bios-tables-test-allowed-diff.h -+++ b/tests/bios-tables-test-allowed-diff.h -@@ -1,4 +1,17 @@ - /* List of comma-separated changed AML files to ignore */ - "tests/data/acpi/virt/DSDT", -+"tests/data/acpi/virt/APIC.memhp", -+"tests/data/acpi/virt/APIC.numamem", - "tests/data/acpi/virt/DSDT.memhp", - "tests/data/acpi/virt/DSDT.numamem", -+"tests/data/acpi/virt/FACP.memhp", -+"tests/data/acpi/virt/FACP.numamem", -+"tests/data/acpi/virt/GTDT.memhp", -+"tests/data/acpi/virt/GTDT.numamem", -+"tests/data/acpi/virt/MCFG.memhp", -+"tests/data/acpi/virt/MCFG.numamem", -+"tests/data/acpi/virt/SLIT.memhp", -+"tests/data/acpi/virt/SPCR.memhp", -+"tests/data/acpi/virt/SPCR.numamem", -+"tests/data/acpi/virt/SRAT.memhp", -+"tests/data/acpi/virt/SRAT.numamem", --- -2.19.1 diff --git a/tests-acpi-add-empty-files.patch b/tests-acpi-add-empty-files.patch deleted file mode 100644 index 46e51c0de0e0ba84b6edf01fb62e3005acd37697..0000000000000000000000000000000000000000 --- a/tests-acpi-add-empty-files.patch +++ /dev/null @@ -1,88 +0,0 @@ -From c943416df54931cea8b19183fd7c4f2dbd86ec72 Mon Sep 17 00:00:00 2001 -From: "Michael S. Tsirkin" -Date: Sun, 29 Sep 2019 10:54:12 -0400 -Subject: [PATCH] tests/acpi: add empty files - -Needed to make tests pass. Will replace with actual files. - -Signed-off-by: Michael S. Tsirkin ---- - tests/data/acpi/virt/APIC.memhp | 0 - tests/data/acpi/virt/APIC.numamem | 0 - tests/data/acpi/virt/DSDT.memhp | 0 - tests/data/acpi/virt/DSDT.numamem | 0 - tests/data/acpi/virt/FACP.memhp | 0 - tests/data/acpi/virt/FACP.numamem | 0 - tests/data/acpi/virt/GTDT.memhp | 0 - tests/data/acpi/virt/GTDT.numamem | 0 - tests/data/acpi/virt/MCFG.memhp | 0 - tests/data/acpi/virt/MCFG.numamem | 0 - tests/data/acpi/virt/SLIT.memhp | 0 - tests/data/acpi/virt/SPCR.memhp | 0 - tests/data/acpi/virt/SPCR.numamem | 0 - tests/data/acpi/virt/SRAT.memhp | 0 - tests/data/acpi/virt/SRAT.numamem | 0 - 15 files changed, 0 insertions(+), 0 deletions(-) - create mode 100644 tests/data/acpi/virt/APIC.memhp - create mode 100644 tests/data/acpi/virt/APIC.numamem - create mode 100644 tests/data/acpi/virt/DSDT.memhp - create mode 100644 tests/data/acpi/virt/DSDT.numamem - create mode 100644 tests/data/acpi/virt/FACP.memhp - create mode 100644 tests/data/acpi/virt/FACP.numamem - create mode 100644 tests/data/acpi/virt/GTDT.memhp - create mode 100644 tests/data/acpi/virt/GTDT.numamem - create mode 100644 tests/data/acpi/virt/MCFG.memhp - create mode 100644 tests/data/acpi/virt/MCFG.numamem - create mode 100644 tests/data/acpi/virt/SLIT.memhp - create mode 100644 tests/data/acpi/virt/SPCR.memhp - create mode 100644 tests/data/acpi/virt/SPCR.numamem - create mode 100644 tests/data/acpi/virt/SRAT.memhp - create mode 100644 tests/data/acpi/virt/SRAT.numamem - -diff --git a/tests/data/acpi/virt/APIC.memhp b/tests/data/acpi/virt/APIC.memhp -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/tests/data/acpi/virt/APIC.numamem b/tests/data/acpi/virt/APIC.numamem -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/tests/data/acpi/virt/DSDT.memhp b/tests/data/acpi/virt/DSDT.memhp -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/tests/data/acpi/virt/DSDT.numamem b/tests/data/acpi/virt/DSDT.numamem -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/tests/data/acpi/virt/FACP.memhp b/tests/data/acpi/virt/FACP.memhp -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/tests/data/acpi/virt/FACP.numamem b/tests/data/acpi/virt/FACP.numamem -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/tests/data/acpi/virt/GTDT.memhp b/tests/data/acpi/virt/GTDT.memhp -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/tests/data/acpi/virt/GTDT.numamem b/tests/data/acpi/virt/GTDT.numamem -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/tests/data/acpi/virt/MCFG.memhp b/tests/data/acpi/virt/MCFG.memhp -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/tests/data/acpi/virt/MCFG.numamem b/tests/data/acpi/virt/MCFG.numamem -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/tests/data/acpi/virt/SLIT.memhp b/tests/data/acpi/virt/SLIT.memhp -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/tests/data/acpi/virt/SPCR.memhp b/tests/data/acpi/virt/SPCR.memhp -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/tests/data/acpi/virt/SPCR.numamem b/tests/data/acpi/virt/SPCR.numamem -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/tests/data/acpi/virt/SRAT.memhp b/tests/data/acpi/virt/SRAT.memhp -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/tests/data/acpi/virt/SRAT.numamem b/tests/data/acpi/virt/SRAT.numamem -new file mode 100644 -index 0000000000..e69de29bb2 --- -2.19.1 diff --git a/tests-acpi-bios-table-test-Update-expected-virt-DSDT.patch b/tests-acpi-bios-table-test-Update-expected-virt-DSDT.patch new file mode 100644 index 0000000000000000000000000000000000000000..22b88989e27f8a8ca7d34726a68b48ba63cb2ca5 --- /dev/null +++ b/tests-acpi-bios-table-test-Update-expected-virt-DSDT.patch @@ -0,0 +1,26 @@ +From d3d158cbf6b236022794e867ac395f75fb4f6436 Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 11 Feb 2022 16:07:31 +0800 +Subject: [PATCH] tests/acpi/bios-table-test: Update expected virt/DSDT file + +Update DSDT binary and empty bios-tables-test-allowd-diff.h + +Signed-off-by: Keqian Zhu +--- + tests/data/acpi/virt/DSDT | Bin 5669 -> 5669 bytes + tests/data/acpi/virt/DSDT.memhp | Bin 7030 -> 7030 bytes + tests/data/acpi/virt/DSDT.numamem | Bin 5669 -> 5669 bytes + tests/data/acpi/virt/DSDT.pxb | Bin 8152 -> 8152 bytes + tests/qtest/bios-tables-test-allowed-diff.h | 1 - + 5 files changed, 1 deletion(-) + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index 7b4adbc822..dfb8523c8b 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1,2 +1 @@ + /* List of comma-separated changed AML files to ignore */ +-"tests/data/acpi/virt/DSDT", +-- +2.27.0 + diff --git a/tests-acpi-bios-table-test-Update-expected-virt-PPTT.patch b/tests-acpi-bios-table-test-Update-expected-virt-PPTT.patch new file mode 100644 index 0000000000000000000000000000000000000000..8f1de286e32e21794adfb2f054ea79278def18f4 --- /dev/null +++ b/tests-acpi-bios-table-test-Update-expected-virt-PPTT.patch @@ -0,0 +1,110 @@ +From 6f89f06e686a61acf681038ac06732facc6e7b93 Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Fri, 7 Jan 2022 16:32:32 +0800 +Subject: [PATCH 20/24] tests/acpi/bios-table-test: Update expected virt/PPTT + file + +Run ./tests/data/acpi/rebuild-expected-aml.sh from build directory +to update PPTT binary. Also empty bios-tables-test-allowed-diff.h. + +The disassembled differences between actual and expected PPTT: + + /* + * Intel ACPI Component Architecture + * AML/ASL+ Disassembler version 20200528 (64-bit version) + * Copyright (c) 2000 - 2020 Intel Corporation + * +- * Disassembly of tests/data/acpi/virt/PPTT, Tue Jan 4 12:51:11 2022 ++ * Disassembly of /tmp/aml-2ZGOF1, Tue Jan 4 12:51:11 2022 + * + * ACPI Data Table [PPTT] + * + * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue + */ + + [000h 0000 4] Signature : "PPTT" [Processor Properties Topology Table] +-[004h 0004 4] Table Length : 0000004C ++[004h 0004 4] Table Length : 00000060 + [008h 0008 1] Revision : 02 +-[009h 0009 1] Checksum : A8 ++[009h 0009 1] Checksum : 48 + [00Ah 0010 6] Oem ID : "BOCHS " + [010h 0016 8] Oem Table ID : "BXPC " + [018h 0024 4] Oem Revision : 00000001 + [01Ch 0028 4] Asl Compiler ID : "BXPC" + [020h 0032 4] Asl Compiler Revision : 00000001 + + [024h 0036 1] Subtable Type : 00 [Processor Hierarchy Node] + [025h 0037 1] Length : 14 + [026h 0038 2] Reserved : 0000 + [028h 0040 4] Flags (decoded below) : 00000001 + Physical package : 1 + ACPI Processor ID valid : 0 + Processor is a thread : 0 + Node is a leaf : 0 + Identical Implementation : 0 + [02Ch 0044 4] Parent : 00000000 + [030h 0048 4] ACPI Processor ID : 00000000 + [034h 0052 4] Private Resource Number : 00000000 + + [038h 0056 1] Subtable Type : 00 [Processor Hierarchy Node] + [039h 0057 1] Length : 14 + [03Ah 0058 2] Reserved : 0000 +-[03Ch 0060 4] Flags (decoded below) : 0000000A ++[03Ch 0060 4] Flags (decoded below) : 00000000 + Physical package : 0 +- ACPI Processor ID valid : 1 ++ ACPI Processor ID valid : 0 + Processor is a thread : 0 +- Node is a leaf : 1 ++ Node is a leaf : 0 + Identical Implementation : 0 + [040h 0064 4] Parent : 00000024 + [044h 0068 4] ACPI Processor ID : 00000000 + [048h 0072 4] Private Resource Number : 00000000 + +-Raw Table Data: Length 76 (0x4C) ++[04Ch 0076 1] Subtable Type : 00 [Processor Hierarchy Node] ++[04Dh 0077 1] Length : 14 ++[04Eh 0078 2] Reserved : 0000 ++[050h 0080 4] Flags (decoded below) : 0000000A ++ Physical package : 0 ++ ACPI Processor ID valid : 1 ++ Processor is a thread : 0 ++ Node is a leaf : 1 ++ Identical Implementation : 0 ++[054h 0084 4] Parent : 00000038 ++[058h 0088 4] ACPI Processor ID : 00000000 ++[05Ch 0092 4] Private Resource Number : 00000000 ++ ++Raw Table Data: Length 96 (0x60) + +- 0000: 50 50 54 54 4C 00 00 00 02 A8 42 4F 43 48 53 20 // PPTTL.....BOCHS ++ 0000: 50 50 54 54 60 00 00 00 02 48 42 4F 43 48 53 20 // PPTT`....HBOCHS + 0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43 // BXPC ....BXPC + 0020: 01 00 00 00 00 14 00 00 01 00 00 00 00 00 00 00 // ................ +- 0030: 00 00 00 00 00 00 00 00 00 14 00 00 0A 00 00 00 // ................ +- 0040: 24 00 00 00 00 00 00 00 00 00 00 00 // $........... ++ 0030: 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 // ................ ++ 0040: 24 00 00 00 00 00 00 00 00 00 00 00 00 14 00 00 // $............... ++ 0050: 0A 00 00 00 38 00 00 00 00 00 00 00 00 00 00 00 // ....8........... + +Signed-off-by: Yanan Wang +Reviewed-by: Ani Sinha +Message-id: 20220107083232.16256-7-wangyanan55@huawei.com +Signed-off-by: Peter Maydell +--- + tests/data/acpi/virt/PPTT | Bin 76 -> 96 bytes + tests/qtest/bios-tables-test-allowed-diff.h | 1 - + 2 files changed, 1 deletion(-) + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index cb143a55a6..dfb8523c8b 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1,2 +1 @@ + /* List of comma-separated changed AML files to ignore */ +-"tests/data/acpi/virt/PPTT", +-- +2.27.0 + diff --git a/tests-acpi-bios-tables-test-Allow-changes-to-virt-DS.patch b/tests-acpi-bios-tables-test-Allow-changes-to-virt-DS.patch new file mode 100644 index 0000000000000000000000000000000000000000..585df22e40a21c84d9df3e883197c42ec3868ced --- /dev/null +++ b/tests-acpi-bios-tables-test-Allow-changes-to-virt-DS.patch @@ -0,0 +1,22 @@ +From d215714b9ab38f6c9e0aacf2120b44888936a1ed Mon Sep 17 00:00:00 2001 +From: Keqian Zhu +Date: Fri, 11 Feb 2022 15:48:16 +0800 +Subject: [PATCH] tests/acpi/bios-tables-test: Allow changes to virt/DSDT file + +Let virt/DSDT as the expected file allowed to be changed. + +Signed-off-by: Keqian Zhu +--- + tests/qtest/bios-tables-test-allowed-diff.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index dfb8523c8b..7b4adbc822 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1 +1,2 @@ + /* List of comma-separated changed AML files to ignore */ ++"tests/data/acpi/virt/DSDT", +-- +2.27.0 + diff --git a/tests-acpi-bios-tables-test-Allow-changes-to-virt-PP.patch b/tests-acpi-bios-tables-test-Allow-changes-to-virt-PP.patch new file mode 100644 index 0000000000000000000000000000000000000000..a4801e55cd027f94f9e929f5dc86dcc5780620c6 --- /dev/null +++ b/tests-acpi-bios-tables-test-Allow-changes-to-virt-PP.patch @@ -0,0 +1,27 @@ +From 225034a72c803b8e3819cec22bc6fb8bfc9e7366 Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Fri, 7 Jan 2022 16:32:30 +0800 +Subject: [PATCH 18/24] tests/acpi/bios-tables-test: Allow changes to virt/PPTT + file + +List test/data/acpi/virt/PPTT as the expected files allowed to +be changed in tests/qtest/bios-tables-test-allowed-diff.h + +Signed-off-by: Yanan Wang +Acked-by: Ani Sinha +Message-id: 20220107083232.16256-5-wangyanan55@huawei.com +Signed-off-by: Peter Maydell +--- + tests/qtest/bios-tables-test-allowed-diff.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h +index dfb8523c8b..cb143a55a6 100644 +--- a/tests/qtest/bios-tables-test-allowed-diff.h ++++ b/tests/qtest/bios-tables-test-allowed-diff.h +@@ -1 +1,2 @@ + /* List of comma-separated changed AML files to ignore */ ++"tests/data/acpi/virt/PPTT", +-- +2.27.0 + diff --git a/tests-allow-empty-expected-files.patch b/tests-allow-empty-expected-files.patch deleted file mode 100644 index 615fb2121d3ffd93d926fe4f3e9623ffce16eb88..0000000000000000000000000000000000000000 --- a/tests-allow-empty-expected-files.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 2ab0636e0c8fcb8b5b1b222f0d5ae7f4dfc663c5 Mon Sep 17 00:00:00 2001 -From: "Michael S. Tsirkin" -Date: Sat, 5 Oct 2019 17:09:17 -0400 -Subject: [PATCH] tests: allow empty expected files - -An empty expected file is a handy way to seed the files -without creating merge conflicts. - -Signed-off-by: Michael S. Tsirkin ---- - tests/bios-tables-test.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c -index a356ac3489..53a91a8067 100644 ---- a/tests/bios-tables-test.c -+++ b/tests/bios-tables-test.c -@@ -334,7 +334,10 @@ try_again: - g_assert(ret); - g_assert_no_error(error); - g_assert(exp_sdt.aml); -- g_assert(exp_sdt.aml_len); -+ if (!exp_sdt.aml_len) { -+ fprintf(stderr, "Warning! zero length expected file '%s'\n", -+ aml_file); -+ } - - g_array_append_val(exp_tables, exp_sdt); - } --- -2.19.1 diff --git a/tests-allow-filtering-crypto-cipher-benchmark-tests.patch b/tests-allow-filtering-crypto-cipher-benchmark-tests.patch deleted file mode 100644 index 51f6b70461b0ade8ff80b2f8ac0302546593228f..0000000000000000000000000000000000000000 --- a/tests-allow-filtering-crypto-cipher-benchmark-tests.patch +++ /dev/null @@ -1,56 +0,0 @@ -From c2a6b4b3204aef2efc39f1b59bc110b54ca24587 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= -Date: Tue, 15 Oct 2019 11:19:29 +0100 -Subject: [PATCH] tests: allow filtering crypto cipher benchmark tests -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add support for specifying a cipher mode and chunk size as argv to -filter which combinations are benchmarked. For example to only -benchmark XTS mode with 512 byte chunks: - - ./tests/benchmark-crypto-cipher xts 512 - -Reviewed-by: Philippe Mathieu-Daudé -Reviewed-by: Stefano Garzarella -Signed-off-by: Daniel P. Berrangé ---- - tests/benchmark-crypto-cipher.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - -diff --git a/tests/benchmark-crypto-cipher.c b/tests/benchmark-crypto-cipher.c -index cb6b7200a5..53032334ec 100644 ---- a/tests/benchmark-crypto-cipher.c -+++ b/tests/benchmark-crypto-cipher.c -@@ -163,15 +163,26 @@ static void test_cipher_speed_xts_aes_256(const void *opaque) - - int main(int argc, char **argv) - { -+ char *alg = NULL; -+ char *size = NULL; - g_test_init(&argc, &argv, NULL); - g_assert(qcrypto_init(NULL) == 0); - - #define ADD_TEST(mode, cipher, keysize, chunk) \ -- g_test_add_data_func( \ -+ if ((!alg || g_str_equal(alg, #mode)) && \ -+ (!size || g_str_equal(size, #chunk))) \ -+ g_test_add_data_func( \ - "/crypto/cipher/" #mode "-" #cipher "-" #keysize "/chunk-" #chunk, \ - (void *)chunk, \ - test_cipher_speed_ ## mode ## _ ## cipher ## _ ## keysize) - -+ if (argc >= 2) { -+ alg = argv[1]; -+ } -+ if (argc >= 3) { -+ size = argv[2]; -+ } -+ - #define ADD_TESTS(chunk) \ - do { \ - ADD_TEST(ecb, aes, 128, chunk); \ --- -2.27.0 - diff --git a/tests-benchmark-crypto-with-fixed-data-size-not-time.patch b/tests-benchmark-crypto-with-fixed-data-size-not-time.patch deleted file mode 100644 index 8841294a8a43877948bd2c74228794aafdaf0114..0000000000000000000000000000000000000000 --- a/tests-benchmark-crypto-with-fixed-data-size-not-time.patch +++ /dev/null @@ -1,150 +0,0 @@ -From c151519a7f5c08dde9a32534bc485588a5793967 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= -Date: Thu, 17 Oct 2019 14:22:19 +0100 -Subject: [PATCH] tests: benchmark crypto with fixed data size, not time period -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Currently the crypto benchmarks are processing data in varying chunk -sizes, over a fixed time period. This turns out to be a terrible idea -because with small chunk sizes the overhead of checking the elapsed -time on each loop iteration masks the true performance. - -Benchmarking over a fixed data size avoids the loop running any system -calls which can interfere with the performance measurements. - -Before this change - -Enc chunk 512 bytes 2283.47 MB/sec Dec chunk 512 bytes 2236.23 MB/sec OK -Enc chunk 4096 bytes 2744.97 MB/sec Dec chunk 4096 bytes 2614.71 MB/sec OK -Enc chunk 16384 bytes 2777.53 MB/sec Dec chunk 16384 bytes 2678.44 MB/sec OK -Enc chunk 65536 bytes 2809.34 MB/sec Dec chunk 65536 bytes 2699.47 MB/sec OK - -After this change - -Enc chunk 512 bytes 2058.22 MB/sec Dec chunk 512 bytes 2030.11 MB/sec OK -Enc chunk 4096 bytes 2699.27 MB/sec Dec chunk 4096 bytes 2573.78 MB/sec OK -Enc chunk 16384 bytes 2748.52 MB/sec Dec chunk 16384 bytes 2653.76 MB/sec OK -Enc chunk 65536 bytes 2814.08 MB/sec Dec chunk 65536 bytes 2712.74 MB/sec OK - -The actual crypto performance hasn't changed, which shows how -significant the mis-measurement has been for small data sizes. - -Reviewed-by: Philippe Mathieu-Daudé -Reviewed-by: Stefano Garzarella -Signed-off-by: Daniel P. Berrangé ---- - tests/benchmark-crypto-cipher.c | 26 ++++++++++++++------------ - tests/benchmark-crypto-hash.c | 17 +++++++++-------- - 2 files changed, 23 insertions(+), 20 deletions(-) - -diff --git a/tests/benchmark-crypto-cipher.c b/tests/benchmark-crypto-cipher.c -index 67fdf8c31d..cb6b7200a5 100644 ---- a/tests/benchmark-crypto-cipher.c -+++ b/tests/benchmark-crypto-cipher.c -@@ -21,11 +21,12 @@ static void test_cipher_speed(size_t chunk_size, - { - QCryptoCipher *cipher; - Error *err = NULL; -- double total = 0.0; - uint8_t *key = NULL, *iv = NULL; - uint8_t *plaintext = NULL, *ciphertext = NULL; - size_t nkey; - size_t niv; -+ const size_t total = 2 * GiB; -+ size_t remain; - - if (!qcrypto_cipher_supports(alg, mode)) { - return; -@@ -58,33 +59,34 @@ static void test_cipher_speed(size_t chunk_size, - &err) == 0); - - g_test_timer_start(); -- do { -+ remain = total; -+ while (remain) { - g_assert(qcrypto_cipher_encrypt(cipher, - plaintext, - ciphertext, - chunk_size, - &err) == 0); -- total += chunk_size; -- } while (g_test_timer_elapsed() < 1.0); -+ remain -= chunk_size; -+ } -+ g_test_timer_elapsed(); - -- total /= MiB; - g_print("Enc chunk %zu bytes ", chunk_size); -- g_print("%.2f MB/sec ", total / g_test_timer_last()); -+ g_print("%.2f MB/sec ", (double)total / MiB / g_test_timer_last()); - -- total = 0.0; - g_test_timer_start(); -- do { -+ remain = total; -+ while (remain) { - g_assert(qcrypto_cipher_decrypt(cipher, - plaintext, - ciphertext, - chunk_size, - &err) == 0); -- total += chunk_size; -- } while (g_test_timer_elapsed() < 1.0); -+ remain -= chunk_size; -+ } -+ g_test_timer_elapsed(); - -- total /= MiB; - g_print("Dec chunk %zu bytes ", chunk_size); -- g_print("%.2f MB/sec ", total / g_test_timer_last()); -+ g_print("%.2f MB/sec ", (double)total / MiB / g_test_timer_last()); - - qcrypto_cipher_free(cipher); - g_free(plaintext); -diff --git a/tests/benchmark-crypto-hash.c b/tests/benchmark-crypto-hash.c -index 9b6f7a9155..7f659f7323 100644 ---- a/tests/benchmark-crypto-hash.c -+++ b/tests/benchmark-crypto-hash.c -@@ -20,7 +20,8 @@ static void test_hash_speed(const void *opaque) - size_t chunk_size = (size_t)opaque; - uint8_t *in = NULL, *out = NULL; - size_t out_len = 0; -- double total = 0.0; -+ const size_t total = 2 * GiB; -+ size_t remain; - struct iovec iov; - int ret; - -@@ -31,20 +32,20 @@ static void test_hash_speed(const void *opaque) - iov.iov_len = chunk_size; - - g_test_timer_start(); -- do { -+ remain = total; -+ while (remain) { - ret = qcrypto_hash_bytesv(QCRYPTO_HASH_ALG_SHA256, - &iov, 1, &out, &out_len, - NULL); - g_assert(ret == 0); - -- total += chunk_size; -- } while (g_test_timer_elapsed() < 5.0); -+ remain -= chunk_size; -+ } -+ g_test_timer_elapsed(); - -- total /= MiB; - g_print("sha256: "); -- g_print("Testing chunk_size %zu bytes ", chunk_size); -- g_print("done: %.2f MB in %.2f secs: ", total, g_test_timer_last()); -- g_print("%.2f MB/sec\n", total / g_test_timer_last()); -+ g_print("Hash %zu GB chunk size %zu bytes ", total / GiB, chunk_size); -+ g_print("%.2f MB/sec ", (double)total / MiB / g_test_timer_last()); - - g_free(out); - g_free(in); --- -2.27.0 - diff --git a/tests-bios-tables-test-disable-this-testcase.patch b/tests-bios-tables-test-disable-this-testcase.patch deleted file mode 100644 index 993fee935546735c16bfe9a30ff856ac135f4d53..0000000000000000000000000000000000000000 --- a/tests-bios-tables-test-disable-this-testcase.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0814ef80cdf212c68b73fc1fbad4eeece3560ef9 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 15 Apr 2020 19:52:09 +0800 -Subject: [PATCH] tests/bios-tables-test: disable this testcase - -We will change ARM virt ACPI FACP and PPTT table in order to -support CPU topology information presentation. However our -change make this testcase fail since we changed the table -totally and we cannot apply patch with rpmbuild system. - -Signed-off-by: Ying Fang ---- - tests/Makefile.include | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/tests/Makefile.include b/tests/Makefile.include -index fd7fdb86..d8cf00c1 100644 ---- a/tests/Makefile.include -+++ b/tests/Makefile.include -@@ -164,7 +164,7 @@ check-qtest-i386-y += tests/ide-test$(EXESUF) - check-qtest-i386-y += tests/ahci-test$(EXESUF) - check-qtest-i386-y += tests/hd-geo-test$(EXESUF) - check-qtest-i386-y += tests/boot-order-test$(EXESUF) --check-qtest-i386-y += tests/bios-tables-test$(EXESUF) -+# check-qtest-i386-y += tests/bios-tables-test$(EXESUF) - check-qtest-i386-$(CONFIG_SGA) += tests/boot-serial-test$(EXESUF) - check-qtest-i386-$(CONFIG_SLIRP) += tests/pxe-test$(EXESUF) - check-qtest-i386-y += tests/rtc-test$(EXESUF) -@@ -269,7 +269,7 @@ check-qtest-aarch64-y += tests/boot-serial-test$(EXESUF) - check-qtest-aarch64-y += tests/migration-test$(EXESUF) - # TODO: once aarch64 TCG is fixed on ARM 32 bit host, make test unconditional - ifneq ($(ARCH),arm) --check-qtest-aarch64-y += tests/bios-tables-test$(EXESUF) -+#check-qtest-aarch64-y += tests/bios-tables-test$(EXESUF) - endif - - check-qtest-microblazeel-y += $(check-qtest-microblaze-y) -@@ -783,7 +783,7 @@ tests/ipmi-bt-test$(EXESUF): tests/ipmi-bt-test.o - tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o - tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y) - tests/boot-serial-test$(EXESUF): tests/boot-serial-test.o $(libqos-obj-y) --tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \ -+#tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \ - tests/boot-sector.o tests/acpi-utils.o $(libqos-obj-y) - tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y) - tests/microbit-test$(EXESUF): tests/microbit-test.o --- -2.23.0 diff --git a/tests-document-how-to-update-acpi-tables.patch b/tests-document-how-to-update-acpi-tables.patch deleted file mode 100644 index c961069b6e77c2a193b34d606466f04c7b059611..0000000000000000000000000000000000000000 --- a/tests-document-how-to-update-acpi-tables.patch +++ /dev/null @@ -1,53 +0,0 @@ -From d9642ad522d34f0d803a87654a2c258baf1070dd Mon Sep 17 00:00:00 2001 -From: "Michael S. Tsirkin" -Date: Sat, 5 Oct 2019 17:25:55 -0400 -Subject: [PATCH] tests: document how to update acpi tables - -Looks like no one understands how to do it. -Document the process. - -Signed-off-by: Michael S. Tsirkin ---- - tests/bios-tables-test.c | 27 +++++++++++++++++++++++++++ - 1 file changed, 27 insertions(+) - -diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c -index 5e177b7155..d47ee9be99 100644 ---- a/tests/bios-tables-test.c -+++ b/tests/bios-tables-test.c -@@ -10,6 +10,33 @@ - * See the COPYING file in the top-level directory. - */ - -+/* -+ * How to add or update the tests: -+ * Contributor: -+ * 1. add empty files for new tables, if any, under tests/data/acpi -+ * 2. list any changed files in tests/bios-tables-test-allowed-diff.h -+ * 3. commit the above *before* making changes that affect the tables -+ * Maintainer: -+ * After 1-3 above tests will pass but ignore differences with the expected files. -+ * You will also notice that tests/bios-tables-test-allowed-diff.h lists -+ * a bunch of files. This is your hint that you need to do the below: -+ * 4. Run -+ * make check V=1 -+ * this will produce a bunch of warnings about differences -+ * beween actual and expected ACPI tables. If you have IASL installed, -+ * they will also be disassembled so you can look at the disassembled -+ * output. If not - disassemble them yourself in any way you like. -+ * Look at the differences - make sure they make sense and match what the -+ * changes you are merging are supposed to do. -+ * -+ * 5. From build directory, run: -+ * $(SRC_PATH)/tests/data/acpi/rebuild-expected-aml.sh -+ * 6. Now commit any changes. -+ * 7. Before doing a pull request, make sure tests/bios-tables-test-allowed-diff.h -+ * is empty - this will ensure following changes to ACPI tables will -+ * be noticed. -+ */ -+ - #include "qemu/osdep.h" - #include - #include "qemu-common.h" --- -2.19.1 diff --git a/tests-unit-test-smp-parse-Add-smp-generic-invalid-ma.patch b/tests-unit-test-smp-parse-Add-smp-generic-invalid-ma.patch new file mode 100644 index 0000000000000000000000000000000000000000..5ea0e6cd48e1d0df115b00da2711627375e7b5fd --- /dev/null +++ b/tests-unit-test-smp-parse-Add-smp-generic-invalid-ma.patch @@ -0,0 +1,87 @@ +From 9a98659dcb37c81e69f54d8f6cbe5116ceba5a36 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 15 Nov 2021 15:44:07 +0100 +Subject: [PATCH 05/24] tests/unit/test-smp-parse: Add 'smp-generic-invalid' + machine type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Avoid modifying the MachineClass internals by adding the +'smp-generic-invalid' machine, which inherits from TYPE_MACHINE. + +Reviewed-by: Richard Henderson +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Yanan Wang +Message-Id: <20211216132015.815493-5-philmd@redhat.com> +--- + tests/unit/test-smp-parse.c | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index f66cf7bb59..47e11089e2 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -487,6 +487,17 @@ static void machine_base_class_init(ObjectClass *oc, void *data) + mc->name = g_strdup(SMP_MACHINE_NAME); + } + ++static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) ++{ ++ MachineClass *mc = MACHINE_CLASS(oc); ++ ++ /* Force invalid min CPUs and max CPUs */ ++ mc->min_cpus = 2; ++ mc->max_cpus = 511; ++ ++ mc->smp_props.dies_supported = false; ++} ++ + static void machine_with_dies_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); +@@ -530,10 +541,6 @@ static void test_generic_invalid(const void *opaque) + SMPTestData *data = &(SMPTestData){}; + int i; + +- /* Force invalid min CPUs and max CPUs */ +- mc->min_cpus = 2; +- mc->max_cpus = 511; +- + for (i = 0; i < ARRAY_SIZE(data_generic_invalid); i++) { + *data = data_generic_invalid[i]; + unsupported_params_init(mc, data); +@@ -541,10 +548,6 @@ static void test_generic_invalid(const void *opaque) + smp_parse_test(ms, data, false); + } + +- /* Reset the supported min CPUs and max CPUs */ +- mc->min_cpus = MIN_CPUS; +- mc->max_cpus = MAX_CPUS; +- + object_unref(obj); + } + +@@ -606,6 +609,10 @@ static const TypeInfo smp_machine_types[] = { + .class_init = machine_base_class_init, + .class_size = sizeof(MachineClass), + .instance_size = sizeof(MachineState), ++ }, { ++ .name = MACHINE_TYPE_NAME("smp-generic-invalid"), ++ .parent = TYPE_MACHINE, ++ .class_init = machine_generic_invalid_class_init, + }, { + .name = MACHINE_TYPE_NAME("smp-with-dies"), + .parent = TYPE_MACHINE, +@@ -625,7 +632,7 @@ int main(int argc, char *argv[]) + TYPE_MACHINE, + test_generic_valid); + g_test_add_data_func("/test-smp-parse/generic/invalid", +- TYPE_MACHINE, ++ MACHINE_TYPE_NAME("smp-generic-invalid"), + test_generic_invalid); + g_test_add_data_func("/test-smp-parse/with_dies", + MACHINE_TYPE_NAME("smp-with-dies"), +-- +2.27.0 + diff --git a/tests-unit-test-smp-parse-Add-smp-generic-valid-mach.patch b/tests-unit-test-smp-parse-Add-smp-generic-valid-mach.patch new file mode 100644 index 0000000000000000000000000000000000000000..a8b17e751a578f914102e7911b820888227dbe54 --- /dev/null +++ b/tests-unit-test-smp-parse-Add-smp-generic-valid-mach.patch @@ -0,0 +1,75 @@ +From c33c7dd51eebf5ae7b7ece1e829b0a5ffdcebfe1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 15 Nov 2021 15:49:59 +0100 +Subject: [PATCH 06/24] tests/unit/test-smp-parse: Add 'smp-generic-valid' + machine type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Keep the common TYPE_MACHINE class initialization in +machine_base_class_init(), make it abstract, and move +the non-common code to a new class: "smp-generic-valid". + +Reviewed-by: Richard Henderson +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Yanan Wang +Message-Id: <20211216132015.815493-6-philmd@redhat.com> +--- + tests/unit/test-smp-parse.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index 47e11089e2..b20bf2c235 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -478,13 +478,19 @@ static void machine_base_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); + ++ mc->smp_props.prefer_sockets = true; ++ ++ mc->name = g_strdup(SMP_MACHINE_NAME); ++} ++ ++static void machine_generic_valid_class_init(ObjectClass *oc, void *data) ++{ ++ MachineClass *mc = MACHINE_CLASS(oc); ++ + mc->min_cpus = MIN_CPUS; + mc->max_cpus = MAX_CPUS; + +- mc->smp_props.prefer_sockets = true; + mc->smp_props.dies_supported = false; +- +- mc->name = g_strdup(SMP_MACHINE_NAME); + } + + static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) +@@ -606,9 +612,14 @@ static const TypeInfo smp_machine_types[] = { + { + .name = TYPE_MACHINE, + .parent = TYPE_OBJECT, ++ .abstract = true, + .class_init = machine_base_class_init, + .class_size = sizeof(MachineClass), + .instance_size = sizeof(MachineState), ++ }, { ++ .name = MACHINE_TYPE_NAME("smp-generic-valid"), ++ .parent = TYPE_MACHINE, ++ .class_init = machine_generic_valid_class_init, + }, { + .name = MACHINE_TYPE_NAME("smp-generic-invalid"), + .parent = TYPE_MACHINE, +@@ -629,7 +640,7 @@ int main(int argc, char *argv[]) + g_test_init(&argc, &argv, NULL); + + g_test_add_data_func("/test-smp-parse/generic/valid", +- TYPE_MACHINE, ++ MACHINE_TYPE_NAME("smp-generic-valid"), + test_generic_valid); + g_test_add_data_func("/test-smp-parse/generic/invalid", + MACHINE_TYPE_NAME("smp-generic-invalid"), +-- +2.27.0 + diff --git a/tests-unit-test-smp-parse-Add-smp-with-dies-machine-.patch b/tests-unit-test-smp-parse-Add-smp-with-dies-machine-.patch new file mode 100644 index 0000000000000000000000000000000000000000..1d779fc274a8d8140d71c76d165fd0ca5e0644da --- /dev/null +++ b/tests-unit-test-smp-parse-Add-smp-with-dies-machine-.patch @@ -0,0 +1,85 @@ +From 4981e75623db6ca681d13719ffcf61b0cfac3edc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 15 Nov 2021 12:39:12 +0100 +Subject: [PATCH 04/24] tests/unit/test-smp-parse: Add 'smp-with-dies' machine + type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Avoid modifying the MachineClass internals by adding the +'smp-with-dies' machine, which inherits from TYPE_MACHINE. + +Reviewed-by: Richard Henderson +Reviewed-by: Yanan Wang +Tested-by: Yanan Wang +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211216132015.815493-4-philmd@redhat.com> +--- + tests/unit/test-smp-parse.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index 425ed6b6b9..f66cf7bb59 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -487,6 +487,16 @@ static void machine_base_class_init(ObjectClass *oc, void *data) + mc->name = g_strdup(SMP_MACHINE_NAME); + } + ++static void machine_with_dies_class_init(ObjectClass *oc, void *data) ++{ ++ MachineClass *mc = MACHINE_CLASS(oc); ++ ++ mc->min_cpus = MIN_CPUS; ++ mc->max_cpus = MAX_CPUS; ++ ++ mc->smp_props.dies_supported = true; ++} ++ + static void test_generic_valid(const void *opaque) + { + const char *machine_type = opaque; +@@ -548,9 +558,6 @@ static void test_with_dies(const void *opaque) + unsigned int num_dies = 2; + int i; + +- /* Force the SMP compat properties */ +- mc->smp_props.dies_supported = true; +- + for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { + *data = data_generic_valid[i]; + unsupported_params_init(mc, data); +@@ -588,9 +595,6 @@ static void test_with_dies(const void *opaque) + smp_parse_test(ms, data, false); + } + +- /* Restore the SMP compat properties */ +- mc->smp_props.dies_supported = false; +- + object_unref(obj); + } + +@@ -602,6 +606,10 @@ static const TypeInfo smp_machine_types[] = { + .class_init = machine_base_class_init, + .class_size = sizeof(MachineClass), + .instance_size = sizeof(MachineState), ++ }, { ++ .name = MACHINE_TYPE_NAME("smp-with-dies"), ++ .parent = TYPE_MACHINE, ++ .class_init = machine_with_dies_class_init, + } + }; + +@@ -620,7 +628,7 @@ int main(int argc, char *argv[]) + TYPE_MACHINE, + test_generic_invalid); + g_test_add_data_func("/test-smp-parse/with_dies", +- TYPE_MACHINE, ++ MACHINE_TYPE_NAME("smp-with-dies"), + test_with_dies); + + g_test_run(); +-- +2.27.0 + diff --git a/tests-unit-test-smp-parse-Add-testcases-for-CPU-clus.patch b/tests-unit-test-smp-parse-Add-testcases-for-CPU-clus.patch new file mode 100644 index 0000000000000000000000000000000000000000..e9c9aefbb230a5b0fb05a8e7f9f03f2bf6592158 --- /dev/null +++ b/tests-unit-test-smp-parse-Add-testcases-for-CPU-clus.patch @@ -0,0 +1,254 @@ +From 5e8a39a560ea58308f66d47639c0d5d2e704997f Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Tue, 28 Dec 2021 17:22:11 +0800 +Subject: [PATCH 12/24] tests/unit/test-smp-parse: Add testcases for CPU + clusters +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add testcases for parsing of the four-level CPU topology hierarchy, +ie sockets/clusters/cores/threads, which will be supported on ARM +virt machines. + +Signed-off-by: Yanan Wang +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20211228092221.21068-5-wangyanan55@huawei.com> +Signed-off-by: Philippe Mathieu-Daudé +--- + tests/unit/test-smp-parse.c | 130 ++++++++++++++++++++++++++++++++++-- + 1 file changed, 123 insertions(+), 7 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index b6df8137fc..331719bbc4 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -61,6 +61,20 @@ + .has_maxcpus = hf, .maxcpus = f, \ + } + ++/* ++ * Currently a 4-level topology hierarchy is supported on ARM virt machines ++ * -sockets/clusters/cores/threads ++ */ ++#define SMP_CONFIG_WITH_CLUSTERS(ha, a, hb, b, hc, c, hd, d, he, e, hf, f) \ ++ { \ ++ .has_cpus = ha, .cpus = a, \ ++ .has_sockets = hb, .sockets = b, \ ++ .has_clusters = hc, .clusters = c, \ ++ .has_cores = hd, .cores = d, \ ++ .has_threads = he, .threads = e, \ ++ .has_maxcpus = hf, .maxcpus = f, \ ++ } ++ + /** + * @config - the given SMP configuration + * @expect_prefer_sockets - the expected parsing result for the +@@ -290,6 +304,10 @@ static const struct SMPTestData data_generic_invalid[] = { + /* config: -smp 2,dies=2 */ + .config = SMP_CONFIG_WITH_DIES(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0), + .expect_error = "dies not supported by this machine's CPU topology", ++ }, { ++ /* config: -smp 2,clusters=2 */ ++ .config = SMP_CONFIG_WITH_CLUSTERS(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0), ++ .expect_error = "clusters not supported by this machine's CPU topology", + }, { + /* config: -smp 8,sockets=2,cores=4,threads=2,maxcpus=8 */ + .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 2, T, 8), +@@ -337,20 +355,40 @@ static const struct SMPTestData data_with_dies_invalid[] = { + }, + }; + ++static const struct SMPTestData data_with_clusters_invalid[] = { ++ { ++ /* config: -smp 16,sockets=2,clusters=2,cores=4,threads=2,maxcpus=16 */ ++ .config = SMP_CONFIG_WITH_CLUSTERS(T, 16, T, 2, T, 2, T, 4, T, 2, T, 16), ++ .expect_error = "Invalid CPU topology: " ++ "product of the hierarchy must match maxcpus: " ++ "sockets (2) * clusters (2) * cores (4) * threads (2) " ++ "!= maxcpus (16)", ++ }, { ++ /* config: -smp 34,sockets=2,clusters=2,cores=4,threads=2,maxcpus=32 */ ++ .config = SMP_CONFIG_WITH_CLUSTERS(T, 34, T, 2, T, 2, T, 4, T, 2, T, 32), ++ .expect_error = "Invalid CPU topology: " ++ "maxcpus must be equal to or greater than smp: " ++ "sockets (2) * clusters (2) * cores (4) * threads (2) " ++ "== maxcpus (32) < smp_cpus (34)", ++ }, ++}; ++ + static char *smp_config_to_string(const SMPConfiguration *config) + { + return g_strdup_printf( + "(SMPConfiguration) {\n" +- " .has_cpus = %5s, cpus = %" PRId64 ",\n" +- " .has_sockets = %5s, sockets = %" PRId64 ",\n" +- " .has_dies = %5s, dies = %" PRId64 ",\n" +- " .has_cores = %5s, cores = %" PRId64 ",\n" +- " .has_threads = %5s, threads = %" PRId64 ",\n" +- " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n" ++ " .has_cpus = %5s, cpus = %" PRId64 ",\n" ++ " .has_sockets = %5s, sockets = %" PRId64 ",\n" ++ " .has_dies = %5s, dies = %" PRId64 ",\n" ++ " .has_clusters = %5s, clusters = %" PRId64 ",\n" ++ " .has_cores = %5s, cores = %" PRId64 ",\n" ++ " .has_threads = %5s, threads = %" PRId64 ",\n" ++ " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n" + "}", + config->has_cpus ? "true" : "false", config->cpus, + config->has_sockets ? "true" : "false", config->sockets, + config->has_dies ? "true" : "false", config->dies, ++ config->has_clusters ? "true" : "false", config->clusters, + config->has_cores ? "true" : "false", config->cores, + config->has_threads ? "true" : "false", config->threads, + config->has_maxcpus ? "true" : "false", config->maxcpus); +@@ -363,11 +401,12 @@ static char *cpu_topology_to_string(const CpuTopology *topo) + " .cpus = %u,\n" + " .sockets = %u,\n" + " .dies = %u,\n" ++ " .clusters = %u,\n" + " .cores = %u,\n" + " .threads = %u,\n" + " .max_cpus = %u,\n" + "}", +- topo->cpus, topo->sockets, topo->dies, ++ topo->cpus, topo->sockets, topo->dies, topo->clusters, + topo->cores, topo->threads, topo->max_cpus); + } + +@@ -391,6 +430,7 @@ static void check_parse(MachineState *ms, const SMPConfiguration *config, + (ms->smp.cpus == expect_topo->cpus) && + (ms->smp.sockets == expect_topo->sockets) && + (ms->smp.dies == expect_topo->dies) && ++ (ms->smp.clusters == expect_topo->clusters) && + (ms->smp.cores == expect_topo->cores) && + (ms->smp.threads == expect_topo->threads) && + (ms->smp.max_cpus == expect_topo->max_cpus)) { +@@ -472,6 +512,11 @@ static void unsupported_params_init(const MachineClass *mc, SMPTestData *data) + data->expect_prefer_sockets.dies = 1; + data->expect_prefer_cores.dies = 1; + } ++ ++ if (!mc->smp_props.clusters_supported) { ++ data->expect_prefer_sockets.clusters = 1; ++ data->expect_prefer_cores.clusters = 1; ++ } + } + + static void machine_base_class_init(ObjectClass *oc, void *data) +@@ -491,6 +536,7 @@ static void machine_generic_valid_class_init(ObjectClass *oc, void *data) + mc->max_cpus = MAX_CPUS; + + mc->smp_props.dies_supported = false; ++ mc->smp_props.clusters_supported = false; + } + + static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) +@@ -502,6 +548,7 @@ static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) + mc->max_cpus = 511; + + mc->smp_props.dies_supported = false; ++ mc->smp_props.clusters_supported = false; + } + + static void machine_with_dies_class_init(ObjectClass *oc, void *data) +@@ -512,6 +559,18 @@ static void machine_with_dies_class_init(ObjectClass *oc, void *data) + mc->max_cpus = MAX_CPUS; + + mc->smp_props.dies_supported = true; ++ mc->smp_props.clusters_supported = false; ++} ++ ++static void machine_with_clusters_class_init(ObjectClass *oc, void *data) ++{ ++ MachineClass *mc = MACHINE_CLASS(oc); ++ ++ mc->min_cpus = MIN_CPUS; ++ mc->max_cpus = MAX_CPUS; ++ ++ mc->smp_props.clusters_supported = true; ++ mc->smp_props.dies_supported = false; + } + + static void test_generic_valid(const void *opaque) +@@ -607,6 +666,56 @@ static void test_with_dies(const void *opaque) + object_unref(obj); + } + ++static void test_with_clusters(const void *opaque) ++{ ++ const char *machine_type = opaque; ++ Object *obj = object_new(machine_type); ++ MachineState *ms = MACHINE(obj); ++ MachineClass *mc = MACHINE_GET_CLASS(obj); ++ SMPTestData data = {}; ++ unsigned int num_clusters = 2; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { ++ data = data_generic_valid[i]; ++ unsupported_params_init(mc, &data); ++ ++ /* when clusters parameter is omitted, it will be set as 1 */ ++ data.expect_prefer_sockets.clusters = 1; ++ data.expect_prefer_cores.clusters = 1; ++ ++ smp_parse_test(ms, &data, true); ++ ++ /* when clusters parameter is specified */ ++ data.config.has_clusters = true; ++ data.config.clusters = num_clusters; ++ if (data.config.has_cpus) { ++ data.config.cpus *= num_clusters; ++ } ++ if (data.config.has_maxcpus) { ++ data.config.maxcpus *= num_clusters; ++ } ++ ++ data.expect_prefer_sockets.clusters = num_clusters; ++ data.expect_prefer_sockets.cpus *= num_clusters; ++ data.expect_prefer_sockets.max_cpus *= num_clusters; ++ data.expect_prefer_cores.clusters = num_clusters; ++ data.expect_prefer_cores.cpus *= num_clusters; ++ data.expect_prefer_cores.max_cpus *= num_clusters; ++ ++ smp_parse_test(ms, &data, true); ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(data_with_clusters_invalid); i++) { ++ data = data_with_clusters_invalid[i]; ++ unsupported_params_init(mc, &data); ++ ++ smp_parse_test(ms, &data, false); ++ } ++ ++ object_unref(obj); ++} ++ + /* Type info of the tested machine */ + static const TypeInfo smp_machine_types[] = { + { +@@ -628,6 +737,10 @@ static const TypeInfo smp_machine_types[] = { + .name = MACHINE_TYPE_NAME("smp-with-dies"), + .parent = TYPE_MACHINE, + .class_init = machine_with_dies_class_init, ++ }, { ++ .name = MACHINE_TYPE_NAME("smp-with-clusters"), ++ .parent = TYPE_MACHINE, ++ .class_init = machine_with_clusters_class_init, + } + }; + +@@ -648,6 +761,9 @@ int main(int argc, char *argv[]) + g_test_add_data_func("/test-smp-parse/with_dies", + MACHINE_TYPE_NAME("smp-with-dies"), + test_with_dies); ++ g_test_add_data_func("/test-smp-parse/with_clusters", ++ MACHINE_TYPE_NAME("smp-with-clusters"), ++ test_with_clusters); + + g_test_run(); + +-- +2.27.0 + diff --git a/tests-unit-test-smp-parse-Constify-some-pointer-stru.patch b/tests-unit-test-smp-parse-Constify-some-pointer-stru.patch new file mode 100644 index 0000000000000000000000000000000000000000..85a56a425c7be042146bc96406b52e162a5544da --- /dev/null +++ b/tests-unit-test-smp-parse-Constify-some-pointer-stru.patch @@ -0,0 +1,82 @@ +From bcf4b802bd8971c0c5a255e606b15900cd47c6b6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 11 Nov 2021 10:23:06 +0100 +Subject: [PATCH 08/24] tests/unit/test-smp-parse: Constify some pointer/struct +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Declare structures const when we don't need to modify +them at runtime. + +Reviewed-by: Andrew Jones +Reviewed-by: Richard Henderson +Reviewed-by: Yanan Wang +Tested-by: Yanan Wang +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211216132015.815493-8-philmd@redhat.com> +--- + tests/unit/test-smp-parse.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index 395929b66c..0f98c9509e 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -83,7 +83,7 @@ typedef struct SMPTestData { + * then test the automatic calculation algorithm of the missing + * values in the parser. + */ +-static struct SMPTestData data_generic_valid[] = { ++static const struct SMPTestData data_generic_valid[] = { + { + /* config: no configuration provided + * expect: cpus=1,sockets=1,cores=1,threads=1,maxcpus=1 */ +@@ -285,7 +285,7 @@ static struct SMPTestData data_generic_valid[] = { + }, + }; + +-static struct SMPTestData data_generic_invalid[] = { ++static const struct SMPTestData data_generic_invalid[] = { + { + /* config: -smp 2,dies=2 */ + .config = SMP_CONFIG_WITH_DIES(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0), +@@ -319,7 +319,7 @@ static struct SMPTestData data_generic_invalid[] = { + }, + }; + +-static struct SMPTestData data_with_dies_invalid[] = { ++static const struct SMPTestData data_with_dies_invalid[] = { + { + /* config: -smp 16,sockets=2,dies=2,cores=4,threads=2,maxcpus=16 */ + .config = SMP_CONFIG_WITH_DIES(T, 16, T, 2, T, 2, T, 4, T, 2, T, 16), +@@ -356,7 +356,7 @@ static char *smp_config_to_string(SMPConfiguration *config) + config->has_maxcpus ? "true" : "false", config->maxcpus); + } + +-static char *cpu_topology_to_string(CpuTopology *topo) ++static char *cpu_topology_to_string(const CpuTopology *topo) + { + return g_strdup_printf( + "(CpuTopology) {\n" +@@ -372,7 +372,7 @@ static char *cpu_topology_to_string(CpuTopology *topo) + } + + static void check_parse(MachineState *ms, SMPConfiguration *config, +- CpuTopology *expect_topo, const char *expect_err, ++ const CpuTopology *expect_topo, const char *expect_err, + bool is_valid) + { + g_autofree char *config_str = smp_config_to_string(config); +@@ -466,7 +466,7 @@ static void smp_parse_test(MachineState *ms, SMPTestData *data, bool is_valid) + } + + /* The parsed results of the unsupported parameters should be 1 */ +-static void unsupported_params_init(MachineClass *mc, SMPTestData *data) ++static void unsupported_params_init(const MachineClass *mc, SMPTestData *data) + { + if (!mc->smp_props.dies_supported) { + data->expect_prefer_sockets.dies = 1; +-- +2.27.0 + diff --git a/tests-unit-test-smp-parse-Keep-default-MIN-MAX-CPUs-.patch b/tests-unit-test-smp-parse-Keep-default-MIN-MAX-CPUs-.patch new file mode 100644 index 0000000000000000000000000000000000000000..6e343576fdca6a1ef4713535849d6d9375c71cd9 --- /dev/null +++ b/tests-unit-test-smp-parse-Keep-default-MIN-MAX-CPUs-.patch @@ -0,0 +1,76 @@ +From 214511b1799b94cfd514a222d087bb888ed808ba Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Tue, 28 Dec 2021 17:22:13 +0800 +Subject: [PATCH 14/24] tests/unit/test-smp-parse: Keep default MIN/MAX CPUs in + machine_base_class_init +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Most machine types in test-smp-parse will be OK to have the default +MIN/MAX CPUs except "smp-generic-invalid", let's keep the default +values in machine_base_class_init which will be inherited. And if +we hope a different value for a specific machine, modify it in its +own initialization function. + +Signed-off-by: Yanan Wang +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20211228092221.21068-7-wangyanan55@huawei.com> +Signed-off-by: Philippe Mathieu-Daudé +--- + tests/unit/test-smp-parse.c | 16 ++-------------- + 1 file changed, 2 insertions(+), 14 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index 72d83d1bbc..fdc39a846c 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -523,15 +523,10 @@ static void machine_base_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); + +- mc->name = g_strdup(SMP_MACHINE_NAME); +-} +- +-static void machine_generic_valid_class_init(ObjectClass *oc, void *data) +-{ +- MachineClass *mc = MACHINE_CLASS(oc); +- + mc->min_cpus = MIN_CPUS; + mc->max_cpus = MAX_CPUS; ++ ++ mc->name = g_strdup(SMP_MACHINE_NAME); + } + + static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) +@@ -547,9 +542,6 @@ static void machine_with_dies_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); + +- mc->min_cpus = MIN_CPUS; +- mc->max_cpus = MAX_CPUS; +- + mc->smp_props.dies_supported = true; + } + +@@ -557,9 +549,6 @@ static void machine_with_clusters_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); + +- mc->min_cpus = MIN_CPUS; +- mc->max_cpus = MAX_CPUS; +- + mc->smp_props.clusters_supported = true; + } + +@@ -718,7 +707,6 @@ static const TypeInfo smp_machine_types[] = { + }, { + .name = MACHINE_TYPE_NAME("smp-generic-valid"), + .parent = TYPE_MACHINE, +- .class_init = machine_generic_valid_class_init, + }, { + .name = MACHINE_TYPE_NAME("smp-generic-invalid"), + .parent = TYPE_MACHINE, +-- +2.27.0 + diff --git a/tests-unit-test-smp-parse-No-need-to-explicitly-zero.patch b/tests-unit-test-smp-parse-No-need-to-explicitly-zero.patch new file mode 100644 index 0000000000000000000000000000000000000000..59157169c32a498e5ae0455aaaf6dd1312c4b17f --- /dev/null +++ b/tests-unit-test-smp-parse-No-need-to-explicitly-zero.patch @@ -0,0 +1,75 @@ +From 77bca7d51e99f8ba4d11635ff9f51615739f4d55 Mon Sep 17 00:00:00 2001 +From: Yanan Wang +Date: Tue, 28 Dec 2021 17:22:12 +0800 +Subject: [PATCH 13/24] tests/unit/test-smp-parse: No need to explicitly zero + MachineClass members +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The default value of the MachineClass members is 0, which +means we don't have to explicitly zero them. Also the value +of "mc->smp_props.prefer_sockets" will be taken care of by +smp_parse_test(), we don't necessarily need the statement +in machine_base_class_init() either. + +Signed-off-by: Yanan Wang +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20211228092221.21068-6-wangyanan55@huawei.com> +Signed-off-by: Philippe Mathieu-Daudé +--- + tests/unit/test-smp-parse.c | 10 ---------- + 1 file changed, 10 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index 331719bbc4..72d83d1bbc 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -523,8 +523,6 @@ static void machine_base_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); + +- mc->smp_props.prefer_sockets = true; +- + mc->name = g_strdup(SMP_MACHINE_NAME); + } + +@@ -534,9 +532,6 @@ static void machine_generic_valid_class_init(ObjectClass *oc, void *data) + + mc->min_cpus = MIN_CPUS; + mc->max_cpus = MAX_CPUS; +- +- mc->smp_props.dies_supported = false; +- mc->smp_props.clusters_supported = false; + } + + static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) +@@ -546,9 +541,6 @@ static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) + /* Force invalid min CPUs and max CPUs */ + mc->min_cpus = 2; + mc->max_cpus = 511; +- +- mc->smp_props.dies_supported = false; +- mc->smp_props.clusters_supported = false; + } + + static void machine_with_dies_class_init(ObjectClass *oc, void *data) +@@ -559,7 +551,6 @@ static void machine_with_dies_class_init(ObjectClass *oc, void *data) + mc->max_cpus = MAX_CPUS; + + mc->smp_props.dies_supported = true; +- mc->smp_props.clusters_supported = false; + } + + static void machine_with_clusters_class_init(ObjectClass *oc, void *data) +@@ -570,7 +561,6 @@ static void machine_with_clusters_class_init(ObjectClass *oc, void *data) + mc->max_cpus = MAX_CPUS; + + mc->smp_props.clusters_supported = true; +- mc->smp_props.dies_supported = false; + } + + static void test_generic_valid(const void *opaque) +-- +2.27.0 + diff --git a/tests-unit-test-smp-parse-Pass-machine-type-as-argum.patch b/tests-unit-test-smp-parse-Pass-machine-type-as-argum.patch new file mode 100644 index 0000000000000000000000000000000000000000..d30509c63c2344dd3d7f27352b874426505be9c6 --- /dev/null +++ b/tests-unit-test-smp-parse-Pass-machine-type-as-argum.patch @@ -0,0 +1,69 @@ +From d8b2aee4fd6ccd8eb621522b647c392c1dd7955c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 15 Nov 2021 12:32:09 +0100 +Subject: [PATCH 02/24] tests/unit/test-smp-parse: Pass machine type as + argument to tests +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use g_test_add_data_func() instead of g_test_add_func() so we can +pass the machine type to the tests (we will soon have different +machine types). + +Reviewed-by: Richard Henderson +Reviewed-by: Yanan Wang +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211216132015.815493-2-philmd@redhat.com> +--- + tests/unit/test-smp-parse.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index b02450e25a..37c6b4981d 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -487,9 +487,10 @@ static void machine_base_class_init(ObjectClass *oc, void *data) + mc->name = g_strdup(SMP_MACHINE_NAME); + } + +-static void test_generic(void) ++static void test_generic(const void *opaque) + { +- Object *obj = object_new(TYPE_MACHINE); ++ const char *machine_type = opaque; ++ Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); + SMPTestData *data = &(SMPTestData){{ }}; +@@ -525,9 +526,10 @@ static void test_generic(void) + object_unref(obj); + } + +-static void test_with_dies(void) ++static void test_with_dies(const void *opaque) + { +- Object *obj = object_new(TYPE_MACHINE); ++ const char *machine_type = opaque; ++ Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); + SMPTestData *data = &(SMPTestData){{ }}; +@@ -599,8 +601,12 @@ int main(int argc, char *argv[]) + + g_test_init(&argc, &argv, NULL); + +- g_test_add_func("/test-smp-parse/generic", test_generic); +- g_test_add_func("/test-smp-parse/with_dies", test_with_dies); ++ g_test_add_data_func("/test-smp-parse/generic", ++ TYPE_MACHINE, ++ test_generic); ++ g_test_add_data_func("/test-smp-parse/with_dies", ++ TYPE_MACHINE, ++ test_with_dies); + + g_test_run(); + +-- +2.27.0 + diff --git a/tests-unit-test-smp-parse-Simplify-pointer-to-compou.patch b/tests-unit-test-smp-parse-Simplify-pointer-to-compou.patch new file mode 100644 index 0000000000000000000000000000000000000000..68cc318f4b2054ce0adf70d4d66b2a4d09ce16e0 --- /dev/null +++ b/tests-unit-test-smp-parse-Simplify-pointer-to-compou.patch @@ -0,0 +1,143 @@ +From 964965721bbed1941bf77e5a748efc1274b7c289 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 11 Nov 2021 08:58:40 +0100 +Subject: [PATCH 07/24] tests/unit/test-smp-parse: Simplify pointer to compound + literal use +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We can simply use a local variable (and pass its pointer) instead +of a pointer to a compound literal. + +Reviewed-by: Andrew Jones +Reviewed-by: Richard Henderson +Reviewed-by: Yanan Wang +Tested-by: Yanan Wang +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211216132015.815493-7-philmd@redhat.com> +--- + tests/unit/test-smp-parse.c | 66 ++++++++++++++++++------------------- + 1 file changed, 33 insertions(+), 33 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index b20bf2c235..395929b66c 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -520,19 +520,19 @@ static void test_generic_valid(const void *opaque) + Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); +- SMPTestData *data = &(SMPTestData){{ }}; ++ SMPTestData data = {}; + int i; + + for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { +- *data = data_generic_valid[i]; +- unsupported_params_init(mc, data); ++ data = data_generic_valid[i]; ++ unsupported_params_init(mc, &data); + +- smp_parse_test(ms, data, true); ++ smp_parse_test(ms, &data, true); + + /* Unsupported parameters can be provided with their values as 1 */ +- data->config.has_dies = true; +- data->config.dies = 1; +- smp_parse_test(ms, data, true); ++ data.config.has_dies = true; ++ data.config.dies = 1; ++ smp_parse_test(ms, &data, true); + } + + object_unref(obj); +@@ -544,14 +544,14 @@ static void test_generic_invalid(const void *opaque) + Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); +- SMPTestData *data = &(SMPTestData){}; ++ SMPTestData data = {}; + int i; + + for (i = 0; i < ARRAY_SIZE(data_generic_invalid); i++) { +- *data = data_generic_invalid[i]; +- unsupported_params_init(mc, data); ++ data = data_generic_invalid[i]; ++ unsupported_params_init(mc, &data); + +- smp_parse_test(ms, data, false); ++ smp_parse_test(ms, &data, false); + } + + object_unref(obj); +@@ -563,45 +563,45 @@ static void test_with_dies(const void *opaque) + Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); +- SMPTestData *data = &(SMPTestData){{ }}; ++ SMPTestData data = {}; + unsigned int num_dies = 2; + int i; + + for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { +- *data = data_generic_valid[i]; +- unsupported_params_init(mc, data); ++ data = data_generic_valid[i]; ++ unsupported_params_init(mc, &data); + + /* when dies parameter is omitted, it will be set as 1 */ +- data->expect_prefer_sockets.dies = 1; +- data->expect_prefer_cores.dies = 1; ++ data.expect_prefer_sockets.dies = 1; ++ data.expect_prefer_cores.dies = 1; + +- smp_parse_test(ms, data, true); ++ smp_parse_test(ms, &data, true); + + /* when dies parameter is specified */ +- data->config.has_dies = true; +- data->config.dies = num_dies; +- if (data->config.has_cpus) { +- data->config.cpus *= num_dies; ++ data.config.has_dies = true; ++ data.config.dies = num_dies; ++ if (data.config.has_cpus) { ++ data.config.cpus *= num_dies; + } +- if (data->config.has_maxcpus) { +- data->config.maxcpus *= num_dies; ++ if (data.config.has_maxcpus) { ++ data.config.maxcpus *= num_dies; + } + +- data->expect_prefer_sockets.dies = num_dies; +- data->expect_prefer_sockets.cpus *= num_dies; +- data->expect_prefer_sockets.max_cpus *= num_dies; +- data->expect_prefer_cores.dies = num_dies; +- data->expect_prefer_cores.cpus *= num_dies; +- data->expect_prefer_cores.max_cpus *= num_dies; ++ data.expect_prefer_sockets.dies = num_dies; ++ data.expect_prefer_sockets.cpus *= num_dies; ++ data.expect_prefer_sockets.max_cpus *= num_dies; ++ data.expect_prefer_cores.dies = num_dies; ++ data.expect_prefer_cores.cpus *= num_dies; ++ data.expect_prefer_cores.max_cpus *= num_dies; + +- smp_parse_test(ms, data, true); ++ smp_parse_test(ms, &data, true); + } + + for (i = 0; i < ARRAY_SIZE(data_with_dies_invalid); i++) { +- *data = data_with_dies_invalid[i]; +- unsupported_params_init(mc, data); ++ data = data_with_dies_invalid[i]; ++ unsupported_params_init(mc, &data); + +- smp_parse_test(ms, data, false); ++ smp_parse_test(ms, &data, false); + } + + object_unref(obj); +-- +2.27.0 + diff --git a/tests-unit-test-smp-parse-Split-the-generic-test-in-.patch b/tests-unit-test-smp-parse-Split-the-generic-test-in-.patch new file mode 100644 index 0000000000000000000000000000000000000000..dc13f6dfd02c8d576d0674a8ce577b5ed17c6588 --- /dev/null +++ b/tests-unit-test-smp-parse-Split-the-generic-test-in-.patch @@ -0,0 +1,71 @@ +From fad259cf9996dbc4001cb94ec3c846d649401027 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Mon, 15 Nov 2021 12:35:43 +0100 +Subject: [PATCH 03/24] tests/unit/test-smp-parse: Split the 'generic' test in + valid / invalid +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Split the 'generic' test in two tests: 'valid' and 'invalid'. +This will allow us to remove the hack which modifies the +MachineClass internal state. + +Reviewed-by: Richard Henderson +Reviewed-by: Yanan Wang +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211216132015.815493-3-philmd@redhat.com> +--- + tests/unit/test-smp-parse.c | 21 ++++++++++++++++++--- + 1 file changed, 18 insertions(+), 3 deletions(-) + +diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c +index 37c6b4981d..425ed6b6b9 100644 +--- a/tests/unit/test-smp-parse.c ++++ b/tests/unit/test-smp-parse.c +@@ -487,7 +487,7 @@ static void machine_base_class_init(ObjectClass *oc, void *data) + mc->name = g_strdup(SMP_MACHINE_NAME); + } + +-static void test_generic(const void *opaque) ++static void test_generic_valid(const void *opaque) + { + const char *machine_type = opaque; + Object *obj = object_new(machine_type); +@@ -508,6 +508,18 @@ static void test_generic(const void *opaque) + smp_parse_test(ms, data, true); + } + ++ object_unref(obj); ++} ++ ++static void test_generic_invalid(const void *opaque) ++{ ++ const char *machine_type = opaque; ++ Object *obj = object_new(machine_type); ++ MachineState *ms = MACHINE(obj); ++ MachineClass *mc = MACHINE_GET_CLASS(obj); ++ SMPTestData *data = &(SMPTestData){}; ++ int i; ++ + /* Force invalid min CPUs and max CPUs */ + mc->min_cpus = 2; + mc->max_cpus = 511; +@@ -601,9 +613,12 @@ int main(int argc, char *argv[]) + + g_test_init(&argc, &argv, NULL); + +- g_test_add_data_func("/test-smp-parse/generic", ++ g_test_add_data_func("/test-smp-parse/generic/valid", ++ TYPE_MACHINE, ++ test_generic_valid); ++ g_test_add_data_func("/test-smp-parse/generic/invalid", + TYPE_MACHINE, +- test_generic); ++ test_generic_invalid); + g_test_add_data_func("/test-smp-parse/with_dies", + TYPE_MACHINE, + test_with_dies); +-- +2.27.0 + diff --git a/tftp-check-tftp_input-buffer-size.patch b/tftp-check-tftp_input-buffer-size.patch deleted file mode 100644 index 1c642f67211af98d470831738cc1cda621461420..0000000000000000000000000000000000000000 --- a/tftp-check-tftp_input-buffer-size.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 968656cf302ba7f8a3dfaf1013f7d8e80663e63e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Fri, 4 Jun 2021 16:34:30 +0400 -Subject: [PATCH 5/6] tftp: check tftp_input buffer size -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fixes: CVE-2021-3595 -Fixes: https://gitlab.freedesktop.org/slirp/libslirp/-/issues/46 - -Signed-off-by: Marc-André Lureau -Signed-off-by: imxcc ---- - slirp/src/tftp.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/slirp/src/tftp.c b/slirp/src/tftp.c -index 2b4176cc..035a0cab 100644 ---- a/slirp/src/tftp.c -+++ b/slirp/src/tftp.c -@@ -449,7 +449,11 @@ static void tftp_handle_error(Slirp *slirp, struct sockaddr_storage *srcsas, - - void tftp_input(struct sockaddr_storage *srcsas, struct mbuf *m) - { -- struct tftp_t *tp = (struct tftp_t *)m->m_data; -+ struct tftp_t *tp = mtod_check(m, offsetof(struct tftp_t, x.tp_buf)); -+ -+ if (tp == NULL) { -+ return; -+ } - - switch (ntohs(tp->tp_op)) { - case TFTP_RRQ: --- -2.27.0 - diff --git a/tftp-introduce-a-header-structure.patch b/tftp-introduce-a-header-structure.patch deleted file mode 100644 index 8f9c7905bdd9578fcee1edb6050e316cf578db4c..0000000000000000000000000000000000000000 --- a/tftp-introduce-a-header-structure.patch +++ /dev/null @@ -1,252 +0,0 @@ -From 4330205483be65148e365d968d21efc3f56c4228 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Fri, 4 Jun 2021 20:01:20 +0400 -Subject: [PATCH 6/6] tftp: introduce a header structure -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Instead of using a composed structure and potentially reading past the -incoming buffer, use a different structure for the header. - -Signed-off-by: Marc-André Lureau -Signed-off-by: imxcc ---- - slirp/src/tftp.c | 61 ++++++++++++++++++++++++------------------------ - slirp/src/tftp.h | 6 ++++- - 2 files changed, 36 insertions(+), 31 deletions(-) - -diff --git a/slirp/src/tftp.c b/slirp/src/tftp.c -index 035a0cab..ed89e0b5 100644 ---- a/slirp/src/tftp.c -+++ b/slirp/src/tftp.c -@@ -50,7 +50,7 @@ static void tftp_session_terminate(struct tftp_session *spt) - } - - static int tftp_session_allocate(Slirp *slirp, struct sockaddr_storage *srcsas, -- struct tftp_t *tp) -+ struct tftphdr *hdr) - { - struct tftp_session *spt; - int k; -@@ -75,7 +75,7 @@ found: - memcpy(&spt->client_addr, srcsas, sockaddr_size(srcsas)); - spt->fd = -1; - spt->block_size = 512; -- spt->client_port = tp->udp.uh_sport; -+ spt->client_port = hdr->udp.uh_sport; - spt->slirp = slirp; - - tftp_session_update(spt); -@@ -84,7 +84,7 @@ found: - } - - static int tftp_session_find(Slirp *slirp, struct sockaddr_storage *srcsas, -- struct tftp_t *tp) -+ struct tftphdr *hdr) - { - struct tftp_session *spt; - int k; -@@ -94,7 +94,7 @@ static int tftp_session_find(Slirp *slirp, struct sockaddr_storage *srcsas, - - if (tftp_session_in_use(spt)) { - if (sockaddr_equal(&spt->client_addr, srcsas)) { -- if (spt->client_port == tp->udp.uh_sport) { -+ if (spt->client_port == hdr->udp.uh_sport) { - return k; - } - } -@@ -146,13 +146,13 @@ static struct tftp_t *tftp_prep_mbuf_data(struct tftp_session *spt, - } - - static void tftp_udp_output(struct tftp_session *spt, struct mbuf *m, -- struct tftp_t *recv_tp) -+ struct tftphdr *hdr) - { - if (spt->client_addr.ss_family == AF_INET6) { - struct sockaddr_in6 sa6, da6; - - sa6.sin6_addr = spt->slirp->vhost_addr6; -- sa6.sin6_port = recv_tp->udp.uh_dport; -+ sa6.sin6_port = hdr->udp.uh_dport; - da6.sin6_addr = ((struct sockaddr_in6 *)&spt->client_addr)->sin6_addr; - da6.sin6_port = spt->client_port; - -@@ -161,7 +161,7 @@ static void tftp_udp_output(struct tftp_session *spt, struct mbuf *m, - struct sockaddr_in sa4, da4; - - sa4.sin_addr = spt->slirp->vhost_addr; -- sa4.sin_port = recv_tp->udp.uh_dport; -+ sa4.sin_port = hdr->udp.uh_dport; - da4.sin_addr = ((struct sockaddr_in *)&spt->client_addr)->sin_addr; - da4.sin_port = spt->client_port; - -@@ -183,7 +183,7 @@ static int tftp_send_oack(struct tftp_session *spt, const char *keys[], - - tp = tftp_prep_mbuf_data(spt, m); - -- tp->tp_op = htons(TFTP_OACK); -+ tp->hdr.tp_op = htons(TFTP_OACK); - for (i = 0; i < nb; i++) { - n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%s", - keys[i]) + -@@ -193,9 +193,8 @@ static int tftp_send_oack(struct tftp_session *spt, const char *keys[], - 1; - } - -- m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX + 2) + n - -- sizeof(struct udphdr); -- tftp_udp_output(spt, m, recv_tp); -+ m->m_len = G_SIZEOF_MEMBER(struct tftp_t, hdr.tp_op) + n; -+ tftp_udp_output(spt, m, &recv_tp->hdr); - - return 0; - } -@@ -216,21 +215,21 @@ static void tftp_send_error(struct tftp_session *spt, uint16_t errorcode, - - tp = tftp_prep_mbuf_data(spt, m); - -- tp->tp_op = htons(TFTP_ERROR); -+ tp->hdr.tp_op = htons(TFTP_ERROR); - tp->x.tp_error.tp_error_code = htons(errorcode); - slirp_pstrcpy((char *)tp->x.tp_error.tp_msg, sizeof(tp->x.tp_error.tp_msg), - msg); - - m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX + 2) + 3 + - strlen(msg) - sizeof(struct udphdr); -- tftp_udp_output(spt, m, recv_tp); -+ tftp_udp_output(spt, m, &recv_tp->hdr); - - out: - tftp_session_terminate(spt); - } - - static void tftp_send_next_block(struct tftp_session *spt, -- struct tftp_t *recv_tp) -+ struct tftphdr *hdr) - { - struct mbuf *m; - struct tftp_t *tp; -@@ -244,7 +243,7 @@ static void tftp_send_next_block(struct tftp_session *spt, - - tp = tftp_prep_mbuf_data(spt, m); - -- tp->tp_op = htons(TFTP_DATA); -+ tp->hdr.tp_op = htons(TFTP_DATA); - tp->x.tp_data.tp_block_nr = htons((spt->block_nr + 1) & 0xffff); - - nobytes = tftp_read_data(spt, spt->block_nr, tp->x.tp_data.tp_buf, -@@ -262,7 +261,7 @@ static void tftp_send_next_block(struct tftp_session *spt, - - m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX - nobytes) - - sizeof(struct udphdr); -- tftp_udp_output(spt, m, recv_tp); -+ tftp_udp_output(spt, m, hdr); - - if (nobytes == spt->block_size) { - tftp_session_update(spt); -@@ -285,12 +284,12 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas, - int nb_options = 0; - - /* check if a session already exists and if so terminate it */ -- s = tftp_session_find(slirp, srcsas, tp); -+ s = tftp_session_find(slirp, srcsas, &tp->hdr); - if (s >= 0) { - tftp_session_terminate(&slirp->tftp_sessions[s]); - } - -- s = tftp_session_allocate(slirp, srcsas, tp); -+ s = tftp_session_allocate(slirp, srcsas, &tp->hdr); - - if (s < 0) { - return; -@@ -416,29 +415,29 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas, - } - - spt->block_nr = 0; -- tftp_send_next_block(spt, tp); -+ tftp_send_next_block(spt, &tp->hdr); - } - - static void tftp_handle_ack(Slirp *slirp, struct sockaddr_storage *srcsas, -- struct tftp_t *tp, int pktlen) -+ struct tftphdr *hdr) - { - int s; - -- s = tftp_session_find(slirp, srcsas, tp); -+ s = tftp_session_find(slirp, srcsas, hdr); - - if (s < 0) { - return; - } - -- tftp_send_next_block(&slirp->tftp_sessions[s], tp); -+ tftp_send_next_block(&slirp->tftp_sessions[s], hdr); - } - - static void tftp_handle_error(Slirp *slirp, struct sockaddr_storage *srcsas, -- struct tftp_t *tp, int pktlen) -+ struct tftphdr *hdr) - { - int s; - -- s = tftp_session_find(slirp, srcsas, tp); -+ s = tftp_session_find(slirp, srcsas, hdr); - - if (s < 0) { - return; -@@ -449,23 +448,25 @@ static void tftp_handle_error(Slirp *slirp, struct sockaddr_storage *srcsas, - - void tftp_input(struct sockaddr_storage *srcsas, struct mbuf *m) - { -- struct tftp_t *tp = mtod_check(m, offsetof(struct tftp_t, x.tp_buf)); -+ struct tftphdr *hdr = mtod_check(m, sizeof(struct tftphdr)); - -- if (tp == NULL) { -+ if (hdr == NULL) { - return; - } - -- switch (ntohs(tp->tp_op)) { -+ switch (ntohs(hdr->tp_op)) { - case TFTP_RRQ: -- tftp_handle_rrq(m->slirp, srcsas, tp, m->m_len); -+ tftp_handle_rrq(m->slirp, srcsas, -+ mtod(m, struct tftp_t *), -+ m->m_len); - break; - - case TFTP_ACK: -- tftp_handle_ack(m->slirp, srcsas, tp, m->m_len); -+ tftp_handle_ack(m->slirp, srcsas, hdr); - break; - - case TFTP_ERROR: -- tftp_handle_error(m->slirp, srcsas, tp, m->m_len); -+ tftp_handle_error(m->slirp, srcsas, hdr); - break; - } - } -diff --git a/slirp/src/tftp.h b/slirp/src/tftp.h -index c47bb43c..021f6cf1 100644 ---- a/slirp/src/tftp.h -+++ b/slirp/src/tftp.h -@@ -18,9 +18,13 @@ - #define TFTP_FILENAME_MAX 512 - #define TFTP_BLOCKSIZE_MAX 1428 - --struct tftp_t { -+struct tftphdr { - struct udphdr udp; - uint16_t tp_op; -+} SLIRP_PACKED; -+ -+struct tftp_t { -+ struct tftphdr hdr; - union { - struct { - uint16_t tp_block_nr; --- -2.27.0 - diff --git a/tools-virtiofsd-Add-rseq-syscall-to-the-seccomp-allo.patch b/tools-virtiofsd-Add-rseq-syscall-to-the-seccomp-allo.patch new file mode 100644 index 0000000000000000000000000000000000000000..b59ef0fb1cc4fb68c6f5fd1d148e4d4cf3cd7d76 --- /dev/null +++ b/tools-virtiofsd-Add-rseq-syscall-to-the-seccomp-allo.patch @@ -0,0 +1,58 @@ +From 5ca1beec7030b5d9fea36eb4f037d4e0e6c260bd Mon Sep 17 00:00:00 2001 +From: Christian Ehrhardt +Date: Wed, 9 Feb 2022 12:14:56 +0100 +Subject: [PATCH] tools/virtiofsd: Add rseq syscall to the seccomp allowlist + +The virtiofsd currently crashes when used with glibc 2.35. +That is due to the rseq system call being added to every thread +creation [1][2]. + +[1]: https://www.efficios.com/blog/2019/02/08/linux-restartable-sequences/ +[2]: https://sourceware.org/pipermail/libc-alpha/2022-February/136040.html + +This happens not at daemon start, but when a guest connects + + /usr/lib/qemu/virtiofsd -f --socket-path=/tmp/testvfsd -o sandbox=chroot \ + -o source=/var/guests/j-virtiofs --socket-group=kvm + virtio_session_mount: Waiting for vhost-user socket connection... + # start ok, now guest will connect + virtio_session_mount: Received vhost-user socket connection + virtio_loop: Entry + fv_queue_set_started: qidx=0 started=1 + fv_queue_set_started: qidx=1 started=1 + Bad system call (core dumped) + +We have to put rseq on the seccomp allowlist to avoid that the daemon +is crashing in this case. + +Reported-by: Michael Hudson-Doyle +Signed-off-by: Christian Ehrhardt +Reviewed-by: Dr. David Alan Gilbert +Message-id: 20220209111456.3328420-1-christian.ehrhardt@canonical.com + +[Moved rseq to its alphabetically ordered position in the seccomp +allowlist. +--Stefan] +Signed-off-by: Stefan Hajnoczi +Signed-off-by: qinyu +--- + tools/virtiofsd/passthrough_seccomp.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tools/virtiofsd/passthrough_seccomp.c b/tools/virtiofsd/passthrough_seccomp.c +index a3ce9f898d..2bc0127b69 100644 +--- a/tools/virtiofsd/passthrough_seccomp.c ++++ b/tools/virtiofsd/passthrough_seccomp.c +@@ -91,6 +91,9 @@ static const int syscall_allowlist[] = { + SCMP_SYS(renameat2), + SCMP_SYS(removexattr), + SCMP_SYS(restart_syscall), ++#ifdef __NR_rseq ++ SCMP_SYS(rseq), /* required since glibc 2.35 */ ++#endif + SCMP_SYS(rt_sigaction), + SCMP_SYS(rt_sigprocmask), + SCMP_SYS(rt_sigreturn), +-- +2.27.0 + diff --git a/tpm-Add-the-SysBus-TPM-TIS-device.patch b/tpm-Add-the-SysBus-TPM-TIS-device.patch deleted file mode 100644 index e0a6254025932eb942b3a15d16b66d4808a33f42..0000000000000000000000000000000000000000 --- a/tpm-Add-the-SysBus-TPM-TIS-device.patch +++ /dev/null @@ -1,231 +0,0 @@ -From 4fe655326eeae322b621dcc25c53af722d2e1afa Mon Sep 17 00:00:00 2001 -From: jiangfangjie -Date: Tue, 11 Aug 2020 11:23:34 +0800 -Subject: [PATCH 14/19] tpm: Add the SysBus TPM TIS device - -Introduce the tpm-tis-device which is a sysbus device -and is bound to be used on ARM. - -Signed-off-by: Eric Auger -Reviewed-by: Stefan Berger -Tested-by: Ard Biesheuvel -Acked-by: Ard Biesheuvel -Message-id: 20200305165149.618-6-eric.auger@redhat.com -Signed-off-by: Stefan Berger -Signed-off-by: jiangfangjie ---- - hw/tpm/Kconfig | 5 ++ - hw/tpm/Makefile.objs | 1 + - hw/tpm/tpm_tis_sysbus.c | 159 ++++++++++++++++++++++++++++++++++++++++ - include/sysemu/tpm.h | 1 + - 4 files changed, 166 insertions(+) - create mode 100644 hw/tpm/tpm_tis_sysbus.c - -diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig -index 686f8206..4794e7fe 100644 ---- a/hw/tpm/Kconfig -+++ b/hw/tpm/Kconfig -@@ -7,6 +7,11 @@ config TPM_TIS_ISA - depends on TPM && ISA_BUS - select TPM_TIS - -+config TPM_TIS_SYSBUS -+ bool -+ depends on TPM -+ select TPM_TIS -+ - config TPM_TIS - bool - depends on TPM -diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs -index 3ef2036c..f1ec4beb 100644 ---- a/hw/tpm/Makefile.objs -+++ b/hw/tpm/Makefile.objs -@@ -1,6 +1,7 @@ - common-obj-$(CONFIG_TPM) += tpm_util.o - obj-$(call lor,$(CONFIG_TPM_TIS),$(CONFIG_TPM_CRB)) += tpm_ppi.o - common-obj-$(CONFIG_TPM_TIS_ISA) += tpm_tis_isa.o -+common-obj-$(CONFIG_TPM_TIS_SYSBUS) += tpm_tis_sysbus.o - common-obj-$(CONFIG_TPM_TIS) += tpm_tis_common.o - common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o - common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o -diff --git a/hw/tpm/tpm_tis_sysbus.c b/hw/tpm/tpm_tis_sysbus.c -new file mode 100644 -index 00000000..18c02aed ---- /dev/null -+++ b/hw/tpm/tpm_tis_sysbus.c -@@ -0,0 +1,159 @@ -+/* -+ * tpm_tis_sysbus.c - QEMU's TPM TIS SYSBUS Device -+ * -+ * Copyright (C) 2006,2010-2013 IBM Corporation -+ * -+ * Authors: -+ * Stefan Berger -+ * David Safford -+ * -+ * Xen 4 support: Andrease Niederl -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ * -+ * Implementation of the TIS interface according to specs found at -+ * http://www.trustedcomputinggroup.org. This implementation currently -+ * supports version 1.3, 21 March 2013 -+ * In the developers menu choose the PC Client section then find the TIS -+ * specification. -+ * -+ * TPM TIS for TPM 2 implementation following TCG PC Client Platform -+ * TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43 -+ */ -+ -+#include "qemu/osdep.h" -+#include "hw/qdev-properties.h" -+#include "migration/vmstate.h" -+#include "tpm_util.h" -+#include "hw/sysbus.h" -+#include "tpm_tis.h" -+ -+typedef struct TPMStateSysBus { -+ /*< private >*/ -+ SysBusDevice parent_obj; -+ -+ /*< public >*/ -+ TPMState state; /* not a QOM object */ -+} TPMStateSysBus; -+ -+#define TPM_TIS_SYSBUS(obj) OBJECT_CHECK(TPMStateSysBus, (obj), TYPE_TPM_TIS_SYSBUS) -+ -+static int tpm_tis_pre_save_sysbus(void *opaque) -+{ -+ TPMStateSysBus *sbdev = opaque; -+ -+ return tpm_tis_pre_save(&sbdev->state); -+} -+ -+static const VMStateDescription vmstate_tpm_tis_sysbus = { -+ .name = "tpm-tis", -+ .version_id = 0, -+ .pre_save = tpm_tis_pre_save_sysbus, -+ .fields = (VMStateField[]) { -+ VMSTATE_BUFFER(state.buffer, TPMStateSysBus), -+ VMSTATE_UINT16(state.rw_offset, TPMStateSysBus), -+ VMSTATE_UINT8(state.active_locty, TPMStateSysBus), -+ VMSTATE_UINT8(state.aborting_locty, TPMStateSysBus), -+ VMSTATE_UINT8(state.next_locty, TPMStateSysBus), -+ -+ VMSTATE_STRUCT_ARRAY(state.loc, TPMStateSysBus, TPM_TIS_NUM_LOCALITIES, -+ 0, vmstate_locty, TPMLocality), -+ -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+static void tpm_tis_sysbus_request_completed(TPMIf *ti, int ret) -+{ -+ TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(ti); -+ TPMState *s = &sbdev->state; -+ -+ tpm_tis_request_completed(s, ret); -+} -+ -+static enum TPMVersion tpm_tis_sysbus_get_tpm_version(TPMIf *ti) -+{ -+ TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(ti); -+ TPMState *s = &sbdev->state; -+ -+ return tpm_tis_get_tpm_version(s); -+} -+ -+static void tpm_tis_sysbus_reset(DeviceState *dev) -+{ -+ TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(dev); -+ TPMState *s = &sbdev->state; -+ -+ return tpm_tis_reset(s); -+} -+ -+static Property tpm_tis_sysbus_properties[] = { -+ DEFINE_PROP_UINT32("irq", TPMStateSysBus, state.irq_num, TPM_TIS_IRQ), -+ DEFINE_PROP_TPMBE("tpmdev", TPMStateSysBus, state.be_driver), -+ DEFINE_PROP_BOOL("ppi", TPMStateSysBus, state.ppi_enabled, true), -+ DEFINE_PROP_END_OF_LIST(), -+}; -+ -+static void tpm_tis_sysbus_initfn(Object *obj) -+{ -+ TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(obj); -+ TPMState *s = &sbdev->state; -+ -+ memory_region_init_io(&s->mmio, obj, &tpm_tis_memory_ops, -+ s, "tpm-tis-mmio", -+ TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT); -+ -+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); -+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); -+} -+ -+static void tpm_tis_sysbus_realizefn(DeviceState *dev, Error **errp) -+{ -+ TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(dev); -+ TPMState *s = &sbdev->state; -+ -+ if (!tpm_find()) { -+ error_setg(errp, "at most one TPM device is permitted"); -+ return; -+ } -+ -+ if (!s->be_driver) { -+ error_setg(errp, "'tpmdev' property is required"); -+ return; -+ } -+} -+ -+static void tpm_tis_sysbus_class_init(ObjectClass *klass, void *data) -+{ -+ DeviceClass *dc = DEVICE_CLASS(klass); -+ TPMIfClass *tc = TPM_IF_CLASS(klass); -+ -+ dc->props = tpm_tis_sysbus_properties; -+ dc->vmsd = &vmstate_tpm_tis_sysbus; -+ tc->model = TPM_MODEL_TPM_TIS; -+ dc->realize = tpm_tis_sysbus_realizefn; -+ dc->user_creatable = true; -+ dc->reset = tpm_tis_sysbus_reset; -+ tc->request_completed = tpm_tis_sysbus_request_completed; -+ tc->get_version = tpm_tis_sysbus_get_tpm_version; -+} -+ -+static const TypeInfo tpm_tis_sysbus_info = { -+ .name = TYPE_TPM_TIS_SYSBUS, -+ .parent = TYPE_SYS_BUS_DEVICE, -+ .instance_size = sizeof(TPMStateSysBus), -+ .instance_init = tpm_tis_sysbus_initfn, -+ .class_init = tpm_tis_sysbus_class_init, -+ .interfaces = (InterfaceInfo[]) { -+ { TYPE_TPM_IF }, -+ { } -+ } -+}; -+ -+static void tpm_tis_sysbus_register(void) -+{ -+ type_register_static(&tpm_tis_sysbus_info); -+} -+ -+type_init(tpm_tis_sysbus_register) -diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h -index 1691b92c..f37851b1 100644 ---- a/include/sysemu/tpm.h -+++ b/include/sysemu/tpm.h -@@ -44,6 +44,7 @@ typedef struct TPMIfClass { - } TPMIfClass; - - #define TYPE_TPM_TIS_ISA "tpm-tis" -+#define TYPE_TPM_TIS_SYSBUS "tpm-tis-device" - #define TYPE_TPM_CRB "tpm-crb" - #define TYPE_TPM_SPAPR "tpm-spapr" - --- -2.23.0 - diff --git a/tpm-Move-tpm_tis_show_buffer-to-tpm_util.c.patch b/tpm-Move-tpm_tis_show_buffer-to-tpm_util.c.patch deleted file mode 100644 index 93139b5e7f8284cecf6faa9930eaa8e802db13d9..0000000000000000000000000000000000000000 --- a/tpm-Move-tpm_tis_show_buffer-to-tpm_util.c.patch +++ /dev/null @@ -1,146 +0,0 @@ -From c6cf45f38cb6e28cf4db42296fedcd5f26ca610b Mon Sep 17 00:00:00 2001 -From: Stefan Berger -Date: Tue, 21 Jan 2020 10:29:30 -0500 -Subject: [PATCH 03/19] tpm: Move tpm_tis_show_buffer to tpm_util.c -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Stefan Berger -Reviewed-by: Philippe Mathieu-Daudé -Reviewed-by: David Gibson -Message-Id: <20200121152935.649898-2-stefanb@linux.ibm.com> -Signed-off-by: David Gibson -Signed-off-by: jiangfangjie ---- - hw/tpm/tpm_tis.c | 32 ++++---------------------------- - hw/tpm/tpm_util.c | 25 +++++++++++++++++++++++++ - hw/tpm/tpm_util.h | 3 +++ - hw/tpm/trace-events | 2 +- - 4 files changed, 33 insertions(+), 29 deletions(-) - -diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c -index d6b32128..96a9ac48 100644 ---- a/hw/tpm/tpm_tis.c -+++ b/hw/tpm/tpm_tis.c -@@ -104,30 +104,6 @@ static uint8_t tpm_tis_locality_from_addr(hwaddr addr) - return (uint8_t)((addr >> TPM_TIS_LOCALITY_SHIFT) & 0x7); - } - --static void tpm_tis_show_buffer(const unsigned char *buffer, -- size_t buffer_size, const char *string) --{ -- size_t len, i; -- char *line_buffer, *p; -- -- len = MIN(tpm_cmd_get_size(buffer), buffer_size); -- -- /* -- * allocate enough room for 3 chars per buffer entry plus a -- * newline after every 16 chars and a final null terminator. -- */ -- line_buffer = g_malloc(len * 3 + (len / 16) + 1); -- -- for (i = 0, p = line_buffer; i < len; i++) { -- if (i && !(i % 16)) { -- p += sprintf(p, "\n"); -- } -- p += sprintf(p, "%.2X ", buffer[i]); -- } -- trace_tpm_tis_show_buffer(string, len, line_buffer); -- -- g_free(line_buffer); --} - - /* - * Set the given flags in the STS register by clearing the register but -@@ -153,8 +129,8 @@ static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags) - */ - static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) - { -- if (trace_event_get_state_backends(TRACE_TPM_TIS_SHOW_BUFFER)) { -- tpm_tis_show_buffer(s->buffer, s->be_buffer_size, "To TPM"); -+ if (trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER)) { -+ tpm_util_show_buffer(s->buffer, s->be_buffer_size, "To TPM"); - } - - /* -@@ -322,8 +298,8 @@ static void tpm_tis_request_completed(TPMIf *ti, int ret) - s->loc[locty].state = TPM_TIS_STATE_COMPLETION; - s->rw_offset = 0; - -- if (trace_event_get_state_backends(TRACE_TPM_TIS_SHOW_BUFFER)) { -- tpm_tis_show_buffer(s->buffer, s->be_buffer_size, "From TPM"); -+ if (trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER)) { -+ tpm_util_show_buffer(s->buffer, s->be_buffer_size, "From TPM"); - } - - if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) { -diff --git a/hw/tpm/tpm_util.c b/hw/tpm/tpm_util.c -index ee41757e..8643eb50 100644 ---- a/hw/tpm/tpm_util.c -+++ b/hw/tpm/tpm_util.c -@@ -350,3 +350,28 @@ void tpm_sized_buffer_reset(TPMSizedBuffer *tsb) - tsb->buffer = NULL; - tsb->size = 0; - } -+ -+void tpm_util_show_buffer(const unsigned char *buffer, -+ size_t buffer_size, const char *string) -+{ -+ size_t len, i; -+ char *line_buffer, *p; -+ -+ len = MIN(tpm_cmd_get_size(buffer), buffer_size); -+ -+ /* -+ * allocate enough room for 3 chars per buffer entry plus a -+ * newline after every 16 chars and a final null terminator. -+ */ -+ line_buffer = g_malloc(len * 3 + (len / 16) + 1); -+ -+ for (i = 0, p = line_buffer; i < len; i++) { -+ if (i && !(i % 16)) { -+ p += sprintf(p, "\n"); -+ } -+ p += sprintf(p, "%.2X ", buffer[i]); -+ } -+ trace_tpm_util_show_buffer(string, len, line_buffer); -+ -+ g_free(line_buffer); -+} -diff --git a/hw/tpm/tpm_util.h b/hw/tpm/tpm_util.h -index f397ac21..7889081f 100644 ---- a/hw/tpm/tpm_util.h -+++ b/hw/tpm/tpm_util.h -@@ -79,4 +79,7 @@ typedef struct TPMSizedBuffer { - - void tpm_sized_buffer_reset(TPMSizedBuffer *tsb); - -+void tpm_util_show_buffer(const unsigned char *buffer, -+ size_t buffer_size, const char *string); -+ - #endif /* TPM_TPM_UTIL_H */ -diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events -index 0b94aa15..82c45ee5 100644 ---- a/hw/tpm/trace-events -+++ b/hw/tpm/trace-events -@@ -14,6 +14,7 @@ tpm_util_get_buffer_size_len(uint32_t len, size_t expected) "tpm_resp->len = %u, - tpm_util_get_buffer_size_hdr_len2(uint32_t len, size_t expected) "tpm2_resp->hdr.len = %u, expected = %zu" - tpm_util_get_buffer_size_len2(uint32_t len, size_t expected) "tpm2_resp->len = %u, expected = %zu" - tpm_util_get_buffer_size(size_t len) "buffersize of device: %zu" -+tpm_util_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\n%s" - - # tpm_emulator.c - tpm_emulator_set_locality(uint8_t locty) "setting locality to %d" -@@ -36,7 +37,6 @@ tpm_emulator_pre_save(void) "" - tpm_emulator_inst_init(void) "" - - # tpm_tis.c --tpm_tis_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\nbuf: %s" - tpm_tis_raise_irq(uint32_t irqmask) "Raising IRQ for flag 0x%08x" - tpm_tis_new_active_locality(uint8_t locty) "Active locality is now %d" - tpm_tis_abort(uint8_t locty) "New active locality is %d" --- -2.23.0 - diff --git a/tpm-Separate-TPM_TIS-and-TPM_TIS_ISA-configs.patch b/tpm-Separate-TPM_TIS-and-TPM_TIS_ISA-configs.patch deleted file mode 100644 index 97dcaa000b251bd8a4390a5c68e75011aef9401f..0000000000000000000000000000000000000000 --- a/tpm-Separate-TPM_TIS-and-TPM_TIS_ISA-configs.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 1eca7dbacabbc8ccc737f320839e7800fef5dfa1 Mon Sep 17 00:00:00 2001 -From: jiangfangjie -Date: Tue, 11 Aug 2020 12:42:31 +0800 -Subject: [PATCH 13/19] tpm: Separate TPM_TIS and TPM_TIS_ISA configs - MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 - Content-Transfer-Encoding: 8bit -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Let's separate the compilation of tpm_tis_common.c from -the compilation of tpm_tis_isa.c - -The common part will be also compiled along with the -tpm_tis_sysbus device. - -Signed-off-by: Eric Auger -Reviewed-by: Philippe Mathieu-Daudé -Tested-by: Ard Biesheuvel -Acked-by: Ard Biesheuvel -Message-id: 20200305165149.618-5-eric.auger@redhat.com -Signed-off-by: Stefan Berger -Signed-off-by: jiangfangjie ---- - default-configs/i386-softmmu.mak | 2 +- - hw/i386/Kconfig | 2 +- - hw/tpm/Kconfig | 7 ++++++- - hw/tpm/Makefile.objs | 3 ++- - tests/Makefile.include | 4 ++-- - 5 files changed, 12 insertions(+), 6 deletions(-) - -diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak -index cd5ea391..bdeef670 100644 ---- a/default-configs/i386-softmmu.mak -+++ b/default-configs/i386-softmmu.mak -@@ -17,7 +17,7 @@ - #CONFIG_SGA=n - #CONFIG_TEST_DEVICES=n - #CONFIG_TPM_CRB=n --#CONFIG_TPM_TIS=n -+#CONFIG_TPM_TIS_ISA=n - #CONFIG_VTD=n - - # Boards: -diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig -index 63504380..60334504 100644 ---- a/hw/i386/Kconfig -+++ b/hw/i386/Kconfig -@@ -17,7 +17,7 @@ config PC - imply SGA - imply TEST_DEVICES - imply TPM_CRB -- imply TPM_TIS -+ imply TPM_TIS_ISA - imply VGA_PCI - imply VIRTIO_VGA - select FDC -diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig -index 9e67d990..686f8206 100644 ---- a/hw/tpm/Kconfig -+++ b/hw/tpm/Kconfig -@@ -2,9 +2,14 @@ config TPMDEV - bool - depends on TPM - --config TPM_TIS -+config TPM_TIS_ISA - bool - depends on TPM && ISA_BUS -+ select TPM_TIS -+ -+config TPM_TIS -+ bool -+ depends on TPM - select TPMDEV - - config TPM_CRB -diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs -index fcc4c2f2..3ef2036c 100644 ---- a/hw/tpm/Makefile.objs -+++ b/hw/tpm/Makefile.objs -@@ -1,6 +1,7 @@ - common-obj-$(CONFIG_TPM) += tpm_util.o - obj-$(call lor,$(CONFIG_TPM_TIS),$(CONFIG_TPM_CRB)) += tpm_ppi.o --common-obj-$(CONFIG_TPM_TIS) += tpm_tis_isa.o tpm_tis_common.o -+common-obj-$(CONFIG_TPM_TIS_ISA) += tpm_tis_isa.o -+common-obj-$(CONFIG_TPM_TIS) += tpm_tis_common.o - common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o - common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o - common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o -diff --git a/tests/Makefile.include b/tests/Makefile.include -index f3273ad3..c151de64 100644 ---- a/tests/Makefile.include -+++ b/tests/Makefile.include -@@ -190,8 +190,8 @@ check-qtest-i386-y += tests/q35-test$(EXESUF) - check-qtest-i386-y += tests/vmgenid-test$(EXESUF) - check-qtest-i386-$(CONFIG_TPM_CRB) += tests/tpm-crb-swtpm-test$(EXESUF) - check-qtest-i386-$(CONFIG_TPM_CRB) += tests/tpm-crb-test$(EXESUF) --check-qtest-i386-$(CONFIG_TPM_TIS) += tests/tpm-tis-swtpm-test$(EXESUF) --check-qtest-i386-$(CONFIG_TPM_TIS) += tests/tpm-tis-test$(EXESUF) -+check-qtest-i386-$(CONFIG_TPM_TIS_ISA) += tests/tpm-tis-swtpm-test$(EXESUF) -+check-qtest-i386-$(CONFIG_TPM_TIS_ISA) += tests/tpm-tis-test$(EXESUF) - check-qtest-i386-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF) - check-qtest-i386-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF) - check-qtest-i386-$(CONFIG_RTL8139_PCI) += tests/test-filter-redirector$(EXESUF) --- -2.23.0 - diff --git a/tpm-Separate-tpm_tis-common-functions-from-isa-code.patch b/tpm-Separate-tpm_tis-common-functions-from-isa-code.patch deleted file mode 100644 index 32f180c98d784b1478268a768b4caed6c8a3fa23..0000000000000000000000000000000000000000 --- a/tpm-Separate-tpm_tis-common-functions-from-isa-code.patch +++ /dev/null @@ -1,1194 +0,0 @@ -From 425f6bc8392c71d2f29b572d19232785d0ab0b73 Mon Sep 17 00:00:00 2001 -From: jiangfangjie -Date: Tue, 11 Aug 2020 02:55:35 +0000 -Subject: [PATCH 12/19] tpm: Separate tpm_tis common functions from isa code - -Move the device agnostic code into tpm_tis_common.c and -put the ISA device specific code into tpm_tis_isa.c - -Signed-off-by: Eric Auger -Reviewed-by: Stefan Berger -Tested-by: Ard Biesheuvel -Acked-by: Ard Biesheuvel -Message-id: 20200305165149.618-4-eric.auger@redhat.com -Signed-off-by: Stefan Berger -Signed-off-by: jiangfangjie ---- - hw/tpm/Makefile.objs | 2 +- - hw/tpm/{tpm_tis.c => tpm_tis.c.orig} | 0 - hw/tpm/tpm_tis.h | 91 +++ - hw/tpm/tpm_tis_common.c | 869 +++++++++++++++++++++++++++ - hw/tpm/tpm_tis_isa.c | 170 ++++++ - 5 files changed, 1131 insertions(+), 1 deletion(-) - rename hw/tpm/{tpm_tis.c => tpm_tis.c.orig} (100%) - create mode 100644 hw/tpm/tpm_tis.h - create mode 100644 hw/tpm/tpm_tis_common.c - create mode 100644 hw/tpm/tpm_tis_isa.c - -diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs -index 85eb99ae..fcc4c2f2 100644 ---- a/hw/tpm/Makefile.objs -+++ b/hw/tpm/Makefile.objs -@@ -1,6 +1,6 @@ - common-obj-$(CONFIG_TPM) += tpm_util.o - obj-$(call lor,$(CONFIG_TPM_TIS),$(CONFIG_TPM_CRB)) += tpm_ppi.o --common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o -+common-obj-$(CONFIG_TPM_TIS) += tpm_tis_isa.o tpm_tis_common.o - common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o - common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o - common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o -diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c.orig -similarity index 100% -rename from hw/tpm/tpm_tis.c -rename to hw/tpm/tpm_tis.c.orig -diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h -new file mode 100644 -index 00000000..55549893 ---- /dev/null -+++ b/hw/tpm/tpm_tis.h -@@ -0,0 +1,91 @@ -+/* -+ * tpm_tis.h - QEMU's TPM TIS common header -+ * -+ * Copyright (C) 2006,2010-2013 IBM Corporation -+ * -+ * Authors: -+ * Stefan Berger -+ * David Safford -+ * -+ * Xen 4 support: Andrease Niederl -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ * -+ * Implementation of the TIS interface according to specs found at -+ * http://www.trustedcomputinggroup.org. This implementation currently -+ * supports version 1.3, 21 March 2013 -+ * In the developers menu choose the PC Client section then find the TIS -+ * specification. -+ * -+ * TPM TIS for TPM 2 implementation following TCG PC Client Platform -+ * TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43 -+ */ -+#ifndef TPM_TPM_TIS_H -+#define TPM_TPM_TIS_H -+ -+#include "qemu/osdep.h" -+#include "sysemu/tpm_backend.h" -+#include "tpm_ppi.h" -+ -+#define TPM_TIS_NUM_LOCALITIES 5 /* per spec */ -+#define TPM_TIS_LOCALITY_SHIFT 12 -+#define TPM_TIS_NO_LOCALITY 0xff -+ -+#define TPM_TIS_IS_VALID_LOCTY(x) ((x) < TPM_TIS_NUM_LOCALITIES) -+ -+#define TPM_TIS_BUFFER_MAX 4096 -+ -+typedef enum { -+ TPM_TIS_STATE_IDLE = 0, -+ TPM_TIS_STATE_READY, -+ TPM_TIS_STATE_COMPLETION, -+ TPM_TIS_STATE_EXECUTION, -+ TPM_TIS_STATE_RECEPTION, -+} TPMTISState; -+ -+/* locality data -- all fields are persisted */ -+typedef struct TPMLocality { -+ TPMTISState state; -+ uint8_t access; -+ uint32_t sts; -+ uint32_t iface_id; -+ uint32_t inte; -+ uint32_t ints; -+} TPMLocality; -+ -+typedef struct TPMState { -+ MemoryRegion mmio; -+ -+ unsigned char buffer[TPM_TIS_BUFFER_MAX]; -+ uint16_t rw_offset; -+ -+ uint8_t active_locty; -+ uint8_t aborting_locty; -+ uint8_t next_locty; -+ -+ TPMLocality loc[TPM_TIS_NUM_LOCALITIES]; -+ -+ qemu_irq irq; -+ uint32_t irq_num; -+ -+ TPMBackendCmd cmd; -+ -+ TPMBackend *be_driver; -+ TPMVersion be_tpm_version; -+ -+ size_t be_buffer_size; -+ -+ bool ppi_enabled; -+ TPMPPI ppi; -+} TPMState; -+ -+extern const VMStateDescription vmstate_locty; -+extern const MemoryRegionOps tpm_tis_memory_ops; -+ -+int tpm_tis_pre_save(TPMState *s); -+void tpm_tis_reset(TPMState *s); -+enum TPMVersion tpm_tis_get_tpm_version(TPMState *s); -+void tpm_tis_request_completed(TPMState *s, int ret); -+ -+#endif /* TPM_TPM_TIS_H */ -diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c -new file mode 100644 -index 00000000..9a51c71e ---- /dev/null -+++ b/hw/tpm/tpm_tis_common.c -@@ -0,0 +1,869 @@ -+/* -+ * tpm_tis_common.c - QEMU's TPM TIS interface emulator -+ * device agnostic functions -+ * -+ * Copyright (C) 2006,2010-2013 IBM Corporation -+ * -+ * Authors: -+ * Stefan Berger -+ * David Safford -+ * -+ * Xen 4 support: Andrease Niederl -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ * -+ * Implementation of the TIS interface according to specs found at -+ * http://www.trustedcomputinggroup.org. This implementation currently -+ * supports version 1.3, 21 March 2013 -+ * In the developers menu choose the PC Client section then find the TIS -+ * specification. -+ * -+ * TPM TIS for TPM 2 implementation following TCG PC Client Platform -+ * TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43 -+ */ -+#include "qemu/osdep.h" -+#include "hw/isa/isa.h" -+#include "qapi/error.h" -+#include "qemu/module.h" -+ -+#include "hw/acpi/tpm.h" -+#include "hw/pci/pci_ids.h" -+#include "sysemu/tpm_backend.h" -+#include "tpm_int.h" -+#include "tpm_util.h" -+#include "tpm_ppi.h" -+#include "trace.h" -+ -+#include "tpm_tis.h" -+ -+#define DEBUG_TIS 0 -+ -+/* local prototypes */ -+ -+static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, -+ unsigned size); -+ -+/* utility functions */ -+ -+static uint8_t tpm_tis_locality_from_addr(hwaddr addr) -+{ -+ return (uint8_t)((addr >> TPM_TIS_LOCALITY_SHIFT) & 0x7); -+} -+ -+ -+/* -+ * Set the given flags in the STS register by clearing the register but -+ * preserving the SELFTEST_DONE and TPM_FAMILY_MASK flags and then setting -+ * the new flags. -+ * -+ * The SELFTEST_DONE flag is acquired from the backend that determines it by -+ * peeking into TPM commands. -+ * -+ * A VM suspend/resume will preserve the flag by storing it into the VM -+ * device state, but the backend will not remember it when QEMU is started -+ * again. Therefore, we cache the flag here. Once set, it will not be unset -+ * except by a reset. -+ */ -+static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags) -+{ -+ l->sts &= TPM_TIS_STS_SELFTEST_DONE | TPM_TIS_STS_TPM_FAMILY_MASK; -+ l->sts |= flags; -+} -+ -+/* -+ * Send a request to the TPM. -+ */ -+static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) -+{ -+ if (trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER)) { -+ tpm_util_show_buffer(s->buffer, s->be_buffer_size, "To TPM"); -+ } -+ -+ /* -+ * rw_offset serves as length indicator for length of data; -+ * it's reset when the response comes back -+ */ -+ s->loc[locty].state = TPM_TIS_STATE_EXECUTION; -+ -+ s->cmd = (TPMBackendCmd) { -+ .locty = locty, -+ .in = s->buffer, -+ .in_len = s->rw_offset, -+ .out = s->buffer, -+ .out_len = s->be_buffer_size, -+ }; -+ -+ tpm_backend_deliver_request(s->be_driver, &s->cmd); -+} -+ -+/* raise an interrupt if allowed */ -+static void tpm_tis_raise_irq(TPMState *s, uint8_t locty, uint32_t irqmask) -+{ -+ if (!TPM_TIS_IS_VALID_LOCTY(locty)) { -+ return; -+ } -+ -+ if ((s->loc[locty].inte & TPM_TIS_INT_ENABLED) && -+ (s->loc[locty].inte & irqmask)) { -+ trace_tpm_tis_raise_irq(irqmask); -+ qemu_irq_raise(s->irq); -+ s->loc[locty].ints |= irqmask; -+ } -+} -+ -+static uint32_t tpm_tis_check_request_use_except(TPMState *s, uint8_t locty) -+{ -+ uint8_t l; -+ -+ for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { -+ if (l == locty) { -+ continue; -+ } -+ if ((s->loc[l].access & TPM_TIS_ACCESS_REQUEST_USE)) { -+ return 1; -+ } -+ } -+ -+ return 0; -+} -+ -+static void tpm_tis_new_active_locality(TPMState *s, uint8_t new_active_locty) -+{ -+ bool change = (s->active_locty != new_active_locty); -+ bool is_seize; -+ uint8_t mask; -+ -+ if (change && TPM_TIS_IS_VALID_LOCTY(s->active_locty)) { -+ is_seize = TPM_TIS_IS_VALID_LOCTY(new_active_locty) && -+ s->loc[new_active_locty].access & TPM_TIS_ACCESS_SEIZE; -+ -+ if (is_seize) { -+ mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY); -+ } else { -+ mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY| -+ TPM_TIS_ACCESS_REQUEST_USE); -+ } -+ /* reset flags on the old active locality */ -+ s->loc[s->active_locty].access &= mask; -+ -+ if (is_seize) { -+ s->loc[s->active_locty].access |= TPM_TIS_ACCESS_BEEN_SEIZED; -+ } -+ } -+ -+ s->active_locty = new_active_locty; -+ -+ trace_tpm_tis_new_active_locality(s->active_locty); -+ -+ if (TPM_TIS_IS_VALID_LOCTY(new_active_locty)) { -+ /* set flags on the new active locality */ -+ s->loc[new_active_locty].access |= TPM_TIS_ACCESS_ACTIVE_LOCALITY; -+ s->loc[new_active_locty].access &= ~(TPM_TIS_ACCESS_REQUEST_USE | -+ TPM_TIS_ACCESS_SEIZE); -+ } -+ -+ if (change) { -+ tpm_tis_raise_irq(s, s->active_locty, TPM_TIS_INT_LOCALITY_CHANGED); -+ } -+} -+ -+/* abort -- this function switches the locality */ -+static void tpm_tis_abort(TPMState *s) -+{ -+ s->rw_offset = 0; -+ -+ trace_tpm_tis_abort(s->next_locty); -+ -+ /* -+ * Need to react differently depending on who's aborting now and -+ * which locality will become active afterwards. -+ */ -+ if (s->aborting_locty == s->next_locty) { -+ s->loc[s->aborting_locty].state = TPM_TIS_STATE_READY; -+ tpm_tis_sts_set(&s->loc[s->aborting_locty], -+ TPM_TIS_STS_COMMAND_READY); -+ tpm_tis_raise_irq(s, s->aborting_locty, TPM_TIS_INT_COMMAND_READY); -+ } -+ -+ /* locality after abort is another one than the current one */ -+ tpm_tis_new_active_locality(s, s->next_locty); -+ -+ s->next_locty = TPM_TIS_NO_LOCALITY; -+ /* nobody's aborting a command anymore */ -+ s->aborting_locty = TPM_TIS_NO_LOCALITY; -+} -+ -+/* prepare aborting current command */ -+static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty) -+{ -+ uint8_t busy_locty; -+ -+ assert(TPM_TIS_IS_VALID_LOCTY(newlocty)); -+ -+ s->aborting_locty = locty; /* may also be TPM_TIS_NO_LOCALITY */ -+ s->next_locty = newlocty; /* locality after successful abort */ -+ -+ /* -+ * only abort a command using an interrupt if currently executing -+ * a command AND if there's a valid connection to the vTPM. -+ */ -+ for (busy_locty = 0; busy_locty < TPM_TIS_NUM_LOCALITIES; busy_locty++) { -+ if (s->loc[busy_locty].state == TPM_TIS_STATE_EXECUTION) { -+ /* -+ * request the backend to cancel. Some backends may not -+ * support it -+ */ -+ tpm_backend_cancel_cmd(s->be_driver); -+ return; -+ } -+ } -+ -+ tpm_tis_abort(s); -+} -+ -+/* -+ * Callback from the TPM to indicate that the response was received. -+ */ -+void tpm_tis_request_completed(TPMState *s, int ret) -+{ -+ uint8_t locty = s->cmd.locty; -+ uint8_t l; -+ -+ assert(TPM_TIS_IS_VALID_LOCTY(locty)); -+ -+ if (s->cmd.selftest_done) { -+ for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { -+ s->loc[l].sts |= TPM_TIS_STS_SELFTEST_DONE; -+ } -+ } -+ -+ /* FIXME: report error if ret != 0 */ -+ tpm_tis_sts_set(&s->loc[locty], -+ TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); -+ s->loc[locty].state = TPM_TIS_STATE_COMPLETION; -+ s->rw_offset = 0; -+ -+ if (trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER)) { -+ tpm_util_show_buffer(s->buffer, s->be_buffer_size, "From TPM"); -+ } -+ -+ if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) { -+ tpm_tis_abort(s); -+ } -+ -+ tpm_tis_raise_irq(s, locty, -+ TPM_TIS_INT_DATA_AVAILABLE | TPM_TIS_INT_STS_VALID); -+} -+ -+/* -+ * Read a byte of response data -+ */ -+static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty) -+{ -+ uint32_t ret = TPM_TIS_NO_DATA_BYTE; -+ uint16_t len; -+ -+ if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) { -+ len = MIN(tpm_cmd_get_size(&s->buffer), -+ s->be_buffer_size); -+ -+ ret = s->buffer[s->rw_offset++]; -+ if (s->rw_offset >= len) { -+ /* got last byte */ -+ tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID); -+ tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID); -+ } -+ trace_tpm_tis_data_read(ret, s->rw_offset - 1); -+ } -+ -+ return ret; -+} -+ -+#ifdef DEBUG_TIS -+static void tpm_tis_dump_state(TPMState *s, hwaddr addr) -+{ -+ static const unsigned regs[] = { -+ TPM_TIS_REG_ACCESS, -+ TPM_TIS_REG_INT_ENABLE, -+ TPM_TIS_REG_INT_VECTOR, -+ TPM_TIS_REG_INT_STATUS, -+ TPM_TIS_REG_INTF_CAPABILITY, -+ TPM_TIS_REG_STS, -+ TPM_TIS_REG_DID_VID, -+ TPM_TIS_REG_RID, -+ 0xfff}; -+ int idx; -+ uint8_t locty = tpm_tis_locality_from_addr(addr); -+ hwaddr base = addr & ~0xfff; -+ -+ printf("tpm_tis: active locality : %d\n" -+ "tpm_tis: state of locality %d : %d\n" -+ "tpm_tis: register dump:\n", -+ s->active_locty, -+ locty, s->loc[locty].state); -+ -+ for (idx = 0; regs[idx] != 0xfff; idx++) { -+ printf("tpm_tis: 0x%04x : 0x%08x\n", regs[idx], -+ (int)tpm_tis_mmio_read(s, base + regs[idx], 4)); -+ } -+ -+ printf("tpm_tis: r/w offset : %d\n" -+ "tpm_tis: result buffer : ", -+ s->rw_offset); -+ for (idx = 0; -+ idx < MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size); -+ idx++) { -+ printf("%c%02x%s", -+ s->rw_offset == idx ? '>' : ' ', -+ s->buffer[idx], -+ ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); -+ } -+ printf("\n"); -+} -+#endif -+ -+/* -+ * Read a register of the TIS interface -+ * See specs pages 33-63 for description of the registers -+ */ -+static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, -+ unsigned size) -+{ -+ TPMState *s = opaque; -+ uint16_t offset = addr & 0xffc; -+ uint8_t shift = (addr & 0x3) * 8; -+ uint32_t val = 0xffffffff; -+ uint8_t locty = tpm_tis_locality_from_addr(addr); -+ uint32_t avail; -+ uint8_t v; -+ -+ if (tpm_backend_had_startup_error(s->be_driver)) { -+ return 0; -+ } -+ -+ switch (offset) { -+ case TPM_TIS_REG_ACCESS: -+ /* never show the SEIZE flag even though we use it internally */ -+ val = s->loc[locty].access & ~TPM_TIS_ACCESS_SEIZE; -+ /* the pending flag is always calculated */ -+ if (tpm_tis_check_request_use_except(s, locty)) { -+ val |= TPM_TIS_ACCESS_PENDING_REQUEST; -+ } -+ val |= !tpm_backend_get_tpm_established_flag(s->be_driver); -+ break; -+ case TPM_TIS_REG_INT_ENABLE: -+ val = s->loc[locty].inte; -+ break; -+ case TPM_TIS_REG_INT_VECTOR: -+ val = s->irq_num; -+ break; -+ case TPM_TIS_REG_INT_STATUS: -+ val = s->loc[locty].ints; -+ break; -+ case TPM_TIS_REG_INTF_CAPABILITY: -+ switch (s->be_tpm_version) { -+ case TPM_VERSION_UNSPEC: -+ val = 0; -+ break; -+ case TPM_VERSION_1_2: -+ val = TPM_TIS_CAPABILITIES_SUPPORTED1_3; -+ break; -+ case TPM_VERSION_2_0: -+ val = TPM_TIS_CAPABILITIES_SUPPORTED2_0; -+ break; -+ } -+ break; -+ case TPM_TIS_REG_STS: -+ if (s->active_locty == locty) { -+ if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) { -+ val = TPM_TIS_BURST_COUNT( -+ MIN(tpm_cmd_get_size(&s->buffer), -+ s->be_buffer_size) -+ - s->rw_offset) | s->loc[locty].sts; -+ } else { -+ avail = s->be_buffer_size - s->rw_offset; -+ /* -+ * byte-sized reads should not return 0x00 for 0x100 -+ * available bytes. -+ */ -+ if (size == 1 && avail > 0xff) { -+ avail = 0xff; -+ } -+ val = TPM_TIS_BURST_COUNT(avail) | s->loc[locty].sts; -+ } -+ } -+ break; -+ case TPM_TIS_REG_DATA_FIFO: -+ case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END: -+ if (s->active_locty == locty) { -+ if (size > 4 - (addr & 0x3)) { -+ /* prevent access beyond FIFO */ -+ size = 4 - (addr & 0x3); -+ } -+ val = 0; -+ shift = 0; -+ while (size > 0) { -+ switch (s->loc[locty].state) { -+ case TPM_TIS_STATE_COMPLETION: -+ v = tpm_tis_data_read(s, locty); -+ break; -+ default: -+ v = TPM_TIS_NO_DATA_BYTE; -+ break; -+ } -+ val |= (v << shift); -+ shift += 8; -+ size--; -+ } -+ shift = 0; /* no more adjustments */ -+ } -+ break; -+ case TPM_TIS_REG_INTERFACE_ID: -+ val = s->loc[locty].iface_id; -+ break; -+ case TPM_TIS_REG_DID_VID: -+ val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID; -+ break; -+ case TPM_TIS_REG_RID: -+ val = TPM_TIS_TPM_RID; -+ break; -+#ifdef DEBUG_TIS -+ case TPM_TIS_REG_DEBUG: -+ tpm_tis_dump_state(s, addr); -+ break; -+#endif -+ } -+ -+ if (shift) { -+ val >>= shift; -+ } -+ -+ trace_tpm_tis_mmio_read(size, addr, val); -+ -+ return val; -+} -+ -+/* -+ * Write a value to a register of the TIS interface -+ * See specs pages 33-63 for description of the registers -+ */ -+static void tpm_tis_mmio_write(void *opaque, hwaddr addr, -+ uint64_t val, unsigned size) -+{ -+ TPMState *s = opaque; -+ uint16_t off = addr & 0xffc; -+ uint8_t shift = (addr & 0x3) * 8; -+ uint8_t locty = tpm_tis_locality_from_addr(addr); -+ uint8_t active_locty, l; -+ int c, set_new_locty = 1; -+ uint16_t len; -+ uint32_t mask = (size == 1) ? 0xff : ((size == 2) ? 0xffff : ~0); -+ -+ trace_tpm_tis_mmio_write(size, addr, val); -+ -+ if (locty == 4) { -+ trace_tpm_tis_mmio_write_locty4(); -+ return; -+ } -+ -+ if (tpm_backend_had_startup_error(s->be_driver)) { -+ return; -+ } -+ -+ val &= mask; -+ -+ if (shift) { -+ val <<= shift; -+ mask <<= shift; -+ } -+ -+ mask ^= 0xffffffff; -+ -+ switch (off) { -+ case TPM_TIS_REG_ACCESS: -+ -+ if ((val & TPM_TIS_ACCESS_SEIZE)) { -+ val &= ~(TPM_TIS_ACCESS_REQUEST_USE | -+ TPM_TIS_ACCESS_ACTIVE_LOCALITY); -+ } -+ -+ active_locty = s->active_locty; -+ -+ if ((val & TPM_TIS_ACCESS_ACTIVE_LOCALITY)) { -+ /* give up locality if currently owned */ -+ if (s->active_locty == locty) { -+ trace_tpm_tis_mmio_write_release_locty(locty); -+ -+ uint8_t newlocty = TPM_TIS_NO_LOCALITY; -+ /* anybody wants the locality ? */ -+ for (c = TPM_TIS_NUM_LOCALITIES - 1; c >= 0; c--) { -+ if ((s->loc[c].access & TPM_TIS_ACCESS_REQUEST_USE)) { -+ trace_tpm_tis_mmio_write_locty_req_use(c); -+ newlocty = c; -+ break; -+ } -+ } -+ trace_tpm_tis_mmio_write_next_locty(newlocty); -+ -+ if (TPM_TIS_IS_VALID_LOCTY(newlocty)) { -+ set_new_locty = 0; -+ tpm_tis_prep_abort(s, locty, newlocty); -+ } else { -+ active_locty = TPM_TIS_NO_LOCALITY; -+ } -+ } else { -+ /* not currently the owner; clear a pending request */ -+ s->loc[locty].access &= ~TPM_TIS_ACCESS_REQUEST_USE; -+ } -+ } -+ -+ if ((val & TPM_TIS_ACCESS_BEEN_SEIZED)) { -+ s->loc[locty].access &= ~TPM_TIS_ACCESS_BEEN_SEIZED; -+ } -+ -+ if ((val & TPM_TIS_ACCESS_SEIZE)) { -+ /* -+ * allow seize if a locality is active and the requesting -+ * locality is higher than the one that's active -+ * OR -+ * allow seize for requesting locality if no locality is -+ * active -+ */ -+ while ((TPM_TIS_IS_VALID_LOCTY(s->active_locty) && -+ locty > s->active_locty) || -+ !TPM_TIS_IS_VALID_LOCTY(s->active_locty)) { -+ bool higher_seize = FALSE; -+ -+ /* already a pending SEIZE ? */ -+ if ((s->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) { -+ break; -+ } -+ -+ /* check for ongoing seize by a higher locality */ -+ for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) { -+ if ((s->loc[l].access & TPM_TIS_ACCESS_SEIZE)) { -+ higher_seize = TRUE; -+ break; -+ } -+ } -+ -+ if (higher_seize) { -+ break; -+ } -+ -+ /* cancel any seize by a lower locality */ -+ for (l = 0; l < locty; l++) { -+ s->loc[l].access &= ~TPM_TIS_ACCESS_SEIZE; -+ } -+ -+ s->loc[locty].access |= TPM_TIS_ACCESS_SEIZE; -+ -+ trace_tpm_tis_mmio_write_locty_seized(locty, s->active_locty); -+ trace_tpm_tis_mmio_write_init_abort(); -+ -+ set_new_locty = 0; -+ tpm_tis_prep_abort(s, s->active_locty, locty); -+ break; -+ } -+ } -+ -+ if ((val & TPM_TIS_ACCESS_REQUEST_USE)) { -+ if (s->active_locty != locty) { -+ if (TPM_TIS_IS_VALID_LOCTY(s->active_locty)) { -+ s->loc[locty].access |= TPM_TIS_ACCESS_REQUEST_USE; -+ } else { -+ /* no locality active -> make this one active now */ -+ active_locty = locty; -+ } -+ } -+ } -+ -+ if (set_new_locty) { -+ tpm_tis_new_active_locality(s, active_locty); -+ } -+ -+ break; -+ case TPM_TIS_REG_INT_ENABLE: -+ if (s->active_locty != locty) { -+ break; -+ } -+ -+ s->loc[locty].inte &= mask; -+ s->loc[locty].inte |= (val & (TPM_TIS_INT_ENABLED | -+ TPM_TIS_INT_POLARITY_MASK | -+ TPM_TIS_INTERRUPTS_SUPPORTED)); -+ break; -+ case TPM_TIS_REG_INT_VECTOR: -+ /* hard wired -- ignore */ -+ break; -+ case TPM_TIS_REG_INT_STATUS: -+ if (s->active_locty != locty) { -+ break; -+ } -+ -+ /* clearing of interrupt flags */ -+ if (((val & TPM_TIS_INTERRUPTS_SUPPORTED)) && -+ (s->loc[locty].ints & TPM_TIS_INTERRUPTS_SUPPORTED)) { -+ s->loc[locty].ints &= ~val; -+ if (s->loc[locty].ints == 0) { -+ qemu_irq_lower(s->irq); -+ trace_tpm_tis_mmio_write_lowering_irq(); -+ } -+ } -+ s->loc[locty].ints &= ~(val & TPM_TIS_INTERRUPTS_SUPPORTED); -+ break; -+ case TPM_TIS_REG_STS: -+ if (s->active_locty != locty) { -+ break; -+ } -+ -+ if (s->be_tpm_version == TPM_VERSION_2_0) { -+ /* some flags that are only supported for TPM 2 */ -+ if (val & TPM_TIS_STS_COMMAND_CANCEL) { -+ if (s->loc[locty].state == TPM_TIS_STATE_EXECUTION) { -+ /* -+ * request the backend to cancel. Some backends may not -+ * support it -+ */ -+ tpm_backend_cancel_cmd(s->be_driver); -+ } -+ } -+ -+ if (val & TPM_TIS_STS_RESET_ESTABLISHMENT_BIT) { -+ if (locty == 3 || locty == 4) { -+ tpm_backend_reset_tpm_established_flag(s->be_driver, locty); -+ } -+ } -+ } -+ -+ val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO | -+ TPM_TIS_STS_RESPONSE_RETRY); -+ -+ if (val == TPM_TIS_STS_COMMAND_READY) { -+ switch (s->loc[locty].state) { -+ -+ case TPM_TIS_STATE_READY: -+ s->rw_offset = 0; -+ break; -+ -+ case TPM_TIS_STATE_IDLE: -+ tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_COMMAND_READY); -+ s->loc[locty].state = TPM_TIS_STATE_READY; -+ tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY); -+ break; -+ -+ case TPM_TIS_STATE_EXECUTION: -+ case TPM_TIS_STATE_RECEPTION: -+ /* abort currently running command */ -+ trace_tpm_tis_mmio_write_init_abort(); -+ tpm_tis_prep_abort(s, locty, locty); -+ break; -+ -+ case TPM_TIS_STATE_COMPLETION: -+ s->rw_offset = 0; -+ /* shortcut to ready state with C/R set */ -+ s->loc[locty].state = TPM_TIS_STATE_READY; -+ if (!(s->loc[locty].sts & TPM_TIS_STS_COMMAND_READY)) { -+ tpm_tis_sts_set(&s->loc[locty], -+ TPM_TIS_STS_COMMAND_READY); -+ tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY); -+ } -+ s->loc[locty].sts &= ~(TPM_TIS_STS_DATA_AVAILABLE); -+ break; -+ -+ } -+ } else if (val == TPM_TIS_STS_TPM_GO) { -+ switch (s->loc[locty].state) { -+ case TPM_TIS_STATE_RECEPTION: -+ if ((s->loc[locty].sts & TPM_TIS_STS_EXPECT) == 0) { -+ tpm_tis_tpm_send(s, locty); -+ } -+ break; -+ default: -+ /* ignore */ -+ break; -+ } -+ } else if (val == TPM_TIS_STS_RESPONSE_RETRY) { -+ switch (s->loc[locty].state) { -+ case TPM_TIS_STATE_COMPLETION: -+ s->rw_offset = 0; -+ tpm_tis_sts_set(&s->loc[locty], -+ TPM_TIS_STS_VALID| -+ TPM_TIS_STS_DATA_AVAILABLE); -+ break; -+ default: -+ /* ignore */ -+ break; -+ } -+ } -+ break; -+ case TPM_TIS_REG_DATA_FIFO: -+ case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END: -+ /* data fifo */ -+ if (s->active_locty != locty) { -+ break; -+ } -+ -+ if (s->loc[locty].state == TPM_TIS_STATE_IDLE || -+ s->loc[locty].state == TPM_TIS_STATE_EXECUTION || -+ s->loc[locty].state == TPM_TIS_STATE_COMPLETION) { -+ /* drop the byte */ -+ } else { -+ trace_tpm_tis_mmio_write_data2send(val, size); -+ if (s->loc[locty].state == TPM_TIS_STATE_READY) { -+ s->loc[locty].state = TPM_TIS_STATE_RECEPTION; -+ tpm_tis_sts_set(&s->loc[locty], -+ TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); -+ } -+ -+ val >>= shift; -+ if (size > 4 - (addr & 0x3)) { -+ /* prevent access beyond FIFO */ -+ size = 4 - (addr & 0x3); -+ } -+ -+ while ((s->loc[locty].sts & TPM_TIS_STS_EXPECT) && size > 0) { -+ if (s->rw_offset < s->be_buffer_size) { -+ s->buffer[s->rw_offset++] = -+ (uint8_t)val; -+ val >>= 8; -+ size--; -+ } else { -+ tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID); -+ } -+ } -+ -+ /* check for complete packet */ -+ if (s->rw_offset > 5 && -+ (s->loc[locty].sts & TPM_TIS_STS_EXPECT)) { -+ /* we have a packet length - see if we have all of it */ -+ bool need_irq = !(s->loc[locty].sts & TPM_TIS_STS_VALID); -+ -+ len = tpm_cmd_get_size(&s->buffer); -+ if (len > s->rw_offset) { -+ tpm_tis_sts_set(&s->loc[locty], -+ TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); -+ } else { -+ /* packet complete */ -+ tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID); -+ } -+ if (need_irq) { -+ tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID); -+ } -+ } -+ } -+ break; -+ case TPM_TIS_REG_INTERFACE_ID: -+ if (val & TPM_TIS_IFACE_ID_INT_SEL_LOCK) { -+ for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { -+ s->loc[l].iface_id |= TPM_TIS_IFACE_ID_INT_SEL_LOCK; -+ } -+ } -+ break; -+ } -+} -+ -+const MemoryRegionOps tpm_tis_memory_ops = { -+ .read = tpm_tis_mmio_read, -+ .write = tpm_tis_mmio_write, -+ .endianness = DEVICE_LITTLE_ENDIAN, -+ .valid = { -+ .min_access_size = 1, -+ .max_access_size = 4, -+ }, -+}; -+ -+/* -+ * Get the TPMVersion of the backend device being used -+ */ -+enum TPMVersion tpm_tis_get_tpm_version(TPMState *s) -+{ -+ if (tpm_backend_had_startup_error(s->be_driver)) { -+ return TPM_VERSION_UNSPEC; -+ } -+ -+ return tpm_backend_get_tpm_version(s->be_driver); -+} -+ -+/* -+ * This function is called when the machine starts, resets or due to -+ * S3 resume. -+ */ -+void tpm_tis_reset(TPMState *s) -+{ -+ int c; -+ -+ s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver); -+ s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver), -+ TPM_TIS_BUFFER_MAX); -+ -+ if (s->ppi_enabled) { -+ tpm_ppi_reset(&s->ppi); -+ } -+ tpm_backend_reset(s->be_driver); -+ -+ s->active_locty = TPM_TIS_NO_LOCALITY; -+ s->next_locty = TPM_TIS_NO_LOCALITY; -+ s->aborting_locty = TPM_TIS_NO_LOCALITY; -+ -+ for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) { -+ s->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS; -+ switch (s->be_tpm_version) { -+ case TPM_VERSION_UNSPEC: -+ break; -+ case TPM_VERSION_1_2: -+ s->loc[c].sts = TPM_TIS_STS_TPM_FAMILY1_2; -+ s->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3; -+ break; -+ case TPM_VERSION_2_0: -+ s->loc[c].sts = TPM_TIS_STS_TPM_FAMILY2_0; -+ s->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0; -+ break; -+ } -+ s->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL; -+ s->loc[c].ints = 0; -+ s->loc[c].state = TPM_TIS_STATE_IDLE; -+ -+ s->rw_offset = 0; -+ } -+ -+ if (tpm_backend_startup_tpm(s->be_driver, s->be_buffer_size) < 0) { -+ exit(1); -+ } -+} -+ -+/* persistent state handling */ -+ -+int tpm_tis_pre_save(TPMState *s) -+{ -+ uint8_t locty = s->active_locty; -+ -+ trace_tpm_tis_pre_save(locty, s->rw_offset); -+ -+ if (DEBUG_TIS) { -+ tpm_tis_dump_state(s, 0); -+ } -+ -+ /* -+ * Synchronize with backend completion. -+ */ -+ tpm_backend_finish_sync(s->be_driver); -+ -+ return 0; -+} -+ -+const VMStateDescription vmstate_locty = { -+ .name = "tpm-tis/locty", -+ .version_id = 0, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT32(state, TPMLocality), -+ VMSTATE_UINT32(inte, TPMLocality), -+ VMSTATE_UINT32(ints, TPMLocality), -+ VMSTATE_UINT8(access, TPMLocality), -+ VMSTATE_UINT32(sts, TPMLocality), -+ VMSTATE_UINT32(iface_id, TPMLocality), -+ VMSTATE_END_OF_LIST(), -+ } -+}; -+ -diff --git a/hw/tpm/tpm_tis_isa.c b/hw/tpm/tpm_tis_isa.c -new file mode 100644 -index 00000000..45e25c02 ---- /dev/null -+++ b/hw/tpm/tpm_tis_isa.c -@@ -0,0 +1,170 @@ -+/* -+ * tpm_tis_isa.c - QEMU's TPM TIS ISA Device -+ * -+ * Copyright (C) 2006,2010-2013 IBM Corporation -+ * -+ * Authors: -+ * Stefan Berger -+ * David Safford -+ * -+ * Xen 4 support: Andrease Niederl -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ * -+ * Implementation of the TIS interface according to specs found at -+ * http://www.trustedcomputinggroup.org. This implementation currently -+ * supports version 1.3, 21 March 2013 -+ * In the developers menu choose the PC Client section then find the TIS -+ * specification. -+ * -+ * TPM TIS for TPM 2 implementation following TCG PC Client Platform -+ * TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43 -+ */ -+ -+#include "qemu/osdep.h" -+#include "hw/isa/isa.h" -+#include "hw/qdev-properties.h" -+#include "migration/vmstate.h" -+#include "tpm_util.h" -+#include "tpm_tis.h" -+ -+typedef struct TPMStateISA { -+ /*< private >*/ -+ ISADevice parent_obj; -+ -+ /*< public >*/ -+ TPMState state; /* not a QOM object */ -+} TPMStateISA; -+ -+#define TPM_TIS_ISA(obj) OBJECT_CHECK(TPMStateISA, (obj), TYPE_TPM_TIS_ISA) -+ -+static int tpm_tis_pre_save_isa(void *opaque) -+{ -+ TPMStateISA *isadev = opaque; -+ -+ return tpm_tis_pre_save(&isadev->state); -+} -+ -+static const VMStateDescription vmstate_tpm_tis_isa = { -+ .name = "tpm-tis", -+ .version_id = 0, -+ .pre_save = tpm_tis_pre_save_isa, -+ .fields = (VMStateField[]) { -+ VMSTATE_BUFFER(state.buffer, TPMStateISA), -+ VMSTATE_UINT16(state.rw_offset, TPMStateISA), -+ VMSTATE_UINT8(state.active_locty, TPMStateISA), -+ VMSTATE_UINT8(state.aborting_locty, TPMStateISA), -+ VMSTATE_UINT8(state.next_locty, TPMStateISA), -+ -+ VMSTATE_STRUCT_ARRAY(state.loc, TPMStateISA, TPM_TIS_NUM_LOCALITIES, 0, -+ vmstate_locty, TPMLocality), -+ -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+static void tpm_tis_isa_request_completed(TPMIf *ti, int ret) -+{ -+ TPMStateISA *isadev = TPM_TIS_ISA(ti); -+ TPMState *s = &isadev->state; -+ -+ tpm_tis_request_completed(s, ret); -+} -+ -+static enum TPMVersion tpm_tis_isa_get_tpm_version(TPMIf *ti) -+{ -+ TPMStateISA *isadev = TPM_TIS_ISA(ti); -+ TPMState *s = &isadev->state; -+ -+ return tpm_tis_get_tpm_version(s); -+} -+ -+static void tpm_tis_isa_reset(DeviceState *dev) -+{ -+ TPMStateISA *isadev = TPM_TIS_ISA(dev); -+ TPMState *s = &isadev->state; -+ -+ return tpm_tis_reset(s); -+} -+ -+static Property tpm_tis_isa_properties[] = { -+ DEFINE_PROP_UINT32("irq", TPMStateISA, state.irq_num, TPM_TIS_IRQ), -+ DEFINE_PROP_TPMBE("tpmdev", TPMStateISA, state.be_driver), -+ DEFINE_PROP_BOOL("ppi", TPMStateISA, state.ppi_enabled, true), -+ DEFINE_PROP_END_OF_LIST(), -+}; -+ -+static void tpm_tis_isa_initfn(Object *obj) -+{ -+ TPMStateISA *isadev = TPM_TIS_ISA(obj); -+ TPMState *s = &isadev->state; -+ -+ memory_region_init_io(&s->mmio, obj, &tpm_tis_memory_ops, -+ s, "tpm-tis-mmio", -+ TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT); -+} -+ -+static void tpm_tis_isa_realizefn(DeviceState *dev, Error **errp) -+{ -+ TPMStateISA *isadev = TPM_TIS_ISA(dev); -+ TPMState *s = &isadev->state; -+ -+ if (!tpm_find()) { -+ error_setg(errp, "at most one TPM device is permitted"); -+ return; -+ } -+ -+ if (!s->be_driver) { -+ error_setg(errp, "'tpmdev' property is required"); -+ return; -+ } -+ if (s->irq_num > 15) { -+ error_setg(errp, "IRQ %d is outside valid range of 0 to 15", -+ s->irq_num); -+ return; -+ } -+ -+ isa_init_irq(ISA_DEVICE(dev), &s->irq, s->irq_num); -+ -+ memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)), -+ TPM_TIS_ADDR_BASE, &s->mmio); -+ -+ if (s->ppi_enabled) { -+ tpm_ppi_init(&s->ppi, isa_address_space(ISA_DEVICE(dev)), -+ TPM_PPI_ADDR_BASE, OBJECT(dev)); -+ } -+} -+ -+static void tpm_tis_isa_class_init(ObjectClass *klass, void *data) -+{ -+ DeviceClass *dc = DEVICE_CLASS(klass); -+ TPMIfClass *tc = TPM_IF_CLASS(klass); -+ -+ dc->props = tpm_tis_isa_properties; -+ dc->vmsd = &vmstate_tpm_tis_isa; -+ tc->model = TPM_MODEL_TPM_TIS; -+ dc->realize = tpm_tis_isa_realizefn; -+ dc->reset = tpm_tis_isa_reset; -+ tc->request_completed = tpm_tis_isa_request_completed; -+ tc->get_version = tpm_tis_isa_get_tpm_version; -+} -+ -+static const TypeInfo tpm_tis_isa_info = { -+ .name = TYPE_TPM_TIS_ISA, -+ .parent = TYPE_ISA_DEVICE, -+ .instance_size = sizeof(TPMStateISA), -+ .instance_init = tpm_tis_isa_initfn, -+ .class_init = tpm_tis_isa_class_init, -+ .interfaces = (InterfaceInfo[]) { -+ { TYPE_TPM_IF }, -+ { } -+ } -+}; -+ -+static void tpm_tis_isa_register(void) -+{ -+ type_register_static(&tpm_tis_isa_info); -+} -+ -+type_init(tpm_tis_isa_register) --- -2.23.0 - diff --git a/tpm-Use-TPMState-as-a-common-struct.patch b/tpm-Use-TPMState-as-a-common-struct.patch deleted file mode 100644 index 61a1dd037bb2356cb7307d53f82732af404ed4e2..0000000000000000000000000000000000000000 --- a/tpm-Use-TPMState-as-a-common-struct.patch +++ /dev/null @@ -1,314 +0,0 @@ -From c57e57c86f9d3c13b33746436bc1f09db88d4d42 Mon Sep 17 00:00:00 2001 -From: jiangfangjie -Date: Tue, 11 Aug 2020 02:52:12 +0000 -Subject: [PATCH 11/19] tpm: Use TPMState as a common struct - -As we plan to introduce a SysBus TPM TIS device, let's -make the TPMState a common struct usable by both the -ISADevice and the SysBusDevice. TPMStateISA embeds the -struct and inherits from the ISADevice. - -The prototype of functions bound to be used by both -the ISA and SysBus devices is changed to take TPMState -handle. - -A bunch of structs also are renamed to be specialized -for the ISA device. Besides those transformations, no -functional change is expected. - -Signed-off-by: Eric Auger -Reviewed-by: Stefan Berger -Tested-by: Ard Biesheuvel -Acked-by: Ard Biesheuvel -Message-id: 20200305165149.618-3-eric.auger@redhat.com -Signed-off-by: Stefan Berger -Signed-off-by: jiangfangjie ---- - hw/tpm/tpm_tis.c | 147 +++++++++++++++++++++++++++++------------------ - 1 file changed, 92 insertions(+), 55 deletions(-) - -diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c -index 49d44652..735a528f 100644 ---- a/hw/tpm/tpm_tis.c -+++ b/hw/tpm/tpm_tis.c -@@ -62,7 +62,6 @@ typedef struct TPMLocality { - } TPMLocality; - - typedef struct TPMState { -- ISADevice busdev; - MemoryRegion mmio; - - unsigned char buffer[TPM_TIS_BUFFER_MAX]; -@@ -88,7 +87,15 @@ typedef struct TPMState { - TPMPPI ppi; - } TPMState; - --#define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS_ISA) -+typedef struct TPMStateISA { -+ /*< private >*/ -+ ISADevice parent_obj; -+ -+ /*< public >*/ -+ TPMState state; /* not a QOM object */ -+} TPMStateISA; -+ -+#define TPM_TIS_ISA(obj) OBJECT_CHECK(TPMStateISA, (obj), TYPE_TPM_TIS_ISA) - - #define DEBUG_TIS 0 - -@@ -278,9 +285,8 @@ static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty) - /* - * Callback from the TPM to indicate that the response was received. - */ --static void tpm_tis_request_completed(TPMIf *ti, int ret) -+static void tpm_tis_request_completed(TPMState *s, int ret) - { -- TPMState *s = TPM(ti); - uint8_t locty = s->cmd.locty; - uint8_t l; - -@@ -335,7 +341,7 @@ static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty) - } - - #ifdef DEBUG_TIS --static void tpm_tis_dump_state(void *opaque, hwaddr addr) -+static void tpm_tis_dump_state(TPMState *s, hwaddr addr) - { - static const unsigned regs[] = { - TPM_TIS_REG_ACCESS, -@@ -350,7 +356,6 @@ static void tpm_tis_dump_state(void *opaque, hwaddr addr) - int idx; - uint8_t locty = tpm_tis_locality_from_addr(addr); - hwaddr base = addr & ~0xfff; -- TPMState *s = opaque; - - printf("tpm_tis: active locality : %d\n" - "tpm_tis: state of locality %d : %d\n" -@@ -360,7 +365,7 @@ static void tpm_tis_dump_state(void *opaque, hwaddr addr) - - for (idx = 0; regs[idx] != 0xfff; idx++) { - printf("tpm_tis: 0x%04x : 0x%08x\n", regs[idx], -- (int)tpm_tis_mmio_read(opaque, base + regs[idx], 4)); -+ (int)tpm_tis_mmio_read(s, base + regs[idx], 4)); - } - - printf("tpm_tis: r/w offset : %d\n" -@@ -485,7 +490,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, - break; - #ifdef DEBUG_TIS - case TPM_TIS_REG_DEBUG: -- tpm_tis_dump_state(opaque, addr); -+ tpm_tis_dump_state(s, addr); - break; - #endif - } -@@ -832,10 +837,8 @@ static const MemoryRegionOps tpm_tis_memory_ops = { - /* - * Get the TPMVersion of the backend device being used - */ --static enum TPMVersion tpm_tis_get_tpm_version(TPMIf *ti) -+static enum TPMVersion tpm_tis_get_tpm_version(TPMState *s) - { -- TPMState *s = TPM(ti); -- - if (tpm_backend_had_startup_error(s->be_driver)) { - return TPM_VERSION_UNSPEC; - } -@@ -847,9 +850,8 @@ static enum TPMVersion tpm_tis_get_tpm_version(TPMIf *ti) - * This function is called when the machine starts, resets or due to - * S3 resume. - */ --static void tpm_tis_reset(DeviceState *dev) -+static void tpm_tis_reset(TPMState *s) - { -- TPMState *s = TPM(dev); - int c; - - s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver); -@@ -893,15 +895,14 @@ static void tpm_tis_reset(DeviceState *dev) - - /* persistent state handling */ - --static int tpm_tis_pre_save(void *opaque) -+static int tpm_tis_pre_save(TPMState *s) - { -- TPMState *s = opaque; - uint8_t locty = s->active_locty; - - trace_tpm_tis_pre_save(locty, s->rw_offset); - - if (DEBUG_TIS) { -- tpm_tis_dump_state(opaque, 0); -+ tpm_tis_dump_state(s, 0); - } - - /* -@@ -926,34 +927,78 @@ static const VMStateDescription vmstate_locty = { - } - }; - --static const VMStateDescription vmstate_tpm_tis = { -+/* ISA */ -+ -+static int tpm_tis_pre_save_isa(void *opaque) -+{ -+ TPMStateISA *isadev = opaque; -+ -+ return tpm_tis_pre_save(&isadev->state); -+} -+ -+static const VMStateDescription vmstate_tpm_tis_isa = { - .name = "tpm-tis", - .version_id = 0, -- .pre_save = tpm_tis_pre_save, -+ .pre_save = tpm_tis_pre_save_isa, - .fields = (VMStateField[]) { -- VMSTATE_BUFFER(buffer, TPMState), -- VMSTATE_UINT16(rw_offset, TPMState), -- VMSTATE_UINT8(active_locty, TPMState), -- VMSTATE_UINT8(aborting_locty, TPMState), -- VMSTATE_UINT8(next_locty, TPMState), -+ VMSTATE_BUFFER(state.buffer, TPMStateISA), -+ VMSTATE_UINT16(state.rw_offset, TPMStateISA), -+ VMSTATE_UINT8(state.active_locty, TPMStateISA), -+ VMSTATE_UINT8(state.aborting_locty, TPMStateISA), -+ VMSTATE_UINT8(state.next_locty, TPMStateISA), - -- VMSTATE_STRUCT_ARRAY(loc, TPMState, TPM_TIS_NUM_LOCALITIES, 0, -+ VMSTATE_STRUCT_ARRAY(state.loc, TPMStateISA, TPM_TIS_NUM_LOCALITIES, 0, - vmstate_locty, TPMLocality), - - VMSTATE_END_OF_LIST() - } - }; - --static Property tpm_tis_properties[] = { -- DEFINE_PROP_UINT32("irq", TPMState, irq_num, TPM_TIS_IRQ), -- DEFINE_PROP_TPMBE("tpmdev", TPMState, be_driver), -- DEFINE_PROP_BOOL("ppi", TPMState, ppi_enabled, true), -+static void tpm_tis_isa_request_completed(TPMIf *ti, int ret) -+{ -+ TPMStateISA *isadev = TPM_TIS_ISA(ti); -+ TPMState *s = &isadev->state; -+ -+ tpm_tis_request_completed(s, ret); -+} -+ -+static enum TPMVersion tpm_tis_isa_get_tpm_version(TPMIf *ti) -+{ -+ TPMStateISA *isadev = TPM_TIS_ISA(ti); -+ TPMState *s = &isadev->state; -+ -+ return tpm_tis_get_tpm_version(s); -+} -+ -+static void tpm_tis_isa_reset(DeviceState *dev) -+{ -+ TPMStateISA *isadev = TPM_TIS_ISA(dev); -+ TPMState *s = &isadev->state; -+ -+ return tpm_tis_reset(s); -+} -+ -+static Property tpm_tis_isa_properties[] = { -+ DEFINE_PROP_UINT32("irq", TPMStateISA, state.irq_num, TPM_TIS_IRQ), -+ DEFINE_PROP_TPMBE("tpmdev", TPMStateISA, state.be_driver), -+ DEFINE_PROP_BOOL("ppi", TPMStateISA, state.ppi_enabled, true), - DEFINE_PROP_END_OF_LIST(), - }; - --static void tpm_tis_realizefn(DeviceState *dev, Error **errp) -+static void tpm_tis_isa_initfn(Object *obj) - { -- TPMState *s = TPM(dev); -+ TPMStateISA *isadev = TPM_TIS_ISA(obj); -+ TPMState *s = &isadev->state; -+ -+ memory_region_init_io(&s->mmio, obj, &tpm_tis_memory_ops, -+ s, "tpm-tis-mmio", -+ TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT); -+} -+ -+static void tpm_tis_isa_realizefn(DeviceState *dev, Error **errp) -+{ -+ TPMStateISA *isadev = TPM_TIS_ISA(dev); -+ TPMState *s = &isadev->state; - - if (!tpm_find()) { - error_setg(errp, "at most one TPM device is permitted"); -@@ -970,55 +1015,47 @@ static void tpm_tis_realizefn(DeviceState *dev, Error **errp) - return; - } - -- isa_init_irq(&s->busdev, &s->irq, s->irq_num); -+ isa_init_irq(ISA_DEVICE(dev), &s->irq, s->irq_num); - - memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)), - TPM_TIS_ADDR_BASE, &s->mmio); - - if (s->ppi_enabled) { - tpm_ppi_init(&s->ppi, isa_address_space(ISA_DEVICE(dev)), -- TPM_PPI_ADDR_BASE, OBJECT(s)); -+ TPM_PPI_ADDR_BASE, OBJECT(dev)); - } - } - --static void tpm_tis_initfn(Object *obj) --{ -- TPMState *s = TPM(obj); -- -- memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops, -- s, "tpm-tis-mmio", -- TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT); --} -- --static void tpm_tis_class_init(ObjectClass *klass, void *data) -+static void tpm_tis_isa_class_init(ObjectClass *klass, void *data) - { - DeviceClass *dc = DEVICE_CLASS(klass); - TPMIfClass *tc = TPM_IF_CLASS(klass); - -- dc->realize = tpm_tis_realizefn; -- dc->props = tpm_tis_properties; -- dc->reset = tpm_tis_reset; -- dc->vmsd = &vmstate_tpm_tis; -+ dc->props = tpm_tis_isa_properties; -+ dc->vmsd = &vmstate_tpm_tis_isa; - tc->model = TPM_MODEL_TPM_TIS; -- tc->get_version = tpm_tis_get_tpm_version; -- tc->request_completed = tpm_tis_request_completed; -+ dc->realize = tpm_tis_isa_realizefn; -+ dc->reset = tpm_tis_isa_reset; -+ tc->request_completed = tpm_tis_isa_request_completed; -+ tc->get_version = tpm_tis_isa_get_tpm_version; -+ - } - --static const TypeInfo tpm_tis_info = { -+static const TypeInfo tpm_tis_isa_info = { - .name = TYPE_TPM_TIS_ISA, - .parent = TYPE_ISA_DEVICE, -- .instance_size = sizeof(TPMState), -- .instance_init = tpm_tis_initfn, -- .class_init = tpm_tis_class_init, -+ .instance_size = sizeof(TPMStateISA), -+ .instance_init = tpm_tis_isa_initfn, -+ .class_init = tpm_tis_isa_class_init, - .interfaces = (InterfaceInfo[]) { - { TYPE_TPM_IF }, - { } - } - }; - --static void tpm_tis_register(void) -+static void tpm_tis_isa_register(void) - { -- type_register_static(&tpm_tis_info); -+ type_register_static(&tpm_tis_isa_info); - } - --type_init(tpm_tis_register) -+type_init(tpm_tis_isa_register) --- -2.23.0 - diff --git a/tpm-ppi-page-align-PPI-RAM.patch b/tpm-ppi-page-align-PPI-RAM.patch deleted file mode 100644 index d7ba2c876605392e79d887b89a4a274cb51660d4..0000000000000000000000000000000000000000 --- a/tpm-ppi-page-align-PPI-RAM.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 26b54c545f253049faa633ff886132602ff47241 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Fri, 3 Jan 2020 11:39:59 +0400 -Subject: [PATCH 02/19] tpm-ppi: page-align PPI RAM -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -post-copy migration fails on destination with error such as: -2019-12-26T10:22:44.714644Z qemu-kvm: ram_block_discard_range: -Unaligned start address: 0x559d2afae9a0 - -Use qemu_memalign() to constrain the PPI RAM memory alignment. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Marc-André Lureau -Reviewed-by: Philippe Mathieu-Daudé -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: Stefan Berger -Signed-off-by: Stefan Berger -Message-id: 20200103074000.1006389-3-marcandre.lureau@redhat.com -Signed-off-by: jiangfangjie ---- - hw/tpm/tpm_ppi.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/hw/tpm/tpm_ppi.c b/hw/tpm/tpm_ppi.c -index cd8205f2..6509ffd4 100644 ---- a/hw/tpm/tpm_ppi.c -+++ b/hw/tpm/tpm_ppi.c -@@ -44,7 +44,8 @@ void tpm_ppi_reset(TPMPPI *tpmppi) - void tpm_ppi_init(TPMPPI *tpmppi, struct MemoryRegion *m, - hwaddr addr, Object *obj) - { -- tpmppi->buf = g_malloc0(HOST_PAGE_ALIGN(TPM_PPI_ADDR_SIZE)); -+ tpmppi->buf = qemu_memalign(qemu_real_host_page_size, -+ HOST_PAGE_ALIGN(TPM_PPI_ADDR_SIZE)); - memory_region_init_ram_device_ptr(&tpmppi->ram, obj, "tpm-ppi", - TPM_PPI_ADDR_SIZE, tpmppi->buf); - vmstate_register_ram(&tpmppi->ram, DEVICE(obj)); --- -2.23.0 - diff --git a/tpm-rename-TPM_TIS-into-TPM_TIS_ISA.patch b/tpm-rename-TPM_TIS-into-TPM_TIS_ISA.patch deleted file mode 100644 index ea6e1d28a10cb6d29ba1c1c76245ef6749825ba2..0000000000000000000000000000000000000000 --- a/tpm-rename-TPM_TIS-into-TPM_TIS_ISA.patch +++ /dev/null @@ -1,101 +0,0 @@ -From 7974f8ffd75171be106a1ce2705878abbb6c4477 Mon Sep 17 00:00:00 2001 -From: Eric Auger -Date: Thu, 5 Mar 2020 17:51:40 +0100 -Subject: [PATCH 10/19] tpm: rename TPM_TIS into TPM_TIS_ISA -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -As we plan to introduce a sysbus TPM_TIS, let's rename -TPM_TIS into TPM_TIS_ISA. - -Signed-off-by: Eric Auger -Reviewed-by: Stefan Berger -Reviewed-by: Philippe Mathieu-Daudé -Tested-by: Ard Biesheuvel -Acked-by: Ard Biesheuvel -Message-id: 20200305165149.618-2-eric.auger@redhat.com -Signed-off-by: Stefan Berger -Signed-off-by: jiangfangjie ---- - hw/i386/acpi-build.c | 6 +++--- - hw/tpm/tpm_tis.c | 4 ++-- - include/sysemu/tpm.h | 6 +++--- - 3 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c -index c97731ec..093f7d93 100644 ---- a/hw/i386/acpi-build.c -+++ b/hw/i386/acpi-build.c -@@ -2007,7 +2007,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, - } - } - -- if (TPM_IS_TIS(tpm_find())) { -+ if (TPM_IS_TIS_ISA(tpm_find())) { - aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE, - TPM_TIS_ADDR_SIZE, AML_READ_WRITE)); - } -@@ -2178,7 +2178,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, - /* Scan all PCI buses. Generate tables to support hotplug. */ - build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en); - -- if (TPM_IS_TIS(tpm)) { -+ if (TPM_IS_TIS_ISA(tpm)) { - if (misc->tpm_version == TPM_VERSION_2_0) { - dev = aml_device("TPM"); - aml_append(dev, aml_name_decl("_HID", -@@ -2285,7 +2285,7 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog) - (char *)&tpm2_ptr->log_area_start_address - table_data->data; - - tpm2_ptr->platform_class = cpu_to_le16(TPM2_ACPI_CLASS_CLIENT); -- if (TPM_IS_TIS(tpm_find())) { -+ if (TPM_IS_TIS_ISA(tpm_find())) { - tpm2_ptr->control_area_address = cpu_to_le64(0); - tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO); - } else if (TPM_IS_CRB(tpm_find())) { -diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c -index 96a9ac48..49d44652 100644 ---- a/hw/tpm/tpm_tis.c -+++ b/hw/tpm/tpm_tis.c -@@ -88,7 +88,7 @@ typedef struct TPMState { - TPMPPI ppi; - } TPMState; - --#define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS) -+#define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS_ISA) - - #define DEBUG_TIS 0 - -@@ -1005,7 +1005,7 @@ static void tpm_tis_class_init(ObjectClass *klass, void *data) - } - - static const TypeInfo tpm_tis_info = { -- .name = TYPE_TPM_TIS, -+ .name = TYPE_TPM_TIS_ISA, - .parent = TYPE_ISA_DEVICE, - .instance_size = sizeof(TPMState), - .instance_init = tpm_tis_initfn, -diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h -index 15979a36..1691b92c 100644 ---- a/include/sysemu/tpm.h -+++ b/include/sysemu/tpm.h -@@ -43,12 +43,12 @@ typedef struct TPMIfClass { - enum TPMVersion (*get_version)(TPMIf *obj); - } TPMIfClass; - --#define TYPE_TPM_TIS "tpm-tis" -+#define TYPE_TPM_TIS_ISA "tpm-tis" - #define TYPE_TPM_CRB "tpm-crb" - #define TYPE_TPM_SPAPR "tpm-spapr" - --#define TPM_IS_TIS(chr) \ -- object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS) -+#define TPM_IS_TIS_ISA(chr) \ -+ object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_ISA) - #define TPM_IS_CRB(chr) \ - object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB) - #define TPM_IS_SPAPR(chr) \ --- -2.23.0 - diff --git a/tpm_spapr-Support-TPM-for-ppc64-using-CRQ-based-inte.patch b/tpm_spapr-Support-TPM-for-ppc64-using-CRQ-based-inte.patch deleted file mode 100644 index ffc0b62ed7ef655056cfd1280282b768f22ad501..0000000000000000000000000000000000000000 --- a/tpm_spapr-Support-TPM-for-ppc64-using-CRQ-based-inte.patch +++ /dev/null @@ -1,552 +0,0 @@ -From 14402a8ca57fb722eb324d141fafb41ef06f4c2b Mon Sep 17 00:00:00 2001 -From: Stefan Berger -Date: Tue, 21 Jan 2020 10:29:32 -0500 -Subject: [PATCH 06/19] tpm_spapr: Support TPM for ppc64 using CRQ based - interface - -Implement support for TPM on ppc64 by implementing the vTPM CRQ interface -as a frontend. It can use the tpm_emulator driver backend with the external -swtpm. - -The Linux vTPM driver for ppc64 works with this emulation. - -This TPM emulator also handles the TPM 2 case. - -Signed-off-by: Stefan Berger -Reviewed-by: David Gibson -Message-Id: <20200121152935.649898-4-stefanb@linux.ibm.com> -Signed-off-by: David Gibson -Signed-off-by: jiangfangjie ---- - docs/specs/tpm.txt | 20 ++- - hw/tpm/Kconfig | 6 + - hw/tpm/Makefile.objs | 1 + - hw/tpm/tpm_spapr.c | 379 +++++++++++++++++++++++++++++++++++++++++++ - hw/tpm/trace-events | 12 ++ - include/sysemu/tpm.h | 3 + - qapi/tpm.json | 6 +- - 7 files changed, 423 insertions(+), 4 deletions(-) - create mode 100644 hw/tpm/tpm_spapr.c - -diff --git a/docs/specs/tpm.txt b/docs/specs/tpm.txt -index 9c8cca04..9c3e67d8 100644 ---- a/docs/specs/tpm.txt -+++ b/docs/specs/tpm.txt -@@ -34,6 +34,12 @@ The CRB interface makes a memory mapped IO region in the area 0xfed40000 - - QEMU files related to TPM CRB interface: - - hw/tpm/tpm_crb.c - -+ -+pSeries (ppc64) machines offer a tpm-spapr device model. -+ -+QEMU files related to the SPAPR interface: -+ - hw/tpm/tpm_spapr.c -+ - = fw_cfg interface = - - The bios/firmware may read the "etc/tpm/config" fw_cfg entry for -@@ -281,7 +287,7 @@ swtpm socket --tpmstate dir=/tmp/mytpm1 \ - --log level=20 - - Command line to start QEMU with the TPM emulator device communicating with --the swtpm: -+the swtpm (x86): - - qemu-system-x86_64 -display sdl -accel kvm \ - -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ -@@ -289,6 +295,18 @@ qemu-system-x86_64 -display sdl -accel kvm \ - -tpmdev emulator,id=tpm0,chardev=chrtpm \ - -device tpm-tis,tpmdev=tpm0 test.img - -+In case a pSeries machine is emulated, use the following command line: -+ -+qemu-system-ppc64 -display sdl -machine pseries,accel=kvm \ -+ -m 1024 -bios slof.bin -boot menu=on \ -+ -nodefaults -device VGA -device pci-ohci -device usb-kbd \ -+ -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ -+ -tpmdev emulator,id=tpm0,chardev=chrtpm \ -+ -device tpm-spapr,tpmdev=tpm0 \ -+ -device spapr-vscsi,id=scsi0,reg=0x00002000 \ -+ -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,id=virtio-disk0 \ -+ -drive file=test.img,format=raw,if=none,id=drive-virtio-disk0 -+ - - In case SeaBIOS is used as firmware, it should show the TPM menu item - after entering the menu with 'ESC'. -diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig -index 4c8ee87d..4d4ab085 100644 ---- a/hw/tpm/Kconfig -+++ b/hw/tpm/Kconfig -@@ -22,3 +22,9 @@ config TPM_EMULATOR - bool - default y - depends on TPMDEV -+ -+config TPM_SPAPR -+ bool -+ default n -+ depends on TPM && PSERIES -+ select TPMDEV -diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs -index de0b85d0..85eb99ae 100644 ---- a/hw/tpm/Makefile.objs -+++ b/hw/tpm/Makefile.objs -@@ -4,3 +4,4 @@ common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o - common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o - common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o - common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o -+obj-$(CONFIG_TPM_SPAPR) += tpm_spapr.o -diff --git a/hw/tpm/tpm_spapr.c b/hw/tpm/tpm_spapr.c -new file mode 100644 -index 00000000..1db9696a ---- /dev/null -+++ b/hw/tpm/tpm_spapr.c -@@ -0,0 +1,379 @@ -+/* -+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator -+ * -+ * PAPR Virtual TPM -+ * -+ * Copyright (c) 2015, 2017, 2019 IBM Corporation. -+ * -+ * Authors: -+ * Stefan Berger -+ * -+ * This code is licensed under the GPL version 2 or later. See the -+ * COPYING file in the top-level directory. -+ * -+ */ -+ -+#include "qemu/osdep.h" -+#include "qemu/error-report.h" -+#include "qapi/error.h" -+#include "hw/qdev-properties.h" -+#include "migration/vmstate.h" -+ -+#include "sysemu/tpm_backend.h" -+#include "tpm_int.h" -+#include "tpm_util.h" -+ -+#include "hw/ppc/spapr.h" -+#include "hw/ppc/spapr_vio.h" -+#include "trace.h" -+ -+#define DEBUG_SPAPR 0 -+ -+#define VIO_SPAPR_VTPM(obj) \ -+ OBJECT_CHECK(SpaprTpmState, (obj), TYPE_TPM_SPAPR) -+ -+typedef struct TpmCrq { -+ uint8_t valid; /* 0x80: cmd; 0xc0: init crq */ -+ /* 0x81-0x83: CRQ message response */ -+ uint8_t msg; /* see below */ -+ uint16_t len; /* len of TPM request; len of TPM response */ -+ uint32_t data; /* rtce_dma_handle when sending TPM request */ -+ uint64_t reserved; -+} TpmCrq; -+ -+#define SPAPR_VTPM_VALID_INIT_CRQ_COMMAND 0xC0 -+#define SPAPR_VTPM_VALID_COMMAND 0x80 -+#define SPAPR_VTPM_MSG_RESULT 0x80 -+ -+/* msg types for valid = SPAPR_VTPM_VALID_INIT_CRQ */ -+#define SPAPR_VTPM_INIT_CRQ_RESULT 0x1 -+#define SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT 0x2 -+ -+/* msg types for valid = SPAPR_VTPM_VALID_CMD */ -+#define SPAPR_VTPM_GET_VERSION 0x1 -+#define SPAPR_VTPM_TPM_COMMAND 0x2 -+#define SPAPR_VTPM_GET_RTCE_BUFFER_SIZE 0x3 -+#define SPAPR_VTPM_PREPARE_TO_SUSPEND 0x4 -+ -+/* response error messages */ -+#define SPAPR_VTPM_VTPM_ERROR 0xff -+ -+/* error codes */ -+#define SPAPR_VTPM_ERR_COPY_IN_FAILED 0x3 -+#define SPAPR_VTPM_ERR_COPY_OUT_FAILED 0x4 -+ -+#define TPM_SPAPR_BUFFER_MAX 4096 -+ -+typedef struct { -+ SpaprVioDevice vdev; -+ -+ TpmCrq crq; /* track single TPM command */ -+ -+ uint8_t state; -+#define SPAPR_VTPM_STATE_NONE 0 -+#define SPAPR_VTPM_STATE_EXECUTION 1 -+#define SPAPR_VTPM_STATE_COMPLETION 2 -+ -+ unsigned char *buffer; -+ -+ TPMBackendCmd cmd; -+ -+ TPMBackend *be_driver; -+ TPMVersion be_tpm_version; -+ -+ size_t be_buffer_size; -+} SpaprTpmState; -+ -+/* -+ * Send a request to the TPM. -+ */ -+static void tpm_spapr_tpm_send(SpaprTpmState *s) -+{ -+ if (trace_event_get_state_backends(TRACE_TPM_SPAPR_SHOW_BUFFER)) { -+ tpm_util_show_buffer(s->buffer, s->be_buffer_size, "To TPM"); -+ } -+ -+ s->state = SPAPR_VTPM_STATE_EXECUTION; -+ s->cmd = (TPMBackendCmd) { -+ .locty = 0, -+ .in = s->buffer, -+ .in_len = MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size), -+ .out = s->buffer, -+ .out_len = s->be_buffer_size, -+ }; -+ -+ tpm_backend_deliver_request(s->be_driver, &s->cmd); -+} -+ -+static int tpm_spapr_process_cmd(SpaprTpmState *s, uint64_t dataptr) -+{ -+ long rc; -+ -+ /* a max. of be_buffer_size bytes can be transported */ -+ rc = spapr_vio_dma_read(&s->vdev, dataptr, -+ s->buffer, s->be_buffer_size); -+ if (rc) { -+ error_report("tpm_spapr_got_payload: DMA read failure"); -+ } -+ /* let vTPM handle any malformed request */ -+ tpm_spapr_tpm_send(s); -+ -+ return rc; -+} -+ -+static inline int spapr_tpm_send_crq(struct SpaprVioDevice *dev, TpmCrq *crq) -+{ -+ return spapr_vio_send_crq(dev, (uint8_t *)crq); -+} -+ -+static int tpm_spapr_do_crq(struct SpaprVioDevice *dev, uint8_t *crq_data) -+{ -+ SpaprTpmState *s = VIO_SPAPR_VTPM(dev); -+ TpmCrq local_crq; -+ TpmCrq *crq = &s->crq; /* requests only */ -+ int rc; -+ uint8_t valid = crq_data[0]; -+ uint8_t msg = crq_data[1]; -+ -+ trace_tpm_spapr_do_crq(valid, msg); -+ -+ switch (valid) { -+ case SPAPR_VTPM_VALID_INIT_CRQ_COMMAND: /* Init command/response */ -+ -+ /* Respond to initialization request */ -+ switch (msg) { -+ case SPAPR_VTPM_INIT_CRQ_RESULT: -+ trace_tpm_spapr_do_crq_crq_result(); -+ memset(&local_crq, 0, sizeof(local_crq)); -+ local_crq.valid = SPAPR_VTPM_VALID_INIT_CRQ_COMMAND; -+ local_crq.msg = SPAPR_VTPM_INIT_CRQ_RESULT; -+ spapr_tpm_send_crq(dev, &local_crq); -+ break; -+ -+ case SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT: -+ trace_tpm_spapr_do_crq_crq_complete_result(); -+ memset(&local_crq, 0, sizeof(local_crq)); -+ local_crq.valid = SPAPR_VTPM_VALID_INIT_CRQ_COMMAND; -+ local_crq.msg = SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT; -+ spapr_tpm_send_crq(dev, &local_crq); -+ break; -+ } -+ -+ break; -+ case SPAPR_VTPM_VALID_COMMAND: /* Payloads */ -+ switch (msg) { -+ case SPAPR_VTPM_TPM_COMMAND: -+ trace_tpm_spapr_do_crq_tpm_command(); -+ if (s->state == SPAPR_VTPM_STATE_EXECUTION) { -+ return H_BUSY; -+ } -+ memcpy(crq, crq_data, sizeof(*crq)); -+ -+ rc = tpm_spapr_process_cmd(s, be32_to_cpu(crq->data)); -+ -+ if (rc == H_SUCCESS) { -+ crq->valid = be16_to_cpu(0); -+ } else { -+ local_crq.valid = SPAPR_VTPM_MSG_RESULT; -+ local_crq.msg = SPAPR_VTPM_VTPM_ERROR; -+ local_crq.len = cpu_to_be16(0); -+ local_crq.data = cpu_to_be32(SPAPR_VTPM_ERR_COPY_IN_FAILED); -+ spapr_tpm_send_crq(dev, &local_crq); -+ } -+ break; -+ -+ case SPAPR_VTPM_GET_RTCE_BUFFER_SIZE: -+ trace_tpm_spapr_do_crq_tpm_get_rtce_buffer_size(s->be_buffer_size); -+ local_crq.valid = SPAPR_VTPM_VALID_COMMAND; -+ local_crq.msg = SPAPR_VTPM_GET_RTCE_BUFFER_SIZE | -+ SPAPR_VTPM_MSG_RESULT; -+ local_crq.len = cpu_to_be16(s->be_buffer_size); -+ spapr_tpm_send_crq(dev, &local_crq); -+ break; -+ -+ case SPAPR_VTPM_GET_VERSION: -+ local_crq.valid = SPAPR_VTPM_VALID_COMMAND; -+ local_crq.msg = SPAPR_VTPM_GET_VERSION | SPAPR_VTPM_MSG_RESULT; -+ local_crq.len = cpu_to_be16(0); -+ switch (s->be_tpm_version) { -+ case TPM_VERSION_1_2: -+ local_crq.data = cpu_to_be32(1); -+ break; -+ case TPM_VERSION_2_0: -+ local_crq.data = cpu_to_be32(2); -+ break; -+ default: -+ g_assert_not_reached(); -+ break; -+ } -+ trace_tpm_spapr_do_crq_get_version(be32_to_cpu(local_crq.data)); -+ spapr_tpm_send_crq(dev, &local_crq); -+ break; -+ -+ case SPAPR_VTPM_PREPARE_TO_SUSPEND: -+ trace_tpm_spapr_do_crq_prepare_to_suspend(); -+ local_crq.valid = SPAPR_VTPM_VALID_COMMAND; -+ local_crq.msg = SPAPR_VTPM_PREPARE_TO_SUSPEND | -+ SPAPR_VTPM_MSG_RESULT; -+ spapr_tpm_send_crq(dev, &local_crq); -+ break; -+ -+ default: -+ trace_tpm_spapr_do_crq_unknown_msg_type(crq->msg); -+ } -+ break; -+ default: -+ trace_tpm_spapr_do_crq_unknown_crq(valid, msg); -+ }; -+ -+ return H_SUCCESS; -+} -+ -+static void tpm_spapr_request_completed(TPMIf *ti, int ret) -+{ -+ SpaprTpmState *s = VIO_SPAPR_VTPM(ti); -+ TpmCrq *crq = &s->crq; -+ uint32_t len; -+ int rc; -+ -+ s->state = SPAPR_VTPM_STATE_COMPLETION; -+ -+ /* a max. of be_buffer_size bytes can be transported */ -+ len = MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size); -+ rc = spapr_vio_dma_write(&s->vdev, be32_to_cpu(crq->data), -+ s->buffer, len); -+ -+ if (trace_event_get_state_backends(TRACE_TPM_SPAPR_SHOW_BUFFER)) { -+ tpm_util_show_buffer(s->buffer, len, "From TPM"); -+ } -+ -+ crq->valid = SPAPR_VTPM_MSG_RESULT; -+ if (rc == H_SUCCESS) { -+ crq->msg = SPAPR_VTPM_TPM_COMMAND | SPAPR_VTPM_MSG_RESULT; -+ crq->len = cpu_to_be16(len); -+ } else { -+ error_report("%s: DMA write failure", __func__); -+ crq->msg = SPAPR_VTPM_VTPM_ERROR; -+ crq->len = cpu_to_be16(0); -+ crq->data = cpu_to_be32(SPAPR_VTPM_ERR_COPY_OUT_FAILED); -+ } -+ -+ rc = spapr_tpm_send_crq(&s->vdev, crq); -+ if (rc) { -+ error_report("%s: Error sending response", __func__); -+ } -+} -+ -+static int tpm_spapr_do_startup_tpm(SpaprTpmState *s, size_t buffersize) -+{ -+ return tpm_backend_startup_tpm(s->be_driver, buffersize); -+} -+ -+static const char *tpm_spapr_get_dt_compatible(SpaprVioDevice *dev) -+{ -+ SpaprTpmState *s = VIO_SPAPR_VTPM(dev); -+ -+ switch (s->be_tpm_version) { -+ case TPM_VERSION_1_2: -+ return "IBM,vtpm"; -+ case TPM_VERSION_2_0: -+ return "IBM,vtpm20"; -+ default: -+ g_assert_not_reached(); -+ } -+} -+ -+static void tpm_spapr_reset(SpaprVioDevice *dev) -+{ -+ SpaprTpmState *s = VIO_SPAPR_VTPM(dev); -+ -+ s->state = SPAPR_VTPM_STATE_NONE; -+ -+ s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver); -+ -+ s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver), -+ TPM_SPAPR_BUFFER_MAX); -+ -+ tpm_backend_reset(s->be_driver); -+ tpm_spapr_do_startup_tpm(s, s->be_buffer_size); -+} -+ -+static enum TPMVersion tpm_spapr_get_version(TPMIf *ti) -+{ -+ SpaprTpmState *s = VIO_SPAPR_VTPM(ti); -+ -+ if (tpm_backend_had_startup_error(s->be_driver)) { -+ return TPM_VERSION_UNSPEC; -+ } -+ -+ return tpm_backend_get_tpm_version(s->be_driver); -+} -+ -+static const VMStateDescription vmstate_spapr_vtpm = { -+ .name = "tpm-spapr", -+ .unmigratable = 1, -+}; -+ -+static Property tpm_spapr_properties[] = { -+ DEFINE_SPAPR_PROPERTIES(SpaprTpmState, vdev), -+ DEFINE_PROP_TPMBE("tpmdev", SpaprTpmState, be_driver), -+ DEFINE_PROP_END_OF_LIST(), -+}; -+ -+static void tpm_spapr_realizefn(SpaprVioDevice *dev, Error **errp) -+{ -+ SpaprTpmState *s = VIO_SPAPR_VTPM(dev); -+ -+ if (!tpm_find()) { -+ error_setg(errp, "at most one TPM device is permitted"); -+ return; -+ } -+ -+ dev->crq.SendFunc = tpm_spapr_do_crq; -+ -+ if (!s->be_driver) { -+ error_setg(errp, "'tpmdev' property is required"); -+ return; -+ } -+ s->buffer = g_malloc(TPM_SPAPR_BUFFER_MAX); -+} -+ -+static void tpm_spapr_class_init(ObjectClass *klass, void *data) -+{ -+ DeviceClass *dc = DEVICE_CLASS(klass); -+ SpaprVioDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass); -+ TPMIfClass *tc = TPM_IF_CLASS(klass); -+ -+ k->realize = tpm_spapr_realizefn; -+ k->reset = tpm_spapr_reset; -+ k->dt_name = "vtpm"; -+ k->dt_type = "IBM,vtpm"; -+ k->get_dt_compatible = tpm_spapr_get_dt_compatible; -+ k->signal_mask = 0x00000001; -+ set_bit(DEVICE_CATEGORY_MISC, dc->categories); -+ dc->props = tpm_spapr_properties; -+ k->rtce_window_size = 0x10000000; -+ dc->vmsd = &vmstate_spapr_vtpm; -+ -+ tc->model = TPM_MODEL_TPM_SPAPR; -+ tc->get_version = tpm_spapr_get_version; -+ tc->request_completed = tpm_spapr_request_completed; -+} -+ -+static const TypeInfo tpm_spapr_info = { -+ .name = TYPE_TPM_SPAPR, -+ .parent = TYPE_VIO_SPAPR_DEVICE, -+ .instance_size = sizeof(SpaprTpmState), -+ .class_init = tpm_spapr_class_init, -+ .interfaces = (InterfaceInfo[]) { -+ { TYPE_TPM_IF }, -+ { } -+ } -+}; -+ -+static void tpm_spapr_register_types(void) -+{ -+ type_register_static(&tpm_spapr_info); -+} -+ -+type_init(tpm_spapr_register_types) -diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events -index 82c45ee5..edbe1bd7 100644 ---- a/hw/tpm/trace-events -+++ b/hw/tpm/trace-events -@@ -55,3 +55,15 @@ tpm_tis_pre_save(uint8_t locty, uint32_t rw_offset) "locty: %d, rw_offset = %u" - - # tpm_ppi.c - tpm_ppi_memset(uint8_t *ptr, size_t size) "memset: %p %zu" -+ -+# hw/tpm/tpm_spapr.c -+tpm_spapr_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\n%s" -+tpm_spapr_do_crq(uint8_t raw1, uint8_t raw2) "1st 2 bytes in CRQ: 0x%02x 0x%02x" -+tpm_spapr_do_crq_crq_result(void) "SPAPR_VTPM_INIT_CRQ_RESULT" -+tpm_spapr_do_crq_crq_complete_result(void) "SPAPR_VTPM_INIT_CRQ_COMP_RESULT" -+tpm_spapr_do_crq_tpm_command(void) "got TPM command payload" -+tpm_spapr_do_crq_tpm_get_rtce_buffer_size(size_t buffersize) "response: buffer size is %zu" -+tpm_spapr_do_crq_get_version(uint32_t version) "response: version %u" -+tpm_spapr_do_crq_prepare_to_suspend(void) "response: preparing to suspend" -+tpm_spapr_do_crq_unknown_msg_type(uint8_t type) "Unknown message type 0x%02x" -+tpm_spapr_do_crq_unknown_crq(uint8_t raw1, uint8_t raw2) "unknown CRQ 0x%02x 0x%02x ..." -diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h -index 5b541a71..15979a36 100644 ---- a/include/sysemu/tpm.h -+++ b/include/sysemu/tpm.h -@@ -45,11 +45,14 @@ typedef struct TPMIfClass { - - #define TYPE_TPM_TIS "tpm-tis" - #define TYPE_TPM_CRB "tpm-crb" -+#define TYPE_TPM_SPAPR "tpm-spapr" - - #define TPM_IS_TIS(chr) \ - object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS) - #define TPM_IS_CRB(chr) \ - object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB) -+#define TPM_IS_SPAPR(chr) \ -+ object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR) - - /* returns NULL unless there is exactly one TPM device */ - static inline TPMIf *tpm_find(void) -diff --git a/qapi/tpm.json b/qapi/tpm.json -index b30323bb..63878aa0 100644 ---- a/qapi/tpm.json -+++ b/qapi/tpm.json -@@ -12,11 +12,11 @@ - # - # @tpm-tis: TPM TIS model - # @tpm-crb: TPM CRB model (since 2.12) -+# @tpm-spapr: TPM SPAPR model (since 5.0) - # - # Since: 1.5 - ## --{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] } -- -+{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb', 'tpm-spapr' ] } - ## - # @query-tpm-models: - # -@@ -29,7 +29,7 @@ - # Example: - # - # -> { "execute": "query-tpm-models" } --# <- { "return": [ "tpm-tis", "tpm-crb" ] } -+# <- { "return": [ "tpm-tis", "tpm-crb", "tpm-spapr" ] } - # - ## - { 'command': 'query-tpm-models', 'returns': ['TpmModel'] } --- -2.23.0 - diff --git a/tpm_spapr-Support-suspend-and-resume.patch b/tpm_spapr-Support-suspend-and-resume.patch deleted file mode 100644 index 55ed521a261fe5c058d9f6b95334c0884cdfd7ea..0000000000000000000000000000000000000000 --- a/tpm_spapr-Support-suspend-and-resume.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 2948d9712a7058bcdca6732101874beb1a6e00a9 Mon Sep 17 00:00:00 2001 -From: Stefan Berger -Date: Tue, 21 Jan 2020 10:29:33 -0500 -Subject: [PATCH 07/19] tpm_spapr: Support suspend and resume -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Extend the tpm_spapr frontend with VM suspend and resume support. - -Signed-off-by: Stefan Berger -Message-Id: <20200121152935.649898-5-stefanb@linux.ibm.com> -Reviewed-by: Marc-André Lureau -Signed-off-by: David Gibson -Signed-off-by: jiangfangjie ---- - hw/tpm/tpm_spapr.c | 52 ++++++++++++++++++++++++++++++++++++++++++++- - hw/tpm/trace-events | 2 ++ - 2 files changed, 53 insertions(+), 1 deletion(-) - -diff --git a/hw/tpm/tpm_spapr.c b/hw/tpm/tpm_spapr.c -index 1db9696a..8ba561f4 100644 ---- a/hw/tpm/tpm_spapr.c -+++ b/hw/tpm/tpm_spapr.c -@@ -76,6 +76,8 @@ typedef struct { - - unsigned char *buffer; - -+ uint32_t numbytes; /* number of bytes to deliver on resume */ -+ - TPMBackendCmd cmd; - - TPMBackend *be_driver; -@@ -240,6 +242,14 @@ static void tpm_spapr_request_completed(TPMIf *ti, int ret) - - /* a max. of be_buffer_size bytes can be transported */ - len = MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size); -+ -+ if (runstate_check(RUN_STATE_FINISH_MIGRATE)) { -+ trace_tpm_spapr_caught_response(len); -+ /* defer delivery of response until .post_load */ -+ s->numbytes = len; -+ return; -+ } -+ - rc = spapr_vio_dma_write(&s->vdev, be32_to_cpu(crq->data), - s->buffer, len); - -@@ -288,6 +298,7 @@ static void tpm_spapr_reset(SpaprVioDevice *dev) - SpaprTpmState *s = VIO_SPAPR_VTPM(dev); - - s->state = SPAPR_VTPM_STATE_NONE; -+ s->numbytes = 0; - - s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver); - -@@ -309,9 +320,48 @@ static enum TPMVersion tpm_spapr_get_version(TPMIf *ti) - return tpm_backend_get_tpm_version(s->be_driver); - } - -+/* persistent state handling */ -+ -+static int tpm_spapr_pre_save(void *opaque) -+{ -+ SpaprTpmState *s = opaque; -+ -+ tpm_backend_finish_sync(s->be_driver); -+ /* -+ * we cannot deliver the results to the VM since DMA would touch VM memory -+ */ -+ -+ return 0; -+} -+ -+static int tpm_spapr_post_load(void *opaque, int version_id) -+{ -+ SpaprTpmState *s = opaque; -+ -+ if (s->numbytes) { -+ trace_tpm_spapr_post_load(); -+ /* deliver the results to the VM via DMA */ -+ tpm_spapr_request_completed(TPM_IF(s), 0); -+ s->numbytes = 0; -+ } -+ -+ return 0; -+} -+ - static const VMStateDescription vmstate_spapr_vtpm = { - .name = "tpm-spapr", -- .unmigratable = 1, -+ .pre_save = tpm_spapr_pre_save, -+ .post_load = tpm_spapr_post_load, -+ .fields = (VMStateField[]) { -+ VMSTATE_SPAPR_VIO(vdev, SpaprTpmState), -+ -+ VMSTATE_UINT8(state, SpaprTpmState), -+ VMSTATE_UINT32(numbytes, SpaprTpmState), -+ VMSTATE_VBUFFER_UINT32(buffer, SpaprTpmState, 0, NULL, numbytes), -+ /* remember DMA address */ -+ VMSTATE_UINT32(crq.data, SpaprTpmState), -+ VMSTATE_END_OF_LIST(), -+ } - }; - - static Property tpm_spapr_properties[] = { -diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events -index edbe1bd7..b97eea24 100644 ---- a/hw/tpm/trace-events -+++ b/hw/tpm/trace-events -@@ -67,3 +67,5 @@ tpm_spapr_do_crq_get_version(uint32_t version) "response: version %u" - tpm_spapr_do_crq_prepare_to_suspend(void) "response: preparing to suspend" - tpm_spapr_do_crq_unknown_msg_type(uint8_t type) "Unknown message type 0x%02x" - tpm_spapr_do_crq_unknown_crq(uint8_t raw1, uint8_t raw2) "unknown CRQ 0x%02x 0x%02x ..." -+tpm_spapr_post_load(void) "Delivering TPM response after resume" -+tpm_spapr_caught_response(uint32_t v) "Caught response to deliver after resume: %u bytes" --- -2.23.0 - diff --git a/tz-ppc-add-dummy-read-write-methods.patch b/tz-ppc-add-dummy-read-write-methods.patch deleted file mode 100644 index ee8fa6b096bf8e359cb326c581d0a72733c8c1c4..0000000000000000000000000000000000000000 --- a/tz-ppc-add-dummy-read-write-methods.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 52d1c1a258aef2b8ace50bb202ee7338ed0060f0 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Thu, 25 Mar 2021 17:27:07 +0800 -Subject: [PATCH] tz-ppc: add dummy read/write methods - -fix CVE-2020-15469 - -Add tz-ppc-dummy mmio read/write methods to avoid assert failure -during initialisation. - -Signed-off-by: Prasad J Pandit - -Signed-off-by: Jiajie Li ---- - hw/misc/tz-ppc.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/hw/misc/tz-ppc.c b/hw/misc/tz-ppc.c -index 2a14a26f29..5b7b883866 100644 ---- a/hw/misc/tz-ppc.c -+++ b/hw/misc/tz-ppc.c -@@ -193,7 +193,20 @@ static bool tz_ppc_dummy_accepts(void *opaque, hwaddr addr, - g_assert_not_reached(); - } - -+static uint64_t tz_ppc_dummy_read(void *opaque, hwaddr addr, unsigned size) -+{ -+ g_assert_not_reached(); -+} -+ -+static void tz_ppc_dummy_write(void *opaque, hwaddr addr, -+ uint64_t data, unsigned size) -+{ -+ g_assert_not_reached(); -+} -+ - static const MemoryRegionOps tz_ppc_dummy_ops = { -+ .read = tz_ppc_dummy_read, -+ .write = tz_ppc_dummy_write, - .valid.accepts = tz_ppc_dummy_accepts, - }; - --- -2.27.0 - diff --git a/uas-add-stream-number-sanity-checks.patch b/uas-add-stream-number-sanity-checks.patch deleted file mode 100644 index 6b6840cc9e392a2852f79bfdb6d4447c7b75a8a5..0000000000000000000000000000000000000000 --- a/uas-add-stream-number-sanity-checks.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 2b0a54f7fb36836f148a3a237fd0ee99a1a300a2 Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Wed, 18 Aug 2021 14:05:05 +0200 -Subject: [PATCH] uas: add stream number sanity checks. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The device uses the guest-supplied stream number unchecked, which can -lead to guest-triggered out-of-band access to the UASDevice->data3 and -UASDevice->status3 fields. Add the missing checks. - -Fixes: CVE-2021-3713 -Signed-off-by: Gerd Hoffmann -Reported-by: Chen Zhe -Reported-by: Tan Jingguo -Reviewed-by: Philippe Mathieu-Daudé -Message-Id: <20210818120505.1258262-2-kraxel@redhat.com> ---- - hw/usb/dev-uas.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c -index abd8070d0c..82bbc0d083 100644 ---- a/hw/usb/dev-uas.c -+++ b/hw/usb/dev-uas.c -@@ -827,6 +827,9 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p) - } - break; - case UAS_PIPE_ID_STATUS: -+ if (p->stream > UAS_MAX_STREAMS) { -+ goto err_stream; -+ } - if (p->stream) { - QTAILQ_FOREACH(st, &uas->results, next) { - if (st->stream == p->stream) { -@@ -854,6 +857,9 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p) - break; - case UAS_PIPE_ID_DATA_IN: - case UAS_PIPE_ID_DATA_OUT: -+ if (p->stream > UAS_MAX_STREAMS) { -+ goto err_stream; -+ } - if (p->stream) { - req = usb_uas_find_request(uas, p->stream); - } else { -@@ -889,6 +895,11 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p) - p->status = USB_RET_STALL; - break; - } -+ -+err_stream: -+ error_report("%s: invalid stream %d", __func__, p->stream); -+ p->status = USB_RET_STALL; -+ return; - } - - static void usb_uas_unrealize(USBDevice *dev, Error **errp) --- -2.27.0 - diff --git a/ui-Fix-hanging-up-Cocoa-display-on-macOS-10.15-Catal.patch b/ui-Fix-hanging-up-Cocoa-display-on-macOS-10.15-Catal.patch deleted file mode 100644 index 30724cedb050b52be09a0b081ffe36cd7599d268..0000000000000000000000000000000000000000 --- a/ui-Fix-hanging-up-Cocoa-display-on-macOS-10.15-Catal.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 6705b9344f8d6f134f612c2e35e87cdda5aa6284 Mon Sep 17 00:00:00 2001 -From: Hikaru Nishida -Date: Tue, 15 Oct 2019 10:07:34 +0900 -Subject: [PATCH] ui: Fix hanging up Cocoa display on macOS 10.15 (Catalina) - -macOS API documentation says that before applicationDidFinishLaunching -is called, any events will not be processed. However, some events are -fired before it is called in macOS Catalina. This causes deadlock of -iothread_lock in handleEvent while it will be released after the -app_started_sem is posted. -This patch avoids processing events before the app_started_sem is -posted to prevent this deadlock. - -Buglink: https://bugs.launchpad.net/qemu/+bug/1847906 -Signed-off-by: Hikaru Nishida -Message-id: 20191015010734.85229-1-hikarupsp@gmail.com -Signed-off-by: Gerd Hoffmann -(cherry picked from commit dff742ad27efa474ec04accdbf422c9acfd3e30e) -Signed-off-by: Michael Roth ---- - ui/cocoa.m | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/ui/cocoa.m b/ui/cocoa.m -index c2984028c5..3026ead621 100644 ---- a/ui/cocoa.m -+++ b/ui/cocoa.m -@@ -132,6 +132,7 @@ NSArray * supportedImageFileTypes; - - static QemuSemaphore display_init_sem; - static QemuSemaphore app_started_sem; -+static bool allow_events; - - // Utility functions to run specified code block with iothread lock held - typedef void (^CodeBlock)(void); -@@ -727,6 +728,16 @@ QemuCocoaView *cocoaView; - - - (bool) handleEvent:(NSEvent *)event - { -+ if(!allow_events) { -+ /* -+ * Just let OSX have all events that arrive before -+ * applicationDidFinishLaunching. -+ * This avoids a deadlock on the iothread lock, which cocoa_display_init() -+ * will not drop until after the app_started_sem is posted. (In theory -+ * there should not be any such events, but OSX Catalina now emits some.) -+ */ -+ return false; -+ } - return bool_with_iothread_lock(^{ - return [self handleEventLocked:event]; - }); -@@ -1154,6 +1165,7 @@ QemuCocoaView *cocoaView; - - (void)applicationDidFinishLaunching: (NSNotification *) note - { - COCOA_DEBUG("QemuCocoaAppController: applicationDidFinishLaunching\n"); -+ allow_events = true; - /* Tell cocoa_display_init to proceed */ - qemu_sem_post(&app_started_sem); - } --- -2.23.0 diff --git a/upd6-check-udp6_input-buffer-size.patch b/upd6-check-udp6_input-buffer-size.patch deleted file mode 100644 index d9402fe435016bd9ce9af7581a11208056bed5dd..0000000000000000000000000000000000000000 --- a/upd6-check-udp6_input-buffer-size.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 054a233306e781ae3cf66b386b67b68e8ac33c37 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Fri, 4 Jun 2021 16:32:55 +0400 -Subject: [PATCH 4/6] upd6: check udp6_input buffer size -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fixes: CVE-2021-3593 -Fixes: https://gitlab.freedesktop.org/slirp/libslirp/-/issues/45 - -Signed-off-by: Marc-André Lureau -Signed-off-by: imxcc ---- - slirp/src/udp6.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/slirp/src/udp6.c b/slirp/src/udp6.c -index 6f9486bb..8c490e4d 100644 ---- a/slirp/src/udp6.c -+++ b/slirp/src/udp6.c -@@ -28,7 +28,10 @@ void udp6_input(struct mbuf *m) - ip = mtod(m, struct ip6 *); - m->m_len -= iphlen; - m->m_data += iphlen; -- uh = mtod(m, struct udphdr *); -+ uh = mtod_check(m, sizeof(struct udphdr)); -+ if (uh == NULL) { -+ goto bad; -+ } - m->m_len += iphlen; - m->m_data -= iphlen; - --- -2.27.0 - diff --git a/update-linux-headers-Import-iommu.h.patch b/update-linux-headers-Import-iommu.h.patch index eea744e5063aeba90d9e16967f88b9d902de93f1..5653e6a4ddd6b5cdb7a68dbef54f010d0e3a1cda 100644 --- a/update-linux-headers-Import-iommu.h.patch +++ b/update-linux-headers-Import-iommu.h.patch @@ -1,4 +1,4 @@ -From 78c269f4ed09a3272d99a65d9c86977a01ef99c8 Mon Sep 17 00:00:00 2001 +From 694acf3c321908d26ce508842b7bd076664ffbc6 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 9 May 2019 10:23:42 -0400 Subject: [PATCH] update-linux-headers: Import iommu.h @@ -12,15 +12,15 @@ Signed-off-by: Kunkun Jiang 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh -index f76d77363b..dfdfdfddcf 100755 +index fea4d6eb65..acde610733 100755 --- a/scripts/update-linux-headers.sh +++ b/scripts/update-linux-headers.sh -@@ -141,7 +141,7 @@ done +@@ -144,7 +144,7 @@ done rm -rf "$output/linux-headers/linux" mkdir -p "$output/linux-headers/linux" --for header in kvm.h vfio.h vfio_ccw.h vhost.h \ -+for header in kvm.h vfio.h vfio_ccw.h vhost.h iommu.h \ +-for header in kvm.h vfio.h vfio_ccw.h vfio_zdev.h vhost.h \ ++for header in kvm.h vfio.h vfio_ccw.h vfio_zdev.h vhost.h iommu.h \ psci.h psp-sev.h userfaultfd.h mman.h; do cp "$tmpdir/include/linux/$header" "$output/linux-headers/linux" done diff --git a/usb-limit-combined-packets-to-1-MiB-CVE-2021-3527.patch b/usb-limit-combined-packets-to-1-MiB-CVE-2021-3527.patch deleted file mode 100644 index 836e01ce8c2eda354b60c5b32b0e8303ab652f7c..0000000000000000000000000000000000000000 --- a/usb-limit-combined-packets-to-1-MiB-CVE-2021-3527.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 93be5f3334394aa9a1794007aed79e75cf4d348b Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Mon, 21 Jun 2021 10:19:58 +0800 -Subject: [PATCH] usb: limit combined packets to 1 MiB (CVE-2021-3527) - -Fix CVE-2021-3527 - -usb-host and usb-redirect try to batch bulk transfers by combining many -small usb packets into a single, large transfer request, to reduce the -overhead and improve performance. - -This patch adds a size limit of 1 MiB for those combined packets to -restrict the host resources the guest can bind that way. -Signed-off-by: Gerd Hoffmann's avatarGerd Hoffmann -Message-Id: <20210503132915.2335822-6-kraxel@redhat.com> - -Signed-off-by: Jiajie Li ---- - hw/usb/combined-packet.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/hw/usb/combined-packet.c b/hw/usb/combined-packet.c -index 5d57e883dc..e56802f89a 100644 ---- a/hw/usb/combined-packet.c -+++ b/hw/usb/combined-packet.c -@@ -171,7 +171,9 @@ void usb_ep_combine_input_packets(USBEndpoint *ep) - if ((p->iov.size % ep->max_packet_size) != 0 || !p->short_not_ok || - next == NULL || - /* Work around for Linux usbfs bulk splitting + migration */ -- (totalsize == (16 * KiB - 36) && p->int_req)) { -+ (totalsize == (16 * KiB - 36) && p->int_req) || -+ /* Next package may grow combined package over 1MiB */ -+ totalsize > 1 * MiB - ep->max_packet_size) { - usb_device_handle_data(ep->dev, first); - assert(first->status == USB_RET_ASYNC); - if (first->combined) { --- -2.27.0 - diff --git a/usbredir-Prevent-recursion-in-usbredir_write.patch b/usbredir-Prevent-recursion-in-usbredir_write.patch deleted file mode 100644 index 29eb50f2d08b41c570fa90940ac01894c046e90e..0000000000000000000000000000000000000000 --- a/usbredir-Prevent-recursion-in-usbredir_write.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 30203c01fa1bb2a7b92575683f85695a2d420b38 Mon Sep 17 00:00:00 2001 -From: "Dr. David Alan Gilbert" -Date: Wed, 18 Dec 2019 11:30:12 +0000 -Subject: [PATCH] usbredir: Prevent recursion in usbredir_write - -I've got a case where usbredir_write manages to call back into itself -via spice; this patch causes the recursion to fail (0 bytes) the write; -this seems to avoid the deadlock I was previously seeing. - -I can't say I fully understand the interaction of usbredir and spice; -but there are a few similar guards in spice and usbredir -to catch other cases especially onces also related to spice_server_char_device_wakeup - -This case seems to be triggered by repeated migration+repeated -reconnection of the viewer; but my debugging suggests the migration -finished before this hits. - -The backtrace of the hang looks like: - reds_handle_ticket - reds_handle_other_links - reds_channel_do_link - red_channel_connect - spicevmc_connect - usbredir_create_parser - usbredirparser_do_write - usbredir_write - qemu_chr_fe_write - qemu_chr_write - qemu_chr_write_buffer - spice_chr_write - spice_server_char_device_wakeup - red_char_device_wakeup - red_char_device_write_to_device - vmc_write - usbredirparser_do_write - usbredir_write - qemu_chr_fe_write - qemu_chr_write - qemu_chr_write_buffer - qemu_mutex_lock_impl - -and we fail as we lang through qemu_chr_write_buffer's lock -twice. - -Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1752320 - -Signed-off-by: Dr. David Alan Gilbert -Message-Id: <20191218113012.13331-1-dgilbert@redhat.com> -Signed-off-by: Gerd Hoffmann ---- - hw/usb/redirect.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c -index 9764a57987..3cf82589ed 100644 ---- a/hw/usb/redirect.c -+++ b/hw/usb/redirect.c -@@ -109,6 +109,7 @@ struct USBRedirDevice { - /* Properties */ - CharBackend cs; - bool enable_streams; -+ bool in_write; - uint8_t debug; - int32_t bootindex; - char *filter_str; -@@ -286,6 +287,13 @@ static int usbredir_write(void *priv, uint8_t *data, int count) - return 0; - } - -+ /* Recursion check */ -+ if (dev->in_write) { -+ DPRINTF("usbredir_write recursion\n"); -+ return 0; -+ } -+ dev->in_write = true; -+ - r = qemu_chr_fe_write(&dev->cs, data, count); - if (r < count) { - if (!dev->watch) { -@@ -296,6 +304,7 @@ static int usbredir_write(void *priv, uint8_t *data, int count) - r = 0; - } - } -+ dev->in_write = false; - return r; - } - --- -2.27.0 - diff --git a/usbredir-fix-buffer-overflow-on-vmload.patch b/usbredir-fix-buffer-overflow-on-vmload.patch deleted file mode 100644 index 4a43c35cad37bcece9822ddf61033c18dd7edfc4..0000000000000000000000000000000000000000 --- a/usbredir-fix-buffer-overflow-on-vmload.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 66fce891aecec3969d1ba979cf0a9a6df70afecd Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Wed, 7 Aug 2019 12:40:48 +0400 -Subject: [PATCH] usbredir: fix buffer-overflow on vmload -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -If interface_count is NO_INTERFACE_INFO, let's not access the arrays -out-of-bounds. - -==994==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x625000243930 at pc 0x5642068086a8 bp 0x7f0b6f9ffa50 sp 0x7f0b6f9ffa40 -READ of size 1 at 0x625000243930 thread T0 - #0 0x5642068086a7 in usbredir_check_bulk_receiving /home/elmarco/src/qemu/hw/usb/redirect.c:1503 - #1 0x56420681301c in usbredir_post_load /home/elmarco/src/qemu/hw/usb/redirect.c:2154 - #2 0x5642068a56c2 in vmstate_load_state /home/elmarco/src/qemu/migration/vmstate.c:168 - #3 0x56420688e2ac in vmstate_load /home/elmarco/src/qemu/migration/savevm.c:829 - #4 0x5642068980cb in qemu_loadvm_section_start_full /home/elmarco/src/qemu/migration/savevm.c:2211 - #5 0x564206899645 in qemu_loadvm_state_main /home/elmarco/src/qemu/migration/savevm.c:2395 - #6 0x5642068998cf in qemu_loadvm_state /home/elmarco/src/qemu/migration/savevm.c:2467 - #7 0x56420685f3e9 in process_incoming_migration_co /home/elmarco/src/qemu/migration/migration.c:449 - #8 0x564207106c47 in coroutine_trampoline /home/elmarco/src/qemu/util/coroutine-ucontext.c:115 - #9 0x7f0c0604e37f (/lib64/libc.so.6+0x4d37f) - -Signed-off-by: Marc-André Lureau -Reviewed-by: Liam Merwick -Reviewed-by: Li Qiang -Reviewed-by: Philippe Mathieu-Daudé -Message-id: 20190807084048.4258-1-marcandre.lureau@redhat.com -Signed-off-by: Gerd Hoffmann -Signed-off-by: Zhenyu Ye ---- - hw/usb/redirect.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c -index 998fc6e4..9764a579 100644 ---- a/hw/usb/redirect.c -+++ b/hw/usb/redirect.c -@@ -1495,6 +1495,11 @@ static void usbredir_check_bulk_receiving(USBRedirDevice *dev) - for (i = EP2I(USB_DIR_IN); i < MAX_ENDPOINTS; i++) { - dev->endpoint[i].bulk_receiving_enabled = 0; - } -+ -+ if (dev->interface_info.interface_count == NO_INTERFACE_INFO) { -+ return; -+ } -+ - for (i = 0; i < dev->interface_info.interface_count; i++) { - quirks = usb_get_quirks(dev->device_info.vendor_id, - dev->device_info.product_id, --- -2.22.0.windows.1 - diff --git a/usbredir-fix-free-call.patch b/usbredir-fix-free-call.patch deleted file mode 100644 index d4e65ef4e045e87cb61d8b713260715cedb5d79e..0000000000000000000000000000000000000000 --- a/usbredir-fix-free-call.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 642ace93283c326666a9bbc2f8cf5b483fca2a6a Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Thu, 22 Jul 2021 09:27:56 +0200 -Subject: [PATCH] usbredir: fix free call -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -data might point into the middle of a larger buffer, there is a separate -free_on_destroy pointer passed into bufp_alloc() to handle that. It is -only used in the normal workflow though, not when dropping packets due -to the queue being full. Fix that. - -Resolves: https://gitlab.com/qemu-project/qemu/-/issues/491 -Signed-off-by: Gerd Hoffmann -Reviewed-by: Marc-André Lureau -Message-Id: <20210722072756.647673-1-kraxel@redhat.com> -Signed-off-by: imxcc ---- - hw/usb/redirect.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c -index 3cf82589ed..71f3594f4a 100644 ---- a/hw/usb/redirect.c -+++ b/hw/usb/redirect.c -@@ -468,7 +468,7 @@ static int bufp_alloc(USBRedirDevice *dev, uint8_t *data, uint16_t len, - if (dev->endpoint[EP2I(ep)].bufpq_dropping_packets) { - if (dev->endpoint[EP2I(ep)].bufpq_size > - dev->endpoint[EP2I(ep)].bufpq_target_size) { -- free(data); -+ free(free_on_destroy); - return -1; - } - dev->endpoint[EP2I(ep)].bufpq_dropping_packets = 0; --- -2.27.0 - diff --git a/util-add-slirp_fmt-helpers.patch b/util-add-slirp_fmt-helpers.patch deleted file mode 100644 index b752f1293a0b88ef0ae01410a2fc63f9ff875df8..0000000000000000000000000000000000000000 --- a/util-add-slirp_fmt-helpers.patch +++ /dev/null @@ -1,124 +0,0 @@ -From f3475a4a22dd84be0d2d7daa11676ac861da64bc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureauls?= -Date: Tue, 14 Apr 2020 18:51:39 +0800 -Subject: [PATCH] util: add slirp_fmt() helpers -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Various calls to snprintf() in libslirp assume that snprintf() returns -"only" the number of bytes written (excluding terminating NUL). - -https://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html#tag_16_159_04 - -"Upon successful completion, the snprintf() function shall return the -number of bytes that would be written to s had n been sufficiently -large excluding the terminating null byte." - -Introduce slirp_fmt() that handles several pathological cases the -way libslirp usually expect: - -- treat error as fatal (instead of silently returning -1) - -- fmt0() will always \0 end - -- return the number of bytes actually written (instead of what would -have been written, which would usually result in OOB later), including -the ending \0 for fmt0() - -- warn if truncation happened (instead of ignoring) - -Other less common cases can still be handled with strcpy/snprintf() etc. -Signed-off-by: default avatarMarc-André Lureau -Reviewed-by: Samuel Thibault's avatarSamuel Thibault -Message-Id: <20200127092414.169796-2-marcandre.lureau@redhat.com> ---- - slirp/src/util.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ - slirp/src/util.h | 3 +++ - 2 files changed, 66 insertions(+) - -diff --git a/slirp/src/util.c b/slirp/src/util.c -index e5960871..dcae899e 100644 ---- a/slirp/src/util.c -+++ b/slirp/src/util.c -@@ -364,3 +364,66 @@ void slirp_pstrcpy(char *buf, int buf_size, const char *str) - } - *q = '\0'; - } -+ -+static int slirp_vsnprintf(char *str, size_t size, -+ const char *format, va_list args) -+{ -+ int rv = vsnprintf(str, size, format, args); -+ -+ if (rv < 0) { -+ g_error("vsnprintf() failed: %s", g_strerror(errno)); -+ } -+ -+ return rv; -+} -+ -+/* -+ * A snprintf()-like function that: -+ * - returns the number of bytes written (excluding optional \0-ending) -+ * - dies on error -+ * - warn on truncation -+ */ -+int slirp_fmt(char *str, size_t size, const char *format, ...) -+{ -+ va_list args; -+ int rv; -+ -+ va_start(args, format); -+ rv = slirp_vsnprintf(str, size, format, args); -+ va_end(args); -+ -+ if (rv > size) { -+ g_critical("vsnprintf() truncation"); -+ } -+ -+ return MIN(rv, size); -+} -+ -+/* -+ * A snprintf()-like function that: -+ * - always \0-end (unless size == 0) -+ * - returns the number of bytes actually written, including \0 ending -+ * - dies on error -+ * - warn on truncation -+ */ -+int slirp_fmt0(char *str, size_t size, const char *format, ...) -+{ -+ va_list args; -+ int rv; -+ -+ va_start(args, format); -+ rv = slirp_vsnprintf(str, size, format, args); -+ va_end(args); -+ -+ if (rv >= size) { -+ g_critical("vsnprintf() truncation"); -+ if (size > 0) -+ str[size - 1] = '\0'; -+ rv = size; -+ } else { -+ rv += 1; /* include \0 */ -+ } -+ -+ return rv; -+} -+ -diff --git a/slirp/src/util.h b/slirp/src/util.h -index 3c6223ce..0558dfc2 100644 ---- a/slirp/src/util.h -+++ b/slirp/src/util.h -@@ -177,4 +177,7 @@ static inline int slirp_socket_set_fast_reuse(int fd) - - void slirp_pstrcpy(char *buf, int buf_size, const char *str); - -+int slirp_fmt(char *str, size_t size, const char *format, ...); -+int slirp_fmt0(char *str, size_t size, const char *format, ...); -+ - #endif --- -2.23.0 diff --git a/util-async-hold-AioContext-ref-to-prevent-use-after-free.patch b/util-async-hold-AioContext-ref-to-prevent-use-after-free.patch deleted file mode 100644 index da4403c4ec7757c4860023b2a8e0018c3bf23b9d..0000000000000000000000000000000000000000 --- a/util-async-hold-AioContext-ref-to-prevent-use-after-free.patch +++ /dev/null @@ -1,63 +0,0 @@ -From e965bc6c633921ab238b1f5ea64055975b24e2bb Mon Sep 17 00:00:00 2001 -From: Stefan Hajnoczi -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 -Reviewed-by: Paolo Bonzini -Message-id: 20190723190623.21537-1-stefanha@redhat.com -Message-Id: <20190723190623.21537-1-stefanha@redhat.com> -Signed-off-by: Stefan Hajnoczi -(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 - diff --git a/util-cacheinfo-fix-crash-when-compiling-with-uClibc.patch b/util-cacheinfo-fix-crash-when-compiling-with-uClibc.patch deleted file mode 100644 index 797d71e73d5115ead1f4bdf6ae3ed4aabebeb572..0000000000000000000000000000000000000000 --- a/util-cacheinfo-fix-crash-when-compiling-with-uClibc.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 00b5032eaddb7193f03f0a28b10286244d2e2a7b Mon Sep 17 00:00:00 2001 -From: Carlos Santos -Date: Thu, 17 Oct 2019 09:37:13 -0300 -Subject: [PATCH] util/cacheinfo: fix crash when compiling with uClibc - -uClibc defines _SC_LEVEL1_ICACHE_LINESIZE and _SC_LEVEL1_DCACHE_LINESIZE -but the corresponding sysconf calls returns -1, which is a valid result, -meaning that the limit is indeterminate. - -Handle this situation using the fallback values instead of crashing due -to an assertion failure. - -Signed-off-by: Carlos Santos -Message-Id: <20191017123713.30192-1-casantos@redhat.com> -Signed-off-by: Richard Henderson ---- - util/cacheinfo.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/util/cacheinfo.c b/util/cacheinfo.c -index ea6f3e99bf..d94dc6adc8 100644 ---- a/util/cacheinfo.c -+++ b/util/cacheinfo.c -@@ -93,10 +93,16 @@ static void sys_cache_info(int *isize, int *dsize) - static void sys_cache_info(int *isize, int *dsize) - { - # ifdef _SC_LEVEL1_ICACHE_LINESIZE -- *isize = sysconf(_SC_LEVEL1_ICACHE_LINESIZE); -+ int tmp_isize = (int) sysconf(_SC_LEVEL1_ICACHE_LINESIZE); -+ if (tmp_isize > 0) { -+ *isize = tmp_isize; -+ } - # endif - # ifdef _SC_LEVEL1_DCACHE_LINESIZE -- *dsize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); -+ int tmp_dsize = (int) sysconf(_SC_LEVEL1_DCACHE_LINESIZE); -+ if (tmp_dsize > 0) { -+ *dsize = tmp_dsize; -+ } - # endif - } - #endif /* sys_cache_info */ --- -2.27.0 - diff --git a/util-hbitmap-strict-hbitmap_reset.patch b/util-hbitmap-strict-hbitmap_reset.patch deleted file mode 100644 index b7f568f1bc6d21ae6923a552c2536414d5d33fdd..0000000000000000000000000000000000000000 --- a/util-hbitmap-strict-hbitmap_reset.patch +++ /dev/null @@ -1,77 +0,0 @@ -From fcd7cba6acb7344aca70f5f8ec16626e817b35a5 Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Tue, 6 Aug 2019 18:26:11 +0300 -Subject: [PATCH] util/hbitmap: strict hbitmap_reset - -hbitmap_reset has an unobvious property: it rounds requested region up. -It may provoke bugs, like in recently fixed write-blocking mode of -mirror: user calls reset on unaligned region, not keeping in mind that -there are possible unrelated dirty bytes, covered by rounded-up region -and information of this unrelated "dirtiness" will be lost. - -Make hbitmap_reset strict: assert that arguments are aligned, allowing -only one exception when @start + @count == hb->orig_size. It's needed -to comfort users of hbitmap_next_dirty_area, which cares about -hb->orig_size. - -Signed-off-by: Vladimir Sementsov-Ogievskiy -Reviewed-by: Max Reitz -Message-Id: <20190806152611.280389-1-vsementsov@virtuozzo.com> -[Maintainer edit: Max's suggestions from on-list. --js] -[Maintainer edit: Eric's suggestion for aligned macro. --js] -Signed-off-by: John Snow -(cherry picked from commit 48557b138383aaf69c2617ca9a88bfb394fc50ec) -*prereq for fed33bd175f663cc8c13f8a490a4f35a19756cfe -Signed-off-by: Michael Roth ---- - include/qemu/hbitmap.h | 5 +++++ - tests/test-hbitmap.c | 2 +- - util/hbitmap.c | 4 ++++ - 3 files changed, 10 insertions(+), 1 deletion(-) - -diff --git a/include/qemu/hbitmap.h b/include/qemu/hbitmap.h -index 4afbe6292e..1bf944ca3d 100644 ---- a/include/qemu/hbitmap.h -+++ b/include/qemu/hbitmap.h -@@ -132,6 +132,11 @@ void hbitmap_set(HBitmap *hb, uint64_t start, uint64_t count); - * @count: Number of bits to reset. - * - * Reset a consecutive range of bits in an HBitmap. -+ * @start and @count must be aligned to bitmap granularity. The only exception -+ * is resetting the tail of the bitmap: @count may be equal to hb->orig_size - -+ * @start, in this case @count may be not aligned. The sum of @start + @count is -+ * allowed to be greater than hb->orig_size, but only if @start < hb->orig_size -+ * and @start + @count = ALIGN_UP(hb->orig_size, granularity). - */ - void hbitmap_reset(HBitmap *hb, uint64_t start, uint64_t count); - -diff --git a/tests/test-hbitmap.c b/tests/test-hbitmap.c -index 592d8219db..2be56d1597 100644 ---- a/tests/test-hbitmap.c -+++ b/tests/test-hbitmap.c -@@ -423,7 +423,7 @@ static void test_hbitmap_granularity(TestHBitmapData *data, - hbitmap_test_check(data, 0); - hbitmap_test_set(data, 0, 3); - g_assert_cmpint(hbitmap_count(data->hb), ==, 4); -- hbitmap_test_reset(data, 0, 1); -+ hbitmap_test_reset(data, 0, 2); - g_assert_cmpint(hbitmap_count(data->hb), ==, 2); - } - -diff --git a/util/hbitmap.c b/util/hbitmap.c -index bcc0acdc6a..71c6ba2c52 100644 ---- a/util/hbitmap.c -+++ b/util/hbitmap.c -@@ -476,6 +476,10 @@ void hbitmap_reset(HBitmap *hb, uint64_t start, uint64_t count) - /* Compute range in the last layer. */ - uint64_t first; - uint64_t last = start + count - 1; -+ uint64_t gran = 1ULL << hb->granularity; -+ -+ assert(QEMU_IS_ALIGNED(start, gran)); -+ assert(QEMU_IS_ALIGNED(count, gran) || (start + count == hb->orig_size)); - - trace_hbitmap_reset(hb, start, count, - start >> hb->granularity, last >> hb->granularity); --- -2.23.0 diff --git a/util-iov-improve-qemu_iovec_is_zero.patch b/util-iov-improve-qemu_iovec_is_zero.patch deleted file mode 100644 index 0cca67b8b1ed17eb873514c177eb6e371ae21f17..0000000000000000000000000000000000000000 --- a/util-iov-improve-qemu_iovec_is_zero.patch +++ /dev/null @@ -1,102 +0,0 @@ -From b3b76fc643912d2c86b13caff30a1151f2958702 Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Tue, 4 Jun 2019 19:15:04 +0300 -Subject: [PATCH] util/iov: improve qemu_iovec_is_zero - -We'll need to check a part of qiov soon, so implement it now. - -Optimization with align down to 4 * sizeof(long) is dropped due to: -1. It is strange: it aligns length of the buffer, but where is a - guarantee that buffer pointer is aligned itself? -2. buffer_is_zero() is a better place for optimizations and it has - them. - -Signed-off-by: Vladimir Sementsov-Ogievskiy -Acked-by: Stefan Hajnoczi -Message-id: 20190604161514.262241-3-vsementsov@virtuozzo.com -Message-Id: <20190604161514.262241-3-vsementsov@virtuozzo.com> -Signed-off-by: Stefan Hajnoczi -(cherry picked from commit f76889e7b947d896db51be8a4d9c941c2f70365a) -*prereq for 292d06b9 -Signed-off-by: Michael Roth ---- - block/io.c | 2 +- - include/qemu/iov.h | 2 +- - util/iov.c | 31 +++++++++++++++++++------------ - 3 files changed, 21 insertions(+), 14 deletions(-) - -diff --git a/block/io.c b/block/io.c -index 06305c6ea6..dccf687acc 100644 ---- a/block/io.c -+++ b/block/io.c -@@ -1715,7 +1715,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child, - - if (!ret && bs->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF && - !(flags & BDRV_REQ_ZERO_WRITE) && drv->bdrv_co_pwrite_zeroes && -- qemu_iovec_is_zero(qiov)) { -+ qemu_iovec_is_zero(qiov, 0, qiov->size)) { - flags |= BDRV_REQ_ZERO_WRITE; - if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) { - flags |= BDRV_REQ_MAY_UNMAP; -diff --git a/include/qemu/iov.h b/include/qemu/iov.h -index f3787a0cf7..29957c8a72 100644 ---- a/include/qemu/iov.h -+++ b/include/qemu/iov.h -@@ -212,7 +212,7 @@ void qemu_iovec_concat(QEMUIOVector *dst, - size_t qemu_iovec_concat_iov(QEMUIOVector *dst, - struct iovec *src_iov, unsigned int src_cnt, - size_t soffset, size_t sbytes); --bool qemu_iovec_is_zero(QEMUIOVector *qiov); -+bool qemu_iovec_is_zero(QEMUIOVector *qiov, size_t qiov_offeset, size_t bytes); - void qemu_iovec_destroy(QEMUIOVector *qiov); - void qemu_iovec_reset(QEMUIOVector *qiov); - size_t qemu_iovec_to_buf(QEMUIOVector *qiov, size_t offset, -diff --git a/util/iov.c b/util/iov.c -index 366ff9cdd1..9ac0261853 100644 ---- a/util/iov.c -+++ b/util/iov.c -@@ -451,23 +451,30 @@ void qemu_iovec_init_extended( - } - - /* -- * Check if the contents of the iovecs are all zero -+ * Check if the contents of subrange of qiov data is all zeroes. - */ --bool qemu_iovec_is_zero(QEMUIOVector *qiov) -+bool qemu_iovec_is_zero(QEMUIOVector *qiov, size_t offset, size_t bytes) - { -- int i; -- for (i = 0; i < qiov->niov; i++) { -- size_t offs = QEMU_ALIGN_DOWN(qiov->iov[i].iov_len, 4 * sizeof(long)); -- uint8_t *ptr = qiov->iov[i].iov_base; -- if (offs && !buffer_is_zero(qiov->iov[i].iov_base, offs)) { -+ struct iovec *iov; -+ size_t current_offset; -+ -+ assert(offset + bytes <= qiov->size); -+ -+ iov = iov_skip_offset(qiov->iov, offset, ¤t_offset); -+ -+ while (bytes) { -+ uint8_t *base = (uint8_t *)iov->iov_base + current_offset; -+ size_t len = MIN(iov->iov_len - current_offset, bytes); -+ -+ if (!buffer_is_zero(base, len)) { - return false; - } -- for (; offs < qiov->iov[i].iov_len; offs++) { -- if (ptr[offs]) { -- return false; -- } -- } -+ -+ current_offset = 0; -+ bytes -= len; -+ iov++; - } -+ - return true; - } - --- -2.23.0 diff --git a/util-iov-introduce-qemu_iovec_init_extended.patch b/util-iov-introduce-qemu_iovec_init_extended.patch deleted file mode 100644 index 0a488a63413b69816576ff8394f1e282c292e7d7..0000000000000000000000000000000000000000 --- a/util-iov-introduce-qemu_iovec_init_extended.patch +++ /dev/null @@ -1,177 +0,0 @@ -From cff024fe856ab36db3056ba4cb1d7cfa4c39795d Mon Sep 17 00:00:00 2001 -From: Vladimir Sementsov-Ogievskiy -Date: Tue, 4 Jun 2019 19:15:03 +0300 -Subject: [PATCH] util/iov: introduce qemu_iovec_init_extended - -Introduce new initialization API, to create requests with padding. Will -be used in the following patch. New API uses qemu_iovec_init_buf if -resulting io vector has only one element, to avoid extra allocations. -So, we need to update qemu_iovec_destroy to support destroying such -QIOVs. - -Signed-off-by: Vladimir Sementsov-Ogievskiy -Acked-by: Stefan Hajnoczi -Message-id: 20190604161514.262241-2-vsementsov@virtuozzo.com -Message-Id: <20190604161514.262241-2-vsementsov@virtuozzo.com> -Signed-off-by: Stefan Hajnoczi -(cherry picked from commit d953169d4840f312d3b9a54952f4a7ccfcb3b311) -*prereq for 292d06b9 -Signed-off-by: Michael Roth ---- - include/qemu/iov.h | 7 +++ - util/iov.c | 112 +++++++++++++++++++++++++++++++++++++++++++-- - 2 files changed, 114 insertions(+), 5 deletions(-) - -diff --git a/include/qemu/iov.h b/include/qemu/iov.h -index 48b45987b7..f3787a0cf7 100644 ---- a/include/qemu/iov.h -+++ b/include/qemu/iov.h -@@ -199,6 +199,13 @@ static inline void *qemu_iovec_buf(QEMUIOVector *qiov) - - void qemu_iovec_init(QEMUIOVector *qiov, int alloc_hint); - void qemu_iovec_init_external(QEMUIOVector *qiov, struct iovec *iov, int niov); -+void qemu_iovec_init_extended( -+ QEMUIOVector *qiov, -+ void *head_buf, size_t head_len, -+ QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len, -+ void *tail_buf, size_t tail_len); -+void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source, -+ size_t offset, size_t len); - void qemu_iovec_add(QEMUIOVector *qiov, void *base, size_t len); - void qemu_iovec_concat(QEMUIOVector *dst, - QEMUIOVector *src, size_t soffset, size_t sbytes); -diff --git a/util/iov.c b/util/iov.c -index 74e6ca8ed7..366ff9cdd1 100644 ---- a/util/iov.c -+++ b/util/iov.c -@@ -353,6 +353,103 @@ void qemu_iovec_concat(QEMUIOVector *dst, - qemu_iovec_concat_iov(dst, src->iov, src->niov, soffset, sbytes); - } - -+/* -+ * qiov_find_iov -+ * -+ * Return pointer to iovec structure, where byte at @offset in original vector -+ * @iov exactly is. -+ * Set @remaining_offset to be offset inside that iovec to the same byte. -+ */ -+static struct iovec *iov_skip_offset(struct iovec *iov, size_t offset, -+ size_t *remaining_offset) -+{ -+ while (offset > 0 && offset >= iov->iov_len) { -+ offset -= iov->iov_len; -+ iov++; -+ } -+ *remaining_offset = offset; -+ -+ return iov; -+} -+ -+/* -+ * qiov_slice -+ * -+ * Find subarray of iovec's, containing requested range. @head would -+ * be offset in first iov (returned by the function), @tail would be -+ * count of extra bytes in last iovec (returned iov + @niov - 1). -+ */ -+static struct iovec *qiov_slice(QEMUIOVector *qiov, -+ size_t offset, size_t len, -+ size_t *head, size_t *tail, int *niov) -+{ -+ struct iovec *iov, *end_iov; -+ -+ assert(offset + len <= qiov->size); -+ -+ iov = iov_skip_offset(qiov->iov, offset, head); -+ end_iov = iov_skip_offset(iov, *head + len, tail); -+ -+ if (*tail > 0) { -+ assert(*tail < end_iov->iov_len); -+ *tail = end_iov->iov_len - *tail; -+ end_iov++; -+ } -+ -+ *niov = end_iov - iov; -+ -+ return iov; -+} -+ -+/* -+ * Compile new iovec, combining @head_buf buffer, sub-qiov of @mid_qiov, -+ * and @tail_buf buffer into new qiov. -+ */ -+void qemu_iovec_init_extended( -+ QEMUIOVector *qiov, -+ void *head_buf, size_t head_len, -+ QEMUIOVector *mid_qiov, size_t mid_offset, size_t mid_len, -+ void *tail_buf, size_t tail_len) -+{ -+ size_t mid_head, mid_tail; -+ int total_niov, mid_niov = 0; -+ struct iovec *p, *mid_iov; -+ -+ if (mid_len) { -+ mid_iov = qiov_slice(mid_qiov, mid_offset, mid_len, -+ &mid_head, &mid_tail, &mid_niov); -+ } -+ -+ total_niov = !!head_len + mid_niov + !!tail_len; -+ if (total_niov == 1) { -+ qemu_iovec_init_buf(qiov, NULL, 0); -+ p = &qiov->local_iov; -+ } else { -+ qiov->niov = qiov->nalloc = total_niov; -+ qiov->size = head_len + mid_len + tail_len; -+ p = qiov->iov = g_new(struct iovec, qiov->niov); -+ } -+ -+ if (head_len) { -+ p->iov_base = head_buf; -+ p->iov_len = head_len; -+ p++; -+ } -+ -+ if (mid_len) { -+ memcpy(p, mid_iov, mid_niov * sizeof(*p)); -+ p[0].iov_base = (uint8_t *)p[0].iov_base + mid_head; -+ p[0].iov_len -= mid_head; -+ p[mid_niov - 1].iov_len -= mid_tail; -+ p += mid_niov; -+ } -+ -+ if (tail_len) { -+ p->iov_base = tail_buf; -+ p->iov_len = tail_len; -+ } -+} -+ - /* - * Check if the contents of the iovecs are all zero - */ -@@ -374,14 +471,19 @@ bool qemu_iovec_is_zero(QEMUIOVector *qiov) - return true; - } - -+void qemu_iovec_init_slice(QEMUIOVector *qiov, QEMUIOVector *source, -+ size_t offset, size_t len) -+{ -+ qemu_iovec_init_extended(qiov, NULL, 0, source, offset, len, NULL, 0); -+} -+ - void qemu_iovec_destroy(QEMUIOVector *qiov) - { -- assert(qiov->nalloc != -1); -+ if (qiov->nalloc != -1) { -+ g_free(qiov->iov); -+ } - -- qemu_iovec_reset(qiov); -- g_free(qiov->iov); -- qiov->nalloc = 0; -- qiov->iov = NULL; -+ memset(qiov, 0, sizeof(*qiov)); - } - - void qemu_iovec_reset(QEMUIOVector *qiov) --- -2.23.0 diff --git a/util-log-add-CONFIG_DISABLE_QEMU_LOG-macro.patch b/util-log-add-CONFIG_DISABLE_QEMU_LOG-macro.patch new file mode 100644 index 0000000000000000000000000000000000000000..f6940d69d12b29d8f6740cb87dec83b5eaa1356a --- /dev/null +++ b/util-log-add-CONFIG_DISABLE_QEMU_LOG-macro.patch @@ -0,0 +1,41 @@ +From 05462305ec8b9ce5b414ede1e7e680b16d1a08ad Mon Sep 17 00:00:00 2001 +From: Yan Wang +Date: Fri, 11 Feb 2022 18:20:59 +0800 +Subject: [PATCH] util/log: add CONFIG_DISABLE_QEMU_LOG macro + +Using CONFIG_DISABLE_QEMU_LOG macro to control +qemu_log function. + +Signed-off-by: Yan Wang +--- + util/log.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/util/log.c b/util/log.c +index 2ee1500bee..ed3029fe5c 100644 +--- a/util/log.c ++++ b/util/log.c +@@ -34,6 +34,12 @@ int qemu_loglevel; + static int log_append = 0; + static GArray *debug_regions; + ++#ifdef CONFIG_DISABLE_QEMU_LOG ++int qemu_log(const char *fmt, ...) ++{ ++ return 0; ++} ++#else + /* Return the number of characters emitted. */ + int qemu_log(const char *fmt, ...) + { +@@ -56,6 +62,7 @@ int qemu_log(const char *fmt, ...) + rcu_read_unlock(); + return ret; + } ++#endif + + static void __attribute__((__constructor__)) qemu_logfile_init(void) + { +-- +2.27.0 + diff --git a/vfio-Add-VM-state-change-handler-to-know-state-of-VM.patch b/vfio-Add-VM-state-change-handler-to-know-state-of-VM.patch deleted file mode 100644 index eb8fb5d8f84b88bed1e48516050af5546dfae1cb..0000000000000000000000000000000000000000 --- a/vfio-Add-VM-state-change-handler-to-know-state-of-VM.patch +++ /dev/null @@ -1,258 +0,0 @@ -From 3a875293ae00266e1c82a5c382066efc4acc64ce Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:15 +0530 -Subject: [PATCH] vfio: Add VM state change handler to know state of VM - -VM state change handler is called on change in VM's state. Based on -VM state, VFIO device state should be changed. -Added read/write helper functions for migration region. -Added function to set device_state. - -Signed-off-by: Kirti Wankhede -Reviewed-by: Neo Jia -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: Cornelia Huck -[aw: lx -> HWADDR_PRIx, remove redundant parens] -Signed-off-by: Alex Williamson -Signed-off-by: Shenming Lu ---- - hw/vfio/migration.c | 160 ++++++++++++++++++++++++++++++++++ - hw/vfio/trace-events | 2 + - include/hw/vfio/vfio-common.h | 4 + - 3 files changed, 166 insertions(+) - -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -index fd7faf423c..ca82c78536 100644 ---- a/hw/vfio/migration.c -+++ b/hw/vfio/migration.c -@@ -10,6 +10,7 @@ - #include "qemu/osdep.h" - #include - -+#include "sysemu/sysemu.h" - #include "hw/vfio/vfio-common.h" - #include "cpu.h" - #include "migration/migration.h" -@@ -22,6 +23,157 @@ - #include "exec/ram_addr.h" - #include "pci.h" - #include "trace.h" -+#include "hw/hw.h" -+ -+static inline int vfio_mig_access(VFIODevice *vbasedev, void *val, int count, -+ off_t off, bool iswrite) -+{ -+ int ret; -+ -+ ret = iswrite ? pwrite(vbasedev->fd, val, count, off) : -+ pread(vbasedev->fd, val, count, off); -+ if (ret < count) { -+ error_report("vfio_mig_%s %d byte %s: failed at offset 0x%" -+ HWADDR_PRIx", err: %s", iswrite ? "write" : "read", count, -+ vbasedev->name, off, strerror(errno)); -+ return (ret < 0) ? ret : -EINVAL; -+ } -+ return 0; -+} -+ -+static int vfio_mig_rw(VFIODevice *vbasedev, __u8 *buf, size_t count, -+ off_t off, bool iswrite) -+{ -+ int ret, done = 0; -+ __u8 *tbuf = buf; -+ -+ while (count) { -+ int bytes = 0; -+ -+ if (count >= 8 && !(off % 8)) { -+ bytes = 8; -+ } else if (count >= 4 && !(off % 4)) { -+ bytes = 4; -+ } else if (count >= 2 && !(off % 2)) { -+ bytes = 2; -+ } else { -+ bytes = 1; -+ } -+ -+ ret = vfio_mig_access(vbasedev, tbuf, bytes, off, iswrite); -+ if (ret) { -+ return ret; -+ } -+ -+ count -= bytes; -+ done += bytes; -+ off += bytes; -+ tbuf += bytes; -+ } -+ return done; -+} -+ -+#define vfio_mig_read(f, v, c, o) vfio_mig_rw(f, (__u8 *)v, c, o, false) -+#define vfio_mig_write(f, v, c, o) vfio_mig_rw(f, (__u8 *)v, c, o, true) -+ -+#define VFIO_MIG_STRUCT_OFFSET(f) \ -+ offsetof(struct vfio_device_migration_info, f) -+/* -+ * Change the device_state register for device @vbasedev. Bits set in @mask -+ * are preserved, bits set in @value are set, and bits not set in either @mask -+ * or @value are cleared in device_state. If the register cannot be accessed, -+ * the resulting state would be invalid, or the device enters an error state, -+ * an error is returned. -+ */ -+ -+static int vfio_migration_set_state(VFIODevice *vbasedev, uint32_t mask, -+ uint32_t value) -+{ -+ VFIOMigration *migration = vbasedev->migration; -+ VFIORegion *region = &migration->region; -+ off_t dev_state_off = region->fd_offset + -+ VFIO_MIG_STRUCT_OFFSET(device_state); -+ uint32_t device_state; -+ int ret; -+ -+ ret = vfio_mig_read(vbasedev, &device_state, sizeof(device_state), -+ dev_state_off); -+ if (ret < 0) { -+ return ret; -+ } -+ -+ device_state = (device_state & mask) | value; -+ -+ if (!VFIO_DEVICE_STATE_VALID(device_state)) { -+ return -EINVAL; -+ } -+ -+ ret = vfio_mig_write(vbasedev, &device_state, sizeof(device_state), -+ dev_state_off); -+ if (ret < 0) { -+ int rret; -+ -+ rret = vfio_mig_read(vbasedev, &device_state, sizeof(device_state), -+ dev_state_off); -+ -+ if ((rret < 0) || (VFIO_DEVICE_STATE_IS_ERROR(device_state))) { -+ hw_error("%s: Device in error state 0x%x", vbasedev->name, -+ device_state); -+ return rret ? rret : -EIO; -+ } -+ return ret; -+ } -+ -+ migration->device_state = device_state; -+ trace_vfio_migration_set_state(vbasedev->name, device_state); -+ return 0; -+} -+ -+static void vfio_vmstate_change(void *opaque, int running, RunState state) -+{ -+ VFIODevice *vbasedev = opaque; -+ VFIOMigration *migration = vbasedev->migration; -+ uint32_t value, mask; -+ int ret; -+ -+ if (vbasedev->migration->vm_running == running) { -+ return; -+ } -+ -+ if (running) { -+ /* -+ * Here device state can have one of _SAVING, _RESUMING or _STOP bit. -+ * Transition from _SAVING to _RUNNING can happen if there is migration -+ * failure, in that case clear _SAVING bit. -+ * Transition from _RESUMING to _RUNNING occurs during resuming -+ * phase, in that case clear _RESUMING bit. -+ * In both the above cases, set _RUNNING bit. -+ */ -+ mask = ~VFIO_DEVICE_STATE_MASK; -+ value = VFIO_DEVICE_STATE_RUNNING; -+ } else { -+ /* -+ * Here device state could be either _RUNNING or _SAVING|_RUNNING. Reset -+ * _RUNNING bit -+ */ -+ mask = ~VFIO_DEVICE_STATE_RUNNING; -+ value = 0; -+ } -+ -+ ret = vfio_migration_set_state(vbasedev, mask, value); -+ if (ret) { -+ /* -+ * Migration should be aborted in this case, but vm_state_notify() -+ * currently does not support reporting failures. -+ */ -+ error_report("%s: Failed to set device state 0x%x", vbasedev->name, -+ (migration->device_state & mask) | value); -+ qemu_file_set_error(migrate_get_current()->to_dst_file, ret); -+ } -+ vbasedev->migration->vm_running = running; -+ trace_vfio_vmstate_change(vbasedev->name, running, RunState_str(state), -+ (migration->device_state & mask) | value); -+} - - static void vfio_migration_exit(VFIODevice *vbasedev) - { -@@ -38,6 +190,7 @@ static int vfio_migration_init(VFIODevice *vbasedev, - { - int ret; - Object *obj; -+ VFIOMigration *migration; - - if (!vbasedev->ops->vfio_get_object) { - return -EINVAL; -@@ -64,6 +217,10 @@ static int vfio_migration_init(VFIODevice *vbasedev, - ret = -EINVAL; - goto err; - } -+ -+ migration = vbasedev->migration; -+ migration->vm_state = qemu_add_vm_change_state_handler(vfio_vmstate_change, -+ vbasedev); - return 0; - - err: -@@ -111,6 +268,9 @@ add_blocker: - void vfio_migration_finalize(VFIODevice *vbasedev) - { - if (vbasedev->migration) { -+ VFIOMigration *migration = vbasedev->migration; -+ -+ qemu_del_vm_change_state_handler(migration->vm_state); - vfio_migration_exit(vbasedev); - } - -diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events -index fd034ac536..1626862315 100644 ---- a/hw/vfio/trace-events -+++ b/hw/vfio/trace-events -@@ -146,3 +146,5 @@ vfio_display_edid_write_error(void) "" - - # migration.c - vfio_migration_probe(const char *name, uint32_t index) " (%s) Region %d" -+vfio_migration_set_state(const char *name, uint32_t state) " (%s) state %d" -+vfio_vmstate_change(const char *name, int running, const char *reason, uint32_t dev_state) " (%s) running %d reason %s device state %d" -diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index e0482c2bac..533d6737ac 100644 ---- a/include/hw/vfio/vfio-common.h -+++ b/include/hw/vfio/vfio-common.h -@@ -29,6 +29,7 @@ - #ifdef CONFIG_LINUX - #include - #endif -+#include "sysemu/sysemu.h" - - #define VFIO_MSG_PREFIX "vfio %s: " - -@@ -58,7 +59,10 @@ typedef struct VFIORegion { - } VFIORegion; - - typedef struct VFIOMigration { -+ VMChangeStateEntry *vm_state; - VFIORegion region; -+ uint32_t device_state; -+ int vm_running; - } VFIOMigration; - - typedef struct VFIOAddressSpace { --- -2.27.0 - diff --git a/vfio-Add-function-to-start-and-stop-dirty-pages-trac.patch b/vfio-Add-function-to-start-and-stop-dirty-pages-trac.patch deleted file mode 100644 index b15a1c4bfbeb108bc5a098df8d68aef288b5e9c2..0000000000000000000000000000000000000000 --- a/vfio-Add-function-to-start-and-stop-dirty-pages-trac.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 4363ea5cded9c6d2838a9564b067f583a6ef077f Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:22 +0530 -Subject: [PATCH] vfio: Add function to start and stop dirty pages tracking - -Call VFIO_IOMMU_DIRTY_PAGES ioctl to start and stop dirty pages tracking -for VFIO devices. - -Signed-off-by: Kirti Wankhede -Reviewed-by: Dr. David Alan Gilbert -Signed-off-by: Alex Williamson ---- - hw/vfio/migration.c | 36 ++++++++++++++++++++++++++++++++++++ - 1 file changed, 36 insertions(+) - -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -index 0d2bd9e5cd..0bdf6a1820 100644 ---- a/hw/vfio/migration.c -+++ b/hw/vfio/migration.c -@@ -11,6 +11,7 @@ - #include "qemu/main-loop.h" - #include "qemu/cutils.h" - #include -+#include - - #include "sysemu/sysemu.h" - #include "hw/vfio/vfio-common.h" -@@ -391,10 +392,40 @@ static int vfio_load_device_config_state(QEMUFile *f, void *opaque) - return qemu_file_get_error(f); - } - -+static int vfio_set_dirty_page_tracking(VFIODevice *vbasedev, bool start) -+{ -+ int ret; -+ VFIOMigration *migration = vbasedev->migration; -+ VFIOContainer *container = vbasedev->group->container; -+ struct vfio_iommu_type1_dirty_bitmap dirty = { -+ .argsz = sizeof(dirty), -+ }; -+ -+ if (start) { -+ if (migration->device_state & VFIO_DEVICE_STATE_SAVING) { -+ dirty.flags = VFIO_IOMMU_DIRTY_PAGES_FLAG_START; -+ } else { -+ return -EINVAL; -+ } -+ } else { -+ dirty.flags = VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP; -+ } -+ -+ ret = ioctl(container->fd, VFIO_IOMMU_DIRTY_PAGES, &dirty); -+ if (ret) { -+ error_report("Failed to set dirty tracking flag 0x%x errno: %d", -+ dirty.flags, errno); -+ return -errno; -+ } -+ return ret; -+} -+ - static void vfio_migration_cleanup(VFIODevice *vbasedev) - { - VFIOMigration *migration = vbasedev->migration; - -+ vfio_set_dirty_page_tracking(vbasedev, false); -+ - if (migration->region.mmaps) { - vfio_region_unmap(&migration->region); - } -@@ -435,6 +466,11 @@ static int vfio_save_setup(QEMUFile *f, void *opaque) - return ret; - } - -+ ret = vfio_set_dirty_page_tracking(vbasedev, true); -+ if (ret) { -+ return ret; -+ } -+ - qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); - - ret = qemu_file_get_error(f); --- -2.27.0 - diff --git a/vfio-Add-function-to-unmap-VFIO-region.patch b/vfio-Add-function-to-unmap-VFIO-region.patch deleted file mode 100644 index 2cdd76a09bd44c73b42f4294055b935a31446b7e..0000000000000000000000000000000000000000 --- a/vfio-Add-function-to-unmap-VFIO-region.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 68cc2be61588d14de2313342ee87eb0bb2b990e0 Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:11 +0530 -Subject: [PATCH] vfio: Add function to unmap VFIO region - -This function will be used for migration region. -Migration region is mmaped when migration starts and will be unmapped when -migration is complete. - -Signed-off-by: Kirti Wankhede -Reviewed-by: Neo Jia -Reviewed-by: Cornelia Huck -Signed-off-by: Alex Williamson ---- - hw/vfio/common.c | 32 ++++++++++++++++++++++++++++---- - hw/vfio/trace-events | 1 + - include/hw/vfio/vfio-common.h | 1 + - 3 files changed, 30 insertions(+), 4 deletions(-) - -diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index a859298fda..4c32b1bb99 100644 ---- a/hw/vfio/common.c -+++ b/hw/vfio/common.c -@@ -906,6 +906,18 @@ int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region, - return 0; - } - -+static void vfio_subregion_unmap(VFIORegion *region, int index) -+{ -+ trace_vfio_region_unmap(memory_region_name(®ion->mmaps[index].mem), -+ region->mmaps[index].offset, -+ region->mmaps[index].offset + -+ region->mmaps[index].size - 1); -+ memory_region_del_subregion(region->mem, ®ion->mmaps[index].mem); -+ munmap(region->mmaps[index].mmap, region->mmaps[index].size); -+ object_unparent(OBJECT(®ion->mmaps[index].mem)); -+ region->mmaps[index].mmap = NULL; -+} -+ - int vfio_region_mmap(VFIORegion *region) - { - int i, prot = 0; -@@ -936,10 +948,7 @@ int vfio_region_mmap(VFIORegion *region) - region->mmaps[i].mmap = NULL; - - for (i--; i >= 0; i--) { -- memory_region_del_subregion(region->mem, ®ion->mmaps[i].mem); -- munmap(region->mmaps[i].mmap, region->mmaps[i].size); -- object_unparent(OBJECT(®ion->mmaps[i].mem)); -- region->mmaps[i].mmap = NULL; -+ vfio_subregion_unmap(region, i); - } - - return ret; -@@ -964,6 +973,21 @@ int vfio_region_mmap(VFIORegion *region) - return 0; - } - -+void vfio_region_unmap(VFIORegion *region) -+{ -+ int i; -+ -+ if (!region->mem) { -+ return; -+ } -+ -+ for (i = 0; i < region->nr_mmaps; i++) { -+ if (region->mmaps[i].mmap) { -+ vfio_subregion_unmap(region, i); -+ } -+ } -+} -+ - void vfio_region_exit(VFIORegion *region) - { - int i; -diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events -index b1ef55a33f..8cdc27946c 100644 ---- a/hw/vfio/trace-events -+++ b/hw/vfio/trace-events -@@ -111,6 +111,7 @@ vfio_region_mmap(const char *name, unsigned long offset, unsigned long end) "Reg - vfio_region_exit(const char *name, int index) "Device %s, region %d" - vfio_region_finalize(const char *name, int index) "Device %s, region %d" - vfio_region_mmaps_set_enabled(const char *name, bool enabled) "Region %s mmaps enabled: %d" -+vfio_region_unmap(const char *name, unsigned long offset, unsigned long end) "Region %s unmap [0x%lx - 0x%lx]" - vfio_region_sparse_mmap_header(const char *name, int index, int nr_areas) "Device %s region %d: %d sparse mmap entries" - vfio_region_sparse_mmap_entry(int i, unsigned long start, unsigned long end) "sparse entry %d [0x%lx - 0x%lx]" - vfio_get_dev_region(const char *name, int index, uint32_t type, uint32_t subtype) "%s index %d, %08x/%0x8" -diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index 9107bd41c0..93493891ba 100644 ---- a/include/hw/vfio/vfio-common.h -+++ b/include/hw/vfio/vfio-common.h -@@ -171,6 +171,7 @@ int vfio_region_setup(Object *obj, VFIODevice *vbasedev, VFIORegion *region, - int index, const char *name); - int vfio_region_mmap(VFIORegion *region); - void vfio_region_mmaps_set_enabled(VFIORegion *region, bool enabled); -+void vfio_region_unmap(VFIORegion *region); - void vfio_region_exit(VFIORegion *region); - void vfio_region_finalize(VFIORegion *region); - void vfio_reset_handler(void *opaque); --- -2.27.0 - diff --git a/vfio-Add-ioctl-to-get-dirty-pages-bitmap-during-dma-.patch b/vfio-Add-ioctl-to-get-dirty-pages-bitmap-during-dma-.patch deleted file mode 100644 index 2831e94ca260e5753f2bcd0007ab036cba387b33..0000000000000000000000000000000000000000 --- a/vfio-Add-ioctl-to-get-dirty-pages-bitmap-during-dma-.patch +++ /dev/null @@ -1,162 +0,0 @@ -From 1333031bd3b488ed4904a61fd292cd5aa93f8c5b Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:25 +0530 -Subject: [PATCH] vfio: Add ioctl to get dirty pages bitmap during dma unmap - -With vIOMMU, IO virtual address range can get unmapped while in pre-copy -phase of migration. In that case, unmap ioctl should return pages pinned -in that range and QEMU should find its correcponding guest physical -addresses and report those dirty. - -Suggested-by: Alex Williamson -Signed-off-by: Kirti Wankhede -Reviewed-by: Neo Jia -[aw: fix error_report types, fix cpu_physical_memory_set_dirty_lebitmap() cast] -Signed-off-by: Alex Williamson ---- - hw/vfio/common.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 93 insertions(+), 4 deletions(-) - -diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index 8773b998ac..4ce1c10734 100644 ---- a/hw/vfio/common.c -+++ b/hw/vfio/common.c -@@ -320,11 +320,95 @@ static bool vfio_devices_all_stopped_and_saving(VFIOContainer *container) - return true; - } - -+static bool vfio_devices_all_running_and_saving(VFIOContainer *container) -+{ -+ VFIOGroup *group; -+ VFIODevice *vbasedev; -+ MigrationState *ms = migrate_get_current(); -+ -+ if (!migration_is_setup_or_active(ms->state)) { -+ return false; -+ } -+ -+ QLIST_FOREACH(group, &container->group_list, container_next) { -+ QLIST_FOREACH(vbasedev, &group->device_list, next) { -+ VFIOMigration *migration = vbasedev->migration; -+ -+ if (!migration) { -+ return false; -+ } -+ -+ if ((migration->device_state & VFIO_DEVICE_STATE_SAVING) && -+ (migration->device_state & VFIO_DEVICE_STATE_RUNNING)) { -+ continue; -+ } else { -+ return false; -+ } -+ } -+ } -+ return true; -+} -+ -+static int vfio_dma_unmap_bitmap(VFIOContainer *container, -+ hwaddr iova, ram_addr_t size, -+ IOMMUTLBEntry *iotlb) -+{ -+ struct vfio_iommu_type1_dma_unmap *unmap; -+ struct vfio_bitmap *bitmap; -+ uint64_t pages = TARGET_PAGE_ALIGN(size) >> TARGET_PAGE_BITS; -+ int ret; -+ -+ unmap = g_malloc0(sizeof(*unmap) + sizeof(*bitmap)); -+ -+ unmap->argsz = sizeof(*unmap) + sizeof(*bitmap); -+ unmap->iova = iova; -+ unmap->size = size; -+ unmap->flags |= VFIO_DMA_UNMAP_FLAG_GET_DIRTY_BITMAP; -+ bitmap = (struct vfio_bitmap *)&unmap->data; -+ -+ /* -+ * cpu_physical_memory_set_dirty_lebitmap() expects pages in bitmap of -+ * TARGET_PAGE_SIZE to mark those dirty. Hence set bitmap_pgsize to -+ * TARGET_PAGE_SIZE. -+ */ -+ -+ bitmap->pgsize = TARGET_PAGE_SIZE; -+ bitmap->size = ROUND_UP(pages, sizeof(__u64) * BITS_PER_BYTE) / -+ BITS_PER_BYTE; -+ -+ if (bitmap->size > container->max_dirty_bitmap_size) { -+ error_report("UNMAP: Size of bitmap too big 0x%"PRIx64, -+ (uint64_t)bitmap->size); -+ ret = -E2BIG; -+ goto unmap_exit; -+ } -+ -+ bitmap->data = g_try_malloc0(bitmap->size); -+ if (!bitmap->data) { -+ ret = -ENOMEM; -+ goto unmap_exit; -+ } -+ -+ ret = ioctl(container->fd, VFIO_IOMMU_UNMAP_DMA, unmap); -+ if (!ret) { -+ cpu_physical_memory_set_dirty_lebitmap((unsigned long *)bitmap->data, -+ iotlb->translated_addr, pages); -+ } else { -+ error_report("VFIO_UNMAP_DMA with DIRTY_BITMAP : %m"); -+ } -+ -+ g_free(bitmap->data); -+unmap_exit: -+ g_free(unmap); -+ return ret; -+} -+ - /* - * DMA - Mapping and unmapping for the "type1" IOMMU interface used on x86 - */ - static int vfio_dma_unmap(VFIOContainer *container, -- hwaddr iova, ram_addr_t size) -+ hwaddr iova, ram_addr_t size, -+ IOMMUTLBEntry *iotlb) - { - struct vfio_iommu_type1_dma_unmap unmap = { - .argsz = sizeof(unmap), -@@ -333,6 +417,11 @@ static int vfio_dma_unmap(VFIOContainer *container, - .size = size, - }; - -+ if (iotlb && container->dirty_pages_supported && -+ vfio_devices_all_running_and_saving(container)) { -+ return vfio_dma_unmap_bitmap(container, iova, size, iotlb); -+ } -+ - while (ioctl(container->fd, VFIO_IOMMU_UNMAP_DMA, &unmap)) { - /* - * The type1 backend has an off-by-one bug in the kernel (71a7d3d78e3c -@@ -380,7 +469,7 @@ static int vfio_dma_map(VFIOContainer *container, hwaddr iova, - * the VGA ROM space. - */ - if (ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map) == 0 || -- (errno == EBUSY && vfio_dma_unmap(container, iova, size) == 0 && -+ (errno == EBUSY && vfio_dma_unmap(container, iova, size, NULL) == 0 && - ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map) == 0)) { - return 0; - } -@@ -530,7 +619,7 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) - iotlb->addr_mask + 1, vaddr, ret); - } - } else { -- ret = vfio_dma_unmap(container, iova, iotlb->addr_mask + 1); -+ ret = vfio_dma_unmap(container, iova, iotlb->addr_mask + 1, iotlb); - if (ret) { - error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", " - "0x%"HWADDR_PRIx") = %d (%m)", -@@ -816,7 +905,7 @@ static void vfio_listener_region_del(MemoryListener *listener, - } - - if (try_unmap) { -- ret = vfio_dma_unmap(container, iova, int128_get64(llsize)); -+ ret = vfio_dma_unmap(container, iova, int128_get64(llsize), NULL); - if (ret) { - error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", " - "0x%"HWADDR_PRIx") = %d (%m)", --- -2.27.0 - diff --git a/vfio-Add-load-state-functions-to-SaveVMHandlers.patch b/vfio-Add-load-state-functions-to-SaveVMHandlers.patch deleted file mode 100644 index d70caeeef043b6c6cb53f09c9adb67b40b344862..0000000000000000000000000000000000000000 --- a/vfio-Add-load-state-functions-to-SaveVMHandlers.patch +++ /dev/null @@ -1,266 +0,0 @@ -From ddef5d5257987f2f415ce41fdc482feda61aa796 Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:19 +0530 -Subject: [PATCH] vfio: Add load state functions to SaveVMHandlers - -Sequence during _RESUMING device state: -While data for this device is available, repeat below steps: -a. read data_offset from where user application should write data. -b. write data of data_size to migration region from data_offset. -c. write data_size which indicates vendor driver that data is written in - staging buffer. - -For user, data is opaque. User should write data in the same order as -received. - -Signed-off-by: Kirti Wankhede -Reviewed-by: Neo Jia -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: Yan Zhao -Signed-off-by: Alex Williamson ---- - hw/vfio/migration.c | 195 +++++++++++++++++++++++++++++++++++++++++++ - hw/vfio/trace-events | 4 + - 2 files changed, 199 insertions(+) - -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -index f78a77e1e3..954c064435 100644 ---- a/hw/vfio/migration.c -+++ b/hw/vfio/migration.c -@@ -257,6 +257,77 @@ static int vfio_save_buffer(QEMUFile *f, VFIODevice *vbasedev, uint64_t *size) - return ret; - } - -+static int vfio_load_buffer(QEMUFile *f, VFIODevice *vbasedev, -+ uint64_t data_size) -+{ -+ VFIORegion *region = &vbasedev->migration->region; -+ uint64_t data_offset = 0, size, report_size; -+ int ret; -+ -+ do { -+ ret = vfio_mig_read(vbasedev, &data_offset, sizeof(data_offset), -+ region->fd_offset + VFIO_MIG_STRUCT_OFFSET(data_offset)); -+ if (ret < 0) { -+ return ret; -+ } -+ -+ if (data_offset + data_size > region->size) { -+ /* -+ * If data_size is greater than the data section of migration region -+ * then iterate the write buffer operation. This case can occur if -+ * size of migration region at destination is smaller than size of -+ * migration region at source. -+ */ -+ report_size = size = region->size - data_offset; -+ data_size -= size; -+ } else { -+ report_size = size = data_size; -+ data_size = 0; -+ } -+ -+ trace_vfio_load_state_device_data(vbasedev->name, data_offset, size); -+ -+ while (size) { -+ void *buf; -+ uint64_t sec_size; -+ bool buf_alloc = false; -+ -+ buf = get_data_section_size(region, data_offset, size, &sec_size); -+ -+ if (!buf) { -+ buf = g_try_malloc(sec_size); -+ if (!buf) { -+ error_report("%s: Error allocating buffer ", __func__); -+ return -ENOMEM; -+ } -+ buf_alloc = true; -+ } -+ -+ qemu_get_buffer(f, buf, sec_size); -+ -+ if (buf_alloc) { -+ ret = vfio_mig_write(vbasedev, buf, sec_size, -+ region->fd_offset + data_offset); -+ g_free(buf); -+ -+ if (ret < 0) { -+ return ret; -+ } -+ } -+ size -= sec_size; -+ data_offset += sec_size; -+ } -+ -+ ret = vfio_mig_write(vbasedev, &report_size, sizeof(report_size), -+ region->fd_offset + VFIO_MIG_STRUCT_OFFSET(data_size)); -+ if (ret < 0) { -+ return ret; -+ } -+ } while (data_size); -+ -+ return 0; -+} -+ - static int vfio_update_pending(VFIODevice *vbasedev) - { - VFIOMigration *migration = vbasedev->migration; -@@ -293,6 +364,33 @@ static int vfio_save_device_config_state(QEMUFile *f, void *opaque) - return qemu_file_get_error(f); - } - -+static int vfio_load_device_config_state(QEMUFile *f, void *opaque) -+{ -+ VFIODevice *vbasedev = opaque; -+ uint64_t data; -+ -+ if (vbasedev->ops && vbasedev->ops->vfio_load_config) { -+ int ret; -+ -+ ret = vbasedev->ops->vfio_load_config(vbasedev, f); -+ if (ret) { -+ error_report("%s: Failed to load device config space", -+ vbasedev->name); -+ return ret; -+ } -+ } -+ -+ data = qemu_get_be64(f); -+ if (data != VFIO_MIG_FLAG_END_OF_STATE) { -+ error_report("%s: Failed loading device config space, " -+ "end flag incorrect 0x%"PRIx64, vbasedev->name, data); -+ return -EINVAL; -+ } -+ -+ trace_vfio_load_device_config_state(vbasedev->name); -+ return qemu_file_get_error(f); -+} -+ - static void vfio_migration_cleanup(VFIODevice *vbasedev) - { - VFIOMigration *migration = vbasedev->migration; -@@ -483,12 +581,109 @@ static int vfio_save_complete_precopy(QEMUFile *f, void *opaque) - return ret; - } - -+static int vfio_load_setup(QEMUFile *f, void *opaque) -+{ -+ VFIODevice *vbasedev = opaque; -+ VFIOMigration *migration = vbasedev->migration; -+ int ret = 0; -+ -+ if (migration->region.mmaps) { -+ ret = vfio_region_mmap(&migration->region); -+ if (ret) { -+ error_report("%s: Failed to mmap VFIO migration region %d: %s", -+ vbasedev->name, migration->region.nr, -+ strerror(-ret)); -+ error_report("%s: Falling back to slow path", vbasedev->name); -+ } -+ } -+ -+ ret = vfio_migration_set_state(vbasedev, ~VFIO_DEVICE_STATE_MASK, -+ VFIO_DEVICE_STATE_RESUMING); -+ if (ret) { -+ error_report("%s: Failed to set state RESUMING", vbasedev->name); -+ if (migration->region.mmaps) { -+ vfio_region_unmap(&migration->region); -+ } -+ } -+ return ret; -+} -+ -+static int vfio_load_cleanup(void *opaque) -+{ -+ VFIODevice *vbasedev = opaque; -+ -+ vfio_migration_cleanup(vbasedev); -+ trace_vfio_load_cleanup(vbasedev->name); -+ return 0; -+} -+ -+static int vfio_load_state(QEMUFile *f, void *opaque, int version_id) -+{ -+ VFIODevice *vbasedev = opaque; -+ int ret = 0; -+ uint64_t data; -+ -+ data = qemu_get_be64(f); -+ while (data != VFIO_MIG_FLAG_END_OF_STATE) { -+ -+ trace_vfio_load_state(vbasedev->name, data); -+ -+ switch (data) { -+ case VFIO_MIG_FLAG_DEV_CONFIG_STATE: -+ { -+ ret = vfio_load_device_config_state(f, opaque); -+ if (ret) { -+ return ret; -+ } -+ break; -+ } -+ case VFIO_MIG_FLAG_DEV_SETUP_STATE: -+ { -+ data = qemu_get_be64(f); -+ if (data == VFIO_MIG_FLAG_END_OF_STATE) { -+ return ret; -+ } else { -+ error_report("%s: SETUP STATE: EOS not found 0x%"PRIx64, -+ vbasedev->name, data); -+ return -EINVAL; -+ } -+ break; -+ } -+ case VFIO_MIG_FLAG_DEV_DATA_STATE: -+ { -+ uint64_t data_size = qemu_get_be64(f); -+ -+ if (data_size) { -+ ret = vfio_load_buffer(f, vbasedev, data_size); -+ if (ret < 0) { -+ return ret; -+ } -+ } -+ break; -+ } -+ default: -+ error_report("%s: Unknown tag 0x%"PRIx64, vbasedev->name, data); -+ return -EINVAL; -+ } -+ -+ data = qemu_get_be64(f); -+ ret = qemu_file_get_error(f); -+ if (ret) { -+ return ret; -+ } -+ } -+ return ret; -+} -+ - static SaveVMHandlers savevm_vfio_handlers = { - .save_setup = vfio_save_setup, - .save_cleanup = vfio_save_cleanup, - .save_live_pending = vfio_save_pending, - .save_live_iterate = vfio_save_iterate, - .save_live_complete_precopy = vfio_save_complete_precopy, -+ .load_setup = vfio_load_setup, -+ .load_cleanup = vfio_load_cleanup, -+ .load_state = vfio_load_state, - }; - - /* ---------------------------------------------------------------------- */ -diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events -index 9a1c5e17d9..4f08f5a633 100644 ---- a/hw/vfio/trace-events -+++ b/hw/vfio/trace-events -@@ -157,3 +157,7 @@ vfio_save_device_config_state(const char *name) " (%s)" - vfio_save_pending(const char *name, uint64_t precopy, uint64_t postcopy, uint64_t compatible) " (%s) precopy 0x%"PRIx64" postcopy 0x%"PRIx64" compatible 0x%"PRIx64 - vfio_save_iterate(const char *name, int data_size) " (%s) data_size %d" - vfio_save_complete_precopy(const char *name) " (%s)" -+vfio_load_device_config_state(const char *name) " (%s)" -+vfio_load_state(const char *name, uint64_t data) " (%s) data 0x%"PRIx64 -+vfio_load_state_device_data(const char *name, uint64_t data_offset, uint64_t data_size) " (%s) Offset 0x%"PRIx64" size 0x%"PRIx64 -+vfio_load_cleanup(const char *name) " (%s)" --- -2.27.0 - diff --git a/vfio-Add-migration-region-initialization-and-finaliz.patch b/vfio-Add-migration-region-initialization-and-finaliz.patch deleted file mode 100644 index c804f1f6c353143ca74fe05889d5e163ab9dc8c3..0000000000000000000000000000000000000000 --- a/vfio-Add-migration-region-initialization-and-finaliz.patch +++ /dev/null @@ -1,209 +0,0 @@ -From b7128f8aa03482634c07691cef69e7ed2d35200e Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:14 +0530 -Subject: [PATCH] vfio: Add migration region initialization and finalize - function - -Whether the VFIO device supports migration or not is decided based of -migration region query. If migration region query is successful and migration -region initialization is successful then migration is supported else -migration is blocked. - -Signed-off-by: Kirti Wankhede -Reviewed-by: Neo Jia -Acked-by: Dr. David Alan Gilbert -Reviewed-by: Cornelia Huck -Signed-off-by: Alex Williamson -Signed-off-by: Shenming Lu ---- - hw/vfio/Makefile.objs | 2 +- - hw/vfio/migration.c | 122 ++++++++++++++++++++++++++++++++++ - hw/vfio/trace-events | 3 + - include/hw/vfio/vfio-common.h | 9 +++ - 4 files changed, 135 insertions(+), 1 deletion(-) - create mode 100644 hw/vfio/migration.c - -diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs -index abad8b818c..36033d1437 100644 ---- a/hw/vfio/Makefile.objs -+++ b/hw/vfio/Makefile.objs -@@ -1,4 +1,4 @@ --obj-y += common.o spapr.o -+obj-y += common.o spapr.o migration.o - obj-$(CONFIG_VFIO_PCI) += pci.o pci-quirks.o display.o - obj-$(CONFIG_VFIO_CCW) += ccw.o - obj-$(CONFIG_VFIO_PLATFORM) += platform.o -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -new file mode 100644 -index 0000000000..fd7faf423c ---- /dev/null -+++ b/hw/vfio/migration.c -@@ -0,0 +1,122 @@ -+/* -+ * Migration support for VFIO devices -+ * -+ * Copyright NVIDIA, Inc. 2020 -+ * -+ * This work is licensed under the terms of the GNU GPL, version 2. See -+ * the COPYING file in the top-level directory. -+ */ -+ -+#include "qemu/osdep.h" -+#include -+ -+#include "hw/vfio/vfio-common.h" -+#include "cpu.h" -+#include "migration/migration.h" -+#include "migration/qemu-file.h" -+#include "migration/register.h" -+#include "migration/blocker.h" -+#include "migration/misc.h" -+#include "qapi/error.h" -+#include "exec/ramlist.h" -+#include "exec/ram_addr.h" -+#include "pci.h" -+#include "trace.h" -+ -+static void vfio_migration_exit(VFIODevice *vbasedev) -+{ -+ VFIOMigration *migration = vbasedev->migration; -+ -+ vfio_region_exit(&migration->region); -+ vfio_region_finalize(&migration->region); -+ g_free(vbasedev->migration); -+ vbasedev->migration = NULL; -+} -+ -+static int vfio_migration_init(VFIODevice *vbasedev, -+ struct vfio_region_info *info) -+{ -+ int ret; -+ Object *obj; -+ -+ if (!vbasedev->ops->vfio_get_object) { -+ return -EINVAL; -+ } -+ -+ obj = vbasedev->ops->vfio_get_object(vbasedev); -+ if (!obj) { -+ return -EINVAL; -+ } -+ -+ vbasedev->migration = g_new0(VFIOMigration, 1); -+ -+ ret = vfio_region_setup(obj, vbasedev, &vbasedev->migration->region, -+ info->index, "migration"); -+ if (ret) { -+ error_report("%s: Failed to setup VFIO migration region %d: %s", -+ vbasedev->name, info->index, strerror(-ret)); -+ goto err; -+ } -+ -+ if (!vbasedev->migration->region.size) { -+ error_report("%s: Invalid zero-sized VFIO migration region %d", -+ vbasedev->name, info->index); -+ ret = -EINVAL; -+ goto err; -+ } -+ return 0; -+ -+err: -+ vfio_migration_exit(vbasedev); -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+int vfio_migration_probe(VFIODevice *vbasedev, Error **errp) -+{ -+ struct vfio_region_info *info = NULL; -+ Error *local_err = NULL; -+ int ret; -+ -+ ret = vfio_get_dev_region_info(vbasedev, VFIO_REGION_TYPE_MIGRATION, -+ VFIO_REGION_SUBTYPE_MIGRATION, &info); -+ if (ret) { -+ goto add_blocker; -+ } -+ -+ ret = vfio_migration_init(vbasedev, info); -+ if (ret) { -+ goto add_blocker; -+ } -+ -+ g_free(info); -+ trace_vfio_migration_probe(vbasedev->name, info->index); -+ return 0; -+ -+add_blocker: -+ error_setg(&vbasedev->migration_blocker, -+ "VFIO device doesn't support migration"); -+ g_free(info); -+ -+ ret = migrate_add_blocker(vbasedev->migration_blocker, &local_err); -+ if (local_err) { -+ error_propagate(errp, local_err); -+ error_free(vbasedev->migration_blocker); -+ vbasedev->migration_blocker = NULL; -+ } -+ return ret; -+} -+ -+void vfio_migration_finalize(VFIODevice *vbasedev) -+{ -+ if (vbasedev->migration) { -+ vfio_migration_exit(vbasedev); -+ } -+ -+ if (vbasedev->migration_blocker) { -+ migrate_del_blocker(vbasedev->migration_blocker); -+ error_free(vbasedev->migration_blocker); -+ vbasedev->migration_blocker = NULL; -+ } -+} -diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events -index 8cdc27946c..fd034ac536 100644 ---- a/hw/vfio/trace-events -+++ b/hw/vfio/trace-events -@@ -143,3 +143,6 @@ vfio_display_edid_link_up(void) "" - vfio_display_edid_link_down(void) "" - vfio_display_edid_update(uint32_t prefx, uint32_t prefy) "%ux%u" - vfio_display_edid_write_error(void) "" -+ -+# migration.c -+vfio_migration_probe(const char *name, uint32_t index) " (%s) Region %d" -diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index 6ea4898c4d..e0482c2bac 100644 ---- a/include/hw/vfio/vfio-common.h -+++ b/include/hw/vfio/vfio-common.h -@@ -57,6 +57,10 @@ typedef struct VFIORegion { - uint8_t nr; /* cache the region number for debug */ - } VFIORegion; - -+typedef struct VFIOMigration { -+ VFIORegion region; -+} VFIOMigration; -+ - typedef struct VFIOAddressSpace { - AddressSpace *as; - QLIST_HEAD(, VFIOContainer) containers; -@@ -113,6 +117,8 @@ typedef struct VFIODevice { - unsigned int num_irqs; - unsigned int num_regions; - unsigned int flags; -+ VFIOMigration *migration; -+ Error *migration_blocker; - } VFIODevice; - - struct VFIODeviceOps { -@@ -204,4 +210,7 @@ int vfio_spapr_create_window(VFIOContainer *container, - int vfio_spapr_remove_window(VFIOContainer *container, - hwaddr offset_within_address_space); - -+int vfio_migration_probe(VFIODevice *vbasedev, Error **errp); -+void vfio_migration_finalize(VFIODevice *vbasedev); -+ - #endif /* HW_VFIO_VFIO_COMMON_H */ --- -2.27.0 - diff --git a/vfio-Add-migration-state-change-notifier.patch b/vfio-Add-migration-state-change-notifier.patch deleted file mode 100644 index 5fe73a4cb18cd401d8d63ec8440cc361bbae60d9..0000000000000000000000000000000000000000 --- a/vfio-Add-migration-state-change-notifier.patch +++ /dev/null @@ -1,104 +0,0 @@ -From b61729a5e0ab89d29f041202b50d042405076e62 Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:16 +0530 -Subject: [PATCH] vfio: Add migration state change notifier - -Added migration state change notifier to get notification on migration state -change. These states are translated to VFIO device state and conveyed to -vendor driver. - -Signed-off-by: Kirti Wankhede -Reviewed-by: Neo Jia -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: Cornelia Huck -Signed-off-by: Alex Williamson ---- - hw/vfio/migration.c | 28 ++++++++++++++++++++++++++++ - hw/vfio/trace-events | 1 + - include/hw/vfio/vfio-common.h | 2 ++ - 3 files changed, 31 insertions(+) - -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -index ca82c78536..0c6c9b655f 100644 ---- a/hw/vfio/migration.c -+++ b/hw/vfio/migration.c -@@ -175,6 +175,30 @@ static void vfio_vmstate_change(void *opaque, int running, RunState state) - (migration->device_state & mask) | value); - } - -+static void vfio_migration_state_notifier(Notifier *notifier, void *data) -+{ -+ MigrationState *s = data; -+ VFIOMigration *migration = container_of(notifier, VFIOMigration, -+ migration_state); -+ VFIODevice *vbasedev = migration->vbasedev; -+ int ret; -+ -+ trace_vfio_migration_state_notifier(vbasedev->name, -+ MigrationStatus_str(s->state)); -+ -+ switch (s->state) { -+ case MIGRATION_STATUS_CANCELLING: -+ case MIGRATION_STATUS_CANCELLED: -+ case MIGRATION_STATUS_FAILED: -+ ret = vfio_migration_set_state(vbasedev, -+ ~(VFIO_DEVICE_STATE_SAVING | VFIO_DEVICE_STATE_RESUMING), -+ VFIO_DEVICE_STATE_RUNNING); -+ if (ret) { -+ error_report("%s: Failed to set state RUNNING", vbasedev->name); -+ } -+ } -+} -+ - static void vfio_migration_exit(VFIODevice *vbasedev) - { - VFIOMigration *migration = vbasedev->migration; -@@ -219,8 +243,11 @@ static int vfio_migration_init(VFIODevice *vbasedev, - } - - migration = vbasedev->migration; -+ migration->vbasedev = vbasedev; - migration->vm_state = qemu_add_vm_change_state_handler(vfio_vmstate_change, - vbasedev); -+ migration->migration_state.notify = vfio_migration_state_notifier; -+ add_migration_state_change_notifier(&migration->migration_state); - return 0; - - err: -@@ -270,6 +297,7 @@ void vfio_migration_finalize(VFIODevice *vbasedev) - if (vbasedev->migration) { - VFIOMigration *migration = vbasedev->migration; - -+ remove_migration_state_change_notifier(&migration->migration_state); - qemu_del_vm_change_state_handler(migration->vm_state); - vfio_migration_exit(vbasedev); - } -diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events -index 1626862315..bd3d47b005 100644 ---- a/hw/vfio/trace-events -+++ b/hw/vfio/trace-events -@@ -148,3 +148,4 @@ vfio_display_edid_write_error(void) "" - vfio_migration_probe(const char *name, uint32_t index) " (%s) Region %d" - vfio_migration_set_state(const char *name, uint32_t state) " (%s) state %d" - vfio_vmstate_change(const char *name, int running, const char *reason, uint32_t dev_state) " (%s) running %d reason %s device state %d" -+vfio_migration_state_notifier(const char *name, const char *state) " (%s) state %s" -diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index 533d6737ac..efff0590ae 100644 ---- a/include/hw/vfio/vfio-common.h -+++ b/include/hw/vfio/vfio-common.h -@@ -59,10 +59,12 @@ typedef struct VFIORegion { - } VFIORegion; - - typedef struct VFIOMigration { -+ struct VFIODevice *vbasedev; - VMChangeStateEntry *vm_state; - VFIORegion region; - uint32_t device_state; - int vm_running; -+ Notifier migration_state; - } VFIOMigration; - - typedef struct VFIOAddressSpace { --- -2.27.0 - diff --git a/vfio-Add-save-and-load-functions-for-VFIO-PCI-device.patch b/vfio-Add-save-and-load-functions-for-VFIO-PCI-device.patch deleted file mode 100644 index 232efcf5dbcc072f358e3fec5a5f1186a1a97b55..0000000000000000000000000000000000000000 --- a/vfio-Add-save-and-load-functions-for-VFIO-PCI-device.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 92f104ca6e35acae079ca3bb432f24452058d483 Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:13 +0530 -Subject: [PATCH] vfio: Add save and load functions for VFIO PCI devices - -Added functions to save and restore PCI device specific data, -specifically config space of PCI device. - -Signed-off-by: Kirti Wankhede -Reviewed-by: Neo Jia -Signed-off-by: Alex Williamson ---- - hw/vfio/pci.c | 51 +++++++++++++++++++++++++++++++++++ - include/hw/vfio/vfio-common.h | 2 ++ - 2 files changed, 53 insertions(+) - -diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c -index de0d286fc9..b9fae3ad28 100644 ---- a/hw/vfio/pci.c -+++ b/hw/vfio/pci.c -@@ -35,6 +35,7 @@ - #include "pci.h" - #include "trace.h" - #include "qapi/error.h" -+#include "migration/qemu-file.h" - - #define TYPE_VFIO_PCI "vfio-pci" - #define PCI_VFIO(obj) OBJECT_CHECK(VFIOPCIDevice, obj, TYPE_VFIO_PCI) -@@ -2395,11 +2396,61 @@ static Object *vfio_pci_get_object(VFIODevice *vbasedev) - return OBJECT(vdev); - } - -+static bool vfio_msix_present(void *opaque, int version_id) -+{ -+ PCIDevice *pdev = opaque; -+ -+ return msix_present(pdev); -+} -+ -+const VMStateDescription vmstate_vfio_pci_config = { -+ .name = "VFIOPCIDevice", -+ .version_id = 1, -+ .minimum_version_id = 1, -+ .fields = (VMStateField[]) { -+ VMSTATE_PCI_DEVICE(pdev, VFIOPCIDevice), -+ VMSTATE_MSIX_TEST(pdev, VFIOPCIDevice, vfio_msix_present), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ -+static void vfio_pci_save_config(VFIODevice *vbasedev, QEMUFile *f) -+{ -+ VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev); -+ -+ vmstate_save_state(f, &vmstate_vfio_pci_config, vdev, NULL); -+} -+ -+static int vfio_pci_load_config(VFIODevice *vbasedev, QEMUFile *f) -+{ -+ VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev); -+ PCIDevice *pdev = &vdev->pdev; -+ int ret; -+ -+ ret = vmstate_load_state(f, &vmstate_vfio_pci_config, vdev, 1); -+ if (ret) { -+ return ret; -+ } -+ -+ vfio_pci_write_config(pdev, PCI_COMMAND, -+ pci_get_word(pdev->config + PCI_COMMAND), 2); -+ -+ if (msi_enabled(pdev)) { -+ vfio_msi_enable(vdev); -+ } else if (msix_enabled(pdev)) { -+ vfio_msix_enable(vdev); -+ } -+ -+ return ret; -+} -+ - static VFIODeviceOps vfio_pci_ops = { - .vfio_compute_needs_reset = vfio_pci_compute_needs_reset, - .vfio_hot_reset_multi = vfio_pci_hot_reset_multi, - .vfio_eoi = vfio_intx_eoi, - .vfio_get_object = vfio_pci_get_object, -+ .vfio_save_config = vfio_pci_save_config, -+ .vfio_load_config = vfio_pci_load_config, - }; - - int vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp) -diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index 771b6d59a3..6ea4898c4d 100644 ---- a/include/hw/vfio/vfio-common.h -+++ b/include/hw/vfio/vfio-common.h -@@ -120,6 +120,8 @@ struct VFIODeviceOps { - int (*vfio_hot_reset_multi)(VFIODevice *vdev); - void (*vfio_eoi)(VFIODevice *vdev); - Object *(*vfio_get_object)(VFIODevice *vdev); -+ void (*vfio_save_config)(VFIODevice *vdev, QEMUFile *f); -+ int (*vfio_load_config)(VFIODevice *vdev, QEMUFile *f); - }; - - typedef struct VFIOGroup { --- -2.27.0 - diff --git a/vfio-Add-save-state-functions-to-SaveVMHandlers.patch b/vfio-Add-save-state-functions-to-SaveVMHandlers.patch deleted file mode 100644 index 14047fd8a474c07c71fa4ba622e1fb33d043b02d..0000000000000000000000000000000000000000 --- a/vfio-Add-save-state-functions-to-SaveVMHandlers.patch +++ /dev/null @@ -1,380 +0,0 @@ -From 94f106f95e887d1d706e8f771fd6ad287ddac2dc Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:18 +0530 -Subject: [PATCH] vfio: Add save state functions to SaveVMHandlers - -Added .save_live_pending, .save_live_iterate and .save_live_complete_precopy -functions. These functions handles pre-copy and stop-and-copy phase. - -In _SAVING|_RUNNING device state or pre-copy phase: -- read pending_bytes. If pending_bytes > 0, go through below steps. -- read data_offset - indicates kernel driver to write data to staging - buffer. -- read data_size - amount of data in bytes written by vendor driver in - migration region. -- read data_size bytes of data from data_offset in the migration region. -- Write data packet to file stream as below: -{VFIO_MIG_FLAG_DEV_DATA_STATE, data_size, actual data, -VFIO_MIG_FLAG_END_OF_STATE } - -In _SAVING device state or stop-and-copy phase -a. read config space of device and save to migration file stream. This - doesn't need to be from vendor driver. Any other special config state - from driver can be saved as data in following iteration. -b. read pending_bytes. If pending_bytes > 0, go through below steps. -c. read data_offset - indicates kernel driver to write data to staging - buffer. -d. read data_size - amount of data in bytes written by vendor driver in - migration region. -e. read data_size bytes of data from data_offset in the migration region. -f. Write data packet as below: - {VFIO_MIG_FLAG_DEV_DATA_STATE, data_size, actual data} -g. iterate through steps b to f while (pending_bytes > 0) -h. Write {VFIO_MIG_FLAG_END_OF_STATE} - -When data region is mapped, its user's responsibility to read data from -data_offset of data_size before moving to next steps. - -Added fix suggested by Artem Polyakov to reset pending_bytes in -vfio_save_iterate(). -Added fix suggested by Zhi Wang to add 0 as data size in migration stream and -add END_OF_STATE delimiter to indicate phase complete. - -Suggested-by: Artem Polyakov -Suggested-by: Zhi Wang -Signed-off-by: Kirti Wankhede -Reviewed-by: Neo Jia -Reviewed-by: Yan Zhao -Signed-off-by: Alex Williamson ---- - hw/vfio/migration.c | 276 ++++++++++++++++++++++++++++++++++ - hw/vfio/trace-events | 6 + - include/hw/vfio/vfio-common.h | 1 + - 3 files changed, 283 insertions(+) - -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -index 405228fc5a..f78a77e1e3 100644 ---- a/hw/vfio/migration.c -+++ b/hw/vfio/migration.c -@@ -148,6 +148,151 @@ static int vfio_migration_set_state(VFIODevice *vbasedev, uint32_t mask, - return 0; - } - -+static void *get_data_section_size(VFIORegion *region, uint64_t data_offset, -+ uint64_t data_size, uint64_t *size) -+{ -+ void *ptr = NULL; -+ uint64_t limit = 0; -+ int i; -+ -+ if (!region->mmaps) { -+ if (size) { -+ *size = MIN(data_size, region->size - data_offset); -+ } -+ return ptr; -+ } -+ -+ for (i = 0; i < region->nr_mmaps; i++) { -+ VFIOMmap *map = region->mmaps + i; -+ -+ if ((data_offset >= map->offset) && -+ (data_offset < map->offset + map->size)) { -+ -+ /* check if data_offset is within sparse mmap areas */ -+ ptr = map->mmap + data_offset - map->offset; -+ if (size) { -+ *size = MIN(data_size, map->offset + map->size - data_offset); -+ } -+ break; -+ } else if ((data_offset < map->offset) && -+ (!limit || limit > map->offset)) { -+ /* -+ * data_offset is not within sparse mmap areas, find size of -+ * non-mapped area. Check through all list since region->mmaps list -+ * is not sorted. -+ */ -+ limit = map->offset; -+ } -+ } -+ -+ if (!ptr && size) { -+ *size = limit ? MIN(data_size, limit - data_offset) : data_size; -+ } -+ return ptr; -+} -+ -+static int vfio_save_buffer(QEMUFile *f, VFIODevice *vbasedev, uint64_t *size) -+{ -+ VFIOMigration *migration = vbasedev->migration; -+ VFIORegion *region = &migration->region; -+ uint64_t data_offset = 0, data_size = 0, sz; -+ int ret; -+ -+ ret = vfio_mig_read(vbasedev, &data_offset, sizeof(data_offset), -+ region->fd_offset + VFIO_MIG_STRUCT_OFFSET(data_offset)); -+ if (ret < 0) { -+ return ret; -+ } -+ -+ ret = vfio_mig_read(vbasedev, &data_size, sizeof(data_size), -+ region->fd_offset + VFIO_MIG_STRUCT_OFFSET(data_size)); -+ if (ret < 0) { -+ return ret; -+ } -+ -+ trace_vfio_save_buffer(vbasedev->name, data_offset, data_size, -+ migration->pending_bytes); -+ -+ qemu_put_be64(f, data_size); -+ sz = data_size; -+ -+ while (sz) { -+ void *buf; -+ uint64_t sec_size; -+ bool buf_allocated = false; -+ -+ buf = get_data_section_size(region, data_offset, sz, &sec_size); -+ -+ if (!buf) { -+ buf = g_try_malloc(sec_size); -+ if (!buf) { -+ error_report("%s: Error allocating buffer ", __func__); -+ return -ENOMEM; -+ } -+ buf_allocated = true; -+ -+ ret = vfio_mig_read(vbasedev, buf, sec_size, -+ region->fd_offset + data_offset); -+ if (ret < 0) { -+ g_free(buf); -+ return ret; -+ } -+ } -+ -+ qemu_put_buffer(f, buf, sec_size); -+ -+ if (buf_allocated) { -+ g_free(buf); -+ } -+ sz -= sec_size; -+ data_offset += sec_size; -+ } -+ -+ ret = qemu_file_get_error(f); -+ -+ if (!ret && size) { -+ *size = data_size; -+ } -+ -+ return ret; -+} -+ -+static int vfio_update_pending(VFIODevice *vbasedev) -+{ -+ VFIOMigration *migration = vbasedev->migration; -+ VFIORegion *region = &migration->region; -+ uint64_t pending_bytes = 0; -+ int ret; -+ -+ ret = vfio_mig_read(vbasedev, &pending_bytes, sizeof(pending_bytes), -+ region->fd_offset + VFIO_MIG_STRUCT_OFFSET(pending_bytes)); -+ if (ret < 0) { -+ migration->pending_bytes = 0; -+ return ret; -+ } -+ -+ migration->pending_bytes = pending_bytes; -+ trace_vfio_update_pending(vbasedev->name, pending_bytes); -+ return 0; -+} -+ -+static int vfio_save_device_config_state(QEMUFile *f, void *opaque) -+{ -+ VFIODevice *vbasedev = opaque; -+ -+ qemu_put_be64(f, VFIO_MIG_FLAG_DEV_CONFIG_STATE); -+ -+ if (vbasedev->ops && vbasedev->ops->vfio_save_config) { -+ vbasedev->ops->vfio_save_config(vbasedev, f); -+ } -+ -+ qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); -+ -+ trace_vfio_save_device_config_state(vbasedev->name); -+ -+ return qemu_file_get_error(f); -+} -+ - static void vfio_migration_cleanup(VFIODevice *vbasedev) - { - VFIOMigration *migration = vbasedev->migration; -@@ -210,9 +355,140 @@ static void vfio_save_cleanup(void *opaque) - trace_vfio_save_cleanup(vbasedev->name); - } - -+static void vfio_save_pending(QEMUFile *f, void *opaque, -+ uint64_t threshold_size, -+ uint64_t *res_precopy_only, -+ uint64_t *res_compatible, -+ uint64_t *res_postcopy_only) -+{ -+ VFIODevice *vbasedev = opaque; -+ VFIOMigration *migration = vbasedev->migration; -+ int ret; -+ -+ ret = vfio_update_pending(vbasedev); -+ if (ret) { -+ return; -+ } -+ -+ *res_precopy_only += migration->pending_bytes; -+ -+ trace_vfio_save_pending(vbasedev->name, *res_precopy_only, -+ *res_postcopy_only, *res_compatible); -+} -+ -+static int vfio_save_iterate(QEMUFile *f, void *opaque) -+{ -+ VFIODevice *vbasedev = opaque; -+ VFIOMigration *migration = vbasedev->migration; -+ uint64_t data_size; -+ int ret; -+ -+ qemu_put_be64(f, VFIO_MIG_FLAG_DEV_DATA_STATE); -+ -+ if (migration->pending_bytes == 0) { -+ ret = vfio_update_pending(vbasedev); -+ if (ret) { -+ return ret; -+ } -+ -+ if (migration->pending_bytes == 0) { -+ qemu_put_be64(f, 0); -+ qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); -+ /* indicates data finished, goto complete phase */ -+ return 1; -+ } -+ } -+ -+ ret = vfio_save_buffer(f, vbasedev, &data_size); -+ if (ret) { -+ error_report("%s: vfio_save_buffer failed %s", vbasedev->name, -+ strerror(errno)); -+ return ret; -+ } -+ -+ qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); -+ -+ ret = qemu_file_get_error(f); -+ if (ret) { -+ return ret; -+ } -+ -+ /* -+ * Reset pending_bytes as .save_live_pending is not called during savevm or -+ * snapshot case, in such case vfio_update_pending() at the start of this -+ * function updates pending_bytes. -+ */ -+ migration->pending_bytes = 0; -+ trace_vfio_save_iterate(vbasedev->name, data_size); -+ return 0; -+} -+ -+static int vfio_save_complete_precopy(QEMUFile *f, void *opaque) -+{ -+ VFIODevice *vbasedev = opaque; -+ VFIOMigration *migration = vbasedev->migration; -+ uint64_t data_size; -+ int ret; -+ -+ ret = vfio_migration_set_state(vbasedev, ~VFIO_DEVICE_STATE_RUNNING, -+ VFIO_DEVICE_STATE_SAVING); -+ if (ret) { -+ error_report("%s: Failed to set state STOP and SAVING", -+ vbasedev->name); -+ return ret; -+ } -+ -+ ret = vfio_save_device_config_state(f, opaque); -+ if (ret) { -+ return ret; -+ } -+ -+ ret = vfio_update_pending(vbasedev); -+ if (ret) { -+ return ret; -+ } -+ -+ while (migration->pending_bytes > 0) { -+ qemu_put_be64(f, VFIO_MIG_FLAG_DEV_DATA_STATE); -+ ret = vfio_save_buffer(f, vbasedev, &data_size); -+ if (ret < 0) { -+ error_report("%s: Failed to save buffer", vbasedev->name); -+ return ret; -+ } -+ -+ if (data_size == 0) { -+ break; -+ } -+ -+ ret = vfio_update_pending(vbasedev); -+ if (ret) { -+ return ret; -+ } -+ } -+ -+ qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); -+ -+ ret = qemu_file_get_error(f); -+ if (ret) { -+ return ret; -+ } -+ -+ ret = vfio_migration_set_state(vbasedev, ~VFIO_DEVICE_STATE_SAVING, 0); -+ if (ret) { -+ error_report("%s: Failed to set state STOPPED", vbasedev->name); -+ return ret; -+ } -+ -+ trace_vfio_save_complete_precopy(vbasedev->name); -+ return ret; -+} -+ - static SaveVMHandlers savevm_vfio_handlers = { - .save_setup = vfio_save_setup, - .save_cleanup = vfio_save_cleanup, -+ .save_live_pending = vfio_save_pending, -+ .save_live_iterate = vfio_save_iterate, -+ .save_live_complete_precopy = vfio_save_complete_precopy, - }; - - /* ---------------------------------------------------------------------- */ -diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events -index 86c18def01..9a1c5e17d9 100644 ---- a/hw/vfio/trace-events -+++ b/hw/vfio/trace-events -@@ -151,3 +151,9 @@ vfio_vmstate_change(const char *name, int running, const char *reason, uint32_t - vfio_migration_state_notifier(const char *name, const char *state) " (%s) state %s" - vfio_save_setup(const char *name) " (%s)" - vfio_save_cleanup(const char *name) " (%s)" -+vfio_save_buffer(const char *name, uint64_t data_offset, uint64_t data_size, uint64_t pending) " (%s) Offset 0x%"PRIx64" size 0x%"PRIx64" pending 0x%"PRIx64 -+vfio_update_pending(const char *name, uint64_t pending) " (%s) pending 0x%"PRIx64 -+vfio_save_device_config_state(const char *name) " (%s)" -+vfio_save_pending(const char *name, uint64_t precopy, uint64_t postcopy, uint64_t compatible) " (%s) precopy 0x%"PRIx64" postcopy 0x%"PRIx64" compatible 0x%"PRIx64 -+vfio_save_iterate(const char *name, int data_size) " (%s) data_size %d" -+vfio_save_complete_precopy(const char *name) " (%s)" -diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index efff0590ae..c825524606 100644 ---- a/include/hw/vfio/vfio-common.h -+++ b/include/hw/vfio/vfio-common.h -@@ -65,6 +65,7 @@ typedef struct VFIOMigration { - uint32_t device_state; - int vm_running; - Notifier migration_state; -+ uint64_t pending_bytes; - } VFIOMigration; - - typedef struct VFIOAddressSpace { --- -2.27.0 - diff --git a/vfio-Add-vfio_get_object-callback-to-VFIODeviceOps.patch b/vfio-Add-vfio_get_object-callback-to-VFIODeviceOps.patch deleted file mode 100644 index e13a1daf40d518a550e8af5618b2d2b537cb43cc..0000000000000000000000000000000000000000 --- a/vfio-Add-vfio_get_object-callback-to-VFIODeviceOps.patch +++ /dev/null @@ -1,55 +0,0 @@ -From c1de789d89132b66243fbfe253f10764ce514a08 Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:12 +0530 -Subject: [PATCH] vfio: Add vfio_get_object callback to VFIODeviceOps - -Hook vfio_get_object callback for PCI devices. - -Signed-off-by: Kirti Wankhede -Reviewed-by: Neo Jia -Suggested-by: Cornelia Huck -Reviewed-by: Cornelia Huck -Signed-off-by: Alex Williamson ---- - hw/vfio/pci.c | 8 ++++++++ - include/hw/vfio/vfio-common.h | 1 + - 2 files changed, 9 insertions(+) - -diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c -index d7a4e1875c..de0d286fc9 100644 ---- a/hw/vfio/pci.c -+++ b/hw/vfio/pci.c -@@ -2388,10 +2388,18 @@ static void vfio_pci_compute_needs_reset(VFIODevice *vbasedev) - } - } - -+static Object *vfio_pci_get_object(VFIODevice *vbasedev) -+{ -+ VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev); -+ -+ return OBJECT(vdev); -+} -+ - static VFIODeviceOps vfio_pci_ops = { - .vfio_compute_needs_reset = vfio_pci_compute_needs_reset, - .vfio_hot_reset_multi = vfio_pci_hot_reset_multi, - .vfio_eoi = vfio_intx_eoi, -+ .vfio_get_object = vfio_pci_get_object, - }; - - int vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp) -diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index 93493891ba..771b6d59a3 100644 ---- a/include/hw/vfio/vfio-common.h -+++ b/include/hw/vfio/vfio-common.h -@@ -119,6 +119,7 @@ struct VFIODeviceOps { - void (*vfio_compute_needs_reset)(VFIODevice *vdev); - int (*vfio_hot_reset_multi)(VFIODevice *vdev); - void (*vfio_eoi)(VFIODevice *vdev); -+ Object *(*vfio_get_object)(VFIODevice *vdev); - }; - - typedef struct VFIOGroup { --- -2.27.0 - diff --git a/vfio-Add-vfio_listener_log_sync-to-mark-dirty-pages.patch b/vfio-Add-vfio_listener_log_sync-to-mark-dirty-pages.patch deleted file mode 100644 index 6479a2550592f6eff10e6c244ed3648d887ed1a6..0000000000000000000000000000000000000000 --- a/vfio-Add-vfio_listener_log_sync-to-mark-dirty-pages.patch +++ /dev/null @@ -1,182 +0,0 @@ -From 3ac0647003d192579bcb6c1081b75d9c8ada78e0 Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:23 +0530 -Subject: [PATCH] vfio: Add vfio_listener_log_sync to mark dirty pages - -vfio_listener_log_sync gets list of dirty pages from container using -VFIO_IOMMU_GET_DIRTY_BITMAP ioctl and mark those pages dirty when all -devices are stopped and saving state. -Return early for the RAM block section of mapped MMIO region. - -Signed-off-by: Kirti Wankhede -Reviewed-by: Neo Jia -[aw: fix error_report types, fix cpu_physical_memory_set_dirty_lebitmap() cast] -Signed-off-by: Alex Williamson ---- - hw/vfio/common.c | 116 +++++++++++++++++++++++++++++++++++++++++++ - hw/vfio/trace-events | 1 + - 2 files changed, 117 insertions(+) - -diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index 35168b8f3e..4d2828fc97 100644 ---- a/hw/vfio/common.c -+++ b/hw/vfio/common.c -@@ -29,6 +29,7 @@ - #include "hw/vfio/vfio.h" - #include "exec/address-spaces.h" - #include "exec/memory.h" -+#include "exec/ram_addr.h" - #include "hw/hw.h" - #include "qemu/error-report.h" - #include "qemu/range.h" -@@ -36,6 +37,7 @@ - #include "sysemu/kvm.h" - #include "trace.h" - #include "qapi/error.h" -+#include "migration/migration.h" - - VFIOGroupList vfio_group_list = - QLIST_HEAD_INITIALIZER(vfio_group_list); -@@ -285,6 +287,39 @@ const MemoryRegionOps vfio_region_ops = { - }, - }; - -+/* -+ * Device state interfaces -+ */ -+ -+static bool vfio_devices_all_stopped_and_saving(VFIOContainer *container) -+{ -+ VFIOGroup *group; -+ VFIODevice *vbasedev; -+ MigrationState *ms = migrate_get_current(); -+ -+ if (!migration_is_setup_or_active(ms->state)) { -+ return false; -+ } -+ -+ QLIST_FOREACH(group, &container->group_list, container_next) { -+ QLIST_FOREACH(vbasedev, &group->device_list, next) { -+ VFIOMigration *migration = vbasedev->migration; -+ -+ if (!migration) { -+ return false; -+ } -+ -+ if ((migration->device_state & VFIO_DEVICE_STATE_SAVING) && -+ !(migration->device_state & VFIO_DEVICE_STATE_RUNNING)) { -+ continue; -+ } else { -+ return false; -+ } -+ } -+ } -+ return true; -+} -+ - /* - * DMA - Mapping and unmapping for the "type1" IOMMU interface used on x86 - */ -@@ -794,9 +829,90 @@ static void vfio_listener_region_del(MemoryListener *listener, - } - } - -+static int vfio_get_dirty_bitmap(VFIOContainer *container, uint64_t iova, -+ uint64_t size, ram_addr_t ram_addr) -+{ -+ struct vfio_iommu_type1_dirty_bitmap *dbitmap; -+ struct vfio_iommu_type1_dirty_bitmap_get *range; -+ uint64_t pages; -+ int ret; -+ -+ dbitmap = g_malloc0(sizeof(*dbitmap) + sizeof(*range)); -+ -+ dbitmap->argsz = sizeof(*dbitmap) + sizeof(*range); -+ dbitmap->flags = VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP; -+ range = (struct vfio_iommu_type1_dirty_bitmap_get *)&dbitmap->data; -+ range->iova = iova; -+ range->size = size; -+ -+ /* -+ * cpu_physical_memory_set_dirty_lebitmap() expects pages in bitmap of -+ * TARGET_PAGE_SIZE to mark those dirty. Hence set bitmap's pgsize to -+ * TARGET_PAGE_SIZE. -+ */ -+ range->bitmap.pgsize = TARGET_PAGE_SIZE; -+ -+ pages = TARGET_PAGE_ALIGN(range->size) >> TARGET_PAGE_BITS; -+ range->bitmap.size = ROUND_UP(pages, sizeof(__u64) * BITS_PER_BYTE) / -+ BITS_PER_BYTE; -+ range->bitmap.data = g_try_malloc0(range->bitmap.size); -+ if (!range->bitmap.data) { -+ ret = -ENOMEM; -+ goto err_out; -+ } -+ -+ ret = ioctl(container->fd, VFIO_IOMMU_DIRTY_PAGES, dbitmap); -+ if (ret) { -+ error_report("Failed to get dirty bitmap for iova: 0x%"PRIx64 -+ " size: 0x%"PRIx64" err: %d", (uint64_t)range->iova, -+ (uint64_t)range->size, errno); -+ goto err_out; -+ } -+ -+ cpu_physical_memory_set_dirty_lebitmap((unsigned long *)range->bitmap.data, -+ ram_addr, pages); -+ -+ trace_vfio_get_dirty_bitmap(container->fd, range->iova, range->size, -+ range->bitmap.size, ram_addr); -+err_out: -+ g_free(range->bitmap.data); -+ g_free(dbitmap); -+ -+ return ret; -+} -+ -+static int vfio_sync_dirty_bitmap(VFIOContainer *container, -+ MemoryRegionSection *section) -+{ -+ ram_addr_t ram_addr; -+ -+ ram_addr = memory_region_get_ram_addr(section->mr) + -+ section->offset_within_region; -+ -+ return vfio_get_dirty_bitmap(container, -+ TARGET_PAGE_ALIGN(section->offset_within_address_space), -+ int128_get64(section->size), ram_addr); -+} -+ -+static void vfio_listerner_log_sync(MemoryListener *listener, -+ MemoryRegionSection *section) -+{ -+ VFIOContainer *container = container_of(listener, VFIOContainer, listener); -+ -+ if (vfio_listener_skipped_section(section) || -+ !container->dirty_pages_supported) { -+ return; -+ } -+ -+ if (vfio_devices_all_stopped_and_saving(container)) { -+ vfio_sync_dirty_bitmap(container, section); -+ } -+} -+ - static const MemoryListener vfio_memory_listener = { - .region_add = vfio_listener_region_add, - .region_del = vfio_listener_region_del, -+ .log_sync = vfio_listerner_log_sync, - }; - - static void vfio_listener_release(VFIOContainer *container) -diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events -index 4f08f5a633..4167f35d64 100644 ---- a/hw/vfio/trace-events -+++ b/hw/vfio/trace-events -@@ -161,3 +161,4 @@ vfio_load_device_config_state(const char *name) " (%s)" - vfio_load_state(const char *name, uint64_t data) " (%s) data 0x%"PRIx64 - vfio_load_state_device_data(const char *name, uint64_t data_offset, uint64_t data_size) " (%s) Offset 0x%"PRIx64" size 0x%"PRIx64 - vfio_load_cleanup(const char *name) " (%s)" -+vfio_get_dirty_bitmap(int fd, uint64_t iova, uint64_t size, uint64_t bitmap_size, uint64_t start) "container fd=%d, iova=0x%"PRIx64" size= 0x%"PRIx64" bitmap_size=0x%"PRIx64" start=0x%"PRIx64 --- -2.27.0 - diff --git a/vfio-Add-vfio_prereg_listener_global_log_start-stop-.patch b/vfio-Add-vfio_prereg_listener_global_log_start-stop-.patch index 289638a9e3c453dfe9fa9e863209ddbd5ea0489f..962266210c9ed50027a893c453b59313f4fedc56 100644 --- a/vfio-Add-vfio_prereg_listener_global_log_start-stop-.patch +++ b/vfio-Add-vfio_prereg_listener_global_log_start-stop-.patch @@ -1,4 +1,4 @@ -From 6aa770f4b83ca068d0c8f3102edda32666a8404d Mon Sep 17 00:00:00 2001 +From 287c63ab540533f1f9642e753c091caa7e6e2511 Mon Sep 17 00:00:00 2001 From: Kunkun Jiang Date: Tue, 11 May 2021 10:08:15 +0800 Subject: [PATCH] vfio: Add vfio_prereg_listener_global_log_start/stop in @@ -18,10 +18,10 @@ Signed-off-by: Kunkun Jiang 1 file changed, 24 insertions(+) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index b5f9ba816e..fb7ca63748 100644 +index 20c820aa74..65f3979492 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -1239,6 +1239,17 @@ static void vfio_listener_log_global_start(MemoryListener *listener) +@@ -1501,6 +1501,17 @@ static void vfio_listener_log_global_start(MemoryListener *listener) { VFIOContainer *container = container_of(listener, VFIOContainer, listener); @@ -39,7 +39,7 @@ index b5f9ba816e..fb7ca63748 100644 vfio_set_dirty_page_tracking(container, true); } -@@ -1246,6 +1257,17 @@ static void vfio_listener_log_global_stop(MemoryListener *listener) +@@ -1508,6 +1519,17 @@ static void vfio_listener_log_global_stop(MemoryListener *listener) { VFIOContainer *container = container_of(listener, VFIOContainer, listener); @@ -57,7 +57,7 @@ index b5f9ba816e..fb7ca63748 100644 vfio_set_dirty_page_tracking(container, false); } -@@ -1614,6 +1636,8 @@ static const MemoryListener vfio_memory_listener = { +@@ -1922,6 +1944,8 @@ static const MemoryListener vfio_memory_listener = { static MemoryListener vfio_memory_prereg_listener = { .region_add = vfio_prereg_listener_region_add, .region_del = vfio_prereg_listener_region_del, diff --git a/vfio-Add-vfio_prereg_listener_log_clear-to-re-enable.patch b/vfio-Add-vfio_prereg_listener_log_clear-to-re-enable.patch index e4da89bd477558ea9e58538c75b0c198d27e3d21..a055ed555f3a7fa213a8c16b4983a139de590ec0 100644 --- a/vfio-Add-vfio_prereg_listener_log_clear-to-re-enable.patch +++ b/vfio-Add-vfio_prereg_listener_log_clear-to-re-enable.patch @@ -1,4 +1,4 @@ -From f959faa36fc100894a44f2e6cd7e02a183ba142a Mon Sep 17 00:00:00 2001 +From 7086df6d90cd698a3e20cf4cf6e9a834f168cd8f Mon Sep 17 00:00:00 2001 From: Kunkun Jiang Date: Sat, 31 Jul 2021 09:40:24 +0800 Subject: [PATCH] vfio: Add vfio_prereg_listener_log_clear to re-enable mark @@ -15,10 +15,10 @@ Signed-off-by: Kunkun Jiang 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index 6b00bd4c2f..b5f9ba816e 100644 +index 2506cd57ee..20c820aa74 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -1550,6 +1550,43 @@ static int vfio_physical_log_clear(VFIOContainer *container, +@@ -1857,6 +1857,43 @@ static int vfio_physical_log_clear(VFIOContainer *container, return ret; } @@ -62,7 +62,7 @@ index 6b00bd4c2f..b5f9ba816e 100644 static void vfio_listener_log_clear(MemoryListener *listener, MemoryRegionSection *section) { -@@ -1561,7 +1598,7 @@ static void vfio_listener_log_clear(MemoryListener *listener, +@@ -1868,7 +1905,7 @@ static void vfio_listener_log_clear(MemoryListener *listener, } if (vfio_devices_all_dirty_tracking(container)) { @@ -71,7 +71,7 @@ index 6b00bd4c2f..b5f9ba816e 100644 } } -@@ -1578,6 +1615,7 @@ static MemoryListener vfio_memory_prereg_listener = { +@@ -1886,6 +1923,7 @@ static MemoryListener vfio_memory_prereg_listener = { .region_add = vfio_prereg_listener_region_add, .region_del = vfio_prereg_listener_region_del, .log_sync = vfio_prereg_listener_log_sync, diff --git a/vfio-Add-vfio_prereg_listener_log_sync-in-nested-sta.patch b/vfio-Add-vfio_prereg_listener_log_sync-in-nested-sta.patch index 77a0c8a14d29280b369466b1fa9b55dc62c26228..b1df5a3801a75edaedde9968fbb8db92713dfbd5 100644 --- a/vfio-Add-vfio_prereg_listener_log_sync-in-nested-sta.patch +++ b/vfio-Add-vfio_prereg_listener_log_sync-in-nested-sta.patch @@ -1,4 +1,4 @@ -From 4c5350044ac2f61ab8088278b59eb6388ca49ff1 Mon Sep 17 00:00:00 2001 +From f4523389bf57593484308124e06d67855bb79315 Mon Sep 17 00:00:00 2001 From: Kunkun Jiang Date: Tue, 11 May 2021 10:08:14 +0800 Subject: [PATCH] vfio: Add vfio_prereg_listener_log_sync in nested stage @@ -18,10 +18,10 @@ Signed-off-by: Kunkun Jiang 1 file changed, 27 insertions(+) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index 5176fd3a3d..6b00bd4c2f 100644 +index 6136b1ef61..2506cd57ee 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -1317,6 +1317,22 @@ static int vfio_dma_sync_ram_section_dirty_bitmap(VFIOContainer *container, +@@ -1579,6 +1579,22 @@ static int vfio_dma_sync_ram_section_dirty_bitmap(VFIOContainer *container, int128_get64(section->size), ram_addr); } @@ -44,7 +44,7 @@ index 5176fd3a3d..6b00bd4c2f 100644 typedef struct { IOMMUNotifier n; VFIOGuestIOMMU *giommu; -@@ -1361,6 +1377,16 @@ static int vfio_sync_dirty_bitmap(VFIOContainer *container, +@@ -1666,6 +1682,16 @@ static int vfio_sync_dirty_bitmap(VFIOContainer *container, if (memory_region_is_iommu(section->mr)) { VFIOGuestIOMMU *giommu; @@ -61,7 +61,7 @@ index 5176fd3a3d..6b00bd4c2f 100644 QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) { if (MEMORY_REGION(giommu->iommu) == section->mr && giommu->n.start == section->offset_within_region) { -@@ -1551,6 +1577,7 @@ static const MemoryListener vfio_memory_listener = { +@@ -1859,6 +1885,7 @@ static const MemoryListener vfio_memory_listener = { static MemoryListener vfio_memory_prereg_listener = { .region_add = vfio_prereg_listener_region_add, .region_del = vfio_prereg_listener_region_del, diff --git a/vfio-Avoid-disabling-and-enabling-vectors-repeatedly.patch b/vfio-Avoid-disabling-and-enabling-vectors-repeatedly.patch deleted file mode 100644 index e65b3a8fe54f0fbc3fc5a00949632e67798ce788..0000000000000000000000000000000000000000 --- a/vfio-Avoid-disabling-and-enabling-vectors-repeatedly.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 8113fdcf0c1383ae5b9542563656bea3753d834e Mon Sep 17 00:00:00 2001 -From: Shenming Lu -Date: Wed, 10 Mar 2021 11:02:33 +0800 -Subject: [PATCH] vfio: Avoid disabling and enabling vectors repeatedly in VFIO - migration - -In VFIO migration resume phase and some guest startups, there are -already unmasked vectors in the vector table when calling -vfio_msix_enable(). So in order to avoid inefficiently disabling -and enabling vectors repeatedly, let's allocate all needed vectors -first and then enable these unmasked vectors one by one without -disabling. - -Signed-off-by: Shenming Lu -Message-Id: <20210310030233.1133-4-lushenming@huawei.com> -Signed-off-by: Alex Williamson ---- - hw/vfio/pci.c | 20 +++++++++++++++++--- - 1 file changed, 17 insertions(+), 3 deletions(-) - -diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c -index a637c35e7a..da7c740bce 100644 ---- a/hw/vfio/pci.c -+++ b/hw/vfio/pci.c -@@ -563,6 +563,9 @@ static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr) - - static void vfio_msix_enable(VFIOPCIDevice *vdev) - { -+ PCIDevice *pdev = &vdev->pdev; -+ unsigned int nr, max_vec = 0; -+ - vfio_disable_interrupts(vdev); - - vdev->msi_vectors = g_new0(VFIOMSIVector, vdev->msix->entries); -@@ -581,11 +584,22 @@ static void vfio_msix_enable(VFIOPCIDevice *vdev) - * triggering to userspace, then immediately release the vector, leaving - * the physical device with no vectors enabled, but MSI-X enabled, just - * like the guest view. -+ * If there are already unmasked vectors (in migration resume phase and -+ * some guest startups) which will be enabled soon, we can allocate all -+ * of them here to avoid inefficiently disabling and enabling vectors -+ * repeatedly later. - */ -- vfio_msix_vector_do_use(&vdev->pdev, 0, NULL, NULL); -- vfio_msix_vector_release(&vdev->pdev, 0); -+ if (!pdev->msix_function_masked) { -+ for (nr = 0; nr < msix_nr_vectors_allocated(pdev); nr++) { -+ if (!msix_is_masked(pdev, nr)) { -+ max_vec = nr; -+ } -+ } -+ } -+ vfio_msix_vector_do_use(pdev, max_vec, NULL, NULL); -+ vfio_msix_vector_release(pdev, max_vec); - -- if (msix_set_vector_notifiers(&vdev->pdev, vfio_msix_vector_use, -+ if (msix_set_vector_notifiers(pdev, vfio_msix_vector_use, - vfio_msix_vector_release, NULL)) { - error_report("vfio: msix_set_vector_notifiers failed"); - } --- -2.27.0 - diff --git a/vfio-Change-default-dirty-pages-tracking-behavior-du.patch b/vfio-Change-default-dirty-pages-tracking-behavior-du.patch deleted file mode 100644 index d34f0541c8589124e35a10bb220be59e64f21e53..0000000000000000000000000000000000000000 --- a/vfio-Change-default-dirty-pages-tracking-behavior-du.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 69d1cc17c0a77dbd0d8e811cfaa899b01bf2e5bc Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 23 Nov 2020 19:53:19 +0530 -Subject: [PATCH] vfio: Change default dirty pages tracking behavior during - migration - -By default dirty pages tracking is enabled during iterative phase -(pre-copy phase). -Added per device opt-out option 'x-pre-copy-dirty-page-tracking' to -disable dirty pages tracking during iterative phase. If the option -'x-pre-copy-dirty-page-tracking=off' is set for any VFIO device, dirty -pages tracking during iterative phase will be disabled. - -Signed-off-by: Kirti Wankhede -Signed-off-by: Alex Williamson -Signed-off-by: Kunkun Jiang ---- - hw/vfio/common.c | 11 +++++++---- - hw/vfio/pci.c | 3 +++ - include/hw/vfio/vfio-common.h | 1 + - 3 files changed, 11 insertions(+), 4 deletions(-) - -diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index a86a4c4506..d9cc3509ef 100644 ---- a/hw/vfio/common.c -+++ b/hw/vfio/common.c -@@ -310,7 +310,7 @@ bool vfio_mig_active(void) - return true; - } - --static bool vfio_devices_all_stopped_and_saving(VFIOContainer *container) -+static bool vfio_devices_all_saving(VFIOContainer *container) - { - VFIOGroup *group; - VFIODevice *vbasedev; -@@ -328,8 +328,11 @@ static bool vfio_devices_all_stopped_and_saving(VFIOContainer *container) - return false; - } - -- if ((migration->device_state & VFIO_DEVICE_STATE_SAVING) && -- !(migration->device_state & VFIO_DEVICE_STATE_RUNNING)) { -+ if (migration->device_state & VFIO_DEVICE_STATE_SAVING) { -+ if ((vbasedev->pre_copy_dirty_page_tracking == ON_OFF_AUTO_OFF) -+ && (migration->device_state & VFIO_DEVICE_STATE_RUNNING)) { -+ return false; -+ } - continue; - } else { - return false; -@@ -1088,7 +1091,7 @@ static void vfio_listerner_log_sync(MemoryListener *listener, - return; - } - -- if (vfio_devices_all_stopped_and_saving(container)) { -+ if (vfio_devices_all_saving(container)) { - vfio_sync_dirty_bitmap(container, section); - } - } -diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c -index 2795b8bd12..3641ad0c5c 100644 ---- a/hw/vfio/pci.c -+++ b/hw/vfio/pci.c -@@ -3180,6 +3180,9 @@ static void vfio_instance_init(Object *obj) - static Property vfio_pci_dev_properties[] = { - DEFINE_PROP_PCI_HOST_DEVADDR("host", VFIOPCIDevice, host), - DEFINE_PROP_STRING("sysfsdev", VFIOPCIDevice, vbasedev.sysfsdev), -+ DEFINE_PROP_ON_OFF_AUTO("x-pre-copy-dirty-page-tracking", VFIOPCIDevice, -+ vbasedev.pre_copy_dirty_page_tracking, -+ ON_OFF_AUTO_ON), - DEFINE_PROP_ON_OFF_AUTO("display", VFIOPCIDevice, - display, ON_OFF_AUTO_OFF), - DEFINE_PROP_UINT32("xres", VFIOPCIDevice, display_xres, 0), -diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index 7398631d4c..475aa9fb40 100644 ---- a/include/hw/vfio/vfio-common.h -+++ b/include/hw/vfio/vfio-common.h -@@ -130,6 +130,7 @@ typedef struct VFIODevice { - unsigned int flags; - VFIOMigration *migration; - Error *migration_blocker; -+ OnOffAuto pre_copy_dirty_page_tracking; - } VFIODevice; - - struct VFIODeviceOps { --- -2.27.0 - diff --git a/vfio-Dirty-page-tracking-when-vIOMMU-is-enabled.patch b/vfio-Dirty-page-tracking-when-vIOMMU-is-enabled.patch deleted file mode 100644 index 65949f079ed1eb2baea2e626fbd4d6140d23350c..0000000000000000000000000000000000000000 --- a/vfio-Dirty-page-tracking-when-vIOMMU-is-enabled.patch +++ /dev/null @@ -1,162 +0,0 @@ -From a400753d0f1a008367165aadf375abfe86a66ed7 Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:24 +0530 -Subject: [PATCH] vfio: Dirty page tracking when vIOMMU is enabled - -When vIOMMU is enabled, register MAP notifier from log_sync when all -devices in container are in stop and copy phase of migration. Call replay -and get dirty pages from notifier callback. - -Suggested-by: Alex Williamson -Signed-off-by: Kirti Wankhede -Reviewed-by: Yan Zhao -Signed-off-by: Alex Williamson ---- - hw/vfio/common.c | 88 +++++++++++++++++++++++++++++++++++++++++--- - hw/vfio/trace-events | 1 + - 2 files changed, 83 insertions(+), 6 deletions(-) - -diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index 4d2828fc97..8773b998ac 100644 ---- a/hw/vfio/common.c -+++ b/hw/vfio/common.c -@@ -441,8 +441,8 @@ static bool vfio_listener_skipped_section(MemoryRegionSection *section) - } - - /* Called with rcu_read_lock held. */ --static bool vfio_get_vaddr(IOMMUTLBEntry *iotlb, void **vaddr, -- bool *read_only) -+static bool vfio_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr, -+ ram_addr_t *ram_addr, bool *read_only) - { - MemoryRegion *mr; - hwaddr xlat; -@@ -473,8 +473,17 @@ static bool vfio_get_vaddr(IOMMUTLBEntry *iotlb, void **vaddr, - return false; - } - -- *vaddr = memory_region_get_ram_ptr(mr) + xlat; -- *read_only = !writable || mr->readonly; -+ if (vaddr) { -+ *vaddr = memory_region_get_ram_ptr(mr) + xlat; -+ } -+ -+ if (ram_addr) { -+ *ram_addr = memory_region_get_ram_addr(mr) + xlat; -+ } -+ -+ if (read_only) { -+ *read_only = !writable || mr->readonly; -+ } - - return true; - } -@@ -484,7 +493,6 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) - VFIOGuestIOMMU *giommu = container_of(n, VFIOGuestIOMMU, n); - VFIOContainer *container = giommu->container; - hwaddr iova = iotlb->iova + giommu->iommu_offset; -- bool read_only; - void *vaddr; - int ret; - -@@ -500,7 +508,9 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) - rcu_read_lock(); - - if ((iotlb->perm & IOMMU_RW) != IOMMU_NONE) { -- if (!vfio_get_vaddr(iotlb, &vaddr, &read_only)) { -+ bool read_only; -+ -+ if (!vfio_get_xlat_addr(iotlb, &vaddr, NULL, &read_only)) { - goto out; - } - /* -@@ -881,11 +891,77 @@ err_out: - return ret; - } - -+typedef struct { -+ IOMMUNotifier n; -+ VFIOGuestIOMMU *giommu; -+} vfio_giommu_dirty_notifier; -+ -+static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) -+{ -+ vfio_giommu_dirty_notifier *gdn = container_of(n, -+ vfio_giommu_dirty_notifier, n); -+ VFIOGuestIOMMU *giommu = gdn->giommu; -+ VFIOContainer *container = giommu->container; -+ hwaddr iova = iotlb->iova + giommu->iommu_offset; -+ ram_addr_t translated_addr; -+ -+ trace_vfio_iommu_map_dirty_notify(iova, iova + iotlb->addr_mask); -+ -+ if (iotlb->target_as != &address_space_memory) { -+ error_report("Wrong target AS \"%s\", only system memory is allowed", -+ iotlb->target_as->name ? iotlb->target_as->name : "none"); -+ return; -+ } -+ -+ rcu_read_lock(); -+ if (vfio_get_xlat_addr(iotlb, NULL, &translated_addr, NULL)) { -+ int ret; -+ -+ ret = vfio_get_dirty_bitmap(container, iova, iotlb->addr_mask + 1, -+ translated_addr); -+ if (ret) { -+ error_report("vfio_iommu_map_dirty_notify(%p, 0x%"HWADDR_PRIx", " -+ "0x%"HWADDR_PRIx") = %d (%m)", -+ container, iova, -+ iotlb->addr_mask + 1, ret); -+ } -+ } -+ rcu_read_unlock(); -+} -+ - static int vfio_sync_dirty_bitmap(VFIOContainer *container, - MemoryRegionSection *section) - { - ram_addr_t ram_addr; - -+ if (memory_region_is_iommu(section->mr)) { -+ VFIOGuestIOMMU *giommu; -+ -+ QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) { -+ if (MEMORY_REGION(giommu->iommu) == section->mr && -+ giommu->n.start == section->offset_within_region) { -+ Int128 llend; -+ vfio_giommu_dirty_notifier gdn = { .giommu = giommu }; -+ int idx = memory_region_iommu_attrs_to_index(giommu->iommu, -+ MEMTXATTRS_UNSPECIFIED); -+ -+ llend = int128_add(int128_make64(section->offset_within_region), -+ section->size); -+ llend = int128_sub(llend, int128_one()); -+ -+ iommu_notifier_init(&gdn.n, -+ vfio_iommu_map_dirty_notify, -+ IOMMU_NOTIFIER_MAP, -+ section->offset_within_region, -+ int128_get64(llend), -+ idx); -+ memory_region_iommu_replay(giommu->iommu, &gdn.n); -+ break; -+ } -+ } -+ return 0; -+ } -+ - ram_addr = memory_region_get_ram_addr(section->mr) + - section->offset_within_region; - -diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events -index 4167f35d64..575ebde6e0 100644 ---- a/hw/vfio/trace-events -+++ b/hw/vfio/trace-events -@@ -162,3 +162,4 @@ vfio_load_state(const char *name, uint64_t data) " (%s) data 0x%"PRIx64 - vfio_load_state_device_data(const char *name, uint64_t data_offset, uint64_t data_size) " (%s) Offset 0x%"PRIx64" size 0x%"PRIx64 - vfio_load_cleanup(const char *name) " (%s)" - vfio_get_dirty_bitmap(int fd, uint64_t iova, uint64_t size, uint64_t bitmap_size, uint64_t start) "container fd=%d, iova=0x%"PRIx64" size= 0x%"PRIx64" bitmap_size=0x%"PRIx64" start=0x%"PRIx64 -+vfio_iommu_map_dirty_notify(uint64_t iova_start, uint64_t iova_end) "iommu dirty @ 0x%"PRIx64" - 0x%"PRIx64 --- -2.27.0 - diff --git a/vfio-Fix-unregister-SaveVMHandler-in-vfio_migration_.patch b/vfio-Fix-unregister-SaveVMHandler-in-vfio_migration_.patch deleted file mode 100644 index 47d59923070d7827152f59a60304ef708bcc1c62..0000000000000000000000000000000000000000 --- a/vfio-Fix-unregister-SaveVMHandler-in-vfio_migration_.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 8dc6e7ccc5712aee457ffb1f6cf1bf3f80e778d5 Mon Sep 17 00:00:00 2001 -From: Kunkun Jiang -Date: Thu, 27 May 2021 20:31:01 +0800 -Subject: [PATCH] vfio: Fix unregister SaveVMHandler in vfio_migration_finalize - -In the vfio_migration_init(), the SaveVMHandler is registered for -VFIO device. But it lacks the operation of 'unregister'. It will -lead to 'Segmentation fault (core dumped)' in -qemu_savevm_state_setup(), if performing live migration after a -VFIO device is hot deleted. - -Fixes: cd5b58f2ba (vfio: Register SaveVMHandlers for VFIO device) -Reported-by: Qixin Gan -Signed-off-by: Kunkun Jiang -Message-Id: <20210527123101.289-1-jiangkunkun@huawei.com> -Reviewed by: Kirti Wankhede -Signed-off-by: Alex Williamson ---- - hw/vfio/migration.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -index f1f006d584..d9e0e12824 100644 ---- a/hw/vfio/migration.c -+++ b/hw/vfio/migration.c -@@ -893,6 +893,7 @@ void vfio_migration_finalize(VFIODevice *vbasedev) - - remove_migration_state_change_notifier(&migration->migration_state); - qemu_del_vm_change_state_handler(migration->vm_state); -+ unregister_savevm(vbasedev->dev, "vfio", vbasedev); - vfio_migration_exit(vbasedev); - } - --- -2.27.0 - diff --git a/vfio-Fix-vfio_listener_log_sync-function-name-typo.patch b/vfio-Fix-vfio_listener_log_sync-function-name-typo.patch deleted file mode 100644 index 6a2324b57811f6d375bbc7f795dc07f78baa42e2..0000000000000000000000000000000000000000 --- a/vfio-Fix-vfio_listener_log_sync-function-name-typo.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 094aca3a87e63a0e6ae01b22f382c21dd91bb03e Mon Sep 17 00:00:00 2001 -From: Zenghui Yu -Date: Fri, 4 Dec 2020 09:42:40 +0800 -Subject: [PATCH] vfio: Fix vfio_listener_log_sync function name typo - -There is an obvious typo in the function name of the .log_sync() callback. -Spell it correctly. - -Signed-off-by: Zenghui Yu -Message-Id: <20201204014240.772-1-yuzenghui@huawei.com> -Signed-off-by: Alex Williamson -Signed-off-by: Kunkun Jiang ---- - hw/vfio/common.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index d9cc3509ef..ebd701faa0 100644 ---- a/hw/vfio/common.c -+++ b/hw/vfio/common.c -@@ -1081,7 +1081,7 @@ static int vfio_sync_dirty_bitmap(VFIOContainer *container, - int128_get64(section->size), ram_addr); - } - --static void vfio_listerner_log_sync(MemoryListener *listener, -+static void vfio_listener_log_sync(MemoryListener *listener, - MemoryRegionSection *section) - { - VFIOContainer *container = container_of(listener, VFIOContainer, listener); -@@ -1099,7 +1099,7 @@ static void vfio_listerner_log_sync(MemoryListener *listener, - static const MemoryListener vfio_memory_listener = { - .region_add = vfio_listener_region_add, - .region_del = vfio_listener_region_del, -- .log_sync = vfio_listerner_log_sync, -+ .log_sync = vfio_listener_log_sync, - }; - - static void vfio_listener_release(VFIOContainer *container) --- -2.27.0 - diff --git a/vfio-Force-nested-if-iommu-requires-it.patch b/vfio-Force-nested-if-iommu-requires-it.patch index 6a6b9da3f1ebd6c44f6a298a9c456351a8a93fcd..d580ae5007f6ae7be2adb090d9e6774eeeb323db 100644 --- a/vfio-Force-nested-if-iommu-requires-it.patch +++ b/vfio-Force-nested-if-iommu-requires-it.patch @@ -1,4 +1,4 @@ -From e4122a95a30cd58e1cd6e1742928e68aa94fd7ee Mon Sep 17 00:00:00 2001 +From e7eef5af743a53f0415267ebe9bba2e5f0e05816 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 28 Aug 2018 16:16:20 +0200 Subject: [PATCH] vfio: Force nested if iommu requires it @@ -15,10 +15,10 @@ Signed-off-by: Kunkun Jiang 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index fefa2ccfdf..c78b58d365 100644 +index 6cb91e7ffd..d7533637c9 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -1683,27 +1683,38 @@ static void vfio_put_address_space(VFIOAddressSpace *space) +@@ -2045,27 +2045,38 @@ static void vfio_put_address_space(VFIOAddressSpace *space) * vfio_get_iommu_type - selects the richest iommu_type (v2 first) */ static int vfio_get_iommu_type(VFIOContainer *container, @@ -64,7 +64,7 @@ index fefa2ccfdf..c78b58d365 100644 if (iommu_type < 0) { return iommu_type; } -@@ -1815,6 +1826,14 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, +@@ -2177,6 +2188,14 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, VFIOContainer *container; int ret, fd; VFIOAddressSpace *space; @@ -79,8 +79,8 @@ index fefa2ccfdf..c78b58d365 100644 space = vfio_get_address_space(as); -@@ -1879,13 +1898,14 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, - QLIST_INIT(&container->hostwin_list); +@@ -2257,7 +2276,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, + QLIST_INIT(&container->vrdl_list); QLIST_INIT(&container->dma_list); - ret = vfio_init_container(container, group->fd, errp); @@ -88,7 +88,8 @@ index fefa2ccfdf..c78b58d365 100644 if (ret) { goto free_container_exit; } - trace_vfio_connect_new_container(group->groupid, container->fd); +@@ -2269,6 +2288,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, + } switch (container->iommu_type) { + case VFIO_TYPE1_NESTING_IOMMU: diff --git a/vfio-Get-migration-capability-flags-for-container.patch b/vfio-Get-migration-capability-flags-for-container.patch deleted file mode 100644 index 88b9bb7e6fdfe4f4a75808bbdcb5ec45d354ae15..0000000000000000000000000000000000000000 --- a/vfio-Get-migration-capability-flags-for-container.patch +++ /dev/null @@ -1,186 +0,0 @@ -From fc49c9cbf2deba53370f48ad9db2adc5f6ceb3ba Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:21 +0530 -Subject: [PATCH] vfio: Get migration capability flags for container - -Added helper functions to get IOMMU info capability chain. -Added function to get migration capability information from that -capability chain for IOMMU container. - -Similar change was proposed earlier: -https://lists.gnu.org/archive/html/qemu-devel/2018-05/msg03759.html - -Disable migration for devices if IOMMU module doesn't support migration -capability. - -Signed-off-by: Kirti Wankhede -Cc: Shameer Kolothum -Cc: Eric Auger -Signed-off-by: Alex Williamson ---- - hw/vfio/common.c | 90 +++++++++++++++++++++++++++++++---- - hw/vfio/migration.c | 7 ++- - include/hw/vfio/vfio-common.h | 3 ++ - 3 files changed, 91 insertions(+), 9 deletions(-) - -diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index 4c32b1bb99..35168b8f3e 100644 ---- a/hw/vfio/common.c -+++ b/hw/vfio/common.c -@@ -1210,6 +1210,75 @@ static int vfio_init_container(VFIOContainer *container, int group_fd, - return 0; - } - -+static int vfio_get_iommu_info(VFIOContainer *container, -+ struct vfio_iommu_type1_info **info) -+{ -+ -+ size_t argsz = sizeof(struct vfio_iommu_type1_info); -+ -+ *info = g_new0(struct vfio_iommu_type1_info, 1); -+again: -+ (*info)->argsz = argsz; -+ -+ if (ioctl(container->fd, VFIO_IOMMU_GET_INFO, *info)) { -+ g_free(*info); -+ *info = NULL; -+ return -errno; -+ } -+ -+ if (((*info)->argsz > argsz)) { -+ argsz = (*info)->argsz; -+ *info = g_realloc(*info, argsz); -+ goto again; -+ } -+ -+ return 0; -+} -+ -+static struct vfio_info_cap_header * -+vfio_get_iommu_info_cap(struct vfio_iommu_type1_info *info, uint16_t id) -+{ -+ struct vfio_info_cap_header *hdr; -+ void *ptr = info; -+ -+ if (!(info->flags & VFIO_IOMMU_INFO_CAPS)) { -+ return NULL; -+ } -+ -+ for (hdr = ptr + info->cap_offset; hdr != ptr; hdr = ptr + hdr->next) { -+ if (hdr->id == id) { -+ return hdr; -+ } -+ } -+ -+ return NULL; -+} -+ -+static void vfio_get_iommu_info_migration(VFIOContainer *container, -+ struct vfio_iommu_type1_info *info) -+{ -+ struct vfio_info_cap_header *hdr; -+ struct vfio_iommu_type1_info_cap_migration *cap_mig; -+ -+ hdr = vfio_get_iommu_info_cap(info, VFIO_IOMMU_TYPE1_INFO_CAP_MIGRATION); -+ if (!hdr) { -+ return; -+ } -+ -+ cap_mig = container_of(hdr, struct vfio_iommu_type1_info_cap_migration, -+ header); -+ -+ /* -+ * cpu_physical_memory_set_dirty_lebitmap() expects pages in bitmap of -+ * TARGET_PAGE_SIZE to mark those dirty. -+ */ -+ if (cap_mig->pgsize_bitmap & TARGET_PAGE_SIZE) { -+ container->dirty_pages_supported = true; -+ container->max_dirty_bitmap_size = cap_mig->max_dirty_bitmap_size; -+ container->dirty_pgsizes = cap_mig->pgsize_bitmap; -+ } -+} -+ - static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, - Error **errp) - { -@@ -1273,6 +1342,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, - container = g_malloc0(sizeof(*container)); - container->space = space; - container->fd = fd; -+ container->dirty_pages_supported = false; - QLIST_INIT(&container->giommu_list); - QLIST_INIT(&container->hostwin_list); - -@@ -1285,7 +1355,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, - case VFIO_TYPE1v2_IOMMU: - case VFIO_TYPE1_IOMMU: - { -- struct vfio_iommu_type1_info info; -+ struct vfio_iommu_type1_info *info; - - /* - * FIXME: This assumes that a Type1 IOMMU can map any 64-bit -@@ -1294,15 +1364,19 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, - * existing Type1 IOMMUs generally support any IOVA we're - * going to actually try in practice. - */ -- info.argsz = sizeof(info); -- ret = ioctl(fd, VFIO_IOMMU_GET_INFO, &info); -- /* Ignore errors */ -- if (ret || !(info.flags & VFIO_IOMMU_INFO_PGSIZES)) { -+ ret = vfio_get_iommu_info(container, &info); -+ -+ if (ret || !(info->flags & VFIO_IOMMU_INFO_PGSIZES)) { - /* Assume 4k IOVA page size */ -- info.iova_pgsizes = 4096; -+ info->iova_pgsizes = 4096; - } -- vfio_host_win_add(container, 0, (hwaddr)-1, info.iova_pgsizes); -- container->pgsizes = info.iova_pgsizes; -+ vfio_host_win_add(container, 0, (hwaddr)-1, info->iova_pgsizes); -+ container->pgsizes = info->iova_pgsizes; -+ -+ if (!ret) { -+ vfio_get_iommu_info_migration(container, info); -+ } -+ g_free(info); - break; - } - case VFIO_SPAPR_TCE_v2_IOMMU: -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -index 954c064435..0d2bd9e5cd 100644 ---- a/hw/vfio/migration.c -+++ b/hw/vfio/migration.c -@@ -832,9 +832,14 @@ err: - - int vfio_migration_probe(VFIODevice *vbasedev, Error **errp) - { -+ VFIOContainer *container = vbasedev->group->container; - struct vfio_region_info *info = NULL; - Error *local_err = NULL; -- int ret; -+ int ret = -ENOTSUP; -+ -+ if (!container->dirty_pages_supported) { -+ goto add_blocker; -+ } - - ret = vfio_get_dev_region_info(vbasedev, VFIO_REGION_TYPE_MIGRATION, - VFIO_REGION_SUBTYPE_MIGRATION, &info); -diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index c825524606..8fd0212264 100644 ---- a/include/hw/vfio/vfio-common.h -+++ b/include/hw/vfio/vfio-common.h -@@ -84,6 +84,9 @@ typedef struct VFIOContainer { - unsigned iommu_type; - int error; - bool initialized; -+ bool dirty_pages_supported; -+ uint64_t dirty_pgsizes; -+ uint64_t max_dirty_bitmap_size; - unsigned long pgsizes; - QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; - QLIST_HEAD(, VFIOHostDMAWindow) hostwin_list; --- -2.27.0 - diff --git a/vfio-Helper-to-get-IRQ-info-including-capabilities.patch b/vfio-Helper-to-get-IRQ-info-including-capabilities.patch index 16f16d32faa4d793056700a52ef33b23716801c1..3d4b1667692bf76a3c89c71cd363db5090641986 100644 --- a/vfio-Helper-to-get-IRQ-info-including-capabilities.patch +++ b/vfio-Helper-to-get-IRQ-info-including-capabilities.patch @@ -1,4 +1,4 @@ -From 43fd039dcfee221eb3f86a2cf7deb287cc04e5ad Mon Sep 17 00:00:00 2001 +From a4336765c99a876743c0ead89997ad6f97d7b442 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 20 Jun 2019 16:39:57 +0200 Subject: [PATCH] vfio: Helper to get IRQ info including capabilities @@ -15,11 +15,11 @@ Signed-off-by: Kunkun Jiang 3 files changed, 105 insertions(+) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index db9af3b0e5..98dc9e6f84 100644 +index 1f78af121d..d05a485808 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -1565,6 +1565,25 @@ vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id) - return NULL; +@@ -1919,6 +1919,25 @@ bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, + return true; } +struct vfio_info_cap_header * @@ -44,7 +44,7 @@ index db9af3b0e5..98dc9e6f84 100644 static int vfio_setup_region_sparse_mmaps(VFIORegion *region, struct vfio_region_info *info) { -@@ -2499,6 +2518,33 @@ retry: +@@ -2887,6 +2906,33 @@ retry: return 0; } @@ -78,7 +78,7 @@ index db9af3b0e5..98dc9e6f84 100644 int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, uint32_t subtype, struct vfio_region_info **info) { -@@ -2534,6 +2580,42 @@ int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, +@@ -2922,6 +2968,42 @@ int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, return -ENODEV; } @@ -121,7 +121,7 @@ index db9af3b0e5..98dc9e6f84 100644 bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type) { struct vfio_region_info *info = NULL; -@@ -2549,6 +2631,21 @@ bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type) +@@ -2937,6 +3019,21 @@ bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type) return ret; } @@ -144,7 +144,7 @@ index db9af3b0e5..98dc9e6f84 100644 * Interfaces for IBM EEH (Enhanced Error Handling) */ diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events -index 247b72c1eb..54e10046f5 100644 +index 35bd415d6d..f5fe201ab5 100644 --- a/hw/vfio/trace-events +++ b/hw/vfio/trace-events @@ -117,6 +117,7 @@ vfio_region_unmap(const char *name, unsigned long offset, unsigned long end) "Re @@ -156,13 +156,13 @@ index 247b72c1eb..54e10046f5 100644 vfio_iommu_addr_inv_iotlb(int asid, uint64_t addr, uint64_t size, uint64_t nb_granules, bool leaf) "nested IOTLB invalidate asid=%d, addr=0x%"PRIx64" granule_size=0x%"PRIx64" nb_granules=0x%"PRIx64" leaf=%d" vfio_iommu_asid_inv_iotlb(int asid) "nested IOTLB invalidate asid=%d" diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index b175158138..a82962ab16 100644 +index a838a939e4..7fdca26fa0 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h -@@ -238,6 +238,13 @@ int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, - bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type); +@@ -254,6 +254,13 @@ bool vfio_get_info_dma_avail(struct vfio_iommu_type1_info *info, + unsigned int *avail); struct vfio_info_cap_header * - vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id); + vfio_get_device_info_cap(struct vfio_device_info *info, uint16_t id); +int vfio_get_irq_info(VFIODevice *vbasedev, int index, + struct vfio_irq_info **info); +int vfio_get_dev_irq_info(VFIODevice *vbasedev, uint32_t type, diff --git a/vfio-Introduce-helpers-to-DMA-map-unmap-a-RAM-sectio.patch b/vfio-Introduce-helpers-to-DMA-map-unmap-a-RAM-sectio.patch index 124587d1e081a65740786aefbd1033d895678245..fd6deffd16ce01ee2a97e4061ac358e974a49320 100644 --- a/vfio-Introduce-helpers-to-DMA-map-unmap-a-RAM-sectio.patch +++ b/vfio-Introduce-helpers-to-DMA-map-unmap-a-RAM-sectio.patch @@ -1,4 +1,4 @@ -From eb3bfdb61025efe2891ce6732b8829a48dd75e2d Mon Sep 17 00:00:00 2001 +From dab969657d8ff8b175856f91b035b74849cf69ba Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 30 Aug 2018 15:04:25 +0200 Subject: [PATCH] vfio: Introduce helpers to DMA map/unmap a RAM section @@ -11,20 +11,20 @@ structure may be clearer. Signed-off-by: Eric Auger Signed-off-by: Kunkun Jiang --- - hw/vfio/common.c | 187 +++++++++++++++++++++++++++---------------- + hw/vfio/common.c | 206 +++++++++++++++++++++++++------------------ hw/vfio/trace-events | 4 +- - 2 files changed, 119 insertions(+), 72 deletions(-) + 2 files changed, 123 insertions(+), 87 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index a8db784ac5..8837d33c57 100644 +index d358789f19..b3dc090840 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -709,13 +709,126 @@ hostwin_from_range(VFIOContainer *container, hwaddr iova, hwaddr end) +@@ -922,13 +922,130 @@ hostwin_from_range(VFIOContainer *container, hwaddr iova, hwaddr end) return NULL; } +static int vfio_dma_map_ram_section(VFIOContainer *container, -+ MemoryRegionSection *section) ++ MemoryRegionSection *section, Error **err) +{ + VFIOHostDMAWindow *hostwin; + Int128 llend, llsize; @@ -46,9 +46,8 @@ index a8db784ac5..8837d33c57 100644 + + hostwin = hostwin_from_range(container, iova, end); + if (!hostwin) { -+ error_report("vfio: IOMMU Container %p can't map guest IOVA region" -+ " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx, -+ container, iova, end); ++ error_setg(err, "Container %p can't map guest IOVA region" ++ " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx, container, iova, end); + return -EFAULT; + } + @@ -72,11 +71,12 @@ index a8db784ac5..8837d33c57 100644 + ret = vfio_dma_map(container, iova, int128_get64(llsize), + vaddr, section->readonly); + if (ret) { -+ error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", " -+ "0x%"HWADDR_PRIx", %p) = %d (%m)", -+ container, iova, int128_get64(llsize), vaddr, ret); ++ error_setg(err, "vfio_dma_map(%p, 0x%"HWADDR_PRIx", " ++ "0x%"HWADDR_PRIx", %p) = %d (%m)", ++ container, iova, int128_get64(llsize), vaddr, ret); + if (memory_region_is_ram_device(section->mr)) { + /* Allow unexpected mappings not to be fatal for RAM devices */ ++ error_report_err(*err); + return 0; + } + return ret; @@ -114,6 +114,10 @@ index a8db784ac5..8837d33c57 100644 + + pgmask = (1ULL << ctz64(hostwin->iova_pgsizes)) - 1; + try_unmap = !((iova & pgmask) || (int128_get64(llsize) & pgmask)); ++ } else if (memory_region_has_ram_discard_manager(section->mr)) { ++ vfio_unregister_ram_discard_listener(container, section); ++ /* Unregistering will trigger an unmap. */ ++ try_unmap = false; + } + + if (try_unmap) { @@ -147,12 +151,11 @@ index a8db784ac5..8837d33c57 100644 + Int128 llend; int ret; VFIOHostDMAWindow *hostwin; - -@@ -842,38 +955,7 @@ static void vfio_listener_region_add(MemoryListener *listener, + Error *err = NULL; +@@ -1092,38 +1209,7 @@ static void vfio_listener_region_add(MemoryListener *listener, + return; } - /* Here we assume that memory_region_is_ram(section->mr)==true */ -- - vaddr = memory_region_get_ram_ptr(section->mr) + - section->offset_within_region + - (iova - section->offset_within_address_space); @@ -177,18 +180,19 @@ index a8db784ac5..8837d33c57 100644 - ret = vfio_dma_map(container, iova, int128_get64(llsize), - vaddr, section->readonly); - if (ret) { -- error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", " -- "0x%"HWADDR_PRIx", %p) = %d (%m)", -- container, iova, int128_get64(llsize), vaddr, ret); +- error_setg(&err, "vfio_dma_map(%p, 0x%"HWADDR_PRIx", " +- "0x%"HWADDR_PRIx", %p) = %d (%m)", +- container, iova, int128_get64(llsize), vaddr, ret); - if (memory_region_is_ram_device(section->mr)) { - /* Allow unexpected mappings not to be fatal for RAM devices */ +- error_report_err(err); - return; - } -+ if (vfio_dma_map_ram_section(container, section)) { ++ if (vfio_dma_map_ram_section(container, section, &err)) { goto fail; } -@@ -902,10 +984,6 @@ static void vfio_listener_region_del(MemoryListener *listener, +@@ -1157,10 +1243,6 @@ static void vfio_listener_region_del(MemoryListener *listener, MemoryRegionSection *section) { VFIOContainer *container = container_of(listener, VFIOContainer, listener); @@ -199,7 +203,7 @@ index a8db784ac5..8837d33c57 100644 if (vfio_listener_skipped_section(section)) { trace_vfio_listener_region_del_skip( -@@ -945,38 +1023,7 @@ static void vfio_listener_region_del(MemoryListener *listener, +@@ -1200,53 +1282,7 @@ static void vfio_listener_region_del(MemoryListener *listener, */ } @@ -225,9 +229,24 @@ index a8db784ac5..8837d33c57 100644 - - pgmask = (1ULL << ctz64(hostwin->iova_pgsizes)) - 1; - try_unmap = !((iova & pgmask) || (int128_get64(llsize) & pgmask)); +- } else if (memory_region_has_ram_discard_manager(section->mr)) { +- vfio_unregister_ram_discard_listener(container, section); +- /* Unregistering will trigger an unmap. */ +- try_unmap = false; - } - - if (try_unmap) { +- if (int128_eq(llsize, int128_2_64())) { +- /* The unmap ioctl doesn't accept a full 64-bit span. */ +- llsize = int128_rshift(llsize, 1); +- ret = vfio_dma_unmap(container, iova, int128_get64(llsize), NULL); +- if (ret) { +- error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", " +- "0x%"HWADDR_PRIx") = %d (%m)", +- container, iova, int128_get64(llsize), ret); +- } +- iova += int128_get64(llsize); +- } - ret = vfio_dma_unmap(container, iova, int128_get64(llsize), NULL); - if (ret) { - error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", " @@ -240,10 +259,10 @@ index a8db784ac5..8837d33c57 100644 memory_region_unref(section->mr); diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events -index 561dc6e758..9b6c7ca61b 100644 +index 0ef1b5f4a6..a37563a315 100644 --- a/hw/vfio/trace-events +++ b/hw/vfio/trace-events -@@ -97,10 +97,10 @@ vfio_iommu_map_notify(const char *op, uint64_t iova_start, uint64_t iova_end) "i +@@ -99,10 +99,10 @@ vfio_iommu_map_notify(const char *op, uint64_t iova_start, uint64_t iova_end) "i vfio_listener_region_add_skip(uint64_t start, uint64_t end) "SKIPPING region_add 0x%"PRIx64" - 0x%"PRIx64 vfio_spapr_group_attach(int groupfd, int tablefd) "Attached groupfd %d to liobn fd %d" vfio_listener_region_add_iommu(uint64_t start, uint64_t end) "region_add [iommu] 0x%"PRIx64" - 0x%"PRIx64 @@ -254,8 +273,8 @@ index 561dc6e758..9b6c7ca61b 100644 -vfio_listener_region_del(uint64_t start, uint64_t end) "region_del 0x%"PRIx64" - 0x%"PRIx64 +vfio_dma_unmap_ram(uint64_t start, uint64_t end) "region_del 0x%"PRIx64" - 0x%"PRIx64 vfio_disconnect_container(int fd) "close container->fd=%d" - vfio_connect_existing_container(int groupid, int container_fd) "group=%d existing container fd=%d" - vfio_connect_new_container(int groupid, int container_fd) "group=%d new container fd=%d" + vfio_put_group(int fd) "close group->fd=%d" + vfio_get_device(const char * name, unsigned int flags, unsigned int num_regions, unsigned int num_irqs) "Device %s flags: %u, regions: %u, irqs: %u" -- 2.27.0 diff --git a/vfio-Introduce-helpers-to-mark-dirty-pages-of-a-RAM-.patch b/vfio-Introduce-helpers-to-mark-dirty-pages-of-a-RAM-.patch index 274a0c08a92bfa268f3fab8a5d7842cdbab9d273..e77dd1d64b4bdfb606e7987df653d5e365c27c98 100644 --- a/vfio-Introduce-helpers-to-mark-dirty-pages-of-a-RAM-.patch +++ b/vfio-Introduce-helpers-to-mark-dirty-pages-of-a-RAM-.patch @@ -1,4 +1,4 @@ -From ff9c1f7e3e17cc2afe1b2dfa545065e91941db8b Mon Sep 17 00:00:00 2001 +From 1675d767aa9bd496178b4d74e01a40dbbd97eccb Mon Sep 17 00:00:00 2001 From: Kunkun Jiang Date: Tue, 11 May 2021 10:08:13 +0800 Subject: [PATCH] vfio: Introduce helpers to mark dirty pages of a RAM section @@ -13,10 +13,10 @@ Signed-off-by: Kunkun Jiang 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index 21a866e545..5176fd3a3d 100644 +index bdfcc854fe..6136b1ef61 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -1304,6 +1304,19 @@ err_out: +@@ -1566,6 +1566,19 @@ err_out: return ret; } @@ -36,7 +36,7 @@ index 21a866e545..5176fd3a3d 100644 typedef struct { IOMMUNotifier n; VFIOGuestIOMMU *giommu; -@@ -1345,8 +1358,6 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) +@@ -1650,8 +1663,6 @@ static int vfio_sync_ram_discard_listener_dirty_bitmap(VFIOContainer *container, static int vfio_sync_dirty_bitmap(VFIOContainer *container, MemoryRegionSection *section) { @@ -45,8 +45,8 @@ index 21a866e545..5176fd3a3d 100644 if (memory_region_is_iommu(section->mr)) { VFIOGuestIOMMU *giommu; -@@ -1375,12 +1386,7 @@ static int vfio_sync_dirty_bitmap(VFIOContainer *container, - return 0; +@@ -1682,12 +1693,7 @@ static int vfio_sync_dirty_bitmap(VFIOContainer *container, + return vfio_sync_ram_discard_listener_dirty_bitmap(container, section); } - ram_addr = memory_region_get_ram_addr(section->mr) + diff --git a/vfio-Introduce-hostwin_from_range-helper.patch b/vfio-Introduce-hostwin_from_range-helper.patch index b9a7099de2a6eeaa9265be66c8818ffc852e6583..c8c8ab76922a95fbcfdec74b92b11dc688ce2745 100644 --- a/vfio-Introduce-hostwin_from_range-helper.patch +++ b/vfio-Introduce-hostwin_from_range-helper.patch @@ -1,4 +1,4 @@ -From 25336cd596ff551293f1be6e108ad9277d80be0f Mon Sep 17 00:00:00 2001 +From 85232739b4852f1a51dde58c9007ed0deb17c2f2 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Fri, 22 Mar 2019 18:05:23 +0100 Subject: [PATCH] vfio: Introduce hostwin_from_range helper @@ -16,11 +16,11 @@ Signed-off-by: Kunkun Jiang 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index c78b58d365..a8db784ac5 100644 +index d7533637c9..d358789f19 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -696,6 +696,19 @@ out: - rcu_read_unlock(); +@@ -909,6 +909,19 @@ static void vfio_unregister_ram_discard_listener(VFIOContainer *container, + g_free(vrdl); } +static VFIOHostDMAWindow * @@ -39,15 +39,15 @@ index c78b58d365..a8db784ac5 100644 static void vfio_listener_region_add(MemoryListener *listener, MemoryRegionSection *section) { -@@ -705,7 +718,6 @@ static void vfio_listener_region_add(MemoryListener *listener, +@@ -918,7 +931,6 @@ static void vfio_listener_region_add(MemoryListener *listener, void *vaddr; int ret; VFIOHostDMAWindow *hostwin; - bool hostwin_found; + Error *err = NULL; if (vfio_listener_skipped_section(section)) { - trace_vfio_listener_region_add_skip( -@@ -783,15 +795,8 @@ static void vfio_listener_region_add(MemoryListener *listener, +@@ -1011,15 +1023,8 @@ static void vfio_listener_region_add(MemoryListener *listener, #endif } @@ -62,10 +62,10 @@ index c78b58d365..a8db784ac5 100644 - if (!hostwin_found) { + hostwin = hostwin_from_range(container, iova, end); + if (!hostwin) { - error_report("vfio: IOMMU container %p can't map guest IOVA region" - " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx, - container, iova, end); -@@ -956,16 +961,9 @@ static void vfio_listener_region_del(MemoryListener *listener, + error_setg(&err, "Container %p can't map guest IOVA region" + " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx, container, iova, end); + goto fail; +@@ -1211,16 +1216,9 @@ static void vfio_listener_region_del(MemoryListener *listener, if (memory_region_is_ram_device(section->mr)) { hwaddr pgmask; diff --git a/vfio-Maintain-DMA-mapping-range-for-the-container.patch b/vfio-Maintain-DMA-mapping-range-for-the-container.patch index 901a5e38ea78a2c490875611f12658151da661b9..ba8abb431c5606de905890d5be95e37f4d0ccf8e 100644 --- a/vfio-Maintain-DMA-mapping-range-for-the-container.patch +++ b/vfio-Maintain-DMA-mapping-range-for-the-container.patch @@ -1,4 +1,4 @@ -From 90a6a1ec65d55d27faf79341b2dd9418d99da187 Mon Sep 17 00:00:00 2001 +From ac1bf3edcd2b807cf81ada500716f13b1394d58e Mon Sep 17 00:00:00 2001 From: Zenghui Yu Date: Sat, 8 May 2021 17:31:04 +0800 Subject: [PATCH] vfio: Maintain DMA mapping range for the container @@ -36,10 +36,10 @@ Signed-off-by: Kunkun Jiang 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index 245e32df5b..c33c4c539d 100644 +index 080046e3f5..86ea784919 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -420,6 +420,29 @@ unmap_exit: +@@ -445,6 +445,29 @@ unmap_exit: return ret; } @@ -69,7 +69,7 @@ index 245e32df5b..c33c4c539d 100644 /* * DMA - Mapping and unmapping for the "type1" IOMMU interface used on x86 */ -@@ -433,12 +456,29 @@ static int vfio_dma_unmap(VFIOContainer *container, +@@ -458,12 +481,29 @@ static int vfio_dma_unmap(VFIOContainer *container, .iova = iova, .size = size, }; @@ -99,7 +99,7 @@ index 245e32df5b..c33c4c539d 100644 while (ioctl(container->fd, VFIO_IOMMU_UNMAP_DMA, &unmap)) { /* * The type1 backend has an off-by-one bug in the kernel (71a7d3d78e3c -@@ -475,6 +515,14 @@ static int vfio_dma_map(VFIOContainer *container, hwaddr iova, +@@ -500,6 +540,14 @@ static int vfio_dma_map(VFIOContainer *container, hwaddr iova, .iova = iova, .size = size, }; @@ -114,7 +114,7 @@ index 245e32df5b..c33c4c539d 100644 if (!readonly) { map.flags |= VFIO_DMA_MAP_FLAG_WRITE; -@@ -986,9 +1034,14 @@ static int vfio_get_dirty_bitmap(VFIOContainer *container, uint64_t iova, +@@ -1256,9 +1304,14 @@ static int vfio_get_dirty_bitmap(VFIOContainer *container, uint64_t iova, { struct vfio_iommu_type1_dirty_bitmap *dbitmap; struct vfio_iommu_type1_dirty_bitmap_get *range; @@ -129,7 +129,7 @@ index 245e32df5b..c33c4c539d 100644 dbitmap = g_malloc0(sizeof(*dbitmap) + sizeof(*range)); dbitmap->argsz = sizeof(*dbitmap) + sizeof(*range); -@@ -1007,11 +1060,8 @@ static int vfio_get_dirty_bitmap(VFIOContainer *container, uint64_t iova, +@@ -1277,11 +1330,8 @@ static int vfio_get_dirty_bitmap(VFIOContainer *container, uint64_t iova, pages = REAL_HOST_PAGE_ALIGN(range->size) / qemu_real_host_page_size; range->bitmap.size = ROUND_UP(pages, sizeof(__u64) * BITS_PER_BYTE) / BITS_PER_BYTE; @@ -143,7 +143,7 @@ index 245e32df5b..c33c4c539d 100644 ret = ioctl(container->fd, VFIO_IOMMU_DIRTY_PAGES, dbitmap); if (ret) { -@@ -1027,7 +1077,6 @@ static int vfio_get_dirty_bitmap(VFIOContainer *container, uint64_t iova, +@@ -1297,7 +1347,6 @@ static int vfio_get_dirty_bitmap(VFIOContainer *container, uint64_t iova, trace_vfio_get_dirty_bitmap(container->fd, range->iova, range->size, range->bitmap.size, ram_addr); err_out: @@ -151,16 +151,16 @@ index 245e32df5b..c33c4c539d 100644 g_free(dbitmap); return ret; -@@ -1681,6 +1730,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, - container->dirty_pages_supported = false; +@@ -2061,6 +2110,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, QLIST_INIT(&container->giommu_list); QLIST_INIT(&container->hostwin_list); + QLIST_INIT(&container->vrdl_list); + QLIST_INIT(&container->dma_list); ret = vfio_init_container(container, group->fd, errp); if (ret) { diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index 475aa9fb40..2853dc861e 100644 +index 8af11b0a76..20b9c8a1d3 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -76,6 +76,14 @@ typedef struct VFIOAddressSpace { @@ -178,10 +178,10 @@ index 475aa9fb40..2853dc861e 100644 typedef struct VFIOContainer { VFIOAddressSpace *space; int fd; /* /dev/vfio/vfio, empowered by the attached groups */ -@@ -91,6 +99,7 @@ typedef struct VFIOContainer { - QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; +@@ -93,6 +101,7 @@ typedef struct VFIOContainer { QLIST_HEAD(, VFIOHostDMAWindow) hostwin_list; QLIST_HEAD(, VFIOGroup) group_list; + QLIST_HEAD(, VFIORamDiscardListener) vrdl_list; + QLIST_HEAD(, VFIODMARange) dma_list; QLIST_ENTRY(VFIOContainer) next; } VFIOContainer; diff --git a/vfio-Make-migration-support-experimental.patch b/vfio-Make-migration-support-experimental.patch deleted file mode 100644 index 3bf32ecaf443b40929932743cd3d9f3b951011b2..0000000000000000000000000000000000000000 --- a/vfio-Make-migration-support-experimental.patch +++ /dev/null @@ -1,72 +0,0 @@ -From d0a8ba1957743c55547ec2ccd8cb09b84a3354d2 Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Mon, 9 Nov 2020 11:56:02 -0700 -Subject: [PATCH] vfio: Make migration support experimental - -Support for migration of vfio devices is still in flux. Developers -are attempting to add support for new devices and new architectures, -but none are yet readily available for validation. We have concerns -whether we're transferring device resources at the right point in the -migration, whether we're guaranteeing that updates during pre-copy are -migrated, and whether we can provide bit-stream compatibility should -any of this change. Even the question of whether devices should -participate in dirty page tracking during pre-copy seems contentious. -In short, migration support has not had enough soak time and it feels -premature to mark it as supported. - -Create an experimental option such that we can continue to develop. - -[Retaining previous acks/reviews for a previously identical code - change with different specifics in the commit log.] - -Reviewed-by: Dr. David Alan Gilbert -Acked-by: Cornelia Huck -Signed-off-by: Alex Williamson -Signed-off-by: Kunkun Jiang ---- - hw/vfio/migration.c | 2 +- - hw/vfio/pci.c | 2 ++ - include/hw/vfio/vfio-common.h | 1 + - 3 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -index 8546075706..033cb2b0c9 100644 ---- a/hw/vfio/migration.c -+++ b/hw/vfio/migration.c -@@ -888,7 +888,7 @@ int vfio_migration_probe(VFIODevice *vbasedev, Error **errp) - Error *local_err = NULL; - int ret = -ENOTSUP; - -- if (!container->dirty_pages_supported) { -+ if (!vbasedev->enable_migration || !container->dirty_pages_supported) { - goto add_blocker; - } - -diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c -index da7c740bce..2795b8bd12 100644 ---- a/hw/vfio/pci.c -+++ b/hw/vfio/pci.c -@@ -3192,6 +3192,8 @@ static Property vfio_pci_dev_properties[] = { - VFIO_FEATURE_ENABLE_REQ_BIT, true), - DEFINE_PROP_BIT("x-igd-opregion", VFIOPCIDevice, features, - VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT, false), -+ DEFINE_PROP_BOOL("x-enable-migration", VFIOPCIDevice, -+ vbasedev.enable_migration, false), - DEFINE_PROP_BOOL("x-no-mmap", VFIOPCIDevice, vbasedev.no_mmap, false), - DEFINE_PROP_BOOL("x-balloon-allowed", VFIOPCIDevice, - vbasedev.balloon_allowed, false), -diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index 048731e81f..7398631d4c 100644 ---- a/include/hw/vfio/vfio-common.h -+++ b/include/hw/vfio/vfio-common.h -@@ -123,6 +123,7 @@ typedef struct VFIODevice { - bool needs_reset; - bool no_mmap; - bool balloon_allowed; -+ bool enable_migration; - VFIODeviceOps *ops; - unsigned int num_irqs; - unsigned int num_regions; --- -2.27.0 - diff --git a/vfio-Make-vfio-pci-device-migration-capable.patch b/vfio-Make-vfio-pci-device-migration-capable.patch deleted file mode 100644 index 7e87ec7d7820b8ee4be0de5d55039336c47988fd..0000000000000000000000000000000000000000 --- a/vfio-Make-vfio-pci-device-migration-capable.patch +++ /dev/null @@ -1,73 +0,0 @@ -From b20bf027d44809dd6c6376cf0b77e5c5b2057cba Mon Sep 17 00:00:00 2001 -From: Jens Freimann -Date: Tue, 29 Oct 2019 12:49:05 +0100 -Subject: [PATCH] vfio: Make vfio-pci device migration capable - -If the device is not a failover primary device, call -vfio_migration_probe() and vfio_migration_finalize() to enable -migration support for those devices that support it respectively to -tear it down again. -Removed migration blocker from VFIO PCI device specific structure and use -migration blocker from generic structure of VFIO device. - -Note: Since the current version don't add the failover feature for assigned -PCI devices, just remove the failover related code in the original patch for -simplicity. - -Signed-off-by: Kirti Wankhede -Reviewed-by: Neo Jia -Reviewed-by: Dr. David Alan Gilbert -Reviewed-by: Cornelia Huck -Signed-off-by: Alex Williamson -Signed-off-by: Shenming Lu ---- - hw/vfio/pci.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c -index b9fae3ad28..a637c35e7a 100644 ---- a/hw/vfio/pci.c -+++ b/hw/vfio/pci.c -@@ -3049,6 +3049,11 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) - } - } - -+ ret = vfio_migration_probe(&vdev->vbasedev, errp); -+ if (ret) { -+ error_report("%s: Migration disabled", vdev->vbasedev.name); -+ } -+ - vfio_register_err_notifier(vdev); - vfio_register_req_notifier(vdev); - vfio_setup_resetfn_quirk(vdev); -@@ -3096,6 +3101,7 @@ static void vfio_exitfn(PCIDevice *pdev) - } - vfio_teardown_msi(vdev); - vfio_bars_exit(vdev); -+ vfio_migration_finalize(&vdev->vbasedev); - } - - static void vfio_pci_reset(DeviceState *dev) -@@ -3204,11 +3210,6 @@ static Property vfio_pci_dev_properties[] = { - DEFINE_PROP_END_OF_LIST(), - }; - --static const VMStateDescription vfio_pci_vmstate = { -- .name = "vfio-pci", -- .unmigratable = 1, --}; -- - static void vfio_pci_dev_class_init(ObjectClass *klass, void *data) - { - DeviceClass *dc = DEVICE_CLASS(klass); -@@ -3216,7 +3217,6 @@ static void vfio_pci_dev_class_init(ObjectClass *klass, void *data) - - dc->reset = vfio_pci_reset; - dc->props = vfio_pci_dev_properties; -- dc->vmsd = &vfio_pci_vmstate; - dc->desc = "VFIO-based PCI device assignment"; - set_bit(DEVICE_CATEGORY_MISC, dc->categories); - pdc->realize = vfio_realize; --- -2.27.0 - diff --git a/vfio-Move-the-saving-of-the-config-space-to-the-righ.patch b/vfio-Move-the-saving-of-the-config-space-to-the-righ.patch deleted file mode 100644 index 438c426803c4f77ea21220e6917ecf27ab566857..0000000000000000000000000000000000000000 --- a/vfio-Move-the-saving-of-the-config-space-to-the-righ.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 483baf4c668fbd2da76e6948576e13eded1c54ec Mon Sep 17 00:00:00 2001 -From: Shenming Lu -Date: Wed, 10 Mar 2021 11:02:31 +0800 -Subject: [PATCH] vfio: Move the saving of the config space to the right place - in VFIO migration - -On ARM64 the VFIO SET_IRQS ioctl is dependent on the VM interrupt -setup, if the restoring of the VFIO PCI device config space is -before the VGIC, an error might occur in the kernel. - -So we move the saving of the config space to the non-iterable -process, thus it will be called after the VGIC according to -their priorities. - -As for the possible dependence of the device specific migration -data on it's config space, we can let the vendor driver to -include any config info it needs in its own data stream. - -Signed-off-by: Shenming Lu -Reviewed-by: Kirti Wankhede -Message-Id: <20210310030233.1133-2-lushenming@huawei.com> -Signed-off-by: Alex Williamson ---- - hw/vfio/migration.c | 25 +++++++++++++++---------- - 1 file changed, 15 insertions(+), 10 deletions(-) - -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -index b77c66557e..ea36ae5225 100644 ---- a/hw/vfio/migration.c -+++ b/hw/vfio/migration.c -@@ -575,11 +575,6 @@ static int vfio_save_complete_precopy(QEMUFile *f, void *opaque) - return ret; - } - -- ret = vfio_save_device_config_state(f, opaque); -- if (ret) { -- return ret; -- } -- - ret = vfio_update_pending(vbasedev); - if (ret) { - return ret; -@@ -620,6 +615,19 @@ static int vfio_save_complete_precopy(QEMUFile *f, void *opaque) - return ret; - } - -+static void vfio_save_state(QEMUFile *f, void *opaque) -+{ -+ VFIODevice *vbasedev = opaque; -+ int ret; -+ -+ ret = vfio_save_device_config_state(f, opaque); -+ if (ret) { -+ error_report("%s: Failed to save device config space", -+ vbasedev->name); -+ qemu_file_set_error(f, ret); -+ } -+} -+ - static int vfio_load_setup(QEMUFile *f, void *opaque) - { - VFIODevice *vbasedev = opaque; -@@ -670,11 +678,7 @@ static int vfio_load_state(QEMUFile *f, void *opaque, int version_id) - switch (data) { - case VFIO_MIG_FLAG_DEV_CONFIG_STATE: - { -- ret = vfio_load_device_config_state(f, opaque); -- if (ret) { -- return ret; -- } -- break; -+ return vfio_load_device_config_state(f, opaque); - } - case VFIO_MIG_FLAG_DEV_SETUP_STATE: - { -@@ -720,6 +724,7 @@ static SaveVMHandlers savevm_vfio_handlers = { - .save_live_pending = vfio_save_pending, - .save_live_iterate = vfio_save_iterate, - .save_live_complete_precopy = vfio_save_complete_precopy, -+ .save_state = vfio_save_state, - .load_setup = vfio_load_setup, - .load_cleanup = vfio_load_cleanup, - .load_state = vfio_load_state, --- -2.27.0 - diff --git a/vfio-Pass-stage-1-MSI-bindings-to-the-host.patch b/vfio-Pass-stage-1-MSI-bindings-to-the-host.patch index 1ad94b06ad73ccf44d049daa2b8ff35b3624d539..bed28007ce19c71e58690d3ceb7ce5c9dd87a9d4 100644 --- a/vfio-Pass-stage-1-MSI-bindings-to-the-host.patch +++ b/vfio-Pass-stage-1-MSI-bindings-to-the-host.patch @@ -1,4 +1,4 @@ -From 1729ae16dc557c0ad54cab3096b5cb6649d181ae Mon Sep 17 00:00:00 2001 +From 8b4fbe869f8a1f510896c86067d2e4fc3dc82eb9 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 14 Aug 2018 08:08:11 -0400 Subject: [PATCH] vfio: Pass stage 1 MSI bindings to the host @@ -16,10 +16,10 @@ Signed-off-by: Kunkun Jiang 4 files changed, 147 insertions(+), 2 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index cc50efdbc1..db9af3b0e5 100644 +index 58f8a43a43..1f78af121d 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -709,6 +709,65 @@ static void vfio_iommu_unmap_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) +@@ -774,6 +774,65 @@ static void vfio_iommu_unmap_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) } } @@ -86,10 +86,10 @@ index cc50efdbc1..db9af3b0e5 100644 { VFIOGuestIOMMU *giommu = container_of(n, VFIOGuestIOMMU, n); diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c -index 6c90ec9278..bbcba3fd16 100644 +index ae5e014e5d..99c52a0944 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c -@@ -360,6 +360,65 @@ static void vfio_msi_interrupt(void *opaque) +@@ -365,6 +365,65 @@ static void vfio_msi_interrupt(void *opaque) notify(&vdev->pdev, nr); } @@ -155,7 +155,7 @@ index 6c90ec9278..bbcba3fd16 100644 static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix) { struct vfio_irq_set *irq_set; -@@ -377,7 +436,7 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix) +@@ -382,7 +441,7 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix) fds = (int32_t *)&irq_set->data; for (i = 0; i < vdev->nr_vectors; i++) { @@ -164,7 +164,7 @@ index 6c90ec9278..bbcba3fd16 100644 /* * MSI vs MSI-X - The guest has direct access to MSI mask and pending -@@ -386,6 +445,12 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix) +@@ -391,6 +450,12 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix) * KVM signaling path only when configured and unmasked. */ if (vdev->msi_vectors[i].use) { @@ -177,7 +177,7 @@ index 6c90ec9278..bbcba3fd16 100644 if (vdev->msi_vectors[i].virq < 0 || (msix && msix_is_masked(&vdev->pdev, i))) { fd = event_notifier_get_fd(&vdev->msi_vectors[i].interrupt); -@@ -399,6 +464,7 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix) +@@ -404,6 +469,7 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix) ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set); @@ -185,7 +185,7 @@ index 6c90ec9278..bbcba3fd16 100644 g_free(irq_set); return ret; -@@ -712,7 +778,8 @@ static void vfio_msi_disable_common(VFIOPCIDevice *vdev) +@@ -718,7 +784,8 @@ static void vfio_msi_disable_common(VFIOPCIDevice *vdev) static void vfio_msix_disable(VFIOPCIDevice *vdev) { @@ -195,7 +195,7 @@ index 6c90ec9278..bbcba3fd16 100644 msix_unset_vector_notifiers(&vdev->pdev); -@@ -724,6 +791,11 @@ static void vfio_msix_disable(VFIOPCIDevice *vdev) +@@ -730,6 +797,11 @@ static void vfio_msix_disable(VFIOPCIDevice *vdev) if (vdev->msi_vectors[i].use) { vfio_msix_vector_release(&vdev->pdev, i); msix_vector_unuse(&vdev->pdev, i); @@ -208,7 +208,7 @@ index 6c90ec9278..bbcba3fd16 100644 } diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events -index ee9a67d3ef..247b72c1eb 100644 +index 20069935f5..35bd415d6d 100644 --- a/hw/vfio/trace-events +++ b/hw/vfio/trace-events @@ -120,6 +120,8 @@ vfio_get_dev_region(const char *name, int index, uint32_t type, uint32_t subtype @@ -221,7 +221,7 @@ index ee9a67d3ef..247b72c1eb 100644 # platform.c vfio_platform_base_device_init(char *name, int groupid) "%s belongs to group #%d" diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index 1277914ca8..b175158138 100644 +index 0234f5e1b1..a838a939e4 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -74,6 +74,14 @@ typedef struct VFIOAddressSpace { @@ -239,15 +239,15 @@ index 1277914ca8..b175158138 100644 struct VFIOGroup; typedef struct VFIODMARange { -@@ -101,6 +109,7 @@ typedef struct VFIOContainer { - QLIST_HEAD(, VFIOHostDMAWindow) hostwin_list; +@@ -103,6 +111,7 @@ typedef struct VFIOContainer { QLIST_HEAD(, VFIOGroup) group_list; + QLIST_HEAD(, VFIORamDiscardListener) vrdl_list; QLIST_HEAD(, VFIODMARange) dma_list; + QLIST_HEAD(, VFIOMSIBinding) msibinding_list; QLIST_ENTRY(VFIOContainer) next; } VFIOContainer; -@@ -210,6 +219,9 @@ VFIOGroup *vfio_get_group(int groupid, AddressSpace *as, Error **errp); +@@ -222,6 +231,9 @@ VFIOGroup *vfio_get_group(int groupid, AddressSpace *as, Error **errp); void vfio_put_group(VFIOGroup *group); int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vbasedev, Error **errp); diff --git a/vfio-Register-SaveVMHandlers-for-VFIO-device.patch b/vfio-Register-SaveVMHandlers-for-VFIO-device.patch deleted file mode 100644 index 8e12cd2bb2bbfede3be871fb31a3a96562fedc15..0000000000000000000000000000000000000000 --- a/vfio-Register-SaveVMHandlers-for-VFIO-device.patch +++ /dev/null @@ -1,183 +0,0 @@ -From cd5b58f2ba20e59f2c29d955b8bbd7f5016030b7 Mon Sep 17 00:00:00 2001 -From: Kirti Wankhede -Date: Mon, 26 Oct 2020 15:06:17 +0530 -Subject: [PATCH] vfio: Register SaveVMHandlers for VFIO device - -Define flags to be used as delimiter in migration stream for VFIO devices. -Added .save_setup and .save_cleanup functions. Map & unmap migration -region from these functions at source during saving or pre-copy phase. - -Set VFIO device state depending on VM's state. During live migration, VM is -running when .save_setup is called, _SAVING | _RUNNING state is set for VFIO -device. During save-restore, VM is paused, _SAVING state is set for VFIO device. - -Signed-off-by: Kirti Wankhede -Reviewed-by: Neo Jia -Reviewed-by: Cornelia Huck -Reviewed-by: Yan Zhao -Signed-off-by: Alex Williamson ---- - hw/vfio/migration.c | 102 +++++++++++++++++++++++++++++++++++++++++++ - hw/vfio/trace-events | 2 + - 2 files changed, 104 insertions(+) - -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -index 0c6c9b655f..405228fc5a 100644 ---- a/hw/vfio/migration.c -+++ b/hw/vfio/migration.c -@@ -8,12 +8,15 @@ - */ - - #include "qemu/osdep.h" -+#include "qemu/main-loop.h" -+#include "qemu/cutils.h" - #include - - #include "sysemu/sysemu.h" - #include "hw/vfio/vfio-common.h" - #include "cpu.h" - #include "migration/migration.h" -+#include "migration/vmstate.h" - #include "migration/qemu-file.h" - #include "migration/register.h" - #include "migration/blocker.h" -@@ -25,6 +28,22 @@ - #include "trace.h" - #include "hw/hw.h" - -+/* -+ * Flags to be used as unique delimiters for VFIO devices in the migration -+ * stream. These flags are composed as: -+ * 0xffffffff => MSB 32-bit all 1s -+ * 0xef10 => Magic ID, represents emulated (virtual) function IO -+ * 0x0000 => 16-bits reserved for flags -+ * -+ * The beginning of state information is marked by _DEV_CONFIG_STATE, -+ * _DEV_SETUP_STATE, or _DEV_DATA_STATE, respectively. The end of a -+ * certain state information is marked by _END_OF_STATE. -+ */ -+#define VFIO_MIG_FLAG_END_OF_STATE (0xffffffffef100001ULL) -+#define VFIO_MIG_FLAG_DEV_CONFIG_STATE (0xffffffffef100002ULL) -+#define VFIO_MIG_FLAG_DEV_SETUP_STATE (0xffffffffef100003ULL) -+#define VFIO_MIG_FLAG_DEV_DATA_STATE (0xffffffffef100004ULL) -+ - static inline int vfio_mig_access(VFIODevice *vbasedev, void *val, int count, - off_t off, bool iswrite) - { -@@ -129,6 +148,75 @@ static int vfio_migration_set_state(VFIODevice *vbasedev, uint32_t mask, - return 0; - } - -+static void vfio_migration_cleanup(VFIODevice *vbasedev) -+{ -+ VFIOMigration *migration = vbasedev->migration; -+ -+ if (migration->region.mmaps) { -+ vfio_region_unmap(&migration->region); -+ } -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static int vfio_save_setup(QEMUFile *f, void *opaque) -+{ -+ VFIODevice *vbasedev = opaque; -+ VFIOMigration *migration = vbasedev->migration; -+ int ret; -+ -+ trace_vfio_save_setup(vbasedev->name); -+ -+ qemu_put_be64(f, VFIO_MIG_FLAG_DEV_SETUP_STATE); -+ -+ if (migration->region.mmaps) { -+ /* -+ * Calling vfio_region_mmap() from migration thread. Memory API called -+ * from this function require locking the iothread when called from -+ * outside the main loop thread. -+ */ -+ qemu_mutex_lock_iothread(); -+ ret = vfio_region_mmap(&migration->region); -+ qemu_mutex_unlock_iothread(); -+ if (ret) { -+ error_report("%s: Failed to mmap VFIO migration region: %s", -+ vbasedev->name, strerror(-ret)); -+ error_report("%s: Falling back to slow path", vbasedev->name); -+ } -+ } -+ -+ ret = vfio_migration_set_state(vbasedev, VFIO_DEVICE_STATE_MASK, -+ VFIO_DEVICE_STATE_SAVING); -+ if (ret) { -+ error_report("%s: Failed to set state SAVING", vbasedev->name); -+ return ret; -+ } -+ -+ qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); -+ -+ ret = qemu_file_get_error(f); -+ if (ret) { -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void vfio_save_cleanup(void *opaque) -+{ -+ VFIODevice *vbasedev = opaque; -+ -+ vfio_migration_cleanup(vbasedev); -+ trace_vfio_save_cleanup(vbasedev->name); -+} -+ -+static SaveVMHandlers savevm_vfio_handlers = { -+ .save_setup = vfio_save_setup, -+ .save_cleanup = vfio_save_cleanup, -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ - static void vfio_vmstate_change(void *opaque, int running, RunState state) - { - VFIODevice *vbasedev = opaque; -@@ -215,6 +303,8 @@ static int vfio_migration_init(VFIODevice *vbasedev, - int ret; - Object *obj; - VFIOMigration *migration; -+ char id[256] = ""; -+ g_autofree char *path = NULL, *oid = NULL; - - if (!vbasedev->ops->vfio_get_object) { - return -EINVAL; -@@ -244,6 +334,18 @@ static int vfio_migration_init(VFIODevice *vbasedev, - - migration = vbasedev->migration; - migration->vbasedev = vbasedev; -+ -+ oid = vmstate_if_get_id(VMSTATE_IF(DEVICE(obj))); -+ if (oid) { -+ path = g_strdup_printf("%s/vfio", oid); -+ } else { -+ path = g_strdup("vfio"); -+ } -+ strpadcpy(id, sizeof(id), path, '\0'); -+ -+ register_savevm_live(id, VMSTATE_INSTANCE_ID_ANY, 1, &savevm_vfio_handlers, -+ vbasedev); -+ - migration->vm_state = qemu_add_vm_change_state_handler(vfio_vmstate_change, - vbasedev); - migration->migration_state.notify = vfio_migration_state_notifier; -diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events -index bd3d47b005..86c18def01 100644 ---- a/hw/vfio/trace-events -+++ b/hw/vfio/trace-events -@@ -149,3 +149,5 @@ vfio_migration_probe(const char *name, uint32_t index) " (%s) Region %d" - vfio_migration_set_state(const char *name, uint32_t state) " (%s) state %d" - vfio_vmstate_change(const char *name, int running, const char *reason, uint32_t dev_state) " (%s) running %d reason %s device state %d" - vfio_migration_state_notifier(const char *name, const char *state) " (%s) state %s" -+vfio_save_setup(const char *name) " (%s)" -+vfio_save_cleanup(const char *name) " (%s)" --- -2.27.0 - diff --git a/vfio-Set-the-priority-of-the-VFIO-VM-state-change-ha.patch b/vfio-Set-the-priority-of-the-VFIO-VM-state-change-ha.patch deleted file mode 100644 index d2138b57e71e494198068253be7d7229b510e598..0000000000000000000000000000000000000000 --- a/vfio-Set-the-priority-of-the-VFIO-VM-state-change-ha.patch +++ /dev/null @@ -1,41 +0,0 @@ -From b9d74bcf6aefe8ab607439ad1c518a453053ccee Mon Sep 17 00:00:00 2001 -From: Shenming Lu -Date: Wed, 10 Mar 2021 11:02:32 +0800 -Subject: [PATCH] vfio: Set the priority of the VFIO VM state change handler - explicitly - -In the VFIO VM state change handler when stopping the VM, the _RUNNING -bit in device_state is cleared which makes the VFIO device stop, including -no longer generating interrupts. Then we can save the pending states of -all interrupts in the GIC VM state change handler (on ARM). - -So we have to set the priority of the VFIO VM state change handler -explicitly (like virtio devices) to ensure it is called before the -GIC's in saving. - -Signed-off-by: Shenming Lu -Reviewed-by: Kirti Wankhede -Reviewed-by: Cornelia Huck -Message-Id: <20210310030233.1133-3-lushenming@huawei.com> -Signed-off-by: Alex Williamson ---- - hw/vfio/migration.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -index ea36ae5225..1a97784486 100644 ---- a/hw/vfio/migration.c -+++ b/hw/vfio/migration.c -@@ -862,7 +862,8 @@ static int vfio_migration_init(VFIODevice *vbasedev, - register_savevm_live(id, VMSTATE_INSTANCE_ID_ANY, 1, &savevm_vfio_handlers, - vbasedev); - -- migration->vm_state = qemu_add_vm_change_state_handler(vfio_vmstate_change, -+ migration->vm_state = qdev_add_vm_change_state_handler(vbasedev->dev, -+ vfio_vmstate_change, - vbasedev); - migration->migration_state.notify = vfio_migration_state_notifier; - add_migration_state_change_notifier(&migration->migration_state); --- -2.27.0 - diff --git a/vfio-Set-up-nested-stage-mappings.patch b/vfio-Set-up-nested-stage-mappings.patch index 66659e81a8dacc392f4f6a56ab988c36a52af8a2..c6d87f97be54c3c76b2890ee978723ee946146c6 100644 --- a/vfio-Set-up-nested-stage-mappings.patch +++ b/vfio-Set-up-nested-stage-mappings.patch @@ -1,4 +1,4 @@ -From a65c40f9d1025a9843dec38070d9f26792b00892 Mon Sep 17 00:00:00 2001 +From 96581a5ee46e89dbc9e1ebe247b00adefb1c7a41 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Wed, 29 Aug 2018 18:10:12 +0200 Subject: [PATCH] vfio: Set up nested stage mappings @@ -22,16 +22,16 @@ notifier. Signed-off-by: Eric Auger Signed-off-by: Kunkun Jiang --- - hw/vfio/common.c | 136 +++++++++++++++++++++++++++++++++++++++++-- + hw/vfio/common.c | 139 +++++++++++++++++++++++++++++++++++++++++-- hw/vfio/pci.c | 21 +++++++ hw/vfio/trace-events | 2 + - 3 files changed, 154 insertions(+), 5 deletions(-) + 3 files changed, 157 insertions(+), 5 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index 8837d33c57..cc50efdbc1 100644 +index b3dc090840..58f8a43a43 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -642,6 +642,73 @@ static bool vfio_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr, +@@ -707,6 +707,73 @@ static bool vfio_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr, return true; } @@ -105,7 +105,7 @@ index 8837d33c57..cc50efdbc1 100644 static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) { VFIOGuestIOMMU *giommu = container_of(n, VFIOGuestIOMMU, n); -@@ -823,6 +890,32 @@ static void vfio_dma_unmap_ram_section(VFIOContainer *container, +@@ -1040,6 +1107,35 @@ static void vfio_dma_unmap_ram_section(VFIOContainer *container, } } @@ -114,14 +114,17 @@ index 8837d33c57..cc50efdbc1 100644 +{ + VFIOContainer *container = + container_of(listener, VFIOContainer, prereg_listener); ++ Error *err = NULL; + + if (!memory_region_is_ram(section->mr)) { + return; + } + -+ vfio_dma_map_ram_section(container, section); ++ vfio_dma_map_ram_section(container, section, &err); ++ if (err) { ++ error_report_err(err); ++ } +} -+ +static void vfio_prereg_listener_region_del(MemoryListener *listener, + MemoryRegionSection *section) +{ @@ -138,7 +141,7 @@ index 8837d33c57..cc50efdbc1 100644 static void vfio_listener_region_add(MemoryListener *listener, MemoryRegionSection *section) { -@@ -920,9 +1013,10 @@ static void vfio_listener_region_add(MemoryListener *listener, +@@ -1150,9 +1246,10 @@ static void vfio_listener_region_add(MemoryListener *listener, memory_region_ref(section->mr); if (memory_region_is_iommu(section->mr)) { @@ -150,12 +153,12 @@ index 8837d33c57..cc50efdbc1 100644 trace_vfio_listener_region_add_iommu(iova, end); /* -@@ -941,15 +1035,27 @@ static void vfio_listener_region_add(MemoryListener *listener, +@@ -1171,8 +1268,18 @@ static void vfio_listener_region_add(MemoryListener *listener, llend = int128_sub(llend, int128_one()); iommu_idx = memory_region_iommu_attrs_to_index(iommu_mr, MEMTXATTRS_UNSPECIFIED); - iommu_notifier_init(&giommu->n, vfio_iommu_map_notify, -- IOMMU_NOTIFIER_ALL, +- IOMMU_NOTIFIER_IOTLB_EVENTS, + + if (container->iommu_type == VFIO_TYPE1_NESTING_IOMMU) { + /* IOTLB unmap notifier to propagate guest IOTLB invalidations */ @@ -163,7 +166,7 @@ index 8837d33c57..cc50efdbc1 100644 + notify = vfio_iommu_unmap_notify; + } else { + /* MAP/UNMAP IOTLB notifier */ -+ flags = IOMMU_NOTIFIER_ALL; ++ flags = IOMMU_NOTIFIER_IOTLB_EVENTS; + notify = vfio_iommu_map_notify; + } + @@ -171,9 +174,10 @@ index 8837d33c57..cc50efdbc1 100644 section->offset_within_region, int128_get64(llend), iommu_idx); +@@ -1192,7 +1299,9 @@ static void vfio_listener_region_add(MemoryListener *listener, + goto fail; + } QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next); - - memory_region_register_iommu_notifier(section->mr, &giommu->n); - memory_region_iommu_replay(giommu->iommu, &giommu->n); + if (flags & IOMMU_NOTIFIER_MAP) { + memory_region_iommu_replay(giommu->iommu, &giommu->n); @@ -181,7 +185,7 @@ index 8837d33c57..cc50efdbc1 100644 return; } -@@ -1367,10 +1473,16 @@ static const MemoryListener vfio_memory_listener = { +@@ -1672,10 +1781,16 @@ static const MemoryListener vfio_memory_listener = { .log_clear = vfio_listener_log_clear, }; @@ -199,7 +203,7 @@ index 8837d33c57..cc50efdbc1 100644 memory_listener_unregister(&container->prereg_listener); } } -@@ -1976,6 +2088,20 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, +@@ -2351,6 +2466,20 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, vfio_get_iommu_info_migration(container, info); } g_free(info); @@ -210,10 +214,10 @@ index 8837d33c57..cc50efdbc1 100644 + &address_space_memory); + if (container->error) { + memory_listener_unregister(&container->prereg_listener); -+ ret = container->error; -+ error_setg(errp, -+ "RAM memory listener initialization failed " -+ "for container"); ++ ret = -1; ++ error_propagate_prepend(errp, container->error, ++ "RAM memory listener initialization failed " ++ "for container"); + goto free_container_exit; + } + } @@ -221,10 +225,10 @@ index 8837d33c57..cc50efdbc1 100644 } case VFIO_SPAPR_TCE_v2_IOMMU: diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c -index 3641ad0c5c..6c90ec9278 100644 +index 7b45353ce2..ae5e014e5d 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c -@@ -2766,6 +2766,25 @@ static void vfio_unregister_req_notifier(VFIOPCIDevice *vdev) +@@ -2797,6 +2797,25 @@ static void vfio_unregister_req_notifier(VFIOPCIDevice *vdev) vdev->req_enabled = false; } @@ -249,8 +253,8 @@ index 3641ad0c5c..6c90ec9278 100644 + static void vfio_realize(PCIDevice *pdev, Error **errp) { - VFIOPCIDevice *vdev = PCI_VFIO(pdev); -@@ -3072,6 +3091,8 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) + VFIOPCIDevice *vdev = VFIO_PCI(pdev); +@@ -3108,6 +3127,8 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) vfio_register_req_notifier(vdev); vfio_setup_resetfn_quirk(vdev); @@ -258,9 +262,9 @@ index 3641ad0c5c..6c90ec9278 100644 + return; - out_teardown: + out_deregister: diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events -index 9b6c7ca61b..ee9a67d3ef 100644 +index a37563a315..20069935f5 100644 --- a/hw/vfio/trace-events +++ b/hw/vfio/trace-events @@ -118,6 +118,8 @@ vfio_region_sparse_mmap_header(const char *name, int index, int nr_areas) "Devic diff --git a/vfio-Support-host-translation-granule-size.patch b/vfio-Support-host-translation-granule-size.patch deleted file mode 100644 index d5eab65155770160c38615d038ea66264e284acb..0000000000000000000000000000000000000000 --- a/vfio-Support-host-translation-granule-size.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 594cba5943b3e8bf1bd5720b1fa20d4662920ae0 Mon Sep 17 00:00:00 2001 -From: Kunkun Jiang -Date: Thu, 4 Mar 2021 21:34:46 +0800 -Subject: [PATCH] vfio: Support host translation granule size - -The cpu_physical_memory_set_dirty_lebitmap() can quickly deal with -the dirty pages of memory by bitmap-traveling, regardless of whether -the bitmap is aligned correctly or not. - -cpu_physical_memory_set_dirty_lebitmap() supports pages in bitmap of -host page size. So it'd better to set bitmap_pgsize to host page size -to support more translation granule sizes. - -[aw: The Fixes commit below introduced code to restrict migration -support to configurations where the target page size intersects the -host dirty page support. For example, a 4K guest on a 4K host. -Due to the above flexibility in bitmap handling, this restriction -unnecessarily prevents mixed target/host pages size that could -otherwise be supported. Use host page size for dirty bitmap.] - -Fixes: fc49c9cbf2 ("vfio: Get migration capability flags for container") -Signed-off-by: Kunkun Jiang -Message-Id: <20210304133446.1521-1-jiangkunkun@huawei.com> -Signed-off-by: Alex Williamson ---- - hw/vfio/common.c | 48 +++++++++++++++++++++++++----------------------- - 1 file changed, 25 insertions(+), 23 deletions(-) - -diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index ebd701faa0..a7817c90cc 100644 ---- a/hw/vfio/common.c -+++ b/hw/vfio/common.c -@@ -377,7 +377,7 @@ static int vfio_dma_unmap_bitmap(VFIOContainer *container, - { - struct vfio_iommu_type1_dma_unmap *unmap; - struct vfio_bitmap *bitmap; -- uint64_t pages = TARGET_PAGE_ALIGN(size) >> TARGET_PAGE_BITS; -+ uint64_t pages = REAL_HOST_PAGE_ALIGN(size) / qemu_real_host_page_size; - int ret; - - unmap = g_malloc0(sizeof(*unmap) + sizeof(*bitmap)); -@@ -389,12 +389,12 @@ static int vfio_dma_unmap_bitmap(VFIOContainer *container, - bitmap = (struct vfio_bitmap *)&unmap->data; - - /* -- * cpu_physical_memory_set_dirty_lebitmap() expects pages in bitmap of -- * TARGET_PAGE_SIZE to mark those dirty. Hence set bitmap_pgsize to -- * TARGET_PAGE_SIZE. -+ * cpu_physical_memory_set_dirty_lebitmap() supports pages in bitmap of -+ * qemu_real_host_page_size to mark those dirty. Hence set bitmap_pgsize -+ * to qemu_real_host_page_size. - */ - -- bitmap->pgsize = TARGET_PAGE_SIZE; -+ bitmap->pgsize = qemu_real_host_page_size; - bitmap->size = ROUND_UP(pages, sizeof(__u64) * BITS_PER_BYTE) / - BITS_PER_BYTE; - -@@ -672,16 +672,17 @@ static void vfio_listener_region_add(MemoryListener *listener, - return; - } - -- if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) != -- (section->offset_within_region & ~TARGET_PAGE_MASK))) { -+ if (unlikely((section->offset_within_address_space & -+ ~qemu_real_host_page_mask) != -+ (section->offset_within_region & ~qemu_real_host_page_mask))) { - error_report("%s received unaligned region", __func__); - return; - } - -- iova = TARGET_PAGE_ALIGN(section->offset_within_address_space); -+ iova = REAL_HOST_PAGE_ALIGN(section->offset_within_address_space); - llend = int128_make64(section->offset_within_address_space); - llend = int128_add(llend, section->size); -- llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK)); -+ llend = int128_and(llend, int128_exts64(qemu_real_host_page_mask)); - - if (int128_ge(int128_make64(iova), llend)) { - return; -@@ -866,8 +867,9 @@ static void vfio_listener_region_del(MemoryListener *listener, - return; - } - -- if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) != -- (section->offset_within_region & ~TARGET_PAGE_MASK))) { -+ if (unlikely((section->offset_within_address_space & -+ ~qemu_real_host_page_mask) != -+ (section->offset_within_region & ~qemu_real_host_page_mask))) { - error_report("%s received unaligned region", __func__); - return; - } -@@ -895,10 +897,10 @@ static void vfio_listener_region_del(MemoryListener *listener, - */ - } - -- iova = TARGET_PAGE_ALIGN(section->offset_within_address_space); -+ iova = REAL_HOST_PAGE_ALIGN(section->offset_within_address_space); - llend = int128_make64(section->offset_within_address_space); - llend = int128_add(llend, section->size); -- llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK)); -+ llend = int128_and(llend, int128_exts64(qemu_real_host_page_mask)); - - if (int128_ge(int128_make64(iova), llend)) { - return; -@@ -967,13 +969,13 @@ static int vfio_get_dirty_bitmap(VFIOContainer *container, uint64_t iova, - range->size = size; - - /* -- * cpu_physical_memory_set_dirty_lebitmap() expects pages in bitmap of -- * TARGET_PAGE_SIZE to mark those dirty. Hence set bitmap's pgsize to -- * TARGET_PAGE_SIZE. -+ * cpu_physical_memory_set_dirty_lebitmap() supports pages in bitmap of -+ * qemu_real_host_page_size to mark those dirty. Hence set bitmap's pgsize -+ * to qemu_real_host_page_size. - */ -- range->bitmap.pgsize = TARGET_PAGE_SIZE; -+ range->bitmap.pgsize = qemu_real_host_page_size; - -- pages = TARGET_PAGE_ALIGN(range->size) >> TARGET_PAGE_BITS; -+ pages = REAL_HOST_PAGE_ALIGN(range->size) / qemu_real_host_page_size; - range->bitmap.size = ROUND_UP(pages, sizeof(__u64) * BITS_PER_BYTE) / - BITS_PER_BYTE; - range->bitmap.data = g_try_malloc0(range->bitmap.size); -@@ -1077,8 +1079,8 @@ static int vfio_sync_dirty_bitmap(VFIOContainer *container, - section->offset_within_region; - - return vfio_get_dirty_bitmap(container, -- TARGET_PAGE_ALIGN(section->offset_within_address_space), -- int128_get64(section->size), ram_addr); -+ REAL_HOST_PAGE_ALIGN(section->offset_within_address_space), -+ int128_get64(section->size), ram_addr); - } - - static void vfio_listener_log_sync(MemoryListener *listener, -@@ -1572,10 +1574,10 @@ static void vfio_get_iommu_info_migration(VFIOContainer *container, - header); - - /* -- * cpu_physical_memory_set_dirty_lebitmap() expects pages in bitmap of -- * TARGET_PAGE_SIZE to mark those dirty. -+ * cpu_physical_memory_set_dirty_lebitmap() supports pages in bitmap of -+ * qemu_real_host_page_size to mark those dirty. - */ -- if (cap_mig->pgsize_bitmap & TARGET_PAGE_SIZE) { -+ if (cap_mig->pgsize_bitmap & qemu_real_host_page_size) { - container->dirty_pages_supported = true; - container->max_dirty_bitmap_size = cap_mig->max_dirty_bitmap_size; - container->dirty_pgsizes = cap_mig->pgsize_bitmap; --- -2.27.0 - diff --git a/vfio-add-quirk-device-write-method.patch b/vfio-add-quirk-device-write-method.patch deleted file mode 100644 index d7e2c99dc212605291627dac4dee0512e1b34f86..0000000000000000000000000000000000000000 --- a/vfio-add-quirk-device-write-method.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 95ee5273e25ed606aa86f8a154c06887efc20494 Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit -Date: Thu, 25 Mar 2021 17:12:57 +0800 -Subject: [PATCH] vfio: add quirk device write method - ---- - hw/vfio/pci-quirks.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c -index b35a640030..9ce790bdd2 100644 ---- a/hw/vfio/pci-quirks.c -+++ b/hw/vfio/pci-quirks.c -@@ -12,6 +12,7 @@ - - #include "qemu/osdep.h" - #include "qemu/units.h" -+#include "qemu/log.h" - #include "qemu/error-report.h" - #include "qemu/main-loop.h" - #include "qemu/module.h" -@@ -275,8 +276,15 @@ static uint64_t vfio_ati_3c3_quirk_read(void *opaque, - return data; - } - -+static void vfio_ati_3c3_quirk_write(void *opaque, hwaddr addr, -+ uint64_t data, unsigned size) -+{ -+ qemu_log_mask(LOG_GUEST_ERROR, "%s not implemented\n", __func__); -+} -+ - static const MemoryRegionOps vfio_ati_3c3_quirk = { - .read = vfio_ati_3c3_quirk_read, -+ .write = vfio_ati_3c3_quirk_write, - .endianness = DEVICE_LITTLE_ENDIAN, - }; - --- -2.27.0 - diff --git a/vfio-common-Add-address-alignment-check-in-vfio_list.patch b/vfio-common-Add-address-alignment-check-in-vfio_list.patch index 0aacdcd02d3deecc95da91603e06ec7decc924d1..288f28482314f60dd0396228b35b17c0f9d67b8e 100644 --- a/vfio-common-Add-address-alignment-check-in-vfio_list.patch +++ b/vfio-common-Add-address-alignment-check-in-vfio_list.patch @@ -1,4 +1,4 @@ -From 0a6ee00461c784ef547b8f071ad147fcb89875b6 Mon Sep 17 00:00:00 2001 +From 00c553f53657bf4bc165d859187215dba7110246 Mon Sep 17 00:00:00 2001 From: Kunkun Jiang Date: Tue, 14 Sep 2021 14:21:46 +0800 Subject: [PATCH] vfio/common: Add address alignment check in @@ -21,10 +21,10 @@ Signed-off-by: Kunkun Jiang 1 file changed, 10 insertions(+) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index de166dd5f9..6d6a4c6dee 100644 +index 89c49f5508..4d45c2b625 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -1149,6 +1149,8 @@ static void vfio_listener_region_del(MemoryListener *listener, +@@ -1411,6 +1411,8 @@ static void vfio_listener_region_del(MemoryListener *listener, MemoryRegionSection *section) { VFIOContainer *container = container_of(listener, VFIOContainer, listener); @@ -33,7 +33,7 @@ index de166dd5f9..6d6a4c6dee 100644 if (vfio_listener_skipped_section(section)) { trace_vfio_listener_region_del_skip( -@@ -1198,6 +1200,14 @@ static void vfio_listener_region_del(MemoryListener *listener, +@@ -1460,6 +1462,14 @@ static void vfio_listener_region_del(MemoryListener *listener, */ } diff --git a/vfio-common-Avoid-unmap-ram-section-at-vfio_listener.patch b/vfio-common-Avoid-unmap-ram-section-at-vfio_listener.patch index efcbd1fd03162efd34a1c11bc169e39da757da6b..71302b2d21e9840a0591d2960452de622cd60731 100644 --- a/vfio-common-Avoid-unmap-ram-section-at-vfio_listener.patch +++ b/vfio-common-Avoid-unmap-ram-section-at-vfio_listener.patch @@ -1,4 +1,4 @@ -From 55f3bdd0866be2b1a6223bacf9e00a032daf957c Mon Sep 17 00:00:00 2001 +From 9d7b782a0b2c5288e82f3064b4c5b7bf18887280 Mon Sep 17 00:00:00 2001 From: Kunkun Jiang Date: Sat, 31 Jul 2021 10:02:18 +0800 Subject: [PATCH] vfio/common: Avoid unmap ram section at @@ -14,10 +14,10 @@ Signed-off-by: Kunkun Jiang 1 file changed, 10 insertions(+) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index 98dc9e6f84..21a866e545 100644 +index d05a485808..bdfcc854fe 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -1179,6 +1179,16 @@ static void vfio_listener_region_del(MemoryListener *listener, +@@ -1441,6 +1441,16 @@ static void vfio_listener_region_del(MemoryListener *listener, } } diff --git a/vfio-common-Fix-incorrect-address-alignment-in-vfio_.patch b/vfio-common-Fix-incorrect-address-alignment-in-vfio_.patch index e1b96e6d9547c6d4852fc079e702f5aff82822d3..d61408e6242adbb0c7e95b4cd94ec70fcca19c22 100644 --- a/vfio-common-Fix-incorrect-address-alignment-in-vfio_.patch +++ b/vfio-common-Fix-incorrect-address-alignment-in-vfio_.patch @@ -1,4 +1,4 @@ -From 7438519f5cfb0e07dd54f242901761da87f1156c Mon Sep 17 00:00:00 2001 +From c2a4ce033db6ab74256e28da382c797a98047d4b Mon Sep 17 00:00:00 2001 From: Kunkun Jiang Date: Tue, 7 Sep 2021 15:14:12 +0800 Subject: [PATCH] vfio/common: Fix incorrect address alignment in @@ -19,10 +19,10 @@ Signed-off-by: Zenghui Yu 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index fb7ca63748..de166dd5f9 100644 +index 65f3979492..89c49f5508 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -846,10 +846,10 @@ static int vfio_dma_map_ram_section(VFIOContainer *container, +@@ -1059,10 +1059,10 @@ static int vfio_dma_map_ram_section(VFIOContainer *container, assert(memory_region_is_ram(section->mr)); diff --git a/vfio-migrate-Move-switch-of-dirty-tracking-into-vfio.patch b/vfio-migrate-Move-switch-of-dirty-tracking-into-vfio.patch deleted file mode 100644 index 5f543b40bdb7e93d671edbd834b4279dec69c8c9..0000000000000000000000000000000000000000 --- a/vfio-migrate-Move-switch-of-dirty-tracking-into-vfio.patch +++ /dev/null @@ -1,196 +0,0 @@ -From 74b651428e6ed65177354d80bd888e842a4a5077 Mon Sep 17 00:00:00 2001 -From: Keqian Zhu -Date: Tue, 9 Mar 2021 11:19:13 +0800 -Subject: [PATCH] vfio/migrate: Move switch of dirty tracking into - vfio_memory_listener - -For now the switch of vfio dirty page tracking is integrated into -@vfio_save_handler. The reason is that some PCI vendor driver may -start to track dirty base on _SAVING state of device, so if dirty -tracking is started before setting device state, vfio will report -full-dirty to QEMU. - -However, the dirty bmap of all ramblocks are fully set when setup -ram saving, so it's not matter whether the device is in _SAVING -state when start vfio dirty tracking. - -Moreover, this logic causes some problems [1]. The object of dirty -tracking is guest memory, but the object of @vfio_save_handler is -device state, which produces unnecessary coupling and conflicts: - -1. Coupling: Their saving granule is different (perVM vs perDevice). - vfio will enable dirty_page_tracking for each devices, actually - once is enough. - -2. Conflicts: The ram_save_setup() traverses all memory_listeners - to execute their log_start() and log_sync() hooks to get the - first round dirty bitmap, which is used by the bulk stage of - ram saving. However, as vfio dirty tracking is not yet started, - it can't get dirty bitmap from vfio. Then we give up the chance - to handle vfio dirty page at bulk stage. - -Move the switch of vfio dirty_page_tracking into vfio_memory_listener -can solve above problems. Besides, Do not require devices in SAVING -state for vfio_sync_dirty_bitmap(). - -[1] https://www.spinics.net/lists/kvm/msg229967.html - -Reported-by: Zenghui Yu -Signed-off-by: Keqian Zhu -Suggested-by: Paolo Bonzini -Message-Id: <20210309031913.11508-1-zhukeqian1@huawei.com> -Signed-off-by: Alex Williamson -Signed-off-by: Kunkun Jiang ---- - hw/vfio/common.c | 49 ++++++++++++++++++++++++++++++++++++--------- - hw/vfio/migration.c | 35 -------------------------------- - 2 files changed, 40 insertions(+), 44 deletions(-) - -diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index a7817c90cc..245e32df5b 100644 ---- a/hw/vfio/common.c -+++ b/hw/vfio/common.c -@@ -310,7 +310,7 @@ bool vfio_mig_active(void) - return true; - } - --static bool vfio_devices_all_saving(VFIOContainer *container) -+static bool vfio_devices_all_dirty_tracking(VFIOContainer *container) - { - VFIOGroup *group; - VFIODevice *vbasedev; -@@ -328,13 +328,8 @@ static bool vfio_devices_all_saving(VFIOContainer *container) - return false; - } - -- if (migration->device_state & VFIO_DEVICE_STATE_SAVING) { -- if ((vbasedev->pre_copy_dirty_page_tracking == ON_OFF_AUTO_OFF) -- && (migration->device_state & VFIO_DEVICE_STATE_RUNNING)) { -- return false; -- } -- continue; -- } else { -+ if ((vbasedev->pre_copy_dirty_page_tracking == ON_OFF_AUTO_OFF) -+ && (migration->device_state & VFIO_DEVICE_STATE_RUNNING)) { - return false; - } - } -@@ -952,6 +947,40 @@ static void vfio_listener_region_del(MemoryListener *listener, - } - } - -+static void vfio_set_dirty_page_tracking(VFIOContainer *container, bool start) -+{ -+ int ret; -+ struct vfio_iommu_type1_dirty_bitmap dirty = { -+ .argsz = sizeof(dirty), -+ }; -+ -+ if (start) { -+ dirty.flags = VFIO_IOMMU_DIRTY_PAGES_FLAG_START; -+ } else { -+ dirty.flags = VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP; -+ } -+ -+ ret = ioctl(container->fd, VFIO_IOMMU_DIRTY_PAGES, &dirty); -+ if (ret) { -+ error_report("Failed to set dirty tracking flag 0x%x errno: %d", -+ dirty.flags, errno); -+ } -+} -+ -+static void vfio_listener_log_global_start(MemoryListener *listener) -+{ -+ VFIOContainer *container = container_of(listener, VFIOContainer, listener); -+ -+ vfio_set_dirty_page_tracking(container, true); -+} -+ -+static void vfio_listener_log_global_stop(MemoryListener *listener) -+{ -+ VFIOContainer *container = container_of(listener, VFIOContainer, listener); -+ -+ vfio_set_dirty_page_tracking(container, false); -+} -+ - static int vfio_get_dirty_bitmap(VFIOContainer *container, uint64_t iova, - uint64_t size, ram_addr_t ram_addr) - { -@@ -1093,7 +1122,7 @@ static void vfio_listener_log_sync(MemoryListener *listener, - return; - } - -- if (vfio_devices_all_saving(container)) { -+ if (vfio_devices_all_dirty_tracking(container)) { - vfio_sync_dirty_bitmap(container, section); - } - } -@@ -1101,6 +1130,8 @@ static void vfio_listener_log_sync(MemoryListener *listener, - static const MemoryListener vfio_memory_listener = { - .region_add = vfio_listener_region_add, - .region_del = vfio_listener_region_del, -+ .log_global_start = vfio_listener_log_global_start, -+ .log_global_stop = vfio_listener_log_global_stop, - .log_sync = vfio_listener_log_sync, - }; - -diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c -index 033cb2b0c9..f1f006d584 100644 ---- a/hw/vfio/migration.c -+++ b/hw/vfio/migration.c -@@ -395,40 +395,10 @@ static int vfio_load_device_config_state(QEMUFile *f, void *opaque) - return qemu_file_get_error(f); - } - --static int vfio_set_dirty_page_tracking(VFIODevice *vbasedev, bool start) --{ -- int ret; -- VFIOMigration *migration = vbasedev->migration; -- VFIOContainer *container = vbasedev->group->container; -- struct vfio_iommu_type1_dirty_bitmap dirty = { -- .argsz = sizeof(dirty), -- }; -- -- if (start) { -- if (migration->device_state & VFIO_DEVICE_STATE_SAVING) { -- dirty.flags = VFIO_IOMMU_DIRTY_PAGES_FLAG_START; -- } else { -- return -EINVAL; -- } -- } else { -- dirty.flags = VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP; -- } -- -- ret = ioctl(container->fd, VFIO_IOMMU_DIRTY_PAGES, &dirty); -- if (ret) { -- error_report("Failed to set dirty tracking flag 0x%x errno: %d", -- dirty.flags, errno); -- return -errno; -- } -- return ret; --} -- - static void vfio_migration_cleanup(VFIODevice *vbasedev) - { - VFIOMigration *migration = vbasedev->migration; - -- vfio_set_dirty_page_tracking(vbasedev, false); -- - if (migration->region.mmaps) { - vfio_region_unmap(&migration->region); - } -@@ -469,11 +439,6 @@ static int vfio_save_setup(QEMUFile *f, void *opaque) - return ret; - } - -- ret = vfio_set_dirty_page_tracking(vbasedev, true); -- if (ret) { -- return ret; -- } -- - qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE); - - ret = qemu_file_get_error(f); --- -2.27.0 - diff --git a/vfio-migration-Add-support-for-manual-clear-vfio-dir.patch b/vfio-migration-Add-support-for-manual-clear-vfio-dir.patch index c59bc4e1ff70f6993557329480505c4300ff6aa0..0a5ff88f995220f5c3128eb8e56c86afeffe53e2 100644 --- a/vfio-migration-Add-support-for-manual-clear-vfio-dir.patch +++ b/vfio-migration-Add-support-for-manual-clear-vfio-dir.patch @@ -1,4 +1,4 @@ -From f9574b63bf5e940d794db2c3aaf928bde36d9521 Mon Sep 17 00:00:00 2001 +From 815258f81a660ad87272191dca4a9726cb2bf5b2 Mon Sep 17 00:00:00 2001 From: Zenghui Yu Date: Sat, 8 May 2021 17:31:05 +0800 Subject: [PATCH] vfio/migration: Add support for manual clear vfio dirty log @@ -20,10 +20,10 @@ Signed-off-by: Kunkun Jiang 2 files changed, 148 insertions(+), 2 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c -index c33c4c539d..206fb83e28 100644 +index 86ea784919..6cb91e7ffd 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c -@@ -1045,7 +1045,9 @@ static int vfio_get_dirty_bitmap(VFIOContainer *container, uint64_t iova, +@@ -1315,7 +1315,9 @@ static int vfio_get_dirty_bitmap(VFIOContainer *container, uint64_t iova, dbitmap = g_malloc0(sizeof(*dbitmap) + sizeof(*range)); dbitmap->argsz = sizeof(*dbitmap) + sizeof(*range); @@ -34,7 +34,7 @@ index c33c4c539d..206fb83e28 100644 range = (struct vfio_iommu_type1_dirty_bitmap_get *)&dbitmap->data; range->iova = iova; range->size = size; -@@ -1176,12 +1178,148 @@ static void vfio_listener_log_sync(MemoryListener *listener, +@@ -1491,6 +1493,141 @@ static void vfio_listener_log_sync(MemoryListener *listener, } } @@ -174,8 +174,9 @@ index c33c4c539d..206fb83e28 100644 +} + static const MemoryListener vfio_memory_listener = { + .name = "vfio", .region_add = vfio_listener_region_add, - .region_del = vfio_listener_region_del, +@@ -1498,6 +1635,7 @@ static const MemoryListener vfio_memory_listener = { .log_global_start = vfio_listener_log_global_start, .log_global_stop = vfio_listener_log_global_stop, .log_sync = vfio_listener_log_sync, @@ -183,7 +184,7 @@ index c33c4c539d..206fb83e28 100644 }; static void vfio_listener_release(VFIOContainer *container) -@@ -1563,7 +1701,7 @@ static int vfio_get_iommu_type(VFIOContainer *container, +@@ -1925,7 +2063,7 @@ static int vfio_get_iommu_type(VFIOContainer *container, static int vfio_init_container(VFIOContainer *container, int group_fd, Error **errp) { @@ -192,7 +193,7 @@ index c33c4c539d..206fb83e28 100644 iommu_type = vfio_get_iommu_type(container, errp); if (iommu_type < 0) { -@@ -1592,6 +1730,13 @@ static int vfio_init_container(VFIOContainer *container, int group_fd, +@@ -1954,6 +2092,13 @@ static int vfio_init_container(VFIOContainer *container, int group_fd, } container->iommu_type = iommu_type; @@ -207,11 +208,11 @@ index c33c4c539d..206fb83e28 100644 } diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h -index 2853dc861e..1277914ca8 100644 +index 20b9c8a1d3..0234f5e1b1 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -93,6 +93,7 @@ typedef struct VFIOContainer { - int error; + Error *error; bool initialized; bool dirty_pages_supported; + bool dirty_log_manual_clear; diff --git a/vfio-pci-Ascend310-need-4Bytes-quirk-in-bar4.patch b/vfio-pci-Ascend310-need-4Bytes-quirk-in-bar4.patch new file mode 100644 index 0000000000000000000000000000000000000000..c3ea4c233b747fac21f166edb4b65717b1998cb1 --- /dev/null +++ b/vfio-pci-Ascend310-need-4Bytes-quirk-in-bar4.patch @@ -0,0 +1,105 @@ +From eee7ff398496524881225d503309a9853972c5df Mon Sep 17 00:00:00 2001 +From: Binfeng Wu +Date: Tue, 8 Feb 2022 17:00:39 +0800 +Subject: [PATCH 3/5] vfio/pci: Ascend310 need 4Bytes quirk in bar4 + +--- + hw/vfio/pci-quirks.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 75 insertions(+) + +diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c +index 0cf69a8c6d..d86bcaf309 100644 +--- a/hw/vfio/pci-quirks.c ++++ b/hw/vfio/pci-quirks.c +@@ -1209,6 +1209,80 @@ int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev, + return 0; + } + ++#define PCI_VENDOR_ID_HUAWEI 0x19e5 ++#define PCI_DEVICE_ID_ASCEND310 0xd100 ++#define ASCEND310_XLOADER_SIZE 4 ++#define ASCEND310_XLOADER_OFFSET 0x400 ++ ++typedef struct VFIOAscendBarQuirk { ++ struct VFIOPCIDevice *vdev; ++ pcibus_t offset; ++ uint8_t bar; ++ MemoryRegion *mem; ++} VFIOAscendBarQuirk; ++ ++static uint64_t vfio_ascend_quirk_read(void *opaque, ++ hwaddr addr, unsigned size) ++{ ++ VFIOAscendBarQuirk *quirk = opaque; ++ VFIOPCIDevice *vdev = quirk->vdev; ++ ++ qemu_log("read RO region! addr=0x%" HWADDR_PRIx ", size=%d\n", ++ addr + quirk->offset, size); ++ ++ return vfio_region_read(&vdev->bars[quirk->bar].region, ++ addr + quirk->offset, size); ++} ++ ++static void vfio_ascend_quirk_write(void *opaque, hwaddr addr, ++ uint64_t data, unsigned size) ++{ ++ VFIOAscendBarQuirk *quirk = opaque; ++ ++ qemu_log("modifying RO region is not allowed! addr=0x%" ++ HWADDR_PRIx ", data=0x%" PRIx64 ", size=%d\n", ++ addr + quirk->offset, data, size); ++} ++ ++static const MemoryRegionOps vfio_ascend_intercept_regs_quirk = { ++ .read = vfio_ascend_quirk_read, ++ .write = vfio_ascend_quirk_write, ++ .endianness = DEVICE_LITTLE_ENDIAN, ++}; ++ ++static void vfio_probe_ascend310_bar4_quirk(VFIOPCIDevice *vdev, int nr) ++{ ++ VFIOQuirk *quirk; ++ VFIOAscendBarQuirk *bar4_quirk; ++ ++ if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 4 || ++ vdev->device_id != PCI_DEVICE_ID_ASCEND310) { ++ return; ++ } ++ ++ quirk = g_malloc0(sizeof(*quirk)); ++ quirk->nr_mem = 1; ++ quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); ++ bar4_quirk = quirk->data = g_new0(typeof(*bar4_quirk), quirk->nr_mem); ++ bar4_quirk[0].vdev = vdev; ++ bar4_quirk[0].offset = ASCEND310_XLOADER_OFFSET; ++ bar4_quirk[0].bar = nr; ++ ++ /* ++ * intercept w/r to the xloader-updating register, ++ * so the vm can't enable xloader-updating ++ */ ++ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), ++ &vfio_ascend_intercept_regs_quirk, ++ &bar4_quirk[0], ++ "vfio-ascend310-bar4-intercept-regs-quirk", ++ ASCEND310_XLOADER_SIZE); ++ memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, ++ bar4_quirk[0].offset, ++ &quirk->mem[0], 1); ++ QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); ++} ++ + /* + * Common quirk probe entry points. + */ +@@ -1261,6 +1335,7 @@ void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr) + #ifdef CONFIG_VFIO_IGD + vfio_probe_igd_bar4_quirk(vdev, nr); + #endif ++ vfio_probe_ascend310_bar4_quirk(vdev, nr); + } + + void vfio_bar_quirk_exit(VFIOPCIDevice *vdev, int nr) +-- +2.27.0 + diff --git a/vfio-pci-Ascend710-need-4Bytes-quirk-in-bar0.patch b/vfio-pci-Ascend710-need-4Bytes-quirk-in-bar0.patch new file mode 100644 index 0000000000000000000000000000000000000000..93d7b2584b41a640d2b3615f7495d4734a47ac72 --- /dev/null +++ b/vfio-pci-Ascend710-need-4Bytes-quirk-in-bar0.patch @@ -0,0 +1,75 @@ +From bcc63ff3975cca783308fac7517a7911c29bd7c1 Mon Sep 17 00:00:00 2001 +From: Binfeng Wu +Date: Tue, 8 Feb 2022 17:16:04 +0800 +Subject: [PATCH 4/5] vfio/pci: Ascend710 need 4Bytes quirk in bar0 + +--- + hw/vfio/pci-quirks.c | 37 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 37 insertions(+) + +diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c +index d86bcaf309..6a9fc0afc5 100644 +--- a/hw/vfio/pci-quirks.c ++++ b/hw/vfio/pci-quirks.c +@@ -1210,7 +1210,10 @@ int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev, + } + + #define PCI_VENDOR_ID_HUAWEI 0x19e5 ++#define PCI_DEVICE_ID_ASCEND710 0xd500 + #define PCI_DEVICE_ID_ASCEND310 0xd100 ++#define ASCEND710_XLOADER_SIZE 4 ++#define ASCEND710_XLOADER_OFFSET 0x20430 + #define ASCEND310_XLOADER_SIZE 4 + #define ASCEND310_XLOADER_OFFSET 0x400 + +@@ -1250,6 +1253,39 @@ static const MemoryRegionOps vfio_ascend_intercept_regs_quirk = { + .endianness = DEVICE_LITTLE_ENDIAN, + }; + ++static void vfio_probe_ascend710_bar0_quirk(VFIOPCIDevice *vdev, int nr) ++{ ++ VFIOQuirk *quirk; ++ VFIOAscendBarQuirk *bar0_quirk; ++ ++ if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 0 || ++ vdev->device_id != PCI_DEVICE_ID_ASCEND710) { ++ return; ++ } ++ ++ quirk = g_malloc0(sizeof(*quirk)); ++ quirk->nr_mem = 1; ++ quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); ++ bar0_quirk = quirk->data = g_new0(typeof(*bar0_quirk), quirk->nr_mem); ++ bar0_quirk[0].vdev = vdev; ++ bar0_quirk[0].offset = ASCEND710_XLOADER_OFFSET; ++ bar0_quirk[0].bar = nr; ++ ++ /* ++ * intercept w/r to the xloader-updating register, ++ * so the vm can't enable xloader-updating ++ */ ++ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), ++ &vfio_ascend_intercept_regs_quirk, ++ &bar0_quirk[0], ++ "vfio-ascend710-bar0-intercept-regs-quirk", ++ ASCEND710_XLOADER_SIZE); ++ memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, ++ bar0_quirk[0].offset, ++ &quirk->mem[0], 1); ++ QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); ++} ++ + static void vfio_probe_ascend310_bar4_quirk(VFIOPCIDevice *vdev, int nr) + { + VFIOQuirk *quirk; +@@ -1335,6 +1371,7 @@ void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr) + #ifdef CONFIG_VFIO_IGD + vfio_probe_igd_bar4_quirk(vdev, nr); + #endif ++ vfio_probe_ascend710_bar0_quirk(vdev, nr); + vfio_probe_ascend310_bar4_quirk(vdev, nr); + } + +-- +2.27.0 + diff --git a/vfio-pci-Ascend910-need-4Bytes-quirk-in-bar0.patch b/vfio-pci-Ascend910-need-4Bytes-quirk-in-bar0.patch new file mode 100644 index 0000000000000000000000000000000000000000..34b835d9b297aa8f532ff8498374dd8341d6861f --- /dev/null +++ b/vfio-pci-Ascend910-need-4Bytes-quirk-in-bar0.patch @@ -0,0 +1,76 @@ +From 4cf7d00e43c4e90327e13afa3cbc9c7ca3657c9f Mon Sep 17 00:00:00 2001 +From: Binfeng Wu +Date: Tue, 8 Feb 2022 19:20:36 +0800 +Subject: [PATCH 5/5] vfio/pci: Ascend910 need 4Bytes quirk in bar0 + +--- + hw/vfio/pci-quirks.c | 37 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 37 insertions(+) + +diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c +index 6a9fc0afc5..2457a61196 100644 +--- a/hw/vfio/pci-quirks.c ++++ b/hw/vfio/pci-quirks.c +@@ -1210,8 +1210,11 @@ int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev, + } + + #define PCI_VENDOR_ID_HUAWEI 0x19e5 ++#define PCI_DEVICE_ID_ASCEND910 0xd801 + #define PCI_DEVICE_ID_ASCEND710 0xd500 + #define PCI_DEVICE_ID_ASCEND310 0xd100 ++#define ASCEND910_XLOADER_SIZE 4 ++#define ASCEND910_XLOADER_OFFSET 0x80400 + #define ASCEND710_XLOADER_SIZE 4 + #define ASCEND710_XLOADER_OFFSET 0x20430 + #define ASCEND310_XLOADER_SIZE 4 +@@ -1253,6 +1256,39 @@ static const MemoryRegionOps vfio_ascend_intercept_regs_quirk = { + .endianness = DEVICE_LITTLE_ENDIAN, + }; + ++static void vfio_probe_ascend910_bar0_quirk(VFIOPCIDevice *vdev, int nr) ++{ ++ VFIOQuirk *quirk; ++ VFIOAscendBarQuirk *bar0_quirk; ++ ++ if (vdev->vendor_id != PCI_VENDOR_ID_HUAWEI || nr != 0 || ++ vdev->device_id != PCI_DEVICE_ID_ASCEND910) { ++ return; ++ } ++ ++ quirk = g_malloc0(sizeof(*quirk)); ++ quirk->nr_mem = 1; ++ quirk->mem = g_new0(MemoryRegion, quirk->nr_mem); ++ bar0_quirk = quirk->data = g_new0(typeof(*bar0_quirk), quirk->nr_mem); ++ bar0_quirk[0].vdev = vdev; ++ bar0_quirk[0].offset = ASCEND910_XLOADER_OFFSET; ++ bar0_quirk[0].bar = nr; ++ ++ /* ++ * intercept w/r to the xloader-updating register, ++ * so the vm can't enable xloader-updating ++ */ ++ memory_region_init_io(&quirk->mem[0], OBJECT(vdev), ++ &vfio_ascend_intercept_regs_quirk, ++ &bar0_quirk[0], ++ "vfio-ascend910-bar0-intercept-regs-quirk", ++ ASCEND910_XLOADER_SIZE); ++ memory_region_add_subregion_overlap(vdev->bars[nr].region.mem, ++ bar0_quirk[0].offset, ++ &quirk->mem[0], 1); ++ QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next); ++} ++ + static void vfio_probe_ascend710_bar0_quirk(VFIOPCIDevice *vdev, int nr) + { + VFIOQuirk *quirk; +@@ -1371,6 +1407,7 @@ void vfio_bar_quirk_setup(VFIOPCIDevice *vdev, int nr) + #ifdef CONFIG_VFIO_IGD + vfio_probe_igd_bar4_quirk(vdev, nr); + #endif ++ vfio_probe_ascend910_bar0_quirk(vdev, nr); + vfio_probe_ascend710_bar0_quirk(vdev, nr); + vfio_probe_ascend310_bar4_quirk(vdev, nr); + } +-- +2.27.0 + diff --git a/vfio-pci-Implement-return_page_response-page-respons.patch b/vfio-pci-Implement-return_page_response-page-respons.patch index 721512e4095c6385efe44279e7e44744ea781899..21d88a363a4ddb9305b9990424a121e8ccb68623 100644 --- a/vfio-pci-Implement-return_page_response-page-respons.patch +++ b/vfio-pci-Implement-return_page_response-page-respons.patch @@ -1,4 +1,4 @@ -From dab7c3ad6d51e9f0c65d864d6128f62697db4604 Mon Sep 17 00:00:00 2001 +From 6bbf810edebdb89a6958519ee3adfb1888520231 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Fri, 6 Nov 2020 12:03:29 -0500 Subject: [PATCH] vfio/pci: Implement return_page_response page response @@ -18,10 +18,10 @@ Signed-off-by: Kunkun Jiang 2 files changed, 125 insertions(+) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c -index d1198c8a23..6f4083aec8 100644 +index c54e62fe8f..8e24f9c7d1 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c -@@ -2662,6 +2662,61 @@ out: +@@ -2693,6 +2693,61 @@ out: g_free(fault_region_info); } @@ -83,7 +83,7 @@ index d1198c8a23..6f4083aec8 100644 static void vfio_populate_device(VFIOPCIDevice *vdev, Error **errp) { VFIODevice *vbasedev = &vdev->vbasedev; -@@ -2737,6 +2792,12 @@ static void vfio_populate_device(VFIOPCIDevice *vdev, Error **errp) +@@ -2768,6 +2823,12 @@ static void vfio_populate_device(VFIOPCIDevice *vdev, Error **errp) return; } @@ -96,7 +96,7 @@ index d1198c8a23..6f4083aec8 100644 irq_info.index = VFIO_PCI_ERR_IRQ_INDEX; ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info); -@@ -2915,8 +2976,68 @@ static int vfio_iommu_set_pasid_table(PCIBus *bus, int32_t devfn, +@@ -2946,8 +3007,68 @@ static int vfio_iommu_set_pasid_table(PCIBus *bus, int32_t devfn, return ioctl(container->fd, VFIO_IOMMU_SET_PASID_TABLE, &info); } @@ -165,7 +165,7 @@ index d1198c8a23..6f4083aec8 100644 }; static void vfio_dma_fault_notifier_handler(void *opaque) -@@ -3373,6 +3494,7 @@ static void vfio_instance_finalize(Object *obj) +@@ -3411,6 +3532,7 @@ static void vfio_instance_finalize(Object *obj) vfio_display_finalize(vdev); vfio_bars_finalize(vdev); vfio_region_finalize(&vdev->dma_fault_region); @@ -173,19 +173,19 @@ index d1198c8a23..6f4083aec8 100644 g_free(vdev->emulated_config_bits); g_free(vdev->rom); /* -@@ -3394,6 +3516,7 @@ static void vfio_exitfn(PCIDevice *pdev) +@@ -3432,6 +3554,7 @@ static void vfio_exitfn(PCIDevice *pdev) vfio_unregister_err_notifier(vdev); vfio_unregister_ext_irq_notifiers(vdev); vfio_region_exit(&vdev->dma_fault_region); + vfio_region_exit(&vdev->dma_fault_response_region); pci_device_set_intx_routing_notifier(&vdev->pdev, NULL); - vfio_disable_interrupts(vdev); - if (vdev->intx.mmap_timer) { + if (vdev->irqchip_change_notifier.notify) { + kvm_irqchip_remove_change_notifier(&vdev->irqchip_change_notifier); diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h -index e31bc0173a..7fdcfa0dc8 100644 +index 03ac8919ef..61b3bf1303 100644 --- a/hw/vfio/pci.h +++ b/hw/vfio/pci.h -@@ -143,6 +143,8 @@ typedef struct VFIOPCIDevice { +@@ -147,6 +147,8 @@ struct VFIOPCIDevice { VFIOPCIExtIRQ *ext_irqs; VFIORegion dma_fault_region; uint32_t fault_tail_index; diff --git a/vfio-pci-Implement-the-DMA-fault-handler.patch b/vfio-pci-Implement-the-DMA-fault-handler.patch index ca61b01c4469cd30c3b4b781c2cc527b48c45e80..7d7349c9088662d0e38aa22c0b0ecbea3e0f7506 100644 --- a/vfio-pci-Implement-the-DMA-fault-handler.patch +++ b/vfio-pci-Implement-the-DMA-fault-handler.patch @@ -1,4 +1,4 @@ -From 139d0b3474c29427fea4a0ed47f51c01a76a8636 Mon Sep 17 00:00:00 2001 +From d33cc7eccb68c6a1488804c94ff5c1197ee0fc6e Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Tue, 5 Mar 2019 16:35:32 +0100 Subject: [PATCH] vfio/pci: Implement the DMA fault handler @@ -15,10 +15,10 @@ Signed-off-by: Kunkun Jiang 2 files changed, 51 insertions(+) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c -index 0db7d68258..d1198c8a23 100644 +index 76bc9d3506..c54e62fe8f 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c -@@ -2922,10 +2922,60 @@ static PCIPASIDOps vfio_pci_pasid_ops = { +@@ -2953,10 +2953,60 @@ static PCIPASIDOps vfio_pci_pasid_ops = { static void vfio_dma_fault_notifier_handler(void *opaque) { VFIOPCIExtIRQ *ext_irq = opaque; @@ -80,10 +80,10 @@ index 0db7d68258..d1198c8a23 100644 static int vfio_register_ext_irq_handler(VFIOPCIDevice *vdev, diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h -index 815154656c..e31bc0173a 100644 +index eef91065f1..03ac8919ef 100644 --- a/hw/vfio/pci.h +++ b/hw/vfio/pci.h -@@ -142,6 +142,7 @@ typedef struct VFIOPCIDevice { +@@ -146,6 +146,7 @@ struct VFIOPCIDevice { EventNotifier req_notifier; VFIOPCIExtIRQ *ext_irqs; VFIORegion dma_fault_region; diff --git a/vfio-pci-Register-handler-for-iommu-fault.patch b/vfio-pci-Register-handler-for-iommu-fault.patch index feea0a347baad96a592cefba3dd6957947d1505d..7209a807ee0911af0f6af7e01e29a9ff389944dc 100644 --- a/vfio-pci-Register-handler-for-iommu-fault.patch +++ b/vfio-pci-Register-handler-for-iommu-fault.patch @@ -1,4 +1,4 @@ -From 65b96da46d2c5dfdcf3a4618cf75ca94345164d7 Mon Sep 17 00:00:00 2001 +From 574455d1363e818905e05cd23ef0948e83a16a51 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 13 Dec 2018 04:39:30 -0500 Subject: [PATCH] vfio/pci: Register handler for iommu fault @@ -19,10 +19,10 @@ Signed-off-by: Kunkun Jiang 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c -index bbcba3fd16..f5c05d508d 100644 +index 99c52a0944..37a70932c6 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c -@@ -2857,6 +2857,76 @@ static PCIPASIDOps vfio_pci_pasid_ops = { +@@ -2888,6 +2888,76 @@ static PCIPASIDOps vfio_pci_pasid_ops = { .set_pasid_table = vfio_iommu_set_pasid_table, }; @@ -98,8 +98,8 @@ index bbcba3fd16..f5c05d508d 100644 + static void vfio_realize(PCIDevice *pdev, Error **errp) { - VFIOPCIDevice *vdev = PCI_VFIO(pdev); -@@ -2867,7 +2937,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) + VFIOPCIDevice *vdev = VFIO_PCI(pdev); +@@ -2898,7 +2968,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) ssize_t len; struct stat st; int groupid; @@ -108,7 +108,7 @@ index bbcba3fd16..f5c05d508d 100644 bool is_mdev; if (!vdev->vbasedev.sysfsdev) { -@@ -2955,6 +3025,11 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) +@@ -2986,6 +3056,11 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) goto error; } @@ -120,7 +120,7 @@ index bbcba3fd16..f5c05d508d 100644 vfio_populate_device(vdev, &err); if (err) { error_propagate(errp, err); -@@ -3161,6 +3236,9 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) +@@ -3197,6 +3272,9 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) vfio_register_err_notifier(vdev); vfio_register_req_notifier(vdev); @@ -130,19 +130,19 @@ index bbcba3fd16..f5c05d508d 100644 vfio_setup_resetfn_quirk(vdev); pci_setup_pasid_ops(pdev, &vfio_pci_pasid_ops); -@@ -3201,6 +3279,7 @@ static void vfio_exitfn(PCIDevice *pdev) +@@ -3239,6 +3317,7 @@ static void vfio_exitfn(PCIDevice *pdev) vfio_unregister_req_notifier(vdev); vfio_unregister_err_notifier(vdev); + vfio_unregister_ext_irq_notifiers(vdev); pci_device_set_intx_routing_notifier(&vdev->pdev, NULL); - vfio_disable_interrupts(vdev); - if (vdev->intx.mmap_timer) { + if (vdev->irqchip_change_notifier.notify) { + kvm_irqchip_remove_change_notifier(&vdev->irqchip_change_notifier); diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h -index 834a90d646..893d074375 100644 +index 64777516d1..a8b06737fb 100644 --- a/hw/vfio/pci.h +++ b/hw/vfio/pci.h -@@ -113,6 +113,12 @@ typedef struct VFIOMSIXInfo { +@@ -114,6 +114,12 @@ typedef struct VFIOMSIXInfo { unsigned long *pending; } VFIOMSIXInfo; @@ -152,10 +152,10 @@ index 834a90d646..893d074375 100644 + uint32_t index; +} VFIOPCIExtIRQ; + - typedef struct VFIOPCIDevice { - PCIDevice pdev; - VFIODevice vbasedev; -@@ -134,6 +140,7 @@ typedef struct VFIOPCIDevice { + #define TYPE_VFIO_PCI "vfio-pci" + OBJECT_DECLARE_SIMPLE_TYPE(VFIOPCIDevice, VFIO_PCI) + +@@ -138,6 +144,7 @@ struct VFIOPCIDevice { PCIHostDeviceAddress host; EventNotifier err_notifier; EventNotifier req_notifier; diff --git a/vfio-pci-Set-up-the-DMA-FAULT-region.patch b/vfio-pci-Set-up-the-DMA-FAULT-region.patch index ae70a0696cb8310e2669b7e75d2e12bf8e9911f8..9a4757dc7bbd03571a7d7e5981828ad817da5654 100644 --- a/vfio-pci-Set-up-the-DMA-FAULT-region.patch +++ b/vfio-pci-Set-up-the-DMA-FAULT-region.patch @@ -1,4 +1,4 @@ -From e44d9cc377848f0a560b6d114561852e95fab557 Mon Sep 17 00:00:00 2001 +From e701d0fef4fbb7935d6aa7d22d82eb2dcfee2431 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 13 Dec 2018 10:57:53 -0500 Subject: [PATCH] vfio/pci: Set up the DMA FAULT region @@ -15,10 +15,10 @@ Signed-off-by: Kunkun Jiang 2 files changed, 65 insertions(+) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c -index f5c05d508d..0db7d68258 100644 +index 37a70932c6..76bc9d3506 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c -@@ -2607,11 +2607,67 @@ int vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp) +@@ -2638,11 +2638,67 @@ int vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp) return 0; } @@ -86,7 +86,7 @@ index f5c05d508d..0db7d68258 100644 int i, ret = -1; /* Sanity check device */ -@@ -2675,6 +2731,12 @@ static void vfio_populate_device(VFIOPCIDevice *vdev, Error **errp) +@@ -2706,6 +2762,12 @@ static void vfio_populate_device(VFIOPCIDevice *vdev, Error **errp) } } @@ -99,7 +99,7 @@ index f5c05d508d..0db7d68258 100644 irq_info.index = VFIO_PCI_ERR_IRQ_INDEX; ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info); -@@ -3260,6 +3322,7 @@ static void vfio_instance_finalize(Object *obj) +@@ -3298,6 +3360,7 @@ static void vfio_instance_finalize(Object *obj) vfio_display_finalize(vdev); vfio_bars_finalize(vdev); @@ -107,19 +107,19 @@ index f5c05d508d..0db7d68258 100644 g_free(vdev->emulated_config_bits); g_free(vdev->rom); /* -@@ -3280,6 +3343,7 @@ static void vfio_exitfn(PCIDevice *pdev) +@@ -3318,6 +3381,7 @@ static void vfio_exitfn(PCIDevice *pdev) vfio_unregister_req_notifier(vdev); vfio_unregister_err_notifier(vdev); vfio_unregister_ext_irq_notifiers(vdev); + vfio_region_exit(&vdev->dma_fault_region); pci_device_set_intx_routing_notifier(&vdev->pdev, NULL); - vfio_disable_interrupts(vdev); - if (vdev->intx.mmap_timer) { + if (vdev->irqchip_change_notifier.notify) { + kvm_irqchip_remove_change_notifier(&vdev->irqchip_change_notifier); diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h -index 893d074375..815154656c 100644 +index a8b06737fb..eef91065f1 100644 --- a/hw/vfio/pci.h +++ b/hw/vfio/pci.h -@@ -141,6 +141,7 @@ typedef struct VFIOPCIDevice { +@@ -145,6 +145,7 @@ struct VFIOPCIDevice { EventNotifier err_notifier; EventNotifier req_notifier; VFIOPCIExtIRQ *ext_irqs; diff --git a/vfio.h-and-iommu.h-header-update-against-5.10.patch b/vfio.h-and-iommu.h-header-update-against-5.10.patch index 721f2b6fcbc9de84c77b59ddf68da60d3d1fd255..8272a6793eb1b672efe3980f4abc3ca61cb39732 100644 --- a/vfio.h-and-iommu.h-header-update-against-5.10.patch +++ b/vfio.h-and-iommu.h-header-update-against-5.10.patch @@ -1,4 +1,4 @@ -From 95435c6778f38dee9ed6f3ee6fd9e022107315d7 Mon Sep 17 00:00:00 2001 +From 36b65d7312a343cb636e6963b8262dce9420ebc6 Mon Sep 17 00:00:00 2001 From: Kunkun Jiang Date: Fri, 30 Jul 2021 09:15:31 +0800 Subject: [PATCH] vfio.h and iommu.h header update against 5.10 @@ -6,8 +6,8 @@ Subject: [PATCH] vfio.h and iommu.h header update against 5.10 Signed-off-by: Kunkun Jiang --- linux-headers/linux/iommu.h | 395 ++++++++++++++++++++++++++++++++++++ - linux-headers/linux/vfio.h | 249 ++++++++++++++++++++++- - 2 files changed, 641 insertions(+), 3 deletions(-) + linux-headers/linux/vfio.h | 220 +++++++++++++++++++- + 2 files changed, 613 insertions(+), 2 deletions(-) create mode 100644 linux-headers/linux/iommu.h diff --git a/linux-headers/linux/iommu.h b/linux-headers/linux/iommu.h @@ -412,7 +412,7 @@ index 0000000000..773b7dc2d6 + +#endif /* _UAPI_IOMMU_H */ diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h -index 120387ba58..d6edfbd2f5 100644 +index f4ff038e8c..cf8e208fac 100644 --- a/linux-headers/linux/vfio.h +++ b/linux-headers/linux/vfio.h @@ -14,6 +14,7 @@ @@ -423,35 +423,7 @@ index 120387ba58..d6edfbd2f5 100644 #define VFIO_API_VERSION 0 -@@ -211,8 +212,11 @@ struct vfio_device_info { - #define VFIO_DEVICE_FLAGS_AMBA (1 << 3) /* vfio-amba device */ - #define VFIO_DEVICE_FLAGS_CCW (1 << 4) /* vfio-ccw device */ - #define VFIO_DEVICE_FLAGS_AP (1 << 5) /* vfio-ap device */ -+#define VFIO_DEVICE_FLAGS_FSL_MC (1 << 6) /* vfio-fsl-mc device */ -+#define VFIO_DEVICE_FLAGS_CAPS (1 << 7) /* Info supports caps */ - __u32 num_regions; /* Max region index + 1 */ - __u32 num_irqs; /* Max IRQ index + 1 */ -+ __u32 cap_offset; /* Offset within info struct of first cap */ - }; - #define VFIO_DEVICE_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 7) - -@@ -228,6 +232,15 @@ struct vfio_device_info { - #define VFIO_DEVICE_API_CCW_STRING "vfio-ccw" - #define VFIO_DEVICE_API_AP_STRING "vfio-ap" - -+/* -+ * The following capabilities are unique to s390 zPCI devices. Their contents -+ * are further-defined in vfio_zdev.h -+ */ -+#define VFIO_DEVICE_INFO_CAP_ZPCI_BASE 1 -+#define VFIO_DEVICE_INFO_CAP_ZPCI_GROUP 2 -+#define VFIO_DEVICE_INFO_CAP_ZPCI_UTIL 3 -+#define VFIO_DEVICE_INFO_CAP_ZPCI_PFIP 4 -+ - /** - * VFIO_DEVICE_GET_REGION_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 8, - * struct vfio_region_info) -@@ -316,6 +329,7 @@ struct vfio_region_info_cap_type { +@@ -334,6 +335,7 @@ struct vfio_region_info_cap_type { #define VFIO_REGION_TYPE_GFX (1) #define VFIO_REGION_TYPE_CCW (2) #define VFIO_REGION_TYPE_MIGRATION (3) @@ -459,7 +431,7 @@ index 120387ba58..d6edfbd2f5 100644 /* sub-types for VFIO_REGION_TYPE_PCI_* */ -@@ -340,6 +354,10 @@ struct vfio_region_info_cap_type { +@@ -362,6 +364,10 @@ struct vfio_region_info_cap_type { /* sub-types for VFIO_REGION_TYPE_GFX */ #define VFIO_REGION_SUBTYPE_GFX_EDID (1) @@ -470,16 +442,7 @@ index 120387ba58..d6edfbd2f5 100644 /** * struct vfio_region_gfx_edid - EDID region layout. * -@@ -472,7 +490,7 @@ struct vfio_region_gfx_edid { - * 5. Resumed - * |--------->| - * -- * 0. Default state of VFIO device is _RUNNNG when the user application starts. -+ * 0. Default state of VFIO device is _RUNNING when the user application starts. - * 1. During normal shutdown of the user application, the user application may - * optionally change the VFIO device state from _RUNNING to _STOP. This - * transition is optional. The vendor driver must support this transition but -@@ -695,11 +713,30 @@ struct vfio_irq_info { +@@ -721,11 +727,30 @@ struct vfio_irq_info { #define VFIO_IRQ_INFO_MASKABLE (1 << 1) #define VFIO_IRQ_INFO_AUTOMASKED (1 << 2) #define VFIO_IRQ_INFO_NORESIZE (1 << 3) @@ -510,7 +473,7 @@ index 120387ba58..d6edfbd2f5 100644 /** * VFIO_DEVICE_SET_IRQS - _IOW(VFIO_TYPE, VFIO_BASE + 10, struct vfio_irq_set) * -@@ -801,7 +838,8 @@ enum { +@@ -827,7 +852,8 @@ enum { VFIO_PCI_MSIX_IRQ_INDEX, VFIO_PCI_ERR_IRQ_INDEX, VFIO_PCI_REQ_IRQ_INDEX, @@ -520,7 +483,7 @@ index 120387ba58..d6edfbd2f5 100644 }; /* -@@ -985,6 +1023,68 @@ struct vfio_device_feature { +@@ -1012,6 +1038,68 @@ struct vfio_device_feature { */ #define VFIO_DEVICE_FEATURE_PCI_VF_TOKEN (0) @@ -589,29 +552,7 @@ index 120387ba58..d6edfbd2f5 100644 /* -------- API for Type1 VFIO IOMMU -------- */ /** -@@ -1049,6 +1149,21 @@ struct vfio_iommu_type1_info_cap_migration { - __u64 max_dirty_bitmap_size; /* in bytes */ - }; - -+/* -+ * The DMA available capability allows to report the current number of -+ * simultaneously outstanding DMA mappings that are allowed. -+ * -+ * The structure below defines version 1 of this capability. -+ * -+ * avail: specifies the current number of outstanding DMA mappings allowed. -+ */ -+#define VFIO_IOMMU_TYPE1_INFO_DMA_AVAIL 3 -+ -+struct vfio_iommu_type1_info_dma_avail { -+ struct vfio_info_cap_header header; -+ __u32 avail; -+}; -+ - #define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12) - - /** -@@ -1072,7 +1187,7 @@ struct vfio_iommu_type1_dma_map { +@@ -1124,7 +1212,7 @@ struct vfio_iommu_type1_dma_map { struct vfio_bitmap { __u64 pgsize; /* page size for bitmap in bytes */ __u64 size; /* in bytes */ @@ -620,7 +561,7 @@ index 120387ba58..d6edfbd2f5 100644 }; /** -@@ -1188,6 +1303,134 @@ struct vfio_iommu_type1_dirty_bitmap_get { +@@ -1250,6 +1338,134 @@ struct vfio_iommu_type1_dirty_bitmap_get { #define VFIO_IOMMU_DIRTY_PAGES _IO(VFIO_TYPE, VFIO_BASE + 17) diff --git a/vhost-Add-names-to-section-rounded-warning.patch b/vhost-Add-names-to-section-rounded-warning.patch deleted file mode 100644 index 09c36eda5b8f7063d3543ec1adab3349bf87ba7b..0000000000000000000000000000000000000000 --- a/vhost-Add-names-to-section-rounded-warning.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 437a9d2c7e48495ffc467808eece045579956c79 Mon Sep 17 00:00:00 2001 -From: "Dr. David Alan Gilbert" -Date: Thu, 16 Jan 2020 20:24:13 +0000 -Subject: [PATCH] vhost: Add names to section rounded warning - -Add the memory region names to section rounding/alignment -warnings. - -Signed-off-by: Dr. David Alan Gilbert -Message-Id: <20200116202414.157959-2-dgilbert@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin ---- - hw/virtio/vhost.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c -index 9c16f0d107..ae61c33c15 100644 ---- a/hw/virtio/vhost.c -+++ b/hw/virtio/vhost.c -@@ -591,9 +591,10 @@ static void vhost_region_add_section(struct vhost_dev *dev, - * match up in the same RAMBlock if they do. - */ - if (mrs_gpa < prev_gpa_start) { -- error_report("%s:Section rounded to %"PRIx64 -- " prior to previous %"PRIx64, -- __func__, mrs_gpa, prev_gpa_start); -+ error_report("%s:Section '%s' rounded to %"PRIx64 -+ " prior to previous '%s' %"PRIx64, -+ __func__, section->mr->name, mrs_gpa, -+ prev_sec->mr->name, prev_gpa_start); - /* A way to cleanly fail here would be better */ - return; - } --- -2.27.0 - diff --git a/vhost-Fix-memory-region-section-comparison.patch b/vhost-Fix-memory-region-section-comparison.patch deleted file mode 100644 index f96bbb3795f3b4e8ee72bc8b6c6dd2ccd91aee18..0000000000000000000000000000000000000000 --- a/vhost-Fix-memory-region-section-comparison.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 8df0aa6ebb27fcf535a7d28cfdc006cd9a34a041 Mon Sep 17 00:00:00 2001 -From: "Dr. David Alan Gilbert" -Date: Wed, 14 Aug 2019 18:55:35 +0100 -Subject: [PATCH] vhost: Fix memory region section comparison - -Using memcmp to compare structures wasn't safe, -as I found out on ARM when I was getting falce miscompares. - -Use the helper function for comparing the MRSs. - -Fixes: ade6d081fc33948e56e6 ("vhost: Regenerate region list from changed sections list") -Cc: qemu-stable@nongnu.org -Signed-off-by: Dr. David Alan Gilbert -Message-Id: <20190814175535.2023-4-dgilbert@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry picked from commit 3fc4a64cbaed2ddee4c60ddc06740b320e18ab82) -Signed-off-by: Michael Roth ---- - 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 6d3a013..221e635 100644 ---- a/hw/virtio/vhost.c -+++ b/hw/virtio/vhost.c -@@ -451,8 +451,13 @@ static void vhost_commit(MemoryListener *listener) - changed = true; - } else { - /* Same size, lets check the contents */ -- changed = n_old_sections && memcmp(dev->mem_sections, old_sections, -- n_old_sections * sizeof(old_sections[0])) != 0; -+ for (int i = 0; i < n_old_sections; i++) { -+ if (!MemoryRegionSection_eq(&old_sections[i], -+ &dev->mem_sections[i])) { -+ changed = true; -+ break; -+ } -+ } - } - - trace_vhost_commit(dev->started, changed); --- -1.8.3.1 - diff --git a/vhost-cancel-migration-when-vhost-user-restarted.patch b/vhost-cancel-migration-when-vhost-user-restarted-dur.patch similarity index 79% rename from vhost-cancel-migration-when-vhost-user-restarted.patch rename to vhost-cancel-migration-when-vhost-user-restarted-dur.patch index 38557753ce28b7120f23d21bc4f87fae22160d44..d34d1249ceb70069cd9881bf14765044dc97b3a0 100644 --- a/vhost-cancel-migration-when-vhost-user-restarted.patch +++ b/vhost-cancel-migration-when-vhost-user-restarted-dur.patch @@ -1,8 +1,8 @@ -From 750328e01afe4776eaddacde406063978dbf1291 Mon Sep 17 00:00:00 2001 -From: Ying Fang +From d41206e959717f68a31da4a2d875d33035baeb9f Mon Sep 17 00:00:00 2001 +From: Chuan Zheng Date: Mon, 29 Jul 2019 16:22:12 +0800 -Subject: [PATCH] vhost: cancel migration when vhost-user restarted during - migraiton +Subject: [PATCH 08/14] 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 @@ -17,18 +17,18 @@ Reviewed-by: Gonglei 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c -index 7f61018f..f302c506 100644 +index 437347ad01..dafb23c481 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c -@@ -26,6 +26,7 @@ - #include "hw/virtio/virtio-bus.h" +@@ -25,6 +25,7 @@ #include "hw/virtio/virtio-access.h" #include "migration/blocker.h" + #include "migration/qemu-file-types.h" +#include "migration/migration.h" #include "sysemu/dma.h" + #include "sysemu/tcg.h" #include "trace.h" - -@@ -808,20 +809,24 @@ static int vhost_migration_log(MemoryListener *listener, int enable) +@@ -947,20 +948,24 @@ check_dev_state: static void vhost_log_global_start(MemoryListener *listener) { int r; @@ -56,5 +56,5 @@ index 7f61018f..f302c506 100644 } -- -2.19.1 +2.27.0 diff --git a/vhost-user-Add-support-reconnect-vhost-user-socket.patch b/vhost-user-Add-support-reconnect-vhost-user-socket.patch new file mode 100644 index 0000000000000000000000000000000000000000..cbe49c282b7ba86473e412201d613b6c01040f96 --- /dev/null +++ b/vhost-user-Add-support-reconnect-vhost-user-socket.patch @@ -0,0 +1,168 @@ +From 3a223111d71307eb4fdc18f5ee46ce3d6cb57660 Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Fri, 11 Feb 2022 18:05:47 +0800 +Subject: [PATCH] vhost-user: Add support reconnect vhost-user socket + +Add support reconnect vhost-user socket, the reconnect time +is set to be 3 seconds. + +Signed-off-by: Jinhua Cao +--- + chardev/char-socket.c | 19 ++++++++++++++++++- + hw/net/vhost_net.c | 4 +++- + hw/virtio/vhost-user.c | 6 ++++++ + include/chardev/char.h | 16 ++++++++++++++++ + net/vhost-user.c | 3 +++ + 5 files changed, 46 insertions(+), 2 deletions(-) + +diff --git a/chardev/char-socket.c b/chardev/char-socket.c +index 836cfa0bc2..b1e9f43ec6 100644 +--- a/chardev/char-socket.c ++++ b/chardev/char-socket.c +@@ -393,6 +393,22 @@ static GSource *tcp_chr_add_watch(Chardev *chr, GIOCondition cond) + return qio_channel_create_watch(s->ioc, cond); + } + ++static void tcp_chr_set_reconnect_time(Chardev *chr, ++ int64_t reconnect_time) ++{ ++ SocketChardev *s = SOCKET_CHARDEV(chr); ++ s->reconnect_time = reconnect_time; ++} ++ ++void qemu_chr_set_reconnect_time(Chardev *chr, int64_t reconnect_time) ++{ ++ ChardevClass *cc = CHARDEV_GET_CLASS(chr); ++ ++ if (cc->chr_set_reconnect_time) { ++ cc->chr_set_reconnect_time(chr, reconnect_time); ++ } ++} ++ + static void remove_hup_source(SocketChardev *s) + { + if (s->hup_source != NULL) { +@@ -591,7 +607,7 @@ static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len) + if (s->state != TCP_CHARDEV_STATE_DISCONNECTED) { + qio_channel_set_blocking(s->ioc, false, NULL); + } +- if (size == 0) { ++ if (size == 0 && chr->chr_for_flag != CHR_FOR_VHOST_USER) { + /* connection closed */ + tcp_chr_disconnect(chr); + } +@@ -1585,6 +1601,7 @@ static void char_socket_class_init(ObjectClass *oc, void *data) + cc->set_msgfds = tcp_set_msgfds; + cc->chr_add_client = tcp_chr_add_client; + cc->chr_add_watch = tcp_chr_add_watch; ++ cc->chr_set_reconnect_time = tcp_chr_set_reconnect_time; + cc->chr_update_read_handler = tcp_chr_update_read_handler; + + object_class_property_add(oc, "addr", "SocketAddress", +diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c +index 30379d2ca4..a60f7cef9a 100644 +--- a/hw/net/vhost_net.c ++++ b/hw/net/vhost_net.c +@@ -376,7 +376,9 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, + goto err_start; + } + +- if (peer->vring_enable) { ++ /* ovs needs to restore all states of vring */ ++ if (peer->vring_enable || ++ ncs[i].peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) { + /* restore vring enable state */ + r = vhost_set_vring_enable(peer, peer->vring_enable); + +diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c +index c265e9e92c..fc2b1b81c9 100644 +--- a/hw/virtio/vhost-user.c ++++ b/hw/virtio/vhost-user.c +@@ -1926,9 +1926,15 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque, + uint64_t features, protocol_features, ram_slots; + struct vhost_user *u; + int err; ++ Chardev *chr; + + assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER); + ++ chr = qemu_chr_fe_get_driver(((VhostUserState *)opaque)->chr); ++ if (chr) { ++ chr->chr_for_flag = CHR_FOR_VHOST_USER; ++ } ++ + u = g_new0(struct vhost_user, 1); + u->user = opaque; + u->dev = dev; +diff --git a/include/chardev/char.h b/include/chardev/char.h +index a319b5fdff..f388d4b109 100644 +--- a/include/chardev/char.h ++++ b/include/chardev/char.h +@@ -14,6 +14,8 @@ + #define IAC_SB 250 + #define IAC 255 + ++#define CHR_FOR_VHOST_USER 0x32a1 ++ + /* character device */ + typedef struct CharBackend CharBackend; + +@@ -70,6 +72,7 @@ struct Chardev { + GSource *gsource; + GMainContext *gcontext; + DECLARE_BITMAP(features, QEMU_CHAR_FEATURE_LAST); ++ int chr_for_flag; + }; + + /** +@@ -227,6 +230,16 @@ int qemu_chr_write(Chardev *s, const uint8_t *buf, int len, bool write_all); + #define qemu_chr_write_all(s, buf, len) qemu_chr_write(s, buf, len, true) + int qemu_chr_wait_connected(Chardev *chr, Error **errp); + ++/** ++ * @qemu_chr_set_reconnect_time: ++ * ++ * Set reconnect time for char disconnect. ++ * Currently, only vhost user will call it. ++ * ++ * @reconnect_time the reconnect_time to be set ++ */ ++void qemu_chr_set_reconnect_time(Chardev *chr, int64_t reconnect_time); ++ + #define TYPE_CHARDEV "chardev" + OBJECT_DECLARE_TYPE(Chardev, ChardevClass, CHARDEV) + +@@ -306,6 +319,9 @@ struct ChardevClass { + + /* handle various events */ + void (*chr_be_event)(Chardev *s, QEMUChrEvent event); ++ ++ /* set reconnect time */ ++ void (*chr_set_reconnect_time)(Chardev *chr, int64_t reconnect_time); + }; + + Chardev *qemu_chardev_new(const char *id, const char *typename, +diff --git a/net/vhost-user.c b/net/vhost-user.c +index b1a0247b59..d1aefcb9aa 100644 +--- a/net/vhost-user.c ++++ b/net/vhost-user.c +@@ -21,6 +21,8 @@ + #include "qemu/option.h" + #include "trace.h" + ++#define VHOST_USER_RECONNECT_TIME (3) ++ + typedef struct NetVhostUserState { + NetClientState nc; + CharBackend chr; /* only queue index 0 */ +@@ -287,6 +289,7 @@ static void net_vhost_user_event(void *opaque, QEMUChrEvent event) + trace_vhost_user_event(chr->label, event); + switch (event) { + case CHR_EVENT_OPENED: ++ qemu_chr_set_reconnect_time(chr, VHOST_USER_RECONNECT_TIME); + if (vhost_user_start(queues, ncs, s->vhost_user) < 0) { + qemu_chr_fe_disconnect(&s->chr); + return; +-- +2.27.0 + diff --git a/vhost-user-Print-unexpected-slave-message-types.patch b/vhost-user-Print-unexpected-slave-message-types.patch deleted file mode 100644 index 4287428e059d06ffaac516ed2c2aa83b4f5d4e98..0000000000000000000000000000000000000000 --- a/vhost-user-Print-unexpected-slave-message-types.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 6e084ff24ad73eb4f7541573c6097013f5b94959 Mon Sep 17 00:00:00 2001 -From: "Dr. David Alan Gilbert" -Date: Thu, 7 Feb 2019 18:22:40 +0000 -Subject: [PATCH] vhost-user: Print unexpected slave message types -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When we receive an unexpected message type on the slave fd, print -the type. - -Signed-off-by: Dr. David Alan Gilbert -Reviewed-by: Daniel P. Berrangé -Reviewed-by: Philippe Mathieu-Daudé -Signed-off-by: Dr. David Alan Gilbert ---- - hw/virtio/vhost-user.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c -index 4ca5b2551e..f012774210 100644 ---- a/hw/virtio/vhost-user.c -+++ b/hw/virtio/vhost-user.c -@@ -1054,7 +1054,7 @@ static void slave_read(void *opaque) - fd[0]); - break; - default: -- error_report("Received unexpected msg type."); -+ error_report("Received unexpected msg type: %d.", hdr.request); - ret = -EINVAL; - } - --- -2.27.0 - diff --git a/vhost-user-Set-the-acked_features-to-vm-s-featrue.patch b/vhost-user-Set-the-acked_features-to-vm-s-featrue.patch new file mode 100644 index 0000000000000000000000000000000000000000..63c03535bc4e3e4e8886981205f79aff8b40f145 --- /dev/null +++ b/vhost-user-Set-the-acked_features-to-vm-s-featrue.patch @@ -0,0 +1,96 @@ +From 12af29806ba8ede96567e4df9223f0c02669727c Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Fri, 11 Feb 2022 18:49:21 +0800 +Subject: [PATCH] vhost-user: Set the acked_features to vm's featrue + +Fix the problem when vm restart, the ovs restart and lead to the net +unreachable. The soluation is set the acked_features to vm's featrue +just the same as guest virtio-net mod load. + +Signed-off-by: Jinhua Cao +--- + hw/net/vhost_net.c | 58 +++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 57 insertions(+), 1 deletion(-) + +diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c +index a60f7cef9a..e8a79db94d 100644 +--- a/hw/net/vhost_net.c ++++ b/hw/net/vhost_net.c +@@ -152,9 +152,26 @@ static int vhost_net_get_fd(NetClientState *backend) + } + } + ++static uint64_t vhost_get_mask_features(const int *feature_bits, uint64_t features) ++{ ++ const int *bit = feature_bits; ++ uint64_t out_features = 0; ++ ++ while (*bit != VHOST_INVALID_FEATURE_BIT) { ++ uint64_t bit_mask = (1ULL << *bit); ++ if (features & bit_mask) { ++ out_features |= bit_mask; ++ } ++ bit++; ++ } ++ return out_features; ++} ++ + struct vhost_net *vhost_net_init(VhostNetOptions *options) + { + int r; ++ VirtIONet *n; ++ VirtIODevice *vdev; + bool backend_kernel = options->backend_type == VHOST_BACKEND_TYPE_KERNEL; + struct vhost_net *net = g_new0(struct vhost_net, 1); + uint64_t features = 0; +@@ -180,7 +197,46 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options) + net->backend = r; + net->dev.protocol_features = 0; + } else { +- net->dev.backend_features = 0; ++ /* for ovs restart when vm start. ++ * Normal situation: ++ * 1.vm start. ++ * 2.vhost_net_init init ok, then dev.acked_features is 0x40000000. ++ * 3.guest virtio-net mod load. qemu will call virtio_net_set_features set ++ * dev.acked_features to 0x40408000. ++ * 4.feature set to ovs's vhostuser(0x40408000). ++ * 5.ovs restart. ++ * 6.vhost_user_stop will save net->dev.acked_features(0x40408000) to ++ * VhostUserState's acked_features(0x40408000). ++ * 7.restart ok. ++ * 8.vhost_net_init fun call vhost_user_get_acked_features get the save ++ * features, and set to net->dev.acked_features. ++ * Abnormal situation: ++ * 1.vm start. ++ * 2.vhost_net_init init ok, then dev.acked_features is 0x40000000. ++ * 3.ovs restart. ++ * 4.vhost_user_stop will save net->dev.acked_features(0x40000000) to ++ * VhostUserState's acked_features(0x40000000). ++ * 5.guest virtio-net mod load. qemu will call virtio_net_set_features set ++ * dev.acked_features to 0x40408000. ++ * 6.restart ok. ++ * 7.vhost_net_init fun call vhost_user_get_acked_features get the save ++ * features(0x40000000), and set to net->dev.acked_features(0x40000000). ++ * 8.feature set to ovs's vhostuser(0x40000000). ++ * ++ * in abnormal situation, qemu set the wrong features to ovs's vhostuser, ++ * then the vm's network will be down. ++ * in abnormal situation, we found it just lost the guest feartures in ++ * acked_features, so hear we set the acked_features to vm's featrue ++ * just the same as guest virtio-net mod load. ++ */ ++ if (options->net_backend->peer) { ++ n = qemu_get_nic_opaque(options->net_backend->peer); ++ vdev = VIRTIO_DEVICE(n); ++ net->dev.backend_features = vhost_get_mask_features(vhost_net_get_feature_bits(net), ++ vdev->guest_features); ++ } else { ++ net->dev.backend_features = 0; ++ } + net->dev.protocol_features = 0; + net->backend = -1; + +-- +2.27.0 + diff --git a/vhost-user-add-separate-memslot-counter-for-vhost-us.patch b/vhost-user-add-separate-memslot-counter-for-vhost-us.patch new file mode 100644 index 0000000000000000000000000000000000000000..d84f83043c6570edeb16df68fbf0572906ed7c7d --- /dev/null +++ b/vhost-user-add-separate-memslot-counter-for-vhost-us.patch @@ -0,0 +1,244 @@ +From 185d7efe768229b43911504f64fccd33ad3650ef Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Fri, 11 Feb 2022 19:17:59 +0800 +Subject: [PATCH] vhost-user: add separate memslot counter for vhost-user + +Used_memslots is equal to dev->mem->nregions now, it is true for +vhost kernel, but not for vhost user, which uses the memory regions +that have file descriptor. In fact, not all of the memory regions +have file descriptor. +It is usefully in some scenarios, e.g. used_memslots is 8, and only +5 memory slots can be used by vhost user, it is failed to hot plug +a new memory RAM because vhost_has_free_slot just returned false, +but we can hot plug it safely in fact. + +Signed-off-by: Jinhua Cao +--- + hw/virtio/vhost-backend.c | 14 ++++++++++ + hw/virtio/vhost-user.c | 27 ++++++++++++++++++ + hw/virtio/vhost.c | 46 +++++++++++++++++++++++++------ + include/hw/virtio/vhost-backend.h | 4 +++ + 4 files changed, 82 insertions(+), 9 deletions(-) + +diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c +index b65f8f7e97..2acfb750fd 100644 +--- a/hw/virtio/vhost-backend.c ++++ b/hw/virtio/vhost-backend.c +@@ -20,6 +20,8 @@ + #include + #include + ++static unsigned int vhost_kernel_used_memslots; ++ + static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int request, + void *arg) + { +@@ -293,6 +295,16 @@ static void vhost_kernel_set_iotlb_callback(struct vhost_dev *dev, + qemu_set_fd_handler((uintptr_t)dev->opaque, NULL, NULL, NULL); + } + ++static void vhost_kernel_set_used_memslots(struct vhost_dev *dev) ++{ ++ vhost_kernel_used_memslots = dev->mem->nregions; ++} ++ ++static unsigned int vhost_kernel_get_used_memslots(void) ++{ ++ return vhost_kernel_used_memslots; ++} ++ + const VhostOps kernel_ops = { + .backend_type = VHOST_BACKEND_TYPE_KERNEL, + .vhost_backend_init = vhost_kernel_init, +@@ -325,6 +337,8 @@ const VhostOps kernel_ops = { + #endif /* CONFIG_VHOST_VSOCK */ + .vhost_set_iotlb_callback = vhost_kernel_set_iotlb_callback, + .vhost_send_device_iotlb_msg = vhost_kernel_send_device_iotlb_msg, ++ .vhost_set_used_memslots = vhost_kernel_set_used_memslots, ++ .vhost_get_used_memslots = vhost_kernel_get_used_memslots, + }; + #endif + +diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c +index a8feea489b..176cae9244 100644 +--- a/hw/virtio/vhost-user.c ++++ b/hw/virtio/vhost-user.c +@@ -234,6 +234,7 @@ static VhostUserMsg m __attribute__ ((unused)); + + /* The version of the protocol we support */ + #define VHOST_USER_VERSION (0x1) ++static unsigned int vhost_user_used_memslots; + + struct vhost_user { + struct vhost_dev *dev; +@@ -2524,6 +2525,30 @@ void vhost_user_cleanup(VhostUserState *user) + user->chr = NULL; + } + ++static void vhost_user_set_used_memslots(struct vhost_dev *dev) ++{ ++ unsigned int counter = 0; ++ int i; ++ ++ for (i = 0; i < dev->mem->nregions; ++i) { ++ struct vhost_memory_region *reg = dev->mem->regions + i; ++ ram_addr_t offset; ++ MemoryRegion *mr; ++ ++ mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr, ++ &offset); ++ if (mr && memory_region_get_fd(mr) > 0) { ++ counter++; ++ } ++ } ++ vhost_user_used_memslots = counter; ++} ++ ++static unsigned int vhost_user_get_used_memslots(void) ++{ ++ return vhost_user_used_memslots; ++} ++ + const VhostOps user_ops = { + .backend_type = VHOST_BACKEND_TYPE_USER, + .vhost_backend_init = vhost_user_backend_init, +@@ -2557,4 +2582,6 @@ const VhostOps user_ops = { + .vhost_backend_mem_section_filter = vhost_user_mem_section_filter, + .vhost_get_inflight_fd = vhost_user_get_inflight_fd, + .vhost_set_inflight_fd = vhost_user_set_inflight_fd, ++ .vhost_set_used_memslots = vhost_user_set_used_memslots, ++ .vhost_get_used_memslots = vhost_user_get_used_memslots, + }; +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index dafb23c481..e4809777bc 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -45,20 +45,20 @@ + static struct vhost_log *vhost_log; + static struct vhost_log *vhost_log_shm; + +-static unsigned int used_memslots; + static QLIST_HEAD(, vhost_dev) vhost_devices = + QLIST_HEAD_INITIALIZER(vhost_devices); + + bool vhost_has_free_slot(void) + { +- unsigned int slots_limit = ~0U; + struct vhost_dev *hdev; + + QLIST_FOREACH(hdev, &vhost_devices, entry) { +- unsigned int r = hdev->vhost_ops->vhost_backend_memslots_limit(hdev); +- slots_limit = MIN(slots_limit, r); ++ if (hdev->vhost_ops->vhost_get_used_memslots() >= ++ hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) { ++ return false; ++ } + } +- return slots_limit > used_memslots; ++ return true; + } + + static void vhost_dev_sync_region(struct vhost_dev *dev, +@@ -521,7 +521,6 @@ static void vhost_commit(MemoryListener *listener) + dev->n_mem_sections * sizeof dev->mem->regions[0]; + dev->mem = g_realloc(dev->mem, regions_size); + dev->mem->nregions = dev->n_mem_sections; +- used_memslots = dev->mem->nregions; + for (i = 0; i < dev->n_mem_sections; i++) { + struct vhost_memory_region *cur_vmr = dev->mem->regions + i; + struct MemoryRegionSection *mrs = dev->mem_sections + i; +@@ -697,6 +696,7 @@ static void vhost_region_add_section(struct vhost_dev *dev, + dev->tmp_sections[dev->n_tmp_sections - 1].fv = NULL; + memory_region_ref(section->mr); + } ++ dev->vhost_ops->vhost_set_used_memslots(dev); + } + + /* Used for both add and nop callbacks */ +@@ -712,6 +712,17 @@ static void vhost_region_addnop(MemoryListener *listener, + vhost_region_add_section(dev, section); + } + ++static void vhost_region_del(MemoryListener *listener, ++ MemoryRegionSection *section) ++{ ++ struct vhost_dev *dev = container_of(listener, struct vhost_dev, ++ memory_listener); ++ if (!vhost_section(dev, section)) { ++ return; ++ } ++ dev->vhost_ops->vhost_set_used_memslots(dev); ++} ++ + static void vhost_iommu_unmap_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) + { + struct vhost_iommu *iommu = container_of(n, struct vhost_iommu, n); +@@ -1319,6 +1330,18 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq) + event_notifier_cleanup(&vq->masked_notifier); + } + ++static bool vhost_dev_used_memslots_is_exceeded(struct vhost_dev *hdev) ++{ ++ if (hdev->vhost_ops->vhost_get_used_memslots() > ++ hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) { ++ error_report("vhost backend memory slots limit is less" ++ " than current number of present memory slots"); ++ return true; ++ } ++ ++ return false; ++} ++ + int vhost_dev_init(struct vhost_dev *hdev, void *opaque, + VhostBackendType backend_type, uint32_t busyloop_timeout, + Error **errp) +@@ -1374,6 +1397,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, + .name = "vhost", + .begin = vhost_begin, + .commit = vhost_commit, ++ .region_del = vhost_region_del, + .region_add = vhost_region_addnop, + .region_nop = vhost_region_addnop, + .log_start = vhost_log_start, +@@ -1420,9 +1444,13 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, + memory_listener_register(&hdev->memory_listener, &address_space_memory); + QLIST_INSERT_HEAD(&vhost_devices, hdev, entry); + +- if (used_memslots > hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) { +- error_setg(errp, "vhost backend memory slots limit is less" +- " than current number of present memory slots"); ++ /* ++ * If we started a VM without any vhost device, ++ * vhost_dev_used_memslots_is_exceeded will always return false for the ++ * first time vhost device hot-plug(vhost_get_used_memslots is always 0), ++ * so it needs to double check here ++ */ ++ if (vhost_dev_used_memslots_is_exceeded(hdev)) { + r = -EINVAL; + goto fail_busyloop; + } +diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h +index 81bf3109f8..a64708f456 100644 +--- a/include/hw/virtio/vhost-backend.h ++++ b/include/hw/virtio/vhost-backend.h +@@ -125,6 +125,8 @@ typedef int (*vhost_vq_get_addr_op)(struct vhost_dev *dev, + typedef int (*vhost_get_device_id_op)(struct vhost_dev *dev, uint32_t *dev_id); + + typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev); ++typedef void (*vhost_set_used_memslots_op)(struct vhost_dev *dev); ++typedef unsigned int (*vhost_get_used_memslots_op)(void); + + typedef struct VhostOps { + VhostBackendType backend_type; +@@ -171,6 +173,8 @@ typedef struct VhostOps { + vhost_vq_get_addr_op vhost_vq_get_addr; + vhost_get_device_id_op vhost_get_device_id; + vhost_force_iommu_op vhost_force_iommu; ++ vhost_set_used_memslots_op vhost_set_used_memslots; ++ vhost_get_used_memslots_op vhost_get_used_memslots; + } VhostOps; + + int vhost_backend_update_device_iotlb(struct vhost_dev *dev, +-- +2.27.0 + diff --git a/vhost-user-add-unregister_savevm-when-vhost-user-cle.patch b/vhost-user-add-unregister_savevm-when-vhost-user-cle.patch new file mode 100644 index 0000000000000000000000000000000000000000..95488a220c8d37b4fae6d3ebfc2cc016ea45f364 --- /dev/null +++ b/vhost-user-add-unregister_savevm-when-vhost-user-cle.patch @@ -0,0 +1,33 @@ +From a9459c849c5484a022f67a317b72de764c84c845 Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Thu, 10 Feb 2022 20:21:33 +0800 +Subject: [PATCH] vhost-user: add unregister_savevm when vhost-user cleanup + +Signed-off-by: Jinhua Cao +--- + hw/virtio/vhost-user.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c +index bf6e50223c..c265e9e92c 100644 +--- a/hw/virtio/vhost-user.c ++++ b/hw/virtio/vhost-user.c +@@ -24,6 +24,7 @@ + #include "sysemu/cryptodev.h" + #include "migration/migration.h" + #include "migration/postcopy-ram.h" ++#include "migration/register.h" + #include "trace.h" + + #include +@@ -2068,6 +2069,7 @@ static int vhost_user_backend_cleanup(struct vhost_dev *dev) + u->region_rb_len = 0; + g_free(u); + dev->opaque = 0; ++ unregister_savevm(NULL, "vhost-user", dev); + + return 0; + } +-- +2.27.0 + diff --git a/vhost-user-add-vhost_set_mem_table-when-vm-load_setu.patch b/vhost-user-add-vhost_set_mem_table-when-vm-load_setu.patch new file mode 100644 index 0000000000000000000000000000000000000000..fcd6bbf930f6496eee95cee86459f83b979ab507 --- /dev/null +++ b/vhost-user-add-vhost_set_mem_table-when-vm-load_setu.patch @@ -0,0 +1,61 @@ +From 5c753d539a968f2127ff6e5b916cd4b38a08b40c Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Fri, 11 Feb 2022 18:59:34 +0800 +Subject: [PATCH] vhost-user: add vhost_set_mem_table when vm load_setup at + destination + +When migrate huge vm, packages lost are 90+. + +During the load_setup of the destination vm, pass the +vm mem structure to ovs, the netcard could be enabled +when the migration finish state shifting. + +Signed-off-by: Jinhua Cao +--- + hw/virtio/vhost-user.c | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c +index fc2b1b81c9..a8feea489b 100644 +--- a/hw/virtio/vhost-user.c ++++ b/hw/virtio/vhost-user.c +@@ -1920,6 +1920,28 @@ static int vhost_user_postcopy_notifier(NotifierWithReturn *notifier, + return 0; + } + ++static int vhost_user_load_setup(QEMUFile *f, void *opaque) ++{ ++ struct vhost_dev *hdev = opaque; ++ int r; ++ ++ if (hdev->vhost_ops && hdev->vhost_ops->vhost_set_mem_table) { ++ r = hdev->vhost_ops->vhost_set_mem_table(hdev, hdev->mem); ++ if (r < 0) { ++ qemu_log("error: vhost_set_mem_table failed: %s(%d)\n", ++ strerror(errno), errno); ++ return r; ++ } else { ++ qemu_log("info: vhost_set_mem_table OK\n"); ++ } ++ } ++ return 0; ++} ++ ++SaveVMHandlers savevm_vhost_user_handlers = { ++ .load_setup = vhost_user_load_setup, ++}; ++ + static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque, + Error **errp) + { +@@ -2044,6 +2066,7 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque, + + u->postcopy_notifier.notify = vhost_user_postcopy_notifier; + postcopy_add_notifier(&u->postcopy_notifier); ++ register_savevm_live("vhost-user", -1, 1, &savevm_vhost_user_handlers, dev); + + return 0; + } +-- +2.27.0 + diff --git a/vhost-user-blk-convert-to-new-virtio_delete_queue.patch b/vhost-user-blk-convert-to-new-virtio_delete_queue.patch deleted file mode 100644 index 3f419966ec034fe4eecd8e6606b6e7dc611517e1..0000000000000000000000000000000000000000 --- a/vhost-user-blk-convert-to-new-virtio_delete_queue.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 30d20e1258722431198cd2a8298c85b7af2a0c1b Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Mon, 24 Feb 2020 12:13:36 +0800 -Subject: [PATCH 5/9] vhost-user-blk: convert to new virtio_delete_queue - -use the new virtio_delete_queue function to cleanup. - -Signed-off-by: Pan Nengyuan -Message-Id: <20200224041336.30790-3-pannengyuan@huawei.com> -Reviewed-by: Stefan Hajnoczi -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Signed-off-by: AlexChen ---- - hw/block/vhost-user-blk.c | 20 ++++++++++++-------- - include/hw/virtio/vhost-user-blk.h | 4 +++- - 2 files changed, 15 insertions(+), 9 deletions(-) - -diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c -index dbc0a2e..146b927 100644 ---- a/hw/block/vhost-user-blk.c -+++ b/hw/block/vhost-user-blk.c -@@ -303,7 +303,7 @@ static int vhost_user_blk_connect(DeviceState *dev) - s->connected = true; - - s->dev.nvqs = s->num_queues; -- s->dev.vqs = s->vqs; -+ s->dev.vqs = s->vhost_vqs; - s->dev.vq_index = 0; - s->dev.backend_features = 0; - -@@ -430,13 +430,15 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp) - virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK, - sizeof(struct virtio_blk_config)); - -+ s->virtqs = g_new(VirtQueue *, s->num_queues); - for (i = 0; i < s->num_queues; i++) { -- virtio_add_queue(vdev, s->queue_size, -- vhost_user_blk_handle_output); -+ s->virtqs[i] = virtio_add_queue(vdev, s->queue_size, -+ vhost_user_blk_handle_output); - } - - s->inflight = g_new0(struct vhost_inflight, 1); -- s->vqs = g_new(struct vhost_virtqueue, s->num_queues); -+ s->vhost_vqs = g_new0(struct vhost_virtqueue, s->num_queues); -+ s->watch = 0; - s->connected = false; - - qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, vhost_user_blk_event, -@@ -467,11 +469,12 @@ reconnect: - return; - - virtio_err: -- g_free(s->vqs); -+ g_free(s->vhost_vqs); - g_free(s->inflight); - for (i = 0; i < s->num_queues; i++) { -- virtio_del_queue(vdev, i); -+ virtio_delete_queue(s->virtqs[i]); - } -+ g_free(s->virtqs); - virtio_cleanup(vdev); - vhost_user_cleanup(&s->vhost_user); - } -@@ -487,12 +490,13 @@ static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp) - NULL, NULL, NULL, false); - vhost_dev_cleanup(&s->dev); - vhost_dev_free_inflight(s->inflight); -- g_free(s->vqs); -+ g_free(s->vhost_vqs); - g_free(s->inflight); - - for (i = 0; i < s->num_queues; i++) { -- virtio_del_queue(vdev, i); -+ virtio_delete_queue(s->virtqs[i]); - } -+ g_free(s->virtqs); - virtio_cleanup(vdev); - vhost_user_cleanup(&s->vhost_user); - } -diff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-user-blk.h -index ad9b742..29375dd 100644 ---- a/include/hw/virtio/vhost-user-blk.h -+++ b/include/hw/virtio/vhost-user-blk.h -@@ -37,7 +37,9 @@ typedef struct VHostUserBlk { - struct vhost_dev dev; - struct vhost_inflight *inflight; - VhostUserState vhost_user; -- struct vhost_virtqueue *vqs; -+ struct vhost_virtqueue *vhost_vqs; -+ VirtQueue **virtqs; -+ guint watch; - bool connected; - } VHostUserBlk; - --- -1.8.3.1 - diff --git a/vhost-user-blk-delay-vhost_user_blk_disconnect.patch b/vhost-user-blk-delay-vhost_user_blk_disconnect.patch deleted file mode 100644 index 422e2a17b028d83690cc620a57829260c76aab52..0000000000000000000000000000000000000000 --- a/vhost-user-blk-delay-vhost_user_blk_disconnect.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 632a841b6ba547906b475250f5c2cb46774ab4af Mon Sep 17 00:00:00 2001 -From: Dima Stepanov -Date: Thu, 28 May 2020 12:11:19 +0300 -Subject: [PATCH 14/14] vhost-user-blk: delay vhost_user_blk_disconnect - -A socket write during vhost-user communication may trigger a disconnect -event, calling vhost_user_blk_disconnect() and clearing all the -vhost_dev structures holding data that vhost-user functions expect to -remain valid to roll back initialization correctly. Delay the cleanup to -keep vhost_dev structure valid. -There are two possible states to handle: -1. RUN_STATE_PRELAUNCH: skip bh oneshot call and perform disconnect in -the caller routine. -2. RUN_STATE_RUNNING: delay by using bh - -BH changes are based on the similar changes for the vhost-user-net -device: - commit e7c83a885f865128ae3cf1946f8cb538b63cbfba - "vhost-user: delay vhost_user_stop" - -Signed-off-by: Dima Stepanov -Message-Id: <69b73b94dcd066065595266c852810e0863a0895.1590396396.git.dimastep@yandex-team.ru> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Signed-off-by: Li Feng -Reviewed-by: Raphael Norwitz -Signed-off-by: Peng Liang ---- - hw/block/vhost-user-blk.c | 38 +++++++++++++++++++++++++++++++++++++- - 1 file changed, 37 insertions(+), 1 deletion(-) - -diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c -index dc66f8a5febd..6b719d1d80e1 100644 ---- a/hw/block/vhost-user-blk.c -+++ b/hw/block/vhost-user-blk.c -@@ -346,6 +346,19 @@ static void vhost_user_blk_disconnect(DeviceState *dev) - vhost_dev_cleanup(&s->dev); - } - -+static void vhost_user_blk_event(void *opaque, int event); -+ -+static void vhost_user_blk_chr_closed_bh(void *opaque) -+{ -+ DeviceState *dev = opaque; -+ VirtIODevice *vdev = VIRTIO_DEVICE(dev); -+ VHostUserBlk *s = VHOST_USER_BLK(vdev); -+ -+ vhost_user_blk_disconnect(dev); -+ qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, vhost_user_blk_event, -+ NULL, opaque, NULL, true); -+} -+ - static void vhost_user_blk_event(void *opaque, int event) - { - DeviceState *dev = opaque; -@@ -360,7 +373,30 @@ static void vhost_user_blk_event(void *opaque, int event) - } - break; - case CHR_EVENT_CLOSED: -- vhost_user_blk_disconnect(dev); -+ /* -+ * A close event may happen during a read/write, but vhost -+ * code assumes the vhost_dev remains setup, so delay the -+ * stop & clear. There are two possible paths to hit this -+ * disconnect event: -+ * 1. When VM is in the RUN_STATE_PRELAUNCH state. The -+ * vhost_user_blk_device_realize() is a caller. -+ * 2. In tha main loop phase after VM start. -+ * -+ * For p2 the disconnect event will be delayed. We can't -+ * do the same for p1, because we are not running the loop -+ * at this moment. So just skip this step and perform -+ * disconnect in the caller function. -+ * -+ * TODO: maybe it is a good idea to make the same fix -+ * for other vhost-user devices. -+ */ -+ if (runstate_is_running()) { -+ AioContext *ctx = qemu_get_current_aio_context(); -+ -+ qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, NULL, NULL, -+ NULL, NULL, false); -+ aio_bh_schedule_oneshot(ctx, vhost_user_blk_chr_closed_bh, opaque); -+ } - break; - } - } --- -2.26.2 - diff --git a/vhost-user-blk-delete-virtioqueues-in-unrealize-to-f.patch b/vhost-user-blk-delete-virtioqueues-in-unrealize-to-f.patch deleted file mode 100644 index e57f5b59c972cf4c769d7b87cc2a654b72eb3b64..0000000000000000000000000000000000000000 --- a/vhost-user-blk-delete-virtioqueues-in-unrealize-to-f.patch +++ /dev/null @@ -1,69 +0,0 @@ -From d8febdc4940d719dba77a17a10a8d36ad08305ab Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Mon, 24 Feb 2020 12:13:35 +0800 -Subject: [PATCH 4/9] vhost-user-blk: delete virtioqueues in unrealize to fix - memleaks - -virtio queues forgot to delete in unrealize, and aslo error path in -realize, this patch fix these memleaks, the leak stack is as follow: - -Direct leak of 114688 byte(s) in 16 object(s) allocated from: - #0 0x7f24024fdbf0 in calloc (/lib64/libasan.so.3+0xcabf0) - #1 0x7f2401642015 in g_malloc0 (/lib64/libglib-2.0.so.0+0x50015) - #2 0x55ad175a6447 in virtio_add_queue /mnt/sdb/qemu/hw/virtio/virtio.c:2327 - #3 0x55ad17570cf9 in vhost_user_blk_device_realize /mnt/sdb/qemu/hw/block/vhost-user-blk.c:419 - #4 0x55ad175a3707 in virtio_device_realize /mnt/sdb/qemu/hw/virtio/virtio.c:3509 - #5 0x55ad176ad0d1 in device_set_realized /mnt/sdb/qemu/hw/core/qdev.c:876 - #6 0x55ad1781ff9d in property_set_bool /mnt/sdb/qemu/qom/object.c:2080 - #7 0x55ad178245ae in object_property_set_qobject /mnt/sdb/qemu/qom/qom-qobject.c:26 - #8 0x55ad17821eb4 in object_property_set_bool /mnt/sdb/qemu/qom/object.c:1338 - #9 0x55ad177aeed7 in virtio_pci_realize /mnt/sdb/qemu/hw/virtio/virtio-pci.c:1801 - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan -Reviewed-by: Stefan Hajnoczi -Message-Id: <20200224041336.30790-2-pannengyuan@huawei.com> -Reviewed-by: Stefan Hajnoczi -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Signed-off-by: AlexChen ---- - hw/block/vhost-user-blk.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c -index 6b719d1..dbc0a2e 100644 ---- a/hw/block/vhost-user-blk.c -+++ b/hw/block/vhost-user-blk.c -@@ -469,6 +469,9 @@ reconnect: - virtio_err: - g_free(s->vqs); - g_free(s->inflight); -+ for (i = 0; i < s->num_queues; i++) { -+ virtio_del_queue(vdev, i); -+ } - virtio_cleanup(vdev); - vhost_user_cleanup(&s->vhost_user); - } -@@ -477,6 +480,7 @@ static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp) - { - VirtIODevice *vdev = VIRTIO_DEVICE(dev); - VHostUserBlk *s = VHOST_USER_BLK(dev); -+ int i; - - virtio_set_status(vdev, 0); - qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, NULL, -@@ -485,6 +489,10 @@ static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp) - vhost_dev_free_inflight(s->inflight); - g_free(s->vqs); - g_free(s->inflight); -+ -+ for (i = 0; i < s->num_queues; i++) { -+ virtio_del_queue(vdev, i); -+ } - virtio_cleanup(vdev); - vhost_user_cleanup(&s->vhost_user); - } --- -1.8.3.1 - diff --git a/vhost-user-gpu-fix-OOB-write-in-virgl_cmd_get_capset.patch b/vhost-user-gpu-fix-OOB-write-in-virgl_cmd_get_capset.patch deleted file mode 100644 index 11f9ce807bca6c991b77e007d078a73289d27e2e..0000000000000000000000000000000000000000 --- a/vhost-user-gpu-fix-OOB-write-in-virgl_cmd_get_capset.patch +++ /dev/null @@ -1,51 +0,0 @@ -From acb9f3aadde7222eacf95b2d70204dd6f8351ed7 Mon Sep 17 00:00:00 2001 -From: Li Qiang -Date: Tue, 15 Jun 2021 10:14:06 +0800 -Subject: [PATCH] vhost-user-gpu: fix OOB write in 'virgl_cmd_get_capset' - (CVE-2021-3546) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fix CVE-2021-3544 - -If 'virgl_cmd_get_capset' set 'max_size' to 0, -the 'virgl_renderer_fill_caps' will write the data after the 'resp'. -This patch avoid this by checking the returned 'max_size'. - -virtio-gpu fix: abd7f08b - - ("display: virtio-gpu-3d: check -virgl capabilities max_size") - -Fixes: CVE-2021-3546 -Reported-by: default avatarLi Qiang -Reviewed-by: default avatarPrasad J Pandit -Signed-off-by: default avatarLi Qiang -Reviewed-by: Marc-André Lureau's avatarMarc-André Lureau -Message-Id: <20210516030403.107723-8-liq3ea@163.com> -Signed-off-by: Gerd Hoffmann's avatarGerd Hoffmann - -Signed-off-by: Jiajie Li ---- - contrib/vhost-user-gpu/virgl.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/contrib/vhost-user-gpu/virgl.c b/contrib/vhost-user-gpu/virgl.c -index 44e79ab82a..ad2834902b 100644 ---- a/contrib/vhost-user-gpu/virgl.c -+++ b/contrib/vhost-user-gpu/virgl.c -@@ -173,6 +173,10 @@ virgl_cmd_get_capset(VuGpu *g, - - virgl_renderer_get_cap_set(gc.capset_id, &max_ver, - &max_size); -+ if (!max_size) { -+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER; -+ return; -+ } - resp = g_malloc0(sizeof(*resp) + max_size); - - resp->hdr.type = VIRTIO_GPU_RESP_OK_CAPSET; --- -2.27.0 - diff --git a/vhost-user-gpu-fix-memory-disclosure-in-virgl_cmd_ge.patch b/vhost-user-gpu-fix-memory-disclosure-in-virgl_cmd_ge.patch deleted file mode 100644 index 46353183baae4d3465048614bb198988597901a7..0000000000000000000000000000000000000000 --- a/vhost-user-gpu-fix-memory-disclosure-in-virgl_cmd_ge.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 511cac8cbc60fafdae2589d674b7aeab15388eef Mon Sep 17 00:00:00 2001 -From: Li Qiang -Date: Tue, 15 Jun 2021 10:11:17 +0800 -Subject: [PATCH] vhost-user-gpu: fix memory disclosure in - virgl_cmd_get_capset_info (CVE-2021-3545) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fix CVE-2021-3544 - -Otherwise some of the 'resp' will be leaked to guest. - -Fixes: CVE-2021-3545 -Reported-by: default avatarLi Qiang -virtio-gpu fix: 42a8dadc - - ("virtio-gpu: fix information leak -in getting capset info dispatch") -Signed-off-by: default avatarLi Qiang -Reviewed-by: Marc-André Lureau's avatarMarc-André Lureau -Message-Id: <20210516030403.107723-2-liq3ea@163.com> -Signed-off-by: Gerd Hoffmann's avatarGerd Hoffmann - -Signed-off-by: Jiajie Li ---- - contrib/vhost-user-gpu/virgl.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/contrib/vhost-user-gpu/virgl.c b/contrib/vhost-user-gpu/virgl.c -index 79556df094..44e79ab82a 100644 ---- a/contrib/vhost-user-gpu/virgl.c -+++ b/contrib/vhost-user-gpu/virgl.c -@@ -131,6 +131,7 @@ virgl_cmd_get_capset_info(VuGpu *g, - - VUGPU_FILL_CMD(info); - -+ memset(&resp, 0, sizeof(resp)); - if (info.capset_index == 0) { - resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL; - virgl_renderer_get_cap_set(resp.capset_id, --- -2.27.0 - diff --git a/vhost-user-gpu-fix-memory-leak-in-vg_resource_attach.patch b/vhost-user-gpu-fix-memory-leak-in-vg_resource_attach.patch deleted file mode 100644 index 7c44ec4578db09283d0a6fa67c85298679472f4d..0000000000000000000000000000000000000000 --- a/vhost-user-gpu-fix-memory-leak-in-vg_resource_attach.patch +++ /dev/null @@ -1,49 +0,0 @@ -From b9f6004899adb8e501e1b9ce1cb0976a2268ad60 Mon Sep 17 00:00:00 2001 -From: Li Qiang -Date: Tue, 15 Jun 2021 09:56:42 +0800 -Subject: [PATCH] vhost-user-gpu: fix memory leak in vg_resource_attach_backing - (CVE-2021-3544) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fix CVE-2021-3544 - -Check whether the 'res' has already been attach_backing to avoid -memory leak. - -Fixes: CVE-2021-3544 -Reported-by: default avatarLi Qiang -virtio-gpu fix: 204f01b3 - - ("virtio-gpu: fix memory leak -in resource attach backing") -Signed-off-by: default avatarLi Qiang -Reviewed-by: Marc-André Lureau's avatarMarc-André Lureau -Message-Id: <20210516030403.107723-4-liq3ea@163.com> -Signed-off-by: Gerd Hoffmann's avatarGerd Hoffmann - -Signed-off-by: Jiajie Li ---- - contrib/vhost-user-gpu/main.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/contrib/vhost-user-gpu/main.c b/contrib/vhost-user-gpu/main.c -index f69af7d17f..4f087d6000 100644 ---- a/contrib/vhost-user-gpu/main.c -+++ b/contrib/vhost-user-gpu/main.c -@@ -468,6 +468,11 @@ vg_resource_attach_backing(VuGpu *g, - return; - } - -+ if (res->iov) { -+ cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; -+ return; -+ } -+ - ret = vg_create_mapping_iov(g, &ab, cmd, &res->iov); - if (ret != 0) { - cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; --- -2.27.0 - diff --git a/vhost-user-gpu-fix-memory-leak-in-virgl_cmd_resource.patch b/vhost-user-gpu-fix-memory-leak-in-virgl_cmd_resource.patch deleted file mode 100644 index c0dccd7a33a11fbcc7e14ed605f8eeff080e3c9a..0000000000000000000000000000000000000000 --- a/vhost-user-gpu-fix-memory-leak-in-virgl_cmd_resource.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 5bdbe19681e151318b749cb6b2443626bf54b82e Mon Sep 17 00:00:00 2001 -From: Li Qiang -Date: Tue, 15 Jun 2021 10:05:40 +0800 -Subject: [PATCH] vhost-user-gpu: fix memory leak in 'virgl_cmd_resource_unref' - (CVE-2021-3544) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fix CVE-2021-3544 - -The 'res->iov' will be leaked if the guest trigger following sequences: - - virgl_cmd_create_resource_2d - virgl_resource_attach_backing - virgl_cmd_resource_unref - -This patch fixes this. - -Fixes: CVE-2021-3544 -Reported-by: default avatarLi Qiang -virtio-gpu fix: 5e8e3c4c - - ("virtio-gpu: fix resource leak -in virgl_cmd_resource_unref" -Signed-off-by: default avatarLi Qiang -Reviewed-by: Marc-André Lureau's avatarMarc-André Lureau -Message-Id: <20210516030403.107723-6-liq3ea@163.com> -Signed-off-by: Gerd Hoffmann's avatarGerd Hoffmann - -Signed-off-by: Jiajie Li ---- - contrib/vhost-user-gpu/virgl.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/contrib/vhost-user-gpu/virgl.c b/contrib/vhost-user-gpu/virgl.c -index 43413e29df..4b8b536edf 100644 ---- a/contrib/vhost-user-gpu/virgl.c -+++ b/contrib/vhost-user-gpu/virgl.c -@@ -105,8 +105,14 @@ virgl_cmd_resource_unref(VuGpu *g, - struct virtio_gpu_ctrl_command *cmd) - { - struct virtio_gpu_resource_unref unref; -+ struct iovec *res_iovs = NULL; -+ int num_iovs = 0; - - VUGPU_FILL_CMD(unref); -+ virgl_renderer_resource_detach_iov(unref.resource_id, -+ &res_iovs, -+ &num_iovs); -+ g_free(res_iovs); - - virgl_renderer_resource_unref(unref.resource_id); - } --- -2.27.0 - diff --git a/vhost-user-gpu-fix-memory-leak-in-virgl_resource_att.patch b/vhost-user-gpu-fix-memory-leak-in-virgl_resource_att.patch deleted file mode 100644 index 986a49f81fa988ed176c541265571ca01d5c5c85..0000000000000000000000000000000000000000 --- a/vhost-user-gpu-fix-memory-leak-in-virgl_resource_att.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 6348348ee6a76c28159c64d6392fb6ba5a0b4374 Mon Sep 17 00:00:00 2001 -From: Li Qiang -Date: Tue, 15 Jun 2021 10:09:13 +0800 -Subject: [PATCH] vhost-user-gpu: fix memory leak in - 'virgl_resource_attach_backing' (CVE-2021-3544) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fix CVE-2021-3544 - -If 'virgl_renderer_resource_attach_iov' failed, the 'res_iovs' will -be leaked. - -Fixes: CVE-2021-3544 -Reported-by: default avatarLi Qiang -virtio-gpu fix: 33243031 - - ("virtio-gpu-3d: fix memory leak -in resource attach backing") -Signed-off-by: default avatarLi Qiang -Reviewed-by: Marc-André Lureau's avatarMarc-André Lureau -Message-Id: <20210516030403.107723-7-liq3ea@163.com> -Signed-off-by: Gerd Hoffmann's avatarGerd Hoffmann - -Signed-off-by: Jiajie Li ---- - contrib/vhost-user-gpu/virgl.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/contrib/vhost-user-gpu/virgl.c b/contrib/vhost-user-gpu/virgl.c -index 4b8b536edf..79556df094 100644 ---- a/contrib/vhost-user-gpu/virgl.c -+++ b/contrib/vhost-user-gpu/virgl.c -@@ -282,8 +282,11 @@ virgl_resource_attach_backing(VuGpu *g, - return; - } - -- virgl_renderer_resource_attach_iov(att_rb.resource_id, -+ ret = virgl_renderer_resource_attach_iov(att_rb.resource_id, - res_iovs, att_rb.nr_entries); -+ if (ret != 0) { -+ g_free(res_iovs); -+ } - } - - static void --- -2.27.0 - diff --git a/vhost-user-gpu-fix-memory-leak-while-calling-vg_reso.patch b/vhost-user-gpu-fix-memory-leak-while-calling-vg_reso.patch deleted file mode 100644 index e67cd9a6f4220e628237a6cee4eeb5f755c67196..0000000000000000000000000000000000000000 --- a/vhost-user-gpu-fix-memory-leak-while-calling-vg_reso.patch +++ /dev/null @@ -1,51 +0,0 @@ -From c276538416e9238e352d0f720db57ea1020e555f Mon Sep 17 00:00:00 2001 -From: Li Qiang -Date: Tue, 15 Jun 2021 10:02:08 +0800 -Subject: [PATCH] vhost-user-gpu: fix memory leak while calling - 'vg_resource_unref' (CVE-2021-3544) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fix CVE-2021-3544 - -If the guest trigger following sequences, the attach_backing will be leaked: - - vg_resource_create_2d - vg_resource_attach_backing - vg_resource_unref - -This patch fix this by freeing 'res->iov' in vg_resource_destroy. - -Fixes: CVE-2021-3544 -Reported-by: default avatarLi Qiang -virtio-gpu fix: 5e8e3c4c - - ("virtio-gpu: fix resource leak -in virgl_cmd_resource_unref") -Reviewed-by: default avatarPrasad J Pandit -Signed-off-by: default avatarLi Qiang -Reviewed-by: Marc-André Lureau's avatarMarc-André Lureau -Message-Id: <20210516030403.107723-5-liq3ea@163.com> -Signed-off-by: Gerd Hoffmann's avatarGerd Hoffmann - -Signed-off-by: Jiajie Li ---- - contrib/vhost-user-gpu/main.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/contrib/vhost-user-gpu/main.c b/contrib/vhost-user-gpu/main.c -index 4f087d6000..43d9851800 100644 ---- a/contrib/vhost-user-gpu/main.c -+++ b/contrib/vhost-user-gpu/main.c -@@ -379,6 +379,7 @@ vg_resource_destroy(VuGpu *g, - } - - vugbm_buffer_destroy(&res->buffer); -+ g_free(res->iov); - pixman_image_unref(res->image); - QTAILQ_REMOVE(&g->reslist, res, next); - g_free(res); --- -2.27.0 - diff --git a/vhost-user-gpu-fix-resource-leak-in-vg_resource_crea.patch b/vhost-user-gpu-fix-resource-leak-in-vg_resource_crea.patch deleted file mode 100644 index 8d565004e122e2c0308162fafb5ce3294a69f873..0000000000000000000000000000000000000000 --- a/vhost-user-gpu-fix-resource-leak-in-vg_resource_crea.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 58e7327879e89700630ca766974a18f9ac55897c Mon Sep 17 00:00:00 2001 -From: Li Qiang -Date: Tue, 15 Jun 2021 09:53:22 +0800 -Subject: [PATCH] vhost-user-gpu: fix resource leak in 'vg_resource_create_2d' - (CVE-2021-3544) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fix CVE-2021-3544 - -Call 'vugbm_buffer_destroy' in error path to avoid resource leak. - -Fixes: CVE-2021-3544 -Reported-by: default avatarLi Qiang -Reviewed-by: default avatarPrasad J Pandit -Signed-off-by: default avatarLi Qiang -Reviewed-by: Marc-André Lureau's avatarMarc-André Lureau -Message-Id: <20210516030403.107723-3-liq3ea@163.com> -Signed-off-by: Gerd Hoffmann's avatarGerd Hoffmann - -Signed-off-by: Jiajie Li ---- - contrib/vhost-user-gpu/main.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/contrib/vhost-user-gpu/main.c b/contrib/vhost-user-gpu/main.c -index b45d2019b4..f69af7d17f 100644 ---- a/contrib/vhost-user-gpu/main.c -+++ b/contrib/vhost-user-gpu/main.c -@@ -328,6 +328,7 @@ vg_resource_create_2d(VuGpu *g, - g_critical("%s: resource creation failed %d %d %d", - __func__, c2d.resource_id, c2d.width, c2d.height); - g_free(res); -+ vugbm_buffer_destroy(&res->buffer); - cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY; - return; - } --- -2.27.0 - diff --git a/vhost-user-quit-infinite-loop-while-used-memslots-is.patch b/vhost-user-quit-infinite-loop-while-used-memslots-is.patch new file mode 100644 index 0000000000000000000000000000000000000000..e6990e38165989e32f2c9b443187e805edcbb23b --- /dev/null +++ b/vhost-user-quit-infinite-loop-while-used-memslots-is.patch @@ -0,0 +1,88 @@ +From f46191f24706a6200cfe607a902b3da45f57c9ad Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Fri, 11 Feb 2022 19:24:30 +0800 +Subject: [PATCH] vhost-user: quit infinite loop while used memslots is more + than the backend limit + +When used memslots is more than the backend limit, +the vhost-user netcard would attach fail and quit +infinite loop. + +Signed-off-by: Jinhua Cao +--- + hw/virtio/vhost.c | 9 +++++++++ + include/hw/virtio/vhost.h | 1 + + net/vhost-user.c | 6 ++++++ + 3 files changed, 16 insertions(+) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index e4809777bc..4c4072951c 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -48,6 +48,8 @@ static struct vhost_log *vhost_log_shm; + static QLIST_HEAD(, vhost_dev) vhost_devices = + QLIST_HEAD_INITIALIZER(vhost_devices); + ++bool used_memslots_exceeded; ++ + bool vhost_has_free_slot(void) + { + struct vhost_dev *hdev; +@@ -1336,9 +1338,11 @@ static bool vhost_dev_used_memslots_is_exceeded(struct vhost_dev *hdev) + hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) { + error_report("vhost backend memory slots limit is less" + " than current number of present memory slots"); ++ used_memslots_exceeded = true; + return true; + } + ++ used_memslots_exceeded = false; + return false; + } + +@@ -1895,3 +1899,8 @@ int vhost_net_set_backend(struct vhost_dev *hdev, + + return -1; + } ++ ++bool used_memslots_is_exceeded(void) ++{ ++ return used_memslots_exceeded; ++} +diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h +index 58a73e7b7a..86f36f0106 100644 +--- a/include/hw/virtio/vhost.h ++++ b/include/hw/virtio/vhost.h +@@ -154,4 +154,5 @@ int vhost_dev_set_inflight(struct vhost_dev *dev, + struct vhost_inflight *inflight); + int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size, + struct vhost_inflight *inflight); ++bool used_memslots_is_exceeded(void); + #endif +diff --git a/net/vhost-user.c b/net/vhost-user.c +index d1aefcb9aa..f910a286e4 100644 +--- a/net/vhost-user.c ++++ b/net/vhost-user.c +@@ -20,6 +20,7 @@ + #include "qemu/error-report.h" + #include "qemu/option.h" + #include "trace.h" ++#include "include/hw/virtio/vhost.h" + + #define VHOST_USER_RECONNECT_TIME (3) + +@@ -369,6 +370,11 @@ static int net_vhost_user_init(NetClientState *peer, const char *device, + qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, + net_vhost_user_event, NULL, nc0->name, NULL, + true); ++ if (used_memslots_is_exceeded()) { ++ error_report("used memslots exceeded the backend limit, quit " ++ "loop"); ++ goto err; ++ } + } while (!s->started); + + assert(s->vhost_net); +-- +2.27.0 + diff --git a/vhost-user-save-features-if-the-char-dev-is-closed.patch b/vhost-user-save-features-if-the-char-dev-is-closed.patch deleted file mode 100644 index 9a0d04f4d7d98fd97e84bfba35f99d4871605b37..0000000000000000000000000000000000000000 --- a/vhost-user-save-features-if-the-char-dev-is-closed.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 7b404cae7fa2850d476c29258f03b8e77a5b4bd0 Mon Sep 17 00:00:00 2001 -From: Adrian Moreno -Date: Tue, 24 Sep 2019 18:20:44 +0200 -Subject: [PATCH] vhost-user: save features if the char dev is closed - -That way the state can be correctly restored when the device is opened -again. This might happen if the backend is restarted. - -Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1738768 -Reported-by: Pei Zhang -Fixes: 6ab79a20af3a ("do not call vhost_net_cleanup() on running net from char user event") -Cc: ddstreet@canonical.com -Cc: Michael S. Tsirkin -Cc: qemu-stable@nongnu.org -Signed-off-by: Adrian Moreno -Message-Id: <20190924162044.11414-1-amorenoz@redhat.com> -Acked-by: Jason Wang -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry picked from commit c6beefd674fff8d41b90365dfccad32e53a5abcb) -Signed-off-by: Michael Roth ---- - net/vhost-user.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/net/vhost-user.c b/net/vhost-user.c -index 51921de443..014199d600 100644 ---- a/net/vhost-user.c -+++ b/net/vhost-user.c -@@ -235,6 +235,10 @@ static void chr_closed_bh(void *opaque) - - s = DO_UPCAST(NetVhostUserState, nc, ncs[0]); - -+ if (s->vhost_net) { -+ s->acked_features = vhost_net_get_acked_features(s->vhost_net); -+ } -+ - qmp_set_link(name, false, &err); - - qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, net_vhost_user_event, --- -2.23.0 diff --git a/vhost-user-scsi-add-support-for-SPDK-hot-upgrade.patch b/vhost-user-scsi-add-support-for-SPDK-hot-upgrade.patch new file mode 100644 index 0000000000000000000000000000000000000000..8d54935e19501bf8eda7b896bf937cd68f0b161d --- /dev/null +++ b/vhost-user-scsi-add-support-for-SPDK-hot-upgrade.patch @@ -0,0 +1,94 @@ +From 8c52233c08fe66b2e5c79fd514d4f804aa6fe427 Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Fri, 11 Feb 2022 20:13:50 +0800 +Subject: [PATCH] vhost-user-scsi: add support for SPDK hot upgrade + +In the hot upgrade scenario, the reconnection mechanism of qemu and SPDK after upgrade + +Signed-off-by: Jinhua Cao +--- + hw/scsi/vhost-user-scsi.c | 42 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 41 insertions(+), 1 deletion(-) + +diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c +index 1b2f7eed98..052740a76e 100644 +--- a/hw/scsi/vhost-user-scsi.c ++++ b/hw/scsi/vhost-user-scsi.c +@@ -29,6 +29,9 @@ + #include "hw/virtio/virtio-access.h" + #include "chardev/char-fe.h" + #include "sysemu/sysemu.h" ++#include "qemu/log.h" ++ ++#define VHOST_USER_SCSI_RECONNECT_TIME 3 + + /* Features supported by the host application */ + static const int user_feature_bits[] = { +@@ -59,7 +62,7 @@ static void vhost_user_scsi_set_status(VirtIODevice *vdev, uint8_t status) + ret = vhost_scsi_common_start(vsc); + if (ret < 0) { + error_report("unable to start vhost-user-scsi: %s", strerror(-ret)); +- exit(1); ++ return; + } + } else { + vhost_scsi_common_stop(vsc); +@@ -89,11 +92,43 @@ static void vhost_dummy_handle_output(VirtIODevice *vdev, VirtQueue *vq) + { + } + ++static void vhost_user_scsi_event(void *opaque, QEMUChrEvent event) ++{ ++ int ret; ++ VHostUserSCSI *s = (VHostUserSCSI *)opaque; ++ VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s); ++ VirtIODevice *vdev = VIRTIO_DEVICE(s); ++ ++ qemu_log("event:%d, vdev status:%d\n", event, vdev->status); ++ ++ /* if CHR_EVENT_CLOSED, do nothing */ ++ if (event != CHR_EVENT_OPENED) { ++ return; ++ }; ++ ++ /* if status of vdev is not DRIVER_OK, just waiting. ++ * vsc should start when status change to DRIVER_OK */ ++ if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) { ++ return; ++ } ++ ++ /* vsc may not fully start because of vhost app stopping */ ++ if (vsc->dev.started) { ++ vhost_scsi_common_stop(vsc); ++ } ++ ++ ret = vhost_scsi_common_start(vsc); ++ if (ret < 0) { ++ qemu_log("unable to start vhost-user-scsi: %s\n", strerror(-ret)); ++ } ++} ++ + static void vhost_user_scsi_realize(DeviceState *dev, Error **errp) + { + VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev); + VHostUserSCSI *s = VHOST_USER_SCSI(dev); + VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s); ++ Chardev *chr; + struct vhost_virtqueue *vqs = NULL; + Error *err = NULL; + int ret; +@@ -132,6 +167,11 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp) + vsc->lun = 0; + vsc->target = vs->conf.boot_tpgt; + ++ chr = qemu_chr_fe_get_driver(&vs->conf.chardev); ++ qemu_chr_set_reconnect_time(chr, VHOST_USER_SCSI_RECONNECT_TIME); ++ qemu_chr_fe_set_handlers(&vs->conf.chardev, NULL, NULL, ++ vhost_user_scsi_event, NULL, s, NULL, true); ++ + return; + + free_vhost: +-- +2.27.0 + diff --git a/vhost-user-scsi-prevent-using-uninitialized-vqs.patch b/vhost-user-scsi-prevent-using-uninitialized-vqs.patch deleted file mode 100644 index d1bf2a087bf4fcbedf2a8c0fbb8b62188737d1e7..0000000000000000000000000000000000000000 --- a/vhost-user-scsi-prevent-using-uninitialized-vqs.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 4d8f2885b3f1219c3df2cf1a00dc0c55b23ee715 Mon Sep 17 00:00:00 2001 -From: Raphael Norwitz -Date: Tue, 14 Apr 2020 21:39:05 +0800 -Subject: [PATCH] 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 -Reviewed-by: Stefan Hajnoczi -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 -(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 fcee67d5..affc2431 100644 ---- a/hw/scsi/vhost-user-scsi.c -+++ b/hw/scsi/vhost-user-scsi.c -@@ -91,7 +91,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; - vqs = vsc->dev.vqs; --- -2.23.0 diff --git a/virtio-add-ability-to-delete-vq-through-a-pointer.patch b/virtio-add-ability-to-delete-vq-through-a-pointer.patch deleted file mode 100644 index e0989895e40fe4e0d3816966a24075d74b8797a0..0000000000000000000000000000000000000000 --- a/virtio-add-ability-to-delete-vq-through-a-pointer.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 98ae454efe48b2a465dfe9bc3c412b6375f1fbfc Mon Sep 17 00:00:00 2001 -From: "Michael S. Tsirkin" -Date: Mon, 9 Dec 2019 11:46:13 -0500 -Subject: [PATCH 1/9] virtio: add ability to delete vq through a pointer - -Devices tend to maintain vq pointers, allow deleting them trough a vq pointer. - -Signed-off-by: Michael S. Tsirkin -Reviewed-by: David Hildenbrand -Signed-off-by: AlexChen ---- - hw/virtio/virtio.c | 13 +++++++++---- - include/hw/virtio/virtio.h | 2 ++ - 2 files changed, 11 insertions(+), 4 deletions(-) - -diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c -index 79c2dcf..3d027d3 100644 ---- a/hw/virtio/virtio.c -+++ b/hw/virtio/virtio.c -@@ -1636,16 +1636,21 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, - return &vdev->vq[i]; - } - -+void virtio_delete_queue(VirtQueue *vq) -+{ -+ vq->vring.num = 0; -+ vq->vring.num_default = 0; -+ vq->handle_output = NULL; -+ vq->handle_aio_output = NULL; -+} -+ - void virtio_del_queue(VirtIODevice *vdev, int n) - { - if (n < 0 || n >= VIRTIO_QUEUE_MAX) { - abort(); - } - -- vdev->vq[n].vring.num = 0; -- vdev->vq[n].vring.num_default = 0; -- vdev->vq[n].handle_output = NULL; -- vdev->vq[n].handle_aio_output = NULL; -+ virtio_delete_queue(&vdev->vq[n]); - } - - static void virtio_set_isr(VirtIODevice *vdev, int value) -diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h -index f9f6237..ca2fbae 100644 ---- a/include/hw/virtio/virtio.h -+++ b/include/hw/virtio/virtio.h -@@ -187,6 +187,8 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, - - void virtio_del_queue(VirtIODevice *vdev, int n); - -+void virtio_delete_queue(VirtQueue *vq); -+ - void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem, - unsigned int len); - void virtqueue_flush(VirtQueue *vq, unsigned int count); --- -1.8.3.1 - diff --git a/virtio-balloon-apply-upstream-patch.patch b/virtio-balloon-apply-upstream-patch.patch deleted file mode 100644 index a400a49640174f7807007fad16528db087d1b5b6..0000000000000000000000000000000000000000 --- a/virtio-balloon-apply-upstream-patch.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0d86ceed3cef76334c39d879dd8b532ca258eb65 Mon Sep 17 00:00:00 2001 -From: Ming Yang -Date: Tue, 16 Nov 2021 17:21:09 +0800 -Subject: [PATCH] virtio-balloon: apply upstream patch. - -Signed-off-by: Ming Yang ---- - hw/virtio/virtio-balloon.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c -index 25de154307..17fa767483 100644 ---- a/hw/virtio/virtio-balloon.c -+++ b/hw/virtio/virtio-balloon.c -@@ -830,6 +830,13 @@ static void virtio_balloon_device_unrealize(DeviceState *dev, Error **errp) - } - balloon_stats_destroy_timer(s); - qemu_remove_balloon_handler(s); -+ -+ virtio_del_queue(vdev, 0); -+ virtio_del_queue(vdev, 1); -+ virtio_del_queue(vdev, 2); -+ if (s->free_page_vq) { -+ virtio_del_queue(vdev, 3); -+ } - virtio_cleanup(vdev); - } - --- -2.27.0 - diff --git a/virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch b/virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch deleted file mode 100644 index 3c2a3f2a424bd30ff95b8fcb53ae23c324d43153..0000000000000000000000000000000000000000 --- a/virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 01be50603be4f17af4318a7a3fe58dcc6dab1b31 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= -Date: Fri, 16 Aug 2019 19:15:03 +0200 -Subject: [PATCH] virtio-blk: Cancel the pending BH when the dataplane is reset -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When 'system_reset' is called, the main loop clear the memory -region cache before the BH has a chance to execute. Later when -the deferred function is called, some assumptions that were -made when scheduling them are no longer true when they actually -execute. - -This is what happens using a virtio-blk device (fresh RHEL7.8 install): - - $ (sleep 12.3; echo system_reset; sleep 12.3; echo system_reset; sleep 1; echo q) \ - | qemu-system-x86_64 -m 4G -smp 8 -boot menu=on \ - -device virtio-blk-pci,id=image1,drive=drive_image1 \ - -drive file=/var/lib/libvirt/images/rhel78.qcow2,if=none,id=drive_image1,format=qcow2,cache=none \ - -device virtio-net-pci,netdev=net0,id=nic0,mac=52:54:00:c4:e7:84 \ - -netdev tap,id=net0,script=/bin/true,downscript=/bin/true,vhost=on \ - -monitor stdio -serial null -nographic - (qemu) system_reset - (qemu) system_reset - (qemu) qemu-system-x86_64: hw/virtio/virtio.c:225: vring_get_region_caches: Assertion `caches != NULL' failed. - Aborted - - (gdb) bt - Thread 1 (Thread 0x7f109c17b680 (LWP 10939)): - #0 0x00005604083296d1 in vring_get_region_caches (vq=0x56040a24bdd0) at hw/virtio/virtio.c:227 - #1 0x000056040832972b in vring_avail_flags (vq=0x56040a24bdd0) at hw/virtio/virtio.c:235 - #2 0x000056040832d13d in virtio_should_notify (vdev=0x56040a240630, vq=0x56040a24bdd0) at hw/virtio/virtio.c:1648 - #3 0x000056040832d1f8 in virtio_notify_irqfd (vdev=0x56040a240630, vq=0x56040a24bdd0) at hw/virtio/virtio.c:1662 - #4 0x00005604082d213d in notify_guest_bh (opaque=0x56040a243ec0) at hw/block/dataplane/virtio-blk.c:75 - #5 0x000056040883dc35 in aio_bh_call (bh=0x56040a243f10) at util/async.c:90 - #6 0x000056040883dccd in aio_bh_poll (ctx=0x560409161980) at util/async.c:118 - #7 0x0000560408842af7 in aio_dispatch (ctx=0x560409161980) at util/aio-posix.c:460 - #8 0x000056040883e068 in aio_ctx_dispatch (source=0x560409161980, callback=0x0, user_data=0x0) at util/async.c:261 - #9 0x00007f10a8fca06d in g_main_context_dispatch () at /lib64/libglib-2.0.so.0 - #10 0x0000560408841445 in glib_pollfds_poll () at util/main-loop.c:215 - #11 0x00005604088414bf in os_host_main_loop_wait (timeout=0) at util/main-loop.c:238 - #12 0x00005604088415c4 in main_loop_wait (nonblocking=0) at util/main-loop.c:514 - #13 0x0000560408416b1e in main_loop () at vl.c:1923 - #14 0x000056040841e0e8 in main (argc=20, argv=0x7ffc2c3f9c58, envp=0x7ffc2c3f9d00) at vl.c:4578 - -Fix this by cancelling the BH when the virtio dataplane is stopped. - -[This is version of the patch was modified as discussed with Philippe on -the mailing list thread. ---Stefan] - -Reported-by: Yihuang Yu -Suggested-by: Stefan Hajnoczi -Fixes: https://bugs.launchpad.net/qemu/+bug/1839428 -Signed-off-by: Philippe Mathieu-Daudé -Message-Id: <20190816171503.24761-1-philmd@redhat.com> -Signed-off-by: Stefan Hajnoczi -(cherry picked from commit ebb6ff25cd888a52a64a9adc3692541c6d1d9a42) -Signed-off-by: Michael Roth ---- - hw/block/dataplane/virtio-blk.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c -index 158c78f852..5fea76df85 100644 ---- a/hw/block/dataplane/virtio-blk.c -+++ b/hw/block/dataplane/virtio-blk.c -@@ -297,6 +297,9 @@ void virtio_blk_data_plane_stop(VirtIODevice *vdev) - virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i); - } - -+ qemu_bh_cancel(s->bh); -+ notify_guest_bh(s); /* final chance to notify guest */ -+ - /* Clean up guest notifier (irq) */ - k->set_guest_notifiers(qbus->parent, nvqs, false); - --- -2.23.0 diff --git a/virtio-blk-On-restart-process-queued-requests-in-the.patch b/virtio-blk-On-restart-process-queued-requests-in-the.patch deleted file mode 100644 index 5edb6fd96f56ff66757af73d40bb90db142bbdc9..0000000000000000000000000000000000000000 --- a/virtio-blk-On-restart-process-queued-requests-in-the.patch +++ /dev/null @@ -1,191 +0,0 @@ -From 882897127955fbede44c73703ec297c8ae89775d Mon Sep 17 00:00:00 2001 -From: Sergio Lopez -Date: Thu, 21 Jan 2021 15:46:52 +0800 -Subject: [PATCH] virtio-blk: On restart, process queued requests in the proper - context - -On restart, we were scheduling a BH to process queued requests, which -would run before starting up the data plane, leading to those requests -being assigned and started on coroutines on the main context. - -This could cause requests to be wrongly processed in parallel from -different threads (the main thread and the iothread managing the data -plane), potentially leading to multiple issues. - -For example, stopping and resuming a VM multiple times while the guest -is generating I/O on a virtio_blk device can trigger a crash with a -stack tracing looking like this one: - -<------> - Thread 2 (Thread 0x7ff736765700 (LWP 1062503)): - #0 0x00005567a13b99d6 in iov_memset - (iov=0x6563617073206f4e, iov_cnt=1717922848, offset=516096, fillc=0, bytes=7018105756081554803) - at util/iov.c:69 - #1 0x00005567a13bab73 in qemu_iovec_memset - (qiov=0x7ff73ec99748, offset=516096, fillc=0, bytes=7018105756081554803) at util/iov.c:530 - #2 0x00005567a12f411c in qemu_laio_process_completion (laiocb=0x7ff6512ee6c0) at block/linux-aio.c:86 - #3 0x00005567a12f42ff in qemu_laio_process_completions (s=0x7ff7182e8420) at block/linux-aio.c:217 - #4 0x00005567a12f480d in ioq_submit (s=0x7ff7182e8420) at block/linux-aio.c:323 - #5 0x00005567a12f43d9 in qemu_laio_process_completions_and_submit (s=0x7ff7182e8420) - at block/linux-aio.c:236 - #6 0x00005567a12f44c2 in qemu_laio_poll_cb (opaque=0x7ff7182e8430) at block/linux-aio.c:267 - #7 0x00005567a13aed83 in run_poll_handlers_once (ctx=0x5567a2b58c70, timeout=0x7ff7367645f8) - at util/aio-posix.c:520 - #8 0x00005567a13aee9f in run_poll_handlers (ctx=0x5567a2b58c70, max_ns=16000, timeout=0x7ff7367645f8) - at util/aio-posix.c:562 - #9 0x00005567a13aefde in try_poll_mode (ctx=0x5567a2b58c70, timeout=0x7ff7367645f8) - at util/aio-posix.c:597 - #10 0x00005567a13af115 in aio_poll (ctx=0x5567a2b58c70, blocking=true) at util/aio-posix.c:639 - #11 0x00005567a109acca in iothread_run (opaque=0x5567a2b29760) at iothread.c:75 - #12 0x00005567a13b2790 in qemu_thread_start (args=0x5567a2b694c0) at util/qemu-thread-posix.c:519 - #13 0x00007ff73eedf2de in start_thread () at /lib64/libpthread.so.0 - #14 0x00007ff73ec10e83 in clone () at /lib64/libc.so.6 - - Thread 1 (Thread 0x7ff743986f00 (LWP 1062500)): - #0 0x00005567a13b99d6 in iov_memset - (iov=0x6563617073206f4e, iov_cnt=1717922848, offset=516096, fillc=0, bytes=7018105756081554803) - at util/iov.c:69 - #1 0x00005567a13bab73 in qemu_iovec_memset - (qiov=0x7ff73ec99748, offset=516096, fillc=0, bytes=7018105756081554803) at util/iov.c:530 - #2 0x00005567a12f411c in qemu_laio_process_completion (laiocb=0x7ff6512ee6c0) at block/linux-aio.c:86 - #3 0x00005567a12f42ff in qemu_laio_process_completions (s=0x7ff7182e8420) at block/linux-aio.c:217 - #4 0x00005567a12f480d in ioq_submit (s=0x7ff7182e8420) at block/linux-aio.c:323 - #5 0x00005567a12f4a2f in laio_do_submit (fd=19, laiocb=0x7ff5f4ff9ae0, offset=472363008, type=2) - at block/linux-aio.c:375 - #6 0x00005567a12f4af2 in laio_co_submit - (bs=0x5567a2b8c460, s=0x7ff7182e8420, fd=19, offset=472363008, qiov=0x7ff5f4ff9ca0, type=2) - at block/linux-aio.c:394 - #7 0x00005567a12f1803 in raw_co_prw - (bs=0x5567a2b8c460, offset=472363008, bytes=20480, qiov=0x7ff5f4ff9ca0, type=2) - at block/file-posix.c:1892 - #8 0x00005567a12f1941 in raw_co_pwritev - (bs=0x5567a2b8c460, offset=472363008, bytes=20480, qiov=0x7ff5f4ff9ca0, flags=0) - at block/file-posix.c:1925 - #9 0x00005567a12fe3e1 in bdrv_driver_pwritev - (bs=0x5567a2b8c460, offset=472363008, bytes=20480, qiov=0x7ff5f4ff9ca0, qiov_offset=0, flags=0) - at block/io.c:1183 - #10 0x00005567a1300340 in bdrv_aligned_pwritev - (child=0x5567a2b5b070, req=0x7ff5f4ff9db0, offset=472363008, bytes=20480, align=512, qiov=0x7ff72c0425b8, qiov_offset=0, flags=0) at block/io.c:1980 - #11 0x00005567a1300b29 in bdrv_co_pwritev_part - (child=0x5567a2b5b070, offset=472363008, bytes=20480, qiov=0x7ff72c0425b8, qiov_offset=0, flags=0) - at block/io.c:2137 - #12 0x00005567a12baba1 in qcow2_co_pwritev_task - (bs=0x5567a2b92740, file_cluster_offset=472317952, offset=487305216, bytes=20480, qiov=0x7ff72c0425b8, qiov_offset=0, l2meta=0x0) at block/qcow2.c:2444 - #13 0x00005567a12bacdb in qcow2_co_pwritev_task_entry (task=0x5567a2b48540) at block/qcow2.c:2475 - #14 0x00005567a13167d8 in aio_task_co (opaque=0x5567a2b48540) at block/aio_task.c:45 - #15 0x00005567a13cf00c in coroutine_trampoline (i0=738245600, i1=32759) at util/coroutine-ucontext.c:115 - #16 0x00007ff73eb622e0 in __start_context () at /lib64/libc.so.6 - #17 0x00007ff6626f1350 in () - #18 0x0000000000000000 in () -<------> - -This is also known to cause crashes with this message (assertion -failed): - - aio_co_schedule: Co-routine was already scheduled in 'aio_co_schedule' - -RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1812765 -Signed-off-by: Sergio Lopez -Message-Id: <20200603093240.40489-3-slp(a)redhat.com> -Signed-off-by: Kevin Wolf ---- - hw/block/dataplane/virtio-blk.c | 8 ++++++++ - hw/block/virtio-blk.c | 18 ++++++++++++------ - include/hw/virtio/virtio-blk.h | 2 +- - 3 files changed, 21 insertions(+), 7 deletions(-) - -diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c -index 5fea76df85..4476f97960 100644 ---- a/hw/block/dataplane/virtio-blk.c -+++ b/hw/block/dataplane/virtio-blk.c -@@ -219,6 +219,9 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) - goto fail_guest_notifiers; - } - -+ /* Process queued requests before the ones in vring */ -+ virtio_blk_process_queued_requests(vblk, false); -+ - /* Kick right away to begin processing requests already in vring */ - for (i = 0; i < nvqs; i++) { - VirtQueue *vq = virtio_get_queue(s->vdev, i); -@@ -238,6 +241,11 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) - return 0; - - fail_guest_notifiers: -+ /* -+ * If we failed to set up the guest notifiers queued requests will be -+ * processed on the main context. -+ */ -+ virtio_blk_process_queued_requests(vblk, false); - vblk->dataplane_disabled = true; - s->starting = false; - vblk->dataplane_started = true; -diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c -index cee2c673a5..ddf525b9d7 100644 ---- a/hw/block/virtio-blk.c -+++ b/hw/block/virtio-blk.c -@@ -809,7 +809,7 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) - virtio_blk_handle_output_do(s, vq); - } - --void virtio_blk_process_queued_requests(VirtIOBlock *s) -+void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh) - { - VirtIOBlockReq *req = s->rq; - MultiReqBuffer mrb = {}; -@@ -837,7 +837,9 @@ void virtio_blk_process_queued_requests(VirtIOBlock *s) - if (mrb.num_reqs) { - virtio_blk_submit_multireq(s->blk, &mrb); - } -- blk_dec_in_flight(s->conf.conf.blk); -+ if (is_bh) { -+ blk_dec_in_flight(s->conf.conf.blk); -+ } - aio_context_release(blk_get_aio_context(s->conf.conf.blk)); - } - -@@ -848,21 +850,25 @@ static void virtio_blk_dma_restart_bh(void *opaque) - qemu_bh_delete(s->bh); - s->bh = NULL; - -- virtio_blk_process_queued_requests(s); -+ virtio_blk_process_queued_requests(s, true); - } - - static void virtio_blk_dma_restart_cb(void *opaque, int running, - RunState state) - { - VirtIOBlock *s = opaque; -+ BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s))); -+ VirtioBusState *bus = VIRTIO_BUS(qbus); - - if (!running) { - return; - } - -- if (!s->bh) { -- /* FIXME The data plane is not started yet, so these requests are -- * processed in the main thread. */ -+ /* -+ * If ioeventfd is enabled, don't schedule the BH here as queued -+ * requests will be processed while starting the data plane. -+ */ -+ if (!s->bh && !virtio_bus_ioeventfd_enabled(bus)) { - s->bh = aio_bh_new(blk_get_aio_context(s->conf.conf.blk), - virtio_blk_dma_restart_bh, s); - blk_inc_in_flight(s->conf.conf.blk); -diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h -index cf8eea2f58..e77f0db3b0 100644 ---- a/include/hw/virtio/virtio-blk.h -+++ b/include/hw/virtio/virtio-blk.h -@@ -84,6 +84,6 @@ typedef struct MultiReqBuffer { - } MultiReqBuffer; - - bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq); --void virtio_blk_process_queued_requests(VirtIOBlock *s); -+void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh); - - #endif --- -2.27.0 - diff --git a/virtio-blk-Refactor-the-code-that-processes-queued-r.patch b/virtio-blk-Refactor-the-code-that-processes-queued-r.patch deleted file mode 100644 index 2848fbd0aae20aceae61a1ad4b07a47d147659b4..0000000000000000000000000000000000000000 --- a/virtio-blk-Refactor-the-code-that-processes-queued-r.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 21c5ffb363930dfe6213bb677c5811fede3bcee2 Mon Sep 17 00:00:00 2001 -From: Sergio Lopez -Date: Thu, 21 Jan 2021 15:46:51 +0800 -Subject: [PATCH] virtio-blk: Refactor the code that processes queued requests - -Move the code that processes queued requests from -virtio_blk_dma_restart_bh() to its own, non-static, function. This -will allow us to call it from the virtio_blk_data_plane_start() in a -future patch. - -Signed-off-by: Sergio Lopez -Message-Id: <20200603093240.40489-2-slp(a)redhat.com> -Signed-off-by: Kevin Wolf ---- - hw/block/virtio-blk.c | 16 +++++++++++----- - include/hw/virtio/virtio-blk.h | 1 + - 2 files changed, 12 insertions(+), 5 deletions(-) - -diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c -index 703ed4c93b..cee2c673a5 100644 ---- a/hw/block/virtio-blk.c -+++ b/hw/block/virtio-blk.c -@@ -809,15 +809,11 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) - virtio_blk_handle_output_do(s, vq); - } - --static void virtio_blk_dma_restart_bh(void *opaque) -+void virtio_blk_process_queued_requests(VirtIOBlock *s) - { -- VirtIOBlock *s = opaque; - VirtIOBlockReq *req = s->rq; - MultiReqBuffer mrb = {}; - -- qemu_bh_delete(s->bh); -- s->bh = NULL; -- - s->rq = NULL; - - aio_context_acquire(blk_get_aio_context(s->conf.conf.blk)); -@@ -845,6 +841,16 @@ static void virtio_blk_dma_restart_bh(void *opaque) - aio_context_release(blk_get_aio_context(s->conf.conf.blk)); - } - -+static void virtio_blk_dma_restart_bh(void *opaque) -+{ -+ VirtIOBlock *s = opaque; -+ -+ qemu_bh_delete(s->bh); -+ s->bh = NULL; -+ -+ virtio_blk_process_queued_requests(s); -+} -+ - static void virtio_blk_dma_restart_cb(void *opaque, int running, - RunState state) - { -diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h -index cddcfbebe9..cf8eea2f58 100644 ---- a/include/hw/virtio/virtio-blk.h -+++ b/include/hw/virtio/virtio-blk.h -@@ -84,5 +84,6 @@ typedef struct MultiReqBuffer { - } MultiReqBuffer; - - bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq); -+void virtio_blk_process_queued_requests(VirtIOBlock *s); - - #endif --- -2.27.0 - diff --git a/virtio-blk-delete-vqs-on-the-error-path-in-realize.patch b/virtio-blk-delete-vqs-on-the-error-path-in-realize.patch deleted file mode 100644 index 205f663470d3aa594910bd19e2be8547d226e1a8..0000000000000000000000000000000000000000 --- a/virtio-blk-delete-vqs-on-the-error-path-in-realize.patch +++ /dev/null @@ -1,45 +0,0 @@ -From ec8a25fec9898f46a6a94aa4f328fe02948b3d59 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Sat, 28 Mar 2020 08:57:04 +0800 -Subject: [PATCH 12/14] virtio-blk: delete vqs on the error path in realize() - -virtio_vqs forgot to free on the error path in realize(). Fix that. - -The asan stack: -Direct leak of 14336 byte(s) in 1 object(s) allocated from: - #0 0x7f58b93fd970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970) - #1 0x7f58b858249d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d) - #2 0x5562cc627f49 in virtio_add_queue /mnt/sdb/qemu/hw/virtio/virtio.c:2413 - #3 0x5562cc4b524a in virtio_blk_device_realize /mnt/sdb/qemu/hw/block/virtio-blk.c:1202 - #4 0x5562cc613050 in virtio_device_realize /mnt/sdb/qemu/hw/virtio/virtio.c:3615 - #5 0x5562ccb7a568 in device_set_realized /mnt/sdb/qemu/hw/core/qdev.c:891 - #6 0x5562cd39cd45 in property_set_bool /mnt/sdb/qemu/qom/object.c:2238 - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan -Reviewed-by: Stefano Garzarella -Message-Id: <20200328005705.29898-2-pannengyuan@huawei.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Signed-off-by: Peng Liang ---- - hw/block/virtio-blk.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c -index cbb3729158fe..703ed4c93bff 100644 ---- a/hw/block/virtio-blk.c -+++ b/hw/block/virtio-blk.c -@@ -1173,6 +1173,9 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) - virtio_blk_data_plane_create(vdev, conf, &s->dataplane, &err); - if (err != NULL) { - error_propagate(errp, err); -+ for (i = 0; i < conf->num_queues; i++) { -+ virtio_del_queue(vdev, i); -+ } - virtio_cleanup(vdev); - return; - } --- -2.26.2 - diff --git a/virtio-bugfix-add-rcu_read_lock-when-vring_avail_idx.patch b/virtio-bugfix-add-rcu_read_lock-when-vring_avail_idx.patch new file mode 100644 index 0000000000000000000000000000000000000000..39551a752e5ae493872be352cb39191a026420ad --- /dev/null +++ b/virtio-bugfix-add-rcu_read_lock-when-vring_avail_idx.patch @@ -0,0 +1,38 @@ +From 41aa66e37d04246d48b5417c57967425ecc466a0 Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Thu, 10 Feb 2022 11:16:26 +0800 +Subject: [PATCH] virtio: bugfix: add rcu_read_lock when vring_avail_idx is + called + +viring_avail_idx should be called within rcu_read_lock(), +or may get NULL caches in vring_get_region_caches() and +trigger assert(). + +Signed-off-by: Jinhua Cao +--- + hw/virtio/virtio.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index 007f4c9e26..0af9684881 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -2864,6 +2864,7 @@ static void check_vring_avail_num(VirtIODevice *vdev, int index) + { + uint16_t nheads; + ++ rcu_read_lock(); + /* Check it isn't doing strange things with descriptor numbers. */ + nheads = vring_avail_idx(&vdev->vq[index]) - vdev->vq[index].last_avail_idx; + if (nheads > vdev->vq[index].vring.num) { +@@ -2874,6 +2875,7 @@ static void check_vring_avail_num(VirtIODevice *vdev, int index) + vring_avail_idx(&vdev->vq[index]), + vdev->vq[index].last_avail_idx, nheads); + } ++ rcu_read_unlock(); + } + + int virtio_save(VirtIODevice *vdev, QEMUFile *f) +-- +2.27.0 + diff --git a/virtio-bugfix-check-the-value-of-caches-before-acces.patch b/virtio-bugfix-check-the-value-of-caches-before-acces.patch new file mode 100644 index 0000000000000000000000000000000000000000..8cead345733d1b88a88b21c45c71948e38b147b6 --- /dev/null +++ b/virtio-bugfix-check-the-value-of-caches-before-acces.patch @@ -0,0 +1,42 @@ +From 74ab61b4317f12b231fb2cbcd54a333a07efd678 Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Thu, 10 Feb 2022 14:37:52 +0800 +Subject: [PATCH] virtio: bugfix: check the value of caches before accessing it + +Vring caches may be NULL in check_vring_avail_num() if +virtio_reset() is called at the same time, such as when +the virtual machine starts. +So check it before accessing it in vring_avail_idx(). + +Signed-off-by: Jinhua Cao +--- + hw/virtio/virtio.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index 9a2a83d507..b08fff9419 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -2863,8 +2863,19 @@ static const VMStateDescription vmstate_virtio = { + static void check_vring_avail_num(VirtIODevice *vdev, int index) + { + uint16_t nheads; ++ VRingMemoryRegionCaches *caches; + + rcu_read_lock(); ++ caches = qatomic_rcu_read(&vdev->vq[index].vring.caches); ++ if (caches == NULL) { ++ /* ++ * caches may be NULL if virtio_reset is called at the same time, ++ * such as when the virtual machine starts. ++ */ ++ rcu_read_unlock(); ++ return; ++ } ++ + /* Check it isn't doing strange things with descriptor numbers. */ + nheads = vring_avail_idx(&vdev->vq[index]) - vdev->vq[index].last_avail_idx; + if (nheads > vdev->vq[index].vring.num) { +-- +2.27.0 + diff --git a/virtio-bugfix-clean-up-callback-when-del-virtqueue.patch b/virtio-bugfix-clean-up-callback-when-del-virtqueue.patch new file mode 100644 index 0000000000000000000000000000000000000000..c0e259b19742a5aef0b42e3d8cb16100e6449ae5 --- /dev/null +++ b/virtio-bugfix-clean-up-callback-when-del-virtqueue.patch @@ -0,0 +1,52 @@ +From 95d334a905e8ddaac4a8cec908dcdb03b2e5993f Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Thu, 10 Feb 2022 10:17:20 +0800 +Subject: [PATCH] virtio: bugfix: clean up callback when del virtqueue + +We will access NULL pointer as follow: +1. Start a vm with multiqueue vhost-net +2. then we write VIRTIO_PCI_GUEST_FEATURES in PCI configuration to + trigger multiqueue disable in this vm which will delete the virtqueue. + In this step, the tx_bh is deleted but the callback virtio_net_handle_tx_bh + still exist. +3. Finally, we write VIRTIO_PCI_QUEUE_NOTIFY in PCI configuration to + notify the deleted virtqueue. In this way, virtio_net_handle_tx_bh + will be called and qemu will be crashed. + +Signed-off-by: Jinhua Cao +--- + hw/net/virtio-net.c | 5 ++++- + hw/virtio/virtio.c | 1 + + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index f2014d5ea0..b3a5d0b19e 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -2644,7 +2644,10 @@ static void virtio_net_handle_tx_bh(VirtIODevice *vdev, VirtQueue *vq) + return; + } + virtio_queue_set_notification(vq, 0); +- qemu_bh_schedule(q->tx_bh); ++ ++ if (q->tx_bh) { ++ qemu_bh_schedule(q->tx_bh); ++ } + } + + static void virtio_net_tx_timer(void *opaque) +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index 9b4ac58a16..ec3e96af3b 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -2417,6 +2417,7 @@ void virtio_delete_queue(VirtQueue *vq) + { + vq->vring.num = 0; + vq->vring.num_default = 0; ++ vq->vring.align = 0; + vq->handle_output = NULL; + vq->handle_aio_output = NULL; + g_free(vq->used_elems); +-- +2.27.0 + diff --git a/virtio-check-descriptor-numbers.patch b/virtio-check-descriptor-numbers.patch new file mode 100644 index 0000000000000000000000000000000000000000..ea38103f2e17a2657060d9b72edf6470c8b0041c --- /dev/null +++ b/virtio-check-descriptor-numbers.patch @@ -0,0 +1,52 @@ +From 9e04e1c6a7a12e3e1d0a8a7cf07f441597a1dbb7 Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Thu, 10 Feb 2022 11:09:36 +0800 +Subject: [PATCH] virtio: check descriptor numbers + +Check if the vring num is normal in virtio_save(), and add LOG +the vm push the wrong viring num down through writing IO Port. + +Signed-off-by: Jinhua Cao +--- + hw/virtio/virtio.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index 03afa36e99..007f4c9e26 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -2860,6 +2860,22 @@ static const VMStateDescription vmstate_virtio = { + } + }; + ++static void check_vring_avail_num(VirtIODevice *vdev, int index) ++{ ++ uint16_t nheads; ++ ++ /* Check it isn't doing strange things with descriptor numbers. */ ++ nheads = vring_avail_idx(&vdev->vq[index]) - vdev->vq[index].last_avail_idx; ++ if (nheads > vdev->vq[index].vring.num) { ++ qemu_log("VQ %d size 0x%x Guest index 0x%x " ++ "inconsistent with Host index 0x%x: " ++ "delta 0x%x\n", ++ index, vdev->vq[index].vring.num, ++ vring_avail_idx(&vdev->vq[index]), ++ vdev->vq[index].last_avail_idx, nheads); ++ } ++} ++ + int virtio_save(VirtIODevice *vdev, QEMUFile *f) + { + BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); +@@ -2890,6 +2906,8 @@ int virtio_save(VirtIODevice *vdev, QEMUFile *f) + if (vdev->vq[i].vring.num == 0) + break; + ++ check_vring_avail_num(vdev, i); ++ + qemu_put_be32(f, vdev->vq[i].vring.num); + if (k->has_variable_vring_alignment) { + qemu_put_be32(f, vdev->vq[i].vring.align); +-- +2.27.0 + diff --git a/virtio-crypto-do-delete-ctrl_vq-in-virtio_crypto_dev.patch b/virtio-crypto-do-delete-ctrl_vq-in-virtio_crypto_dev.patch deleted file mode 100644 index aab3e86663021d2576763fff2a4f9c5985a2fb32..0000000000000000000000000000000000000000 --- a/virtio-crypto-do-delete-ctrl_vq-in-virtio_crypto_dev.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 62ded4fc6b38e2642ea4d95a93d70d0f608bee65 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Tue, 25 Feb 2020 15:55:54 +0800 -Subject: [PATCH 3/9] virtio-crypto: do delete ctrl_vq in - virtio_crypto_device_unrealize - -Similar to other virtio-deivces, ctrl_vq forgot to delete in virtio_crypto_device_unrealize, this patch fix it. -This device has aleardy maintained vq pointers. Thus, we use the new virtio_delete_queue function directly to do the cleanup. - -The leak stack: -Direct leak of 10752 byte(s) in 3 object(s) allocated from: - #0 0x7f4c024b1970 in __interceptor_calloc (/lib64/libasan.so.5+0xef970) - #1 0x7f4c018be49d in g_malloc0 (/lib64/libglib-2.0.so.0+0x5249d) - #2 0x55a2f8017279 in virtio_add_queue /mnt/sdb/qemu-new/qemu_test/qemu/hw/virtio/virtio.c:2333 - #3 0x55a2f8057035 in virtio_crypto_device_realize /mnt/sdb/qemu-new/qemu_test/qemu/hw/virtio/virtio-crypto.c:814 - #4 0x55a2f8005d80 in virtio_device_realize /mnt/sdb/qemu-new/qemu_test/qemu/hw/virtio/virtio.c:3531 - #5 0x55a2f8497d1b in device_set_realized /mnt/sdb/qemu-new/qemu_test/qemu/hw/core/qdev.c:891 - #6 0x55a2f8b48595 in property_set_bool /mnt/sdb/qemu-new/qemu_test/qemu/qom/object.c:2238 - #7 0x55a2f8b54fad in object_property_set_qobject /mnt/sdb/qemu-new/qemu_test/qemu/qom/qom-qobject.c:26 - #8 0x55a2f8b4de2c in object_property_set_bool /mnt/sdb/qemu-new/qemu_test/qemu/qom/object.c:1390 - #9 0x55a2f80609c9 in virtio_crypto_pci_realize /mnt/sdb/qemu-new/qemu_test/qemu/hw/virtio/virtio-crypto-pci.c:58 - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan -Cc: "Gonglei (Arei)" -Message-Id: <20200225075554.10835-5-pannengyuan@huawei.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Signed-off-by: AlexChen ---- - hw/virtio/virtio-crypto.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c -index 45187d3..0076b4b 100644 ---- a/hw/virtio/virtio-crypto.c -+++ b/hw/virtio/virtio-crypto.c -@@ -830,12 +830,13 @@ static void virtio_crypto_device_unrealize(DeviceState *dev, Error **errp) - - max_queues = vcrypto->multiqueue ? vcrypto->max_queues : 1; - for (i = 0; i < max_queues; i++) { -- virtio_del_queue(vdev, i); -+ virtio_delete_queue(vcrypto->vqs[i].dataq); - q = &vcrypto->vqs[i]; - qemu_bh_delete(q->dataq_bh); - } - - g_free(vcrypto->vqs); -+ virtio_delete_queue(vcrypto->ctrl_vq); - - virtio_cleanup(vdev); - cryptodev_backend_set_used(vcrypto->cryptodev, false); --- -1.8.3.1 - diff --git a/virtio-don-t-enable-notifications-during-polling.patch b/virtio-don-t-enable-notifications-during-polling.patch deleted file mode 100644 index cb77429e9e2fa70688ed245f7cf440fb61cd38ad..0000000000000000000000000000000000000000 --- a/virtio-don-t-enable-notifications-during-polling.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 0592b1e444e8ef7f00fb04a637dba72b732b70e4 Mon Sep 17 00:00:00 2001 -From: Stefan Hajnoczi -Date: Mon, 9 Dec 2019 21:09:57 +0000 -Subject: [PATCH] virtio: don't enable notifications during polling - -Virtqueue notifications are not necessary during polling, so we disable -them. This allows the guest driver to avoid MMIO vmexits. -Unfortunately the virtio-blk and virtio-scsi handler functions re-enable -notifications, defeating this optimization. - -Fix virtio-blk and virtio-scsi emulation so they leave notifications -disabled. The key thing to remember for correctness is that polling -always checks one last time after ending its loop, therefore it's safe -to lose the race when re-enabling notifications at the end of polling. - -There is a measurable performance improvement of 5-10% with the null-co -block driver. Real-life storage configurations will see a smaller -improvement because the MMIO vmexit overhead contributes less to -latency. - -Signed-off-by: Stefan Hajnoczi -Message-Id: <20191209210957.65087-1-stefanha@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin ---- - hw/block/virtio-blk.c | 9 +++++++-- - hw/scsi/virtio-scsi.c | 9 +++++++-- - hw/virtio/virtio.c | 12 ++++++------ - include/hw/virtio/virtio.h | 1 + - 4 files changed, 21 insertions(+), 10 deletions(-) - -diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c -index 2db9804cfe..fbe2ed6779 100644 ---- a/hw/block/virtio-blk.c -+++ b/hw/block/virtio-blk.c -@@ -766,13 +766,16 @@ bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq) - { - VirtIOBlockReq *req; - MultiReqBuffer mrb = {}; -+ bool suppress_notifications = virtio_queue_get_notification(vq); - bool progress = false; - - aio_context_acquire(blk_get_aio_context(s->blk)); - blk_io_plug(s->blk); - - do { -- virtio_queue_set_notification(vq, 0); -+ if (suppress_notifications) { -+ virtio_queue_set_notification(vq, 0); -+ } - - while ((req = virtio_blk_get_request(s, vq))) { - progress = true; -@@ -783,7 +786,9 @@ bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq) - } - } - -- virtio_queue_set_notification(vq, 1); -+ if (suppress_notifications) { -+ virtio_queue_set_notification(vq, 1); -+ } - } while (!virtio_queue_empty(vq)); - - if (mrb.num_reqs) { -diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c -index 8b9e5e2b49..eddb13e7c6 100644 ---- a/hw/scsi/virtio-scsi.c -+++ b/hw/scsi/virtio-scsi.c -@@ -594,12 +594,15 @@ bool virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq) - { - VirtIOSCSIReq *req, *next; - int ret = 0; -+ bool suppress_notifications = virtio_queue_get_notification(vq); - bool progress = false; - - QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs); - - do { -- virtio_queue_set_notification(vq, 0); -+ if (suppress_notifications) { -+ virtio_queue_set_notification(vq, 0); -+ } - - while ((req = virtio_scsi_pop_req(s, vq))) { - progress = true; -@@ -619,7 +622,9 @@ bool virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq) - } - } - -- virtio_queue_set_notification(vq, 1); -+ if (suppress_notifications) { -+ virtio_queue_set_notification(vq, 1); -+ } - } while (ret != -EINVAL && !virtio_queue_empty(vq)); - - QTAILQ_FOREACH_SAFE(req, &reqs, next, next) { -diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c -index 90971f4afa..daa8250332 100644 ---- a/hw/virtio/virtio.c -+++ b/hw/virtio/virtio.c -@@ -390,6 +390,11 @@ void virtio_queue_set_notification(VirtQueue *vq, int enable) - rcu_read_unlock(); - } - -+bool virtio_queue_get_notification(VirtQueue *vq) -+{ -+ return vq->notification; -+} -+ - int virtio_queue_ready(VirtQueue *vq) - { - return vq->vring.avail != 0; -@@ -2572,17 +2577,12 @@ static bool virtio_queue_host_notifier_aio_poll(void *opaque) - { - EventNotifier *n = opaque; - VirtQueue *vq = container_of(n, VirtQueue, host_notifier); -- bool progress; - - if (!vq->vring.desc || virtio_queue_empty(vq)) { - return false; - } - -- progress = virtio_queue_notify_aio_vq(vq); -- -- /* In case the handler function re-enabled notifications */ -- virtio_queue_set_notification(vq, 0); -- return progress; -+ return virtio_queue_notify_aio_vq(vq); - } - - static void virtio_queue_host_notifier_aio_poll_end(EventNotifier *n) -diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h -index ca2fbaeb35..7394715407 100644 ---- a/include/hw/virtio/virtio.h -+++ b/include/hw/virtio/virtio.h -@@ -229,6 +229,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id); - - void virtio_notify_config(VirtIODevice *vdev); - -+bool virtio_queue_get_notification(VirtQueue *vq); - void virtio_queue_set_notification(VirtQueue *vq, int enable); - - int virtio_queue_ready(VirtQueue *vq); --- -2.27.0 - diff --git a/virtio-gracefully-handle-invalid-region-caches.patch b/virtio-gracefully-handle-invalid-region-caches.patch deleted file mode 100644 index 2793f21b0d988625b4f53624c471c403937fcedc..0000000000000000000000000000000000000000 --- a/virtio-gracefully-handle-invalid-region-caches.patch +++ /dev/null @@ -1,238 +0,0 @@ -From 63a3c25baa9c7372b80df80be4447552af6d6ba0 Mon Sep 17 00:00:00 2001 -From: Stefan Hajnoczi -Date: Fri, 7 Feb 2020 10:46:19 +0000 -Subject: [PATCH 7/9] virtio: gracefully handle invalid region caches - -The virtqueue code sets up MemoryRegionCaches to access the virtqueue -guest RAM data structures. The code currently assumes that -VRingMemoryRegionCaches is initialized before device emulation code -accesses the virtqueue. An assertion will fail in -vring_get_region_caches() when this is not true. Device fuzzing found a -case where this assumption is false (see below). - -Virtqueue guest RAM addresses can also be changed from a vCPU thread -while an IOThread is accessing the virtqueue. This breaks the same -assumption but this time the caches could become invalid partway through -the virtqueue code. The code fetches the caches RCU pointer multiple -times so we will need to validate the pointer every time it is fetched. - -Add checks each time we call vring_get_region_caches() and treat invalid -caches as a nop: memory stores are ignored and memory reads return 0. - -The fuzz test failure is as follows: - - $ qemu -M pc -device virtio-blk-pci,id=drv0,drive=drive0,addr=4.0 \ - -drive if=none,id=drive0,file=null-co://,format=raw,auto-read-only=off \ - -drive if=none,id=drive1,file=null-co://,file.read-zeroes=on,format=raw \ - -display none \ - -qtest stdio - endianness - outl 0xcf8 0x80002020 - outl 0xcfc 0xe0000000 - outl 0xcf8 0x80002004 - outw 0xcfc 0x7 - write 0xe0000000 0x24 0x00ffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffab5cffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffabffffffab0000000001 - inb 0x4 - writew 0xe000001c 0x1 - write 0xe0000014 0x1 0x0d - -The following error message is produced: - - qemu-system-x86_64: /home/stefanha/qemu/hw/virtio/virtio.c:286: vring_get_region_caches: Assertion `caches != NULL' failed. - -The backtrace looks like this: - - #0 0x00007ffff5520625 in raise () at /lib64/libc.so.6 - #1 0x00007ffff55098d9 in abort () at /lib64/libc.so.6 - #2 0x00007ffff55097a9 in _nl_load_domain.cold () at /lib64/libc.so.6 - #3 0x00007ffff5518a66 in annobin_assert.c_end () at /lib64/libc.so.6 - #4 0x00005555559073da in vring_get_region_caches (vq=) at qemu/hw/virtio/virtio.c:286 - #5 vring_get_region_caches (vq=) at qemu/hw/virtio/virtio.c:283 - #6 0x000055555590818d in vring_used_flags_set_bit (mask=1, vq=0x5555575ceea0) at qemu/hw/virtio/virtio.c:398 - #7 virtio_queue_split_set_notification (enable=0, vq=0x5555575ceea0) at qemu/hw/virtio/virtio.c:398 - #8 virtio_queue_set_notification (vq=vq@entry=0x5555575ceea0, enable=enable@entry=0) at qemu/hw/virtio/virtio.c:451 - #9 0x0000555555908512 in virtio_queue_set_notification (vq=vq@entry=0x5555575ceea0, enable=enable@entry=0) at qemu/hw/virtio/virtio.c:444 - #10 0x00005555558c697a in virtio_blk_handle_vq (s=0x5555575c57e0, vq=0x5555575ceea0) at qemu/hw/block/virtio-blk.c:775 - #11 0x0000555555907836 in virtio_queue_notify_aio_vq (vq=0x5555575ceea0) at qemu/hw/virtio/virtio.c:2244 - #12 0x0000555555cb5dd7 in aio_dispatch_handlers (ctx=ctx@entry=0x55555671a420) at util/aio-posix.c:429 - #13 0x0000555555cb67a8 in aio_dispatch (ctx=0x55555671a420) at util/aio-posix.c:460 - #14 0x0000555555cb307e in aio_ctx_dispatch (source=, callback=, user_data=) at util/async.c:260 - #15 0x00007ffff7bbc510 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0 - #16 0x0000555555cb5848 in glib_pollfds_poll () at util/main-loop.c:219 - #17 os_host_main_loop_wait (timeout=) at util/main-loop.c:242 - #18 main_loop_wait (nonblocking=) at util/main-loop.c:518 - #19 0x00005555559b20c9 in main_loop () at vl.c:1683 - #20 0x0000555555838115 in main (argc=, argv=, envp=) at vl.c:4441 - -Reported-by: Alexander Bulekov -Cc: Michael Tsirkin -Cc: Cornelia Huck -Cc: Paolo Bonzini -Cc: qemu-stable@nongnu.org -Signed-off-by: Stefan Hajnoczi -Message-Id: <20200207104619.164892-1-stefanha@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Signed-off-by: AlexChen ---- - hw/virtio/virtio.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++------ - 1 file changed, 59 insertions(+), 7 deletions(-) - -diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c -index 3d027d3..90971f4 100644 ---- a/hw/virtio/virtio.c -+++ b/hw/virtio/virtio.c -@@ -221,15 +221,19 @@ static void vring_desc_read(VirtIODevice *vdev, VRingDesc *desc, - - static VRingMemoryRegionCaches *vring_get_region_caches(struct VirtQueue *vq) - { -- VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); -- assert(caches != NULL); -- return caches; -+ return atomic_rcu_read(&vq->vring.caches); - } -+ - /* Called within rcu_read_lock(). */ - static inline uint16_t vring_avail_flags(VirtQueue *vq) - { - VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); - hwaddr pa = offsetof(VRingAvail, flags); -+ -+ if (!caches) { -+ return 0; -+ } -+ - return virtio_lduw_phys_cached(vq->vdev, &caches->avail, pa); - } - -@@ -238,6 +242,11 @@ static inline uint16_t vring_avail_idx(VirtQueue *vq) - { - VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); - hwaddr pa = offsetof(VRingAvail, idx); -+ -+ if (!caches) { -+ return 0; -+ } -+ - vq->shadow_avail_idx = virtio_lduw_phys_cached(vq->vdev, &caches->avail, pa); - return vq->shadow_avail_idx; - } -@@ -247,6 +256,11 @@ static inline uint16_t vring_avail_ring(VirtQueue *vq, int i) - { - VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); - hwaddr pa = offsetof(VRingAvail, ring[i]); -+ -+ if (!caches) { -+ return 0; -+ } -+ - return virtio_lduw_phys_cached(vq->vdev, &caches->avail, pa); - } - -@@ -262,6 +276,11 @@ static inline void vring_used_write(VirtQueue *vq, VRingUsedElem *uelem, - { - VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); - hwaddr pa = offsetof(VRingUsed, ring[i]); -+ -+ if (!caches) { -+ return; -+ } -+ - virtio_tswap32s(vq->vdev, &uelem->id); - virtio_tswap32s(vq->vdev, &uelem->len); - address_space_write_cached(&caches->used, pa, uelem, sizeof(VRingUsedElem)); -@@ -273,6 +292,11 @@ static uint16_t vring_used_idx(VirtQueue *vq) - { - VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); - hwaddr pa = offsetof(VRingUsed, idx); -+ -+ if (!caches) { -+ return 0; -+ } -+ - return virtio_lduw_phys_cached(vq->vdev, &caches->used, pa); - } - -@@ -281,8 +305,12 @@ static inline void vring_used_idx_set(VirtQueue *vq, uint16_t val) - { - VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); - hwaddr pa = offsetof(VRingUsed, idx); -- virtio_stw_phys_cached(vq->vdev, &caches->used, pa, val); -- address_space_cache_invalidate(&caches->used, pa, sizeof(val)); -+ -+ if (caches) { -+ virtio_stw_phys_cached(vq->vdev, &caches->used, pa, val); -+ address_space_cache_invalidate(&caches->used, pa, sizeof(val)); -+ } -+ - vq->used_idx = val; - } - -@@ -292,8 +320,13 @@ static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask) - VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); - VirtIODevice *vdev = vq->vdev; - hwaddr pa = offsetof(VRingUsed, flags); -- uint16_t flags = virtio_lduw_phys_cached(vq->vdev, &caches->used, pa); -+ uint16_t flags; -+ -+ if (!caches) { -+ return; -+ } - -+ flags = virtio_lduw_phys_cached(vq->vdev, &caches->used, pa); - virtio_stw_phys_cached(vdev, &caches->used, pa, flags | mask); - address_space_cache_invalidate(&caches->used, pa, sizeof(flags)); - } -@@ -304,8 +337,13 @@ static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask) - VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); - VirtIODevice *vdev = vq->vdev; - hwaddr pa = offsetof(VRingUsed, flags); -- uint16_t flags = virtio_lduw_phys_cached(vq->vdev, &caches->used, pa); -+ uint16_t flags; - -+ if (!caches) { -+ return; -+ } -+ -+ flags = virtio_lduw_phys_cached(vq->vdev, &caches->used, pa); - virtio_stw_phys_cached(vdev, &caches->used, pa, flags & ~mask); - address_space_cache_invalidate(&caches->used, pa, sizeof(flags)); - } -@@ -320,6 +358,10 @@ static inline void vring_set_avail_event(VirtQueue *vq, uint16_t val) - } - - caches = vring_get_region_caches(vq); -+ if (!caches) { -+ return; -+ } -+ - pa = offsetof(VRingUsed, ring[vq->vring.num]); - virtio_stw_phys_cached(vq->vdev, &caches->used, pa, val); - address_space_cache_invalidate(&caches->used, pa, sizeof(val)); -@@ -626,6 +668,11 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes, - - max = vq->vring.num; - caches = vring_get_region_caches(vq); -+ if (!caches) { -+ virtio_error(vdev, "Region cached not initialized"); -+ goto err; -+ } -+ - if (caches->desc.len < max * sizeof(VRingDesc)) { - virtio_error(vdev, "Cannot map descriptor ring"); - goto err; -@@ -894,6 +941,11 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz) - i = head; - - caches = vring_get_region_caches(vq); -+ if (!caches) { -+ virtio_error(vdev, "Region caches not initialized"); -+ goto done; -+ } -+ - if (caches->desc.len < max * sizeof(VRingDesc)) { - virtio_error(vdev, "Cannot map descriptor ring"); - goto done; --- -1.8.3.1 - diff --git a/virtio-input-fix-memory-leak-on-unrealize.patch b/virtio-input-fix-memory-leak-on-unrealize.patch deleted file mode 100644 index df83453f04525eb4b9fa29ba3d03dc6fa8b31fc5..0000000000000000000000000000000000000000 --- a/virtio-input-fix-memory-leak-on-unrealize.patch +++ /dev/null @@ -1,45 +0,0 @@ -From e29f08036ff11bf220463b4327b315505e760a44 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Thu, 21 Nov 2019 13:56:49 +0400 -Subject: [PATCH 9/9] virtio-input: fix memory leak on unrealize -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Spotted by ASAN + minor stylistic change. - -Signed-off-by: Marc-André Lureau -Reviewed-by: Michael S. Tsirkin -Message-Id: <20191121095649.25453-1-marcandre.lureau@redhat.com> -Signed-off-by: Michael S. Tsirkin -Signed-off-by: Marc-André Lureau -Reviewed-by: Michael S. Tsirkin -Signed-off-by: AlexChen ---- - hw/input/virtio-input.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c -index 9946394..401c1de 100644 ---- a/hw/input/virtio-input.c -+++ b/hw/input/virtio-input.c -@@ -275,6 +275,7 @@ static void virtio_input_finalize(Object *obj) - - g_free(vinput->queue); - } -+ - static void virtio_input_device_unrealize(DeviceState *dev, Error **errp) - { - VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(dev); -@@ -288,6 +289,8 @@ static void virtio_input_device_unrealize(DeviceState *dev, Error **errp) - return; - } - } -+ virtio_del_queue(vdev, 0); -+ virtio_del_queue(vdev, 1); - virtio_cleanup(vdev); - } - --- -1.8.3.1 - diff --git a/virtio-net-bugfix-do-not-delete-netdev-before-virtio.patch b/virtio-net-bugfix-do-not-delete-netdev-before-virtio.patch new file mode 100644 index 0000000000000000000000000000000000000000..c328f9e30cfa2bc8bcced01feb645324a452fd79 --- /dev/null +++ b/virtio-net-bugfix-do-not-delete-netdev-before-virtio.patch @@ -0,0 +1,38 @@ +From 532566ba64b60f2dd2f8ff41d670712ccafe1e98 Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Thu, 10 Feb 2022 10:31:38 +0800 +Subject: [PATCH] virtio-net: bugfix: do not delete netdev before virtio net + +For the vhost-user net-card, it is allow to delete its +network backend while the virtio-net device still exists. +However, when the status of the device changes in guest, +QEMU will check whether the network backend exists, otherwise +it will crash. +So do not allowed to delete the network backend directly +without delete virtio-net device. + +Signed-off-by: Jinhua Cao +--- + net/net.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/net.c b/net/net.c +index f0d14dbfc1..ed4b1c1740 100644 +--- a/net/net.c ++++ b/net/net.c +@@ -1202,6 +1202,12 @@ void qmp_netdev_del(const char *id, Error **errp) + return; + } + ++ if (nc->info->type == NET_CLIENT_DRIVER_VHOST_USER && nc->peer) { ++ error_setg(errp, "Device '%s' is a netdev for vhostuser," ++ "please delete the peer front-end device (virtio-net) first.", id); ++ return; ++ } ++ + qemu_del_net_client(nc); + + /* +-- +2.27.0 + diff --git a/virtio-net-delete-also-control-queue-when-TX-RX-dele.patch b/virtio-net-delete-also-control-queue-when-TX-RX-dele.patch deleted file mode 100644 index f955fbb1a7f6b0ae8e646a366d3c6401cf699788..0000000000000000000000000000000000000000 --- a/virtio-net-delete-also-control-queue-when-TX-RX-dele.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 358e2bfe2e1a65b1e926163d7d1ffaefd601d874 Mon Sep 17 00:00:00 2001 -From: Julia Suvorova -Date: Wed, 19 Feb 2020 21:34:31 +0000 -Subject: [PATCH] virtio-net: delete also control queue when TX/RX deleted - -RH-Author: Julia Suvorova -Message-id: <20200219213431.11913-5-jusual@redhat.com> -Patchwork-id: 93983 -O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH 4/4] virtio-net: delete also control queue when TX/RX deleted -Bugzilla: 1791590 -RH-Acked-by: Danilo de Paula -RH-Acked-by: Stefano Garzarella -RH-Acked-by: Michael S. Tsirkin - -From: Yuri Benditovich - -https://bugzilla.redhat.com/show_bug.cgi?id=1708480 -If the control queue is not deleted together with TX/RX, it -later will be ignored in freeing cache resources and hot -unplug will not be completed. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Yuri Benditovich -Message-Id: <20191226043649.14481-3-yuri.benditovich@daynix.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry picked from commit d945d9f1731244ef341f74ede93120fc9de35913) -Signed-off-by: Danilo C. L. de Paula ---- - hw/net/virtio-net.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c -index 6adb0fe252..63f1bae99c 100644 ---- a/hw/net/virtio-net.c -+++ b/hw/net/virtio-net.c -@@ -2803,7 +2803,8 @@ static void virtio_net_device_unrealize(DeviceState *dev, Error **errp) - for (i = 0; i < max_queues; i++) { - virtio_net_del_queue(n, i); - } -- -+ /* delete also control vq */ -+ virtio_del_queue(vdev, max_queues * 2); - qemu_announce_timer_del(&n->announce_timer, false); - g_free(n->vqs); - qemu_del_nic(n->nic); --- -2.27.0 - diff --git a/virtio-net-fix-max-vring-buf-size-when-set-ring-num.patch b/virtio-net-fix-max-vring-buf-size-when-set-ring-num.patch new file mode 100644 index 0000000000000000000000000000000000000000..8e2af0ce32cd04a7f50605e8d8be1cc5ac9e0ab8 --- /dev/null +++ b/virtio-net-fix-max-vring-buf-size-when-set-ring-num.patch @@ -0,0 +1,50 @@ +From 318f0eda68554af0c779e5374f16bf8cdb895fe7 Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Thu, 10 Feb 2022 10:48:27 +0800 +Subject: [PATCH] virtio-net: fix max vring buf size when set ring num + +Signed-off-by: Jinhua Cao +--- + hw/virtio/virtio.c | 9 +++++++-- + include/hw/virtio/virtio.h | 1 + + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index ec3e96af3b..03afa36e99 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -2241,12 +2241,17 @@ void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc, + + void virtio_queue_set_num(VirtIODevice *vdev, int n, int num) + { ++ int vq_max_size = VIRTQUEUE_MAX_SIZE; ++ ++ if (!strcmp(vdev->name, "virtio-net")) { ++ vq_max_size = VIRTIO_NET_VQ_MAX_SIZE; ++ } ++ + /* Don't allow guest to flip queue between existent and + * nonexistent states, or to set it to an invalid size. + */ + if (!!num != !!vdev->vq[n].vring.num || +- num > VIRTQUEUE_MAX_SIZE || +- num < 0) { ++ num > vq_max_size || num < 0) { + return; + } + vdev->vq[n].vring.num = num; +diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h +index 8bab9cfb75..b3749ce34b 100644 +--- a/include/hw/virtio/virtio.h ++++ b/include/hw/virtio/virtio.h +@@ -49,6 +49,7 @@ size_t virtio_feature_get_config_size(const VirtIOFeature *features, + typedef struct VirtQueue VirtQueue; + + #define VIRTQUEUE_MAX_SIZE 1024 ++#define VIRTIO_NET_VQ_MAX_SIZE (4096) + + typedef struct VirtQueueElement + { +-- +2.27.0 + diff --git a/virtio-net-fix-use-after-unmap-free-for-sg.patch b/virtio-net-fix-use-after-unmap-free-for-sg.patch deleted file mode 100644 index ee1fa0695da1d960164f576fb1688dad0bacbd01..0000000000000000000000000000000000000000 --- a/virtio-net-fix-use-after-unmap-free-for-sg.patch +++ /dev/null @@ -1,123 +0,0 @@ -From 662633f388c5cead35b6ba5428dc9ab88710a471 Mon Sep 17 00:00:00 2001 -From: Jason Wang -Date: Thu, 2 Sep 2021 13:44:12 +0800 -Subject: [PATCH] virtio-net: fix use after unmap/free for sg - -When mergeable buffer is enabled, we try to set the num_buffers after -the virtqueue elem has been unmapped. This will lead several issues, -E.g a use after free when the descriptor has an address which belongs -to the non direct access region. In this case we use bounce buffer -that is allocated during address_space_map() and freed during -address_space_unmap(). - -Fixing this by storing the elems temporarily in an array and delay the -unmap after we set the the num_buffers. - -This addresses CVE-2021-3748. - -Reported-by: Alexander Bulekov -Fixes: fbe78f4f55c6 ("virtio-net support") -Cc: qemu-stable@nongnu.org -Signed-off-by: Jason Wang -Signed-off-by: imxcc ---- - hw/net/virtio-net.c | 39 ++++++++++++++++++++++++++++++++------- - 1 file changed, 32 insertions(+), 7 deletions(-) - -diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c -index 63f1bae99c..f93823d06d 100644 ---- a/hw/net/virtio-net.c -+++ b/hw/net/virtio-net.c -@@ -1265,10 +1265,13 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, - VirtIONet *n = qemu_get_nic_opaque(nc); - VirtIONetQueue *q = virtio_net_get_subqueue(nc); - VirtIODevice *vdev = VIRTIO_DEVICE(n); -+ VirtQueueElement *elems[VIRTQUEUE_MAX_SIZE]; -+ size_t lens[VIRTQUEUE_MAX_SIZE]; - struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE]; - struct virtio_net_hdr_mrg_rxbuf mhdr; - unsigned mhdr_cnt = 0; -- size_t offset, i, guest_offset; -+ size_t offset, i, guest_offset, j; -+ ssize_t err; - - if (!virtio_net_can_receive(nc)) { - return -1; -@@ -1291,6 +1294,12 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, - - total = 0; - -+ if (i == VIRTQUEUE_MAX_SIZE) { -+ virtio_error(vdev, "virtio-net unexpected long buffer chain"); -+ err = size; -+ goto err; -+ } -+ - elem = virtqueue_pop(q->rx_vq, sizeof(VirtQueueElement)); - if (!elem) { - if (i) { -@@ -1302,7 +1311,8 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, - n->guest_hdr_len, n->host_hdr_len, - vdev->guest_features); - } -- return -1; -+ err = -1; -+ goto err; - } - - if (elem->in_num < 1) { -@@ -1310,7 +1320,8 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, - "virtio-net receive queue contains no in buffers"); - virtqueue_detach_element(q->rx_vq, elem, 0); - g_free(elem); -- return -1; -+ err = -1; -+ goto err; - } - - sg = elem->in_sg; -@@ -1342,12 +1353,13 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, - if (!n->mergeable_rx_bufs && offset < size) { - virtqueue_unpop(q->rx_vq, elem, total); - g_free(elem); -- return size; -+ err = size; -+ goto err; - } - -- /* signal other side */ -- virtqueue_fill(q->rx_vq, elem, total, i++); -- g_free(elem); -+ elems[i] = elem; -+ lens[i] = total; -+ i++; - } - - if (mhdr_cnt) { -@@ -1357,10 +1369,23 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf, - &mhdr.num_buffers, sizeof mhdr.num_buffers); - } - -+ for (j = 0; j < i; j++) { -+ /* signal other side */ -+ virtqueue_fill(q->rx_vq, elems[j], lens[j], j); -+ g_free(elems[j]); -+ } -+ - virtqueue_flush(q->rx_vq, i); - virtio_notify(vdev, q->rx_vq); - - return size; -+ -+err: -+ for (j = 0; j < i; j++) { -+ g_free(elems[j]); -+ } -+ -+ return err; - } - - static ssize_t virtio_net_do_receive(NetClientState *nc, const uint8_t *buf, --- -2.27.0 - diff --git a/virtio-net-prevent-offloads-reset-on-migration.patch b/virtio-net-prevent-offloads-reset-on-migration.patch deleted file mode 100644 index ab8fbe26115279359c6a3928e93bf134ca88a2cb..0000000000000000000000000000000000000000 --- a/virtio-net-prevent-offloads-reset-on-migration.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 4887acf574a573137660aa98d9d422ece0a41a5a Mon Sep 17 00:00:00 2001 -From: Mikhail Sennikovsky -Date: Fri, 11 Oct 2019 15:58:04 +0200 -Subject: [PATCH] virtio-net: prevent offloads reset on migration - -Currently offloads disabled by guest via the VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET -command are not preserved on VM migration. -Instead all offloads reported by guest features (via VIRTIO_PCI_GUEST_FEATURES) -get enabled. -What happens is: first the VirtIONet::curr_guest_offloads gets restored and offloads -are getting set correctly: - - #0 qemu_set_offload (nc=0x555556a11400, csum=1, tso4=0, tso6=0, ecn=0, ufo=0) at net/net.c:474 - #1 virtio_net_apply_guest_offloads (n=0x555557701ca0) at hw/net/virtio-net.c:720 - #2 virtio_net_post_load_device (opaque=0x555557701ca0, version_id=11) at hw/net/virtio-net.c:2334 - #3 vmstate_load_state (f=0x5555569dc010, vmsd=0x555556577c80 , opaque=0x555557701ca0, version_id=11) - at migration/vmstate.c:168 - #4 virtio_load (vdev=0x555557701ca0, f=0x5555569dc010, version_id=11) at hw/virtio/virtio.c:2197 - #5 virtio_device_get (f=0x5555569dc010, opaque=0x555557701ca0, size=0, field=0x55555668cd00 <__compound_literal.5>) at hw/virtio/virtio.c:2036 - #6 vmstate_load_state (f=0x5555569dc010, vmsd=0x555556577ce0 , opaque=0x555557701ca0, version_id=11) at migration/vmstate.c:143 - #7 vmstate_load (f=0x5555569dc010, se=0x5555578189e0) at migration/savevm.c:829 - #8 qemu_loadvm_section_start_full (f=0x5555569dc010, mis=0x5555569eee20) at migration/savevm.c:2211 - #9 qemu_loadvm_state_main (f=0x5555569dc010, mis=0x5555569eee20) at migration/savevm.c:2395 - #10 qemu_loadvm_state (f=0x5555569dc010) at migration/savevm.c:2467 - #11 process_incoming_migration_co (opaque=0x0) at migration/migration.c:449 - -However later on the features are getting restored, and offloads get reset to -everything supported by features: - - #0 qemu_set_offload (nc=0x555556a11400, csum=1, tso4=1, tso6=1, ecn=0, ufo=0) at net/net.c:474 - #1 virtio_net_apply_guest_offloads (n=0x555557701ca0) at hw/net/virtio-net.c:720 - #2 virtio_net_set_features (vdev=0x555557701ca0, features=5104441767) at hw/net/virtio-net.c:773 - #3 virtio_set_features_nocheck (vdev=0x555557701ca0, val=5104441767) at hw/virtio/virtio.c:2052 - #4 virtio_load (vdev=0x555557701ca0, f=0x5555569dc010, version_id=11) at hw/virtio/virtio.c:2220 - #5 virtio_device_get (f=0x5555569dc010, opaque=0x555557701ca0, size=0, field=0x55555668cd00 <__compound_literal.5>) at hw/virtio/virtio.c:2036 - #6 vmstate_load_state (f=0x5555569dc010, vmsd=0x555556577ce0 , opaque=0x555557701ca0, version_id=11) at migration/vmstate.c:143 - #7 vmstate_load (f=0x5555569dc010, se=0x5555578189e0) at migration/savevm.c:829 - #8 qemu_loadvm_section_start_full (f=0x5555569dc010, mis=0x5555569eee20) at migration/savevm.c:2211 - #9 qemu_loadvm_state_main (f=0x5555569dc010, mis=0x5555569eee20) at migration/savevm.c:2395 - #10 qemu_loadvm_state (f=0x5555569dc010) at migration/savevm.c:2467 - #11 process_incoming_migration_co (opaque=0x0) at migration/migration.c:449 - -Fix this by preserving the state in saved_guest_offloads field and -pushing out offload initialization to the new post load hook. - -Cc: qemu-stable@nongnu.org -Signed-off-by: Mikhail Sennikovsky -Signed-off-by: Jason Wang -(cherry picked from commit 7788c3f2e21e35902d45809b236791383bbb613e) -Signed-off-by: Michael Roth ---- - hw/net/virtio-net.c | 27 ++++++++++++++++++++++++--- - include/hw/virtio/virtio-net.h | 2 ++ - 2 files changed, 26 insertions(+), 3 deletions(-) - -diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c -index b9e1cd71cf..6adb0fe252 100644 ---- a/hw/net/virtio-net.c -+++ b/hw/net/virtio-net.c -@@ -2330,9 +2330,13 @@ static int virtio_net_post_load_device(void *opaque, int version_id) - n->curr_guest_offloads = virtio_net_supported_guest_offloads(n); - } - -- if (peer_has_vnet_hdr(n)) { -- virtio_net_apply_guest_offloads(n); -- } -+ /* -+ * curr_guest_offloads will be later overwritten by the -+ * virtio_set_features_nocheck call done from the virtio_load. -+ * Here we make sure it is preserved and restored accordingly -+ * in the virtio_net_post_load_virtio callback. -+ */ -+ n->saved_guest_offloads = n->curr_guest_offloads; - - virtio_net_set_queues(n); - -@@ -2367,6 +2371,22 @@ static int virtio_net_post_load_device(void *opaque, int version_id) - return 0; - } - -+static int virtio_net_post_load_virtio(VirtIODevice *vdev) -+{ -+ VirtIONet *n = VIRTIO_NET(vdev); -+ /* -+ * The actual needed state is now in saved_guest_offloads, -+ * see virtio_net_post_load_device for detail. -+ * Restore it back and apply the desired offloads. -+ */ -+ n->curr_guest_offloads = n->saved_guest_offloads; -+ if (peer_has_vnet_hdr(n)) { -+ virtio_net_apply_guest_offloads(n); -+ } -+ -+ return 0; -+} -+ - /* tx_waiting field of a VirtIONetQueue */ - static const VMStateDescription vmstate_virtio_net_queue_tx_waiting = { - .name = "virtio-net-queue-tx_waiting", -@@ -2909,6 +2929,7 @@ static void virtio_net_class_init(ObjectClass *klass, void *data) - vdc->guest_notifier_mask = virtio_net_guest_notifier_mask; - vdc->guest_notifier_pending = virtio_net_guest_notifier_pending; - vdc->legacy_features |= (0x1 << VIRTIO_NET_F_GSO); -+ vdc->post_load = virtio_net_post_load_virtio; - vdc->vmsd = &vmstate_virtio_net_device; - } - -diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h -index b96f0c643f..07a9319f4b 100644 ---- a/include/hw/virtio/virtio-net.h -+++ b/include/hw/virtio/virtio-net.h -@@ -182,6 +182,8 @@ struct VirtIONet { - char *netclient_name; - char *netclient_type; - uint64_t curr_guest_offloads; -+ /* used on saved state restore phase to preserve the curr_guest_offloads */ -+ uint64_t saved_guest_offloads; - AnnounceTimer announce_timer; - bool needs_vnet_hdr_swap; - bool mtu_bypass_backend; --- -2.23.0 diff --git a/virtio-net-set-the-max-of-queue-size-to-4096.patch b/virtio-net-set-the-max-of-queue-size-to-4096.patch new file mode 100644 index 0000000000000000000000000000000000000000..de0520ec279d7a0a3d95338c959dd3cc619b1582 --- /dev/null +++ b/virtio-net-set-the-max-of-queue-size-to-4096.patch @@ -0,0 +1,68 @@ +From 7beaecc21a8a573d43c7ad7604ac77cdf5bbf405 Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Sat, 12 Feb 2022 17:22:38 +0800 +Subject: [PATCH] virtio-net: set the max of queue size to 4096 + +Signed-off-by: Jinhua Cao +--- + hw/net/virtio-net.c | 10 +++++----- + hw/virtio/virtio.c | 2 +- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 6874c88bc0..009dc9f3d1 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -637,7 +637,7 @@ static int virtio_net_max_tx_queue_size(VirtIONet *n) + return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE; + } + +- return VIRTQUEUE_MAX_SIZE; ++ return VIRTIO_NET_VQ_MAX_SIZE; + } + + static int peer_attach(VirtIONet *n, int index) +@@ -3394,23 +3394,23 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) + * help from us (using virtio 1 and up). + */ + if (n->net_conf.rx_queue_size < VIRTIO_NET_RX_QUEUE_MIN_SIZE || +- n->net_conf.rx_queue_size > VIRTQUEUE_MAX_SIZE || ++ n->net_conf.rx_queue_size > VIRTIO_NET_VQ_MAX_SIZE || + !is_power_of_2(n->net_conf.rx_queue_size)) { + error_setg(errp, "Invalid rx_queue_size (= %" PRIu16 "), " + "must be a power of 2 between %d and %d.", + n->net_conf.rx_queue_size, VIRTIO_NET_RX_QUEUE_MIN_SIZE, +- VIRTQUEUE_MAX_SIZE); ++ VIRTIO_NET_VQ_MAX_SIZE); + virtio_cleanup(vdev); + return; + } + + if (n->net_conf.tx_queue_size < VIRTIO_NET_TX_QUEUE_MIN_SIZE || +- n->net_conf.tx_queue_size > VIRTQUEUE_MAX_SIZE || ++ n->net_conf.tx_queue_size > VIRTIO_NET_VQ_MAX_SIZE || + !is_power_of_2(n->net_conf.tx_queue_size)) { + error_setg(errp, "Invalid tx_queue_size (= %" PRIu16 "), " + "must be a power of 2 between %d and %d", + n->net_conf.tx_queue_size, VIRTIO_NET_TX_QUEUE_MIN_SIZE, +- VIRTQUEUE_MAX_SIZE); ++ VIRTIO_NET_VQ_MAX_SIZE); + virtio_cleanup(vdev); + return; + } +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index b08fff9419..120672672e 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -2401,7 +2401,7 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, + break; + } + +- if (i == VIRTIO_QUEUE_MAX || queue_size > VIRTQUEUE_MAX_SIZE) { ++ if (i == VIRTIO_QUEUE_MAX) { + qemu_log("unacceptable queue_size (%d) or num (%d)\n", + queue_size, i); + abort(); +-- +2.27.0 + diff --git a/virtio-net-tap-bugfix-del-net-client-if-net_init_tap.patch b/virtio-net-tap-bugfix-del-net-client-if-net_init_tap.patch new file mode 100644 index 0000000000000000000000000000000000000000..59b7c25ecfc6ad380a607659c408f24375cdd262 --- /dev/null +++ b/virtio-net-tap-bugfix-del-net-client-if-net_init_tap.patch @@ -0,0 +1,76 @@ +From cee545754b44b6283408ec6a43eb0e317c98ebb1 Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Wed, 9 Feb 2022 20:27:41 +0800 +Subject: [PATCH] virtio: net-tap: bugfix: del net client if net_init_tap_one + failed + +In net_init_tap_one(), if the net-tap initializes successful +but other actions failed during vhost-net hot-plugging, the +net-tap will remain in the net clients.causing next hot-plug +fails again. + +Signed-off-by: Jinhua Cao +--- + net/tap.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/net/tap.c b/net/tap.c +index c5cbeaa7a2..3f79cd06c2 100644 +--- a/net/tap.c ++++ b/net/tap.c +@@ -684,7 +684,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, + tap_set_sndbuf(s->fd, tap, &err); + if (err) { + error_propagate(errp, err); +- return; ++ goto fail; + } + + if (tap->has_fd || tap->has_fds) { +@@ -726,13 +726,13 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, + } else { + warn_report_err(err); + } +- return; ++ goto fail; + } + ret = qemu_try_set_nonblock(vhostfd); + if (ret < 0) { + error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", + name, fd); +- return; ++ goto fail; + } + } else { + vhostfd = open("/dev/vhost-net", O_RDWR); +@@ -744,7 +744,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, + warn_report("tap: open vhost char device failed: %s", + strerror(errno)); + } +- return; ++ goto fail; + } + qemu_set_nonblock(vhostfd); + } +@@ -758,11 +758,17 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, + } else { + warn_report(VHOST_NET_INIT_FAILED); + } +- return; ++ goto fail; + } + } else if (vhostfdname) { + error_setg(errp, "vhostfd(s)= is not valid without vhost"); ++ goto fail; + } ++ ++ return; ++ ++fail: ++ qemu_del_net_client(&s->nc); + } + + static int get_fds(char *str, char *fds[], int max) +-- +2.27.0 + diff --git a/virtio-net-update-the-default-and-max-of-rx-tx_queue.patch b/virtio-net-update-the-default-and-max-of-rx-tx_queue.patch new file mode 100644 index 0000000000000000000000000000000000000000..0d849f97421772a4af00443d60c450a444f6f499 --- /dev/null +++ b/virtio-net-update-the-default-and-max-of-rx-tx_queue.patch @@ -0,0 +1,104 @@ +From 88dfb4236c735c608f8ca91cfbfb5ac424d654aa Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Thu, 10 Feb 2022 17:28:49 +0800 +Subject: [PATCH] virtio-net: update the default and max of rx/tx_queue_size + +Set the max of tx_queue_size to 4096 even if the backends +are not vhost-user. + +Set the default of rx/tx_queue_size to 2048 if the backends +are vhost-user, otherwise to 4096. + +Signed-off-by: Jinhua Cao +--- + hw/net/virtio-net.c | 41 +++++++++++++++++++++++++++++++---------- + 1 file changed, 31 insertions(+), 10 deletions(-) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 009dc9f3d1..e887589a30 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -51,12 +51,11 @@ + #define MAX_VLAN (1 << 12) /* Per 802.1Q definition */ + + /* previously fixed value */ +-#define VIRTIO_NET_RX_QUEUE_DEFAULT_SIZE 256 +-#define VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE 256 ++#define VIRTIO_NET_VHOST_USER_DEFAULT_SIZE 2048 + + /* for now, only allow larger queue_pairs; with virtio-1, guest can downsize */ +-#define VIRTIO_NET_RX_QUEUE_MIN_SIZE VIRTIO_NET_RX_QUEUE_DEFAULT_SIZE +-#define VIRTIO_NET_TX_QUEUE_MIN_SIZE VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE ++#define VIRTIO_NET_RX_QUEUE_MIN_SIZE 256 ++#define VIRTIO_NET_TX_QUEUE_MIN_SIZE 256 + + #define VIRTIO_NET_IP4_ADDR_SIZE 8 /* ipv4 saddr + daddr */ + +@@ -622,6 +621,28 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs, + } + } + ++static void virtio_net_set_default_queue_size(VirtIONet *n) ++{ ++ NetClientState *peer = n->nic_conf.peers.ncs[0]; ++ ++ /* Default value is 0 if not set */ ++ if (n->net_conf.rx_queue_size == 0) { ++ if (peer && peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) { ++ n->net_conf.rx_queue_size = VIRTIO_NET_VHOST_USER_DEFAULT_SIZE; ++ } else { ++ n->net_conf.rx_queue_size = VIRTIO_NET_VQ_MAX_SIZE; ++ } ++ } ++ ++ if (n->net_conf.tx_queue_size == 0) { ++ if (peer && peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) { ++ n->net_conf.tx_queue_size = VIRTIO_NET_VHOST_USER_DEFAULT_SIZE; ++ } else { ++ n->net_conf.tx_queue_size = VIRTIO_NET_VQ_MAX_SIZE; ++ } ++ } ++} ++ + static int virtio_net_max_tx_queue_size(VirtIONet *n) + { + NetClientState *peer = n->nic_conf.peers.ncs[0]; +@@ -630,11 +651,11 @@ static int virtio_net_max_tx_queue_size(VirtIONet *n) + * Backends other than vhost-user don't support max queue size. + */ + if (!peer) { +- return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE; ++ return VIRTIO_NET_VQ_MAX_SIZE; + } + + if (peer->info->type != NET_CLIENT_DRIVER_VHOST_USER) { +- return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE; ++ return VIRTIO_NET_VQ_MAX_SIZE; + } + + return VIRTIO_NET_VQ_MAX_SIZE; +@@ -3388,6 +3409,8 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) + virtio_net_set_config_size(n, n->host_features); + virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size); + ++ virtio_net_set_default_queue_size(n); ++ + /* + * We set a lower limit on RX queue size to what it always was. + * Guests that want a smaller ring can always resize it without +@@ -3679,10 +3702,8 @@ static Property virtio_net_properties[] = { + TX_TIMER_INTERVAL), + DEFINE_PROP_INT32("x-txburst", VirtIONet, net_conf.txburst, TX_BURST), + DEFINE_PROP_STRING("tx", VirtIONet, net_conf.tx), +- DEFINE_PROP_UINT16("rx_queue_size", VirtIONet, net_conf.rx_queue_size, +- VIRTIO_NET_RX_QUEUE_DEFAULT_SIZE), +- DEFINE_PROP_UINT16("tx_queue_size", VirtIONet, net_conf.tx_queue_size, +- VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE), ++ DEFINE_PROP_UINT16("rx_queue_size", VirtIONet, net_conf.rx_queue_size, 0), ++ DEFINE_PROP_UINT16("tx_queue_size", VirtIONet, net_conf.tx_queue_size, 0), + DEFINE_PROP_UINT16("host_mtu", VirtIONet, net_conf.mtu, 0), + DEFINE_PROP_BOOL("x-mtu-bypass-backend", VirtIONet, mtu_bypass_backend, + true), +-- +2.27.0 + diff --git a/virtio-new-post_load-hook.patch b/virtio-new-post_load-hook.patch deleted file mode 100644 index 974f286c6730c66cc3cb0a64b046bea341dd262b..0000000000000000000000000000000000000000 --- a/virtio-new-post_load-hook.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 8010d3fce008dd13f155bc0babfe236ea44a2712 Mon Sep 17 00:00:00 2001 -From: "Michael S. Tsirkin" -Date: Fri, 11 Oct 2019 15:58:03 +0200 -Subject: [PATCH] virtio: new post_load hook - -Post load hook in virtio vmsd is called early while device is processed, -and when VirtIODevice core isn't fully initialized. Most device -specific code isn't ready to deal with a device in such state, and -behaves weirdly. - -Add a new post_load hook in a device class instead. Devices should use -this unless they specifically want to verify the migration stream as -it's processed, e.g. for bounds checking. - -Cc: qemu-stable@nongnu.org -Suggested-by: "Dr. David Alan Gilbert" -Cc: Mikhail Sennikovsky -Signed-off-by: Michael S. Tsirkin -Signed-off-by: Jason Wang -(cherry picked from commit 1dd713837cac8ec5a97d3b8492d72ce5ac94803c) -Signed-off-by: Michael Roth ---- - hw/virtio/virtio.c | 7 +++++++ - include/hw/virtio/virtio.h | 6 ++++++ - 2 files changed, 13 insertions(+) - -diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c -index a94ea18a9c..7c3822c3a0 100644 ---- a/hw/virtio/virtio.c -+++ b/hw/virtio/virtio.c -@@ -2287,6 +2287,13 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) - } - rcu_read_unlock(); - -+ if (vdc->post_load) { -+ ret = vdc->post_load(vdev); -+ if (ret) { -+ return ret; -+ } -+ } -+ - return 0; - } - -diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h -index b189788cb2..f9f62370e9 100644 ---- a/include/hw/virtio/virtio.h -+++ b/include/hw/virtio/virtio.h -@@ -158,6 +158,12 @@ typedef struct VirtioDeviceClass { - */ - void (*save)(VirtIODevice *vdev, QEMUFile *f); - int (*load)(VirtIODevice *vdev, QEMUFile *f, int version_id); -+ /* Post load hook in vmsd is called early while device is processed, and -+ * when VirtIODevice isn't fully initialized. Devices should use this instead, -+ * unless they specifically want to verify the migration stream as it's -+ * processed, e.g. for bounds checking. -+ */ -+ int (*post_load)(VirtIODevice *vdev); - const VMStateDescription *vmsd; - } VirtioDeviceClass; - --- -2.23.0 diff --git a/virtio-pci-fix-queue_enable-write.patch b/virtio-pci-fix-queue_enable-write.patch deleted file mode 100644 index 481b41bbf11f4ebb94ae8fd746b13ad4ac41555d..0000000000000000000000000000000000000000 --- a/virtio-pci-fix-queue_enable-write.patch +++ /dev/null @@ -1,58 +0,0 @@ -From aebd6a1512e03ba51f6824fcdbaa09f67e9ff5e2 Mon Sep 17 00:00:00 2001 -From: Jason Wang -Date: Wed, 10 Jun 2020 13:43:51 +0800 -Subject: [PATCH 11/11] virtio-pci: fix queue_enable write - -Spec said: The driver uses this to selectively prevent the device from -executing requests from this virtqueue. 1 - enabled; 0 - disabled. - -Though write 0 to queue_enable is forbidden by the spec, we should not -assume that the value is 1. - -Fix this by ignore the write value other than 1. - -Signed-off-by: Jason Wang -Message-Id: <20200610054351.15811-1-jasowang@redhat.com> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Reviewed-by: Stefano Garzarella -Reviewed-by: Stefan Hajnoczi -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Signed-off-by: BiaoXiang Ye ---- - hw/virtio/virtio-pci.c | 12 ++++++++---- - 1 file changed, 8 insertions(+), 4 deletions(-) - -diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c -index b4b0ed26..4b8845a6 100644 ---- a/hw/virtio/virtio-pci.c -+++ b/hw/virtio/virtio-pci.c -@@ -1259,16 +1259,20 @@ static void virtio_pci_common_write(void *opaque, hwaddr addr, - virtio_queue_set_vector(vdev, vdev->queue_sel, val); - break; - case VIRTIO_PCI_COMMON_Q_ENABLE: -- virtio_queue_set_num(vdev, vdev->queue_sel, -- proxy->vqs[vdev->queue_sel].num); -- virtio_queue_set_rings(vdev, vdev->queue_sel, -+ if (val == 1) { -+ virtio_queue_set_num(vdev, vdev->queue_sel, -+ proxy->vqs[vdev->queue_sel].num); -+ virtio_queue_set_rings(vdev, vdev->queue_sel, - ((uint64_t)proxy->vqs[vdev->queue_sel].desc[1]) << 32 | - proxy->vqs[vdev->queue_sel].desc[0], - ((uint64_t)proxy->vqs[vdev->queue_sel].avail[1]) << 32 | - proxy->vqs[vdev->queue_sel].avail[0], - ((uint64_t)proxy->vqs[vdev->queue_sel].used[1]) << 32 | - proxy->vqs[vdev->queue_sel].used[0]); -- proxy->vqs[vdev->queue_sel].enabled = 1; -+ proxy->vqs[vdev->queue_sel].enabled = 1; -+ } else { -+ virtio_error(vdev, "wrong value for queue_enable %"PRIx64, val); -+ } - break; - case VIRTIO_PCI_COMMON_Q_DESCLO: - proxy->vqs[vdev->queue_sel].desc[0] = val; --- -2.27.0.dirty - diff --git a/virtio-pmem-do-delete-rq_vq-in-virtio_pmem_unrealize.patch b/virtio-pmem-do-delete-rq_vq-in-virtio_pmem_unrealize.patch deleted file mode 100644 index d8ed58faa8f5c6517d131ced73209bc41122158e..0000000000000000000000000000000000000000 --- a/virtio-pmem-do-delete-rq_vq-in-virtio_pmem_unrealize.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 637606d18c7208e21d8ab4f318cccde64ae58c76 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Tue, 25 Feb 2020 15:55:53 +0800 -Subject: [PATCH 2/9] virtio-pmem: do delete rq_vq in virtio_pmem_unrealize -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Similar to other virtio-devices, rq_vq forgot to delete in -virtio_pmem_unrealize, this patch fix it. This device has already -maintained a vq pointer, thus we use the new virtio_delete_queue -function directly to do the cleanup. - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan -Message-Id: <20200225075554.10835-4-pannengyuan@huawei.com> -Reviewed-by: Philippe Mathieu-Daudé -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Signed-off-by: AlexChen ---- - hw/virtio/virtio-pmem.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/hw/virtio/virtio-pmem.c b/hw/virtio/virtio-pmem.c -index 17c196d..c680b0a 100644 ---- a/hw/virtio/virtio-pmem.c -+++ b/hw/virtio/virtio-pmem.c -@@ -127,6 +127,7 @@ static void virtio_pmem_unrealize(DeviceState *dev, Error **errp) - VirtIOPMEM *pmem = VIRTIO_PMEM(dev); - - host_memory_backend_set_mapped(pmem->memdev, false); -+ virtio_delete_queue(pmem->rq_vq); - virtio_cleanup(vdev); - } - --- -1.8.3.1 - diff --git a/virtio-print-the-guest-virtio_net-features-that-host.patch b/virtio-print-the-guest-virtio_net-features-that-host.patch new file mode 100644 index 0000000000000000000000000000000000000000..5db0434aba861b8347915f104e313807418b01bf --- /dev/null +++ b/virtio-print-the-guest-virtio_net-features-that-host.patch @@ -0,0 +1,105 @@ +From 8a08b3b41400e152cc1786ae5a8a53507f8e925c Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Thu, 10 Feb 2022 14:16:17 +0800 +Subject: [PATCH] virtio: print the guest virtio_net features that host does + not support + +Signed-off-by: Jinhua Cao +--- + hw/net/virtio-net.c | 41 ++++++++++++++++++++++++++++++++++++++ + hw/virtio/virtio.c | 7 +++++++ + include/hw/virtio/virtio.h | 1 + + 3 files changed, 49 insertions(+) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index b3a5d0b19e..6874c88bc0 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -3692,6 +3692,46 @@ static Property virtio_net_properties[] = { + DEFINE_PROP_END_OF_LIST(), + }; + ++static void virtio_net_print_features(uint64_t features) ++{ ++ Property *props = virtio_net_properties; ++ int feature_cnt = 0; ++ ++ if (!features) { ++ return; ++ } ++ printf("virtio_net_feature: "); ++ ++ for (; features && props->name; props++) { ++ /* The bitnr of property may be default(0) besides 'csum' property. */ ++ if (props->bitnr == 0 && strcmp(props->name, "csum")) { ++ continue; ++ } ++ ++ /* Features only support 64bit. */ ++ if (props->bitnr > 63) { ++ continue; ++ } ++ ++ if (virtio_has_feature(features, props->bitnr)) { ++ virtio_clear_feature(&features, props->bitnr); ++ if (feature_cnt != 0) { ++ printf(", "); ++ } ++ printf("%s", props->name); ++ feature_cnt++; ++ } ++ } ++ ++ if (features) { ++ if (feature_cnt != 0) { ++ printf(", "); ++ } ++ printf("unkown bits 0x%." PRIx64, features); ++ } ++ printf("\n"); ++} ++ + static void virtio_net_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); +@@ -3706,6 +3746,7 @@ static void virtio_net_class_init(ObjectClass *klass, void *data) + vdc->set_config = virtio_net_set_config; + vdc->get_features = virtio_net_get_features; + vdc->set_features = virtio_net_set_features; ++ vdc->print_features = virtio_net_print_features; + vdc->bad_features = virtio_net_bad_features; + vdc->reset = virtio_net_reset; + vdc->set_status = virtio_net_set_status; +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index 0af9684881..9a2a83d507 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -2967,6 +2967,13 @@ static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val) + { + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + bool bad = (val & ~(vdev->host_features)) != 0; ++ uint64_t feat = val & ~(vdev->host_features); ++ ++ if (bad && k->print_features) { ++ qemu_log("error: Please check host config, "\ ++ "because host does not support required feature bits 0x%" PRIx64 "\n", feat); ++ k->print_features(feat); ++ } + + val &= vdev->host_features; + if (k->set_features) { +diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h +index b3749ce34b..7472145821 100644 +--- a/include/hw/virtio/virtio.h ++++ b/include/hw/virtio/virtio.h +@@ -127,6 +127,7 @@ struct VirtioDeviceClass { + int (*validate_features)(VirtIODevice *vdev); + void (*get_config)(VirtIODevice *vdev, uint8_t *config); + void (*set_config)(VirtIODevice *vdev, const uint8_t *config); ++ void (*print_features)(uint64_t features); + void (*reset)(VirtIODevice *vdev); + void (*set_status)(VirtIODevice *vdev, uint8_t val); + /* For transitional devices, this is a bitmap of features +-- +2.27.0 + diff --git a/virtio-scsi-bugfix-fix-qemu-crash-for-hotplug-scsi-d.patch b/virtio-scsi-bugfix-fix-qemu-crash-for-hotplug-scsi-d.patch new file mode 100644 index 0000000000000000000000000000000000000000..bca7db04571d8c014d6a3b51b5c7727f2dcc3aed --- /dev/null +++ b/virtio-scsi-bugfix-fix-qemu-crash-for-hotplug-scsi-d.patch @@ -0,0 +1,37 @@ +From 98cbb6d13484e79b6f9da064a40a281f2983be1d Mon Sep 17 00:00:00 2001 +From: Jinhua Cao +Date: Wed, 9 Feb 2022 19:58:21 +0800 +Subject: [PATCH] virtio-scsi: bugfix: fix qemu crash for hotplug scsi disk + with dataplane + +The vm will trigger a disk sweep operation after plugging +a controller who's io type is iothread. If attach a scsi +disk immediately, the sg_inqury request in vm will trigger +the assert in virtio_scsi_ctx_check(), which is called by +virtio_scsi_handle_cmd_req_prepare(). + +Add judgment in virtio_scsi_handle_cmd_req_prepare() and +return IO Error directly if the device has not been +initialized. + +Signed-off-by: Jinhua Cao +--- + hw/scsi/virtio-scsi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c +index 51fd09522a..781a37fe89 100644 +--- a/hw/scsi/virtio-scsi.c ++++ b/hw/scsi/virtio-scsi.c +@@ -638,7 +638,7 @@ static int virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req) + req->req.cmd.tag, req->req.cmd.cdb[0]); + + d = virtio_scsi_device_get(s, req->req.cmd.lun); +- if (!d) { ++ if (!d || !d->qdev.realized) { + req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET; + virtio_scsi_complete_cmd_req(req); + return -ENOENT; +-- +2.27.0 + diff --git a/virtio-serial-bus-Plug-memory-leak-on-realize-error-.patch b/virtio-serial-bus-Plug-memory-leak-on-realize-error-.patch deleted file mode 100644 index 02069901b096cd09b0f30dbef9d55e3fe6dc920d..0000000000000000000000000000000000000000 --- a/virtio-serial-bus-Plug-memory-leak-on-realize-error-.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0d93f5455489274201b1054d987b12f8e8a6206e Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Mon, 9 Mar 2020 10:17:38 +0800 -Subject: [PATCH 11/14] virtio-serial-bus: Plug memory leak on realize() error - paths - -We neglect to free port->bh on the error paths. Fix that. -Reproducer: - {'execute': 'device_add', 'arguments': {'id': 'virtio_serial_pci0', 'driver': 'virtio-serial-pci', 'bus': 'pci.0', 'addr': '0x5'}, 'id': 'yVkZcGgV'} - {'execute': 'device_add', 'arguments': {'id': 'port1', 'driver': 'virtserialport', 'name': 'port1', 'chardev': 'channel1', 'bus': 'virtio_serial_pci0.0', 'nr': 1}, 'id': '3dXdUgJA'} - {'execute': 'device_add', 'arguments': {'id': 'port2', 'driver': 'virtserialport', 'name': 'port2', 'chardev': 'channel2', 'bus': 'virtio_serial_pci0.0', 'nr': 1}, 'id': 'qLzcCkob'} - {'execute': 'device_add', 'arguments': {'id': 'port2', 'driver': 'virtserialport', 'name': 'port2', 'chardev': 'channel2', 'bus': 'virtio_serial_pci0.0', 'nr': 2}, 'id': 'qLzcCkob'} - -The leak stack: -Direct leak of 40 byte(s) in 1 object(s) allocated from: - #0 0x7f04a8008ae8 in __interceptor_malloc (/lib64/libasan.so.5+0xefae8) - #1 0x7f04a73cf1d5 in g_malloc (/lib64/libglib-2.0.so.0+0x531d5) - #2 0x56273eaee484 in aio_bh_new /mnt/sdb/backup/qemu/util/async.c:125 - #3 0x56273eafe9a8 in qemu_bh_new /mnt/sdb/backup/qemu/util/main-loop.c:532 - #4 0x56273d52e62e in virtser_port_device_realize /mnt/sdb/backup/qemu/hw/char/virtio-serial-bus.c:946 - #5 0x56273dcc5040 in device_set_realized /mnt/sdb/backup/qemu/hw/core/qdev.c:891 - #6 0x56273e5ebbce in property_set_bool /mnt/sdb/backup/qemu/qom/object.c:2238 - #7 0x56273e5e5a9c in object_property_set /mnt/sdb/backup/qemu/qom/object.c:1324 - #8 0x56273e5ef5f8 in object_property_set_qobject /mnt/sdb/backup/qemu/qom/qom-qobject.c:26 - #9 0x56273e5e5e6a in object_property_set_bool /mnt/sdb/backup/qemu/qom/object.c:1390 - #10 0x56273daa40de in qdev_device_add /mnt/sdb/backup/qemu/qdev-monitor.c:680 - #11 0x56273daa53e9 in qmp_device_add /mnt/sdb/backup/qemu/qdev-monitor.c:805 - -Fixes: 199646d81522509ac2dba6d28c31e8c7d807bc93 -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan -Reviewed-by: Markus Armbruster -Reviewed-by: Amit Shah -Message-Id: <20200309021738.30072-1-pannengyuan@huawei.com> -Reviewed-by: Laurent Vivier -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -Signed-off-by: Peng Liang ---- - hw/char/virtio-serial-bus.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c -index f7a54f261b21..2d23dae6d2b7 100644 ---- a/hw/char/virtio-serial-bus.c -+++ b/hw/char/virtio-serial-bus.c -@@ -940,7 +940,6 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp) - Error *err = NULL; - - port->vser = bus->vser; -- port->bh = qemu_bh_new(flush_queued_data_bh, port); - - assert(vsc->have_data); - -@@ -989,6 +988,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp) - return; - } - -+ port->bh = qemu_bh_new(flush_queued_data_bh, port); - port->elem = NULL; - } - --- -2.26.2 - diff --git a/virtio_blk-Add-support-for-retry-on-errors.patch b/virtio_blk-Add-support-for-retry-on-errors.patch index e7d8efd7ed99ae35f5309bee2e90bedfcc1f5e86..1d7bd03846fe489f9aab23e1931f9d9f286e51fb 100644 --- a/virtio_blk-Add-support-for-retry-on-errors.patch +++ b/virtio_blk-Add-support-for-retry-on-errors.patch @@ -1,22 +1,23 @@ -From f3158cc327d435939d87ecee23485d082ebf3ba2 Mon Sep 17 00:00:00 2001 +From a81122e37595fe1cc9eaa2adbbfccbfdf8f988b8 Mon Sep 17 00:00:00 2001 From: Jiahui Cen Date: Thu, 21 Jan 2021 15:46:53 +0800 -Subject: [PATCH] virtio_blk: Add support for retry on errors +Subject: [PATCH 7/7] virtio_blk: Add support for retry on errors Insert failed requests into device's list for later retry and handle queued requests to implement retry_request_cb. Signed-off-by: Jiahui Cen Signed-off-by: Ying Fang +Signed-off-by: Alex Chen --- hw/block/virtio-blk.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c -index ddf525b9d7..2db9804cfe 100644 +index f139cd7cc9..c8d94a3dfb 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c -@@ -101,6 +101,10 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, +@@ -108,6 +108,10 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, block_acct_failed(blk_get_stats(s->blk), &req->acct); } virtio_blk_free_request(req); @@ -27,7 +28,7 @@ index ddf525b9d7..2db9804cfe 100644 } blk_error_action(s->blk, action, is_read, error); -@@ -142,6 +146,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret) +@@ -149,6 +153,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret) } } @@ -35,7 +36,7 @@ index ddf525b9d7..2db9804cfe 100644 virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); block_acct_done(blk_get_stats(s->blk), &req->acct); virtio_blk_free_request(req); -@@ -161,6 +166,7 @@ static void virtio_blk_flush_complete(void *opaque, int ret) +@@ -168,6 +173,7 @@ static void virtio_blk_flush_complete(void *opaque, int ret) } } @@ -43,7 +44,7 @@ index ddf525b9d7..2db9804cfe 100644 virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); block_acct_done(blk_get_stats(s->blk), &req->acct); virtio_blk_free_request(req); -@@ -183,6 +189,7 @@ static void virtio_blk_discard_write_zeroes_complete(void *opaque, int ret) +@@ -190,6 +196,7 @@ static void virtio_blk_discard_write_zeroes_complete(void *opaque, int ret) } } @@ -51,7 +52,7 @@ index ddf525b9d7..2db9804cfe 100644 virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); if (is_write_zeroes) { block_acct_done(blk_get_stats(s->blk), &req->acct); -@@ -811,12 +818,12 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) +@@ -828,12 +835,12 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh) { @@ -67,8 +68,8 @@ index ddf525b9d7..2db9804cfe 100644 while (req) { VirtIOBlockReq *next = req->next; if (virtio_blk_handle_request(req, &mrb)) { -@@ -1101,8 +1108,16 @@ static void virtio_blk_resize(void *opaque) - virtio_notify_config(vdev); +@@ -1138,8 +1145,16 @@ static void virtio_blk_resize(void *opaque) + aio_bh_schedule_oneshot(qemu_get_aio_context(), virtio_resize_cb, vdev); } +static void virtio_blk_retry_request(void *opaque) diff --git a/vl-Don-t-mismatch-g_strsplit-g_free.patch b/vl-Don-t-mismatch-g_strsplit-g_free.patch deleted file mode 100644 index dc1f4cc484e8b27af68fa7c533ce338fdfbcf7ad..0000000000000000000000000000000000000000 --- a/vl-Don-t-mismatch-g_strsplit-g_free.patch +++ /dev/null @@ -1,56 +0,0 @@ -From cad4a99e8cab2fe581fb2c6c1421f5547b451e96 Mon Sep 17 00:00:00 2001 -From: Pan Nengyuan -Date: Fri, 10 Jan 2020 17:17:09 +0800 -Subject: [PATCH] vl: Don't mismatch g_strsplit()/g_free() - -It's a mismatch between g_strsplit and g_free, it will cause a memory leak as follow: - -[root@localhost]# ./aarch64-softmmu/qemu-system-aarch64 -accel help -Accelerators supported in QEMU binary: -tcg -kvm -================================================================= -==1207900==ERROR: LeakSanitizer: detected memory leaks - -Direct leak of 8 byte(s) in 2 object(s) allocated from: - #0 0xfffd700231cb in __interceptor_malloc (/lib64/libasan.so.4+0xd31cb) - #1 0xfffd6ec57163 in g_malloc (/lib64/libglib-2.0.so.0+0x57163) - #2 0xfffd6ec724d7 in g_strndup (/lib64/libglib-2.0.so.0+0x724d7) - #3 0xfffd6ec73d3f in g_strsplit (/lib64/libglib-2.0.so.0+0x73d3f) - #4 0xaaab66be5077 in main /mnt/sdc/qemu-master/qemu-4.2.0-rc0/vl.c:3517 - #5 0xfffd6e140b9f in __libc_start_main (/lib64/libc.so.6+0x20b9f) - #6 0xaaab66bf0f53 (./build/aarch64-softmmu/qemu-system-aarch64+0x8a0f53) - -Direct leak of 2 byte(s) in 2 object(s) allocated from: - #0 0xfffd700231cb in __interceptor_malloc (/lib64/libasan.so.4+0xd31cb) - #1 0xfffd6ec57163 in g_malloc (/lib64/libglib-2.0.so.0+0x57163) - #2 0xfffd6ec7243b in g_strdup (/lib64/libglib-2.0.so.0+0x7243b) - #3 0xfffd6ec73e6f in g_strsplit (/lib64/libglib-2.0.so.0+0x73e6f) - #4 0xaaab66be5077 in main /mnt/sdc/qemu-master/qemu-4.2.0-rc0/vl.c:3517 - #5 0xfffd6e140b9f in __libc_start_main (/lib64/libc.so.6+0x20b9f) - #6 0xaaab66bf0f53 (./build/aarch64-softmmu/qemu-system-aarch64+0x8a0f53) - -Reported-by: Euler Robot -Signed-off-by: Pan Nengyuan -Message-Id: <20200110091710.53424-2-pannengyuan@huawei.com> -Signed-off-by: Paolo Bonzini ---- - vl.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/vl.c b/vl.c -index b426b32134..cec0bfdb44 100644 ---- a/vl.c -+++ b/vl.c -@@ -3532,7 +3532,7 @@ int main(int argc, char **argv, char **envp) - gchar **optname = g_strsplit(typename, - ACCEL_CLASS_SUFFIX, 0); - printf("%s\n", optname[0]); -- g_free(optname); -+ g_strfreev(optname); - } - g_free(typename); - } --- -2.27.0 - diff --git a/vmstate-add-qom-interface-to-get-id.patch b/vmstate-add-qom-interface-to-get-id.patch deleted file mode 100644 index 53a004405a907109dfb0bbc9354a3b0ef979846f..0000000000000000000000000000000000000000 --- a/vmstate-add-qom-interface-to-get-id.patch +++ /dev/null @@ -1,210 +0,0 @@ -From d771fca664e40c7d7ec5dfa2c656a282bff705b7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= -Date: Wed, 28 Aug 2019 16:00:19 +0400 -Subject: [PATCH] vmstate: add qom interface to get id -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add an interface to get the instance id, instead of depending on -Device and qdev_get_dev_path(). - -Signed-off-by: Marc-André Lureau -Reviewed-by: Daniel P. Berrangé -Acked-by: Dr. David Alan Gilbert ---- - MAINTAINERS | 2 ++ - hw/core/Makefile.objs | 1 + - hw/core/qdev.c | 14 +++++++++++++ - hw/core/vmstate-if.c | 23 +++++++++++++++++++++ - include/hw/vmstate-if.h | 40 ++++++++++++++++++++++++++++++++++++ - include/migration/register.h | 2 ++ - include/migration/vmstate.h | 2 ++ - tests/Makefile.include | 1 + - 8 files changed, 85 insertions(+) - create mode 100644 hw/core/vmstate-if.c - create mode 100644 include/hw/vmstate-if.h - -diff --git a/MAINTAINERS b/MAINTAINERS -index d6de200453..e2d74d7ec3 100644 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -2135,6 +2135,8 @@ Migration - M: Juan Quintela - M: Dr. David Alan Gilbert - S: Maintained -+F: hw/core/vmstate-if.c -+F: include/hw/vmstate-if.h - F: include/migration/ - F: migration/ - F: scripts/vmstate-static-checker.py -diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs -index f8481d959f..54c51583d8 100644 ---- a/hw/core/Makefile.objs -+++ b/hw/core/Makefile.objs -@@ -8,6 +8,7 @@ common-obj-y += irq.o - common-obj-y += hotplug.o - common-obj-$(CONFIG_SOFTMMU) += nmi.o - common-obj-$(CONFIG_SOFTMMU) += vm-change-state-handler.o -+common-obj-y += vmstate-if.o - - common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o - common-obj-$(CONFIG_XILINX_AXI) += stream.o -diff --git a/hw/core/qdev.c b/hw/core/qdev.c -index 4b32f2f46d..13931b1117 100644 ---- a/hw/core/qdev.c -+++ b/hw/core/qdev.c -@@ -1048,9 +1048,18 @@ static void device_unparent(Object *obj) - } - } - -+static char * -+device_vmstate_if_get_id(VMStateIf *obj) -+{ -+ DeviceState *dev = DEVICE(obj); -+ -+ return qdev_get_dev_path(dev); -+} -+ - static void device_class_init(ObjectClass *class, void *data) - { - DeviceClass *dc = DEVICE_CLASS(class); -+ VMStateIfClass *vc = VMSTATE_IF_CLASS(class); - - class->unparent = device_unparent; - -@@ -1062,6 +1071,7 @@ static void device_class_init(ObjectClass *class, void *data) - */ - dc->hotpluggable = true; - dc->user_creatable = true; -+ vc->get_id = device_vmstate_if_get_id; - } - - void device_class_set_parent_reset(DeviceClass *dc, -@@ -1119,6 +1129,10 @@ static const TypeInfo device_type_info = { - .class_init = device_class_init, - .abstract = true, - .class_size = sizeof(DeviceClass), -+ .interfaces = (InterfaceInfo[]) { -+ { TYPE_VMSTATE_IF }, -+ { } -+ } - }; - - static void qdev_register_types(void) -diff --git a/hw/core/vmstate-if.c b/hw/core/vmstate-if.c -new file mode 100644 -index 0000000000..bf453620fe ---- /dev/null -+++ b/hw/core/vmstate-if.c -@@ -0,0 +1,23 @@ -+/* -+ * VMState interface -+ * -+ * Copyright (c) 2009-2019 Red Hat Inc -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#include "qemu/osdep.h" -+#include "hw/vmstate-if.h" -+ -+static const TypeInfo vmstate_if_info = { -+ .name = TYPE_VMSTATE_IF, -+ .parent = TYPE_INTERFACE, -+ .class_size = sizeof(VMStateIfClass), -+}; -+ -+static void vmstate_register_types(void) -+{ -+ type_register_static(&vmstate_if_info); -+} -+ -+type_init(vmstate_register_types); -diff --git a/include/hw/vmstate-if.h b/include/hw/vmstate-if.h -new file mode 100644 -index 0000000000..8ff7f0f292 ---- /dev/null -+++ b/include/hw/vmstate-if.h -@@ -0,0 +1,40 @@ -+/* -+ * VMState interface -+ * -+ * Copyright (c) 2009-2019 Red Hat Inc -+ * This work is licensed under the terms of the GNU GPL, version 2 or later. -+ * See the COPYING file in the top-level directory. -+ */ -+ -+#ifndef VMSTATE_IF_H -+#define VMSTATE_IF_H -+ -+#include "qom/object.h" -+ -+#define TYPE_VMSTATE_IF "vmstate-if" -+ -+#define VMSTATE_IF_CLASS(klass) \ -+ OBJECT_CLASS_CHECK(VMStateIfClass, (klass), TYPE_VMSTATE_IF) -+#define VMSTATE_IF_GET_CLASS(obj) \ -+ OBJECT_GET_CLASS(VMStateIfClass, (obj), TYPE_VMSTATE_IF) -+#define VMSTATE_IF(obj) \ -+ INTERFACE_CHECK(VMStateIf, (obj), TYPE_VMSTATE_IF) -+ -+typedef struct VMStateIf VMStateIf; -+ -+typedef struct VMStateIfClass { -+ InterfaceClass parent_class; -+ -+ char * (*get_id)(VMStateIf *obj); -+} VMStateIfClass; -+ -+static inline char *vmstate_if_get_id(VMStateIf *vmif) -+{ -+ if (!vmif) { -+ return NULL; -+ } -+ -+ return VMSTATE_IF_GET_CLASS(vmif)->get_id(vmif); -+} -+ -+#endif /* VMSTATE_IF_H */ -diff --git a/include/migration/register.h b/include/migration/register.h -index f3ba10b6ef..158130c8c4 100644 ---- a/include/migration/register.h -+++ b/include/migration/register.h -@@ -14,6 +14,8 @@ - #ifndef MIGRATION_REGISTER_H - #define MIGRATION_REGISTER_H - -+#include "hw/vmstate-if.h" -+ - typedef struct SaveVMHandlers { - /* This runs inside the iothread lock. */ - SaveStateHandler *save_state; -diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h -index 8abd2e3b80..8cc1e19fd9 100644 ---- a/include/migration/vmstate.h -+++ b/include/migration/vmstate.h -@@ -27,6 +27,8 @@ - #ifndef QEMU_VMSTATE_H - #define QEMU_VMSTATE_H - -+#include "hw/vmstate-if.h" -+ - typedef struct VMStateInfo VMStateInfo; - typedef struct VMStateDescription VMStateDescription; - typedef struct VMStateField VMStateField; -diff --git a/tests/Makefile.include b/tests/Makefile.include -index 3be60ab999..1c7772a230 100644 ---- a/tests/Makefile.include -+++ b/tests/Makefile.include -@@ -566,6 +566,7 @@ tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \ - hw/core/irq.o \ - hw/core/fw-path-provider.o \ - hw/core/reset.o \ -+ hw/core/vmstate-if.o \ - $(test-qapi-obj-y) - tests/test-vmstate$(EXESUF): tests/test-vmstate.o \ - migration/vmstate.o migration/vmstate-types.o migration/qemu-file.o \ --- -2.27.0 - diff --git a/vmxcap-correct-the-name-of-the-variables.patch b/vmxcap-correct-the-name-of-the-variables.patch deleted file mode 100644 index 3a402dfa1e6908d301ff51e2499af5b3443e3014..0000000000000000000000000000000000000000 --- a/vmxcap-correct-the-name-of-the-variables.patch +++ /dev/null @@ -1,44 +0,0 @@ -From de8779d10794312d1eb56dda5936df7ad6e3c87f Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 1 Jul 2019 16:51:24 +0200 -Subject: [PATCH] vmxcap: correct the name of the variables - -The low bits are 1 if the control must be one, the high bits -are 1 if the control can be one. Correct the variable names -as they are very confusing. - -Signed-off-by: Paolo Bonzini ---- - scripts/kvm/vmxcap | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/scripts/kvm/vmxcap b/scripts/kvm/vmxcap -index 99a8146aaa..2db683215d 100755 ---- a/scripts/kvm/vmxcap -+++ b/scripts/kvm/vmxcap -@@ -51,15 +51,15 @@ class Control(object): - return (val & 0xffffffff, val >> 32) - def show(self): - print(self.name) -- mbz, mb1 = self.read2(self.cap_msr) -- tmbz, tmb1 = 0, 0 -+ mb1, cb1 = self.read2(self.cap_msr) -+ tmb1, tcb1 = 0, 0 - if self.true_cap_msr: -- tmbz, tmb1 = self.read2(self.true_cap_msr) -+ tmb1, tcb1 = self.read2(self.true_cap_msr) - for bit in sorted(self.bits.keys()): -- zero = not (mbz & (1 << bit)) -- one = mb1 & (1 << bit) -- true_zero = not (tmbz & (1 << bit)) -- true_one = tmb1 & (1 << bit) -+ zero = not (mb1 & (1 << bit)) -+ one = cb1 & (1 << bit) -+ true_zero = not (tmb1 & (1 << bit)) -+ true_one = tcb1 & (1 << bit) - s= '?' - if (self.true_cap_msr and true_zero and true_one - and one and not zero): --- -2.27.0 - diff --git a/vnc-fix-memory-leak-when-vnc-disconnect.patch b/vnc-fix-memory-leak-when-vnc-disconnect.patch deleted file mode 100644 index 3eddde4aafc1a213623db042b0cc94a7942e9574..0000000000000000000000000000000000000000 --- a/vnc-fix-memory-leak-when-vnc-disconnect.patch +++ /dev/null @@ -1,1014 +0,0 @@ -From 6bf21f3d83e95bcc4ba35a7a07cc6655e8b010b0 Mon Sep 17 00:00:00 2001 -From: Li Qiang -Date: Sat, 31 Aug 2019 08:39:22 -0700 -Subject: [PATCH] vnc: fix memory leak when vnc disconnect - -Currently when qemu receives a vnc connect, it creates a 'VncState' to -represent this connection. In 'vnc_worker_thread_loop' it creates a -local 'VncState'. The connection 'VcnState' and local 'VncState' exchange -data in 'vnc_async_encoding_start' and 'vnc_async_encoding_end'. -In 'zrle_compress_data' it calls 'deflateInit2' to allocate the libz library -opaque data. The 'VncState' used in 'zrle_compress_data' is the local -'VncState'. In 'vnc_zrle_clear' it calls 'deflateEnd' to free the libz -library opaque data. The 'VncState' used in 'vnc_zrle_clear' is the connection -'VncState'. In currently implementation there will be a memory leak when the -vnc disconnect. Following is the asan output backtrack: - -Direct leak of 29760 byte(s) in 5 object(s) allocated from: - 0 0xffffa67ef3c3 in __interceptor_calloc (/lib64/libasan.so.4+0xd33c3) - 1 0xffffa65071cb in g_malloc0 (/lib64/libglib-2.0.so.0+0x571cb) - 2 0xffffa5e968f7 in deflateInit2_ (/lib64/libz.so.1+0x78f7) - 3 0xaaaacec58613 in zrle_compress_data ui/vnc-enc-zrle.c:87 - 4 0xaaaacec58613 in zrle_send_framebuffer_update ui/vnc-enc-zrle.c:344 - 5 0xaaaacec34e77 in vnc_send_framebuffer_update ui/vnc.c:919 - 6 0xaaaacec5e023 in vnc_worker_thread_loop ui/vnc-jobs.c:271 - 7 0xaaaacec5e5e7 in vnc_worker_thread ui/vnc-jobs.c:340 - 8 0xaaaacee4d3c3 in qemu_thread_start util/qemu-thread-posix.c:502 - 9 0xffffa544e8bb in start_thread (/lib64/libpthread.so.0+0x78bb) - 10 0xffffa53965cb in thread_start (/lib64/libc.so.6+0xd55cb) - -This is because the opaque allocated in 'deflateInit2' is not freed in -'deflateEnd'. The reason is that the 'deflateEnd' calls 'deflateStateCheck' -and in the latter will check whether 's->strm != strm'(libz's data structure). -This check will be true so in 'deflateEnd' it just return 'Z_STREAM_ERROR' and -not free the data allocated in 'deflateInit2'. - -The reason this happens is that the 'VncState' contains the whole 'VncZrle', -so when calling 'deflateInit2', the 's->strm' will be the local address. -So 's->strm != strm' will be true. - -To fix this issue, we need to make 'zrle' of 'VncState' to be a pointer. -Then the connection 'VncState' and local 'VncState' exchange mechanism will -work as expection. The 'tight' of 'VncState' has the same issue, let's also turn -it to a pointer. - -Reported-by: Ying Fang -Signed-off-by: Li Qiang -Message-id: 20190831153922.121308-1-liq3ea@163.com -Signed-off-by: Gerd Hoffmann ---- - ui/vnc-enc-tight.c | 219 +++++++++++++++++++++++++------------------------- - ui/vnc-enc-zlib.c | 11 +-- - ui/vnc-enc-zrle.c | 68 ++++++++-------- - ui/vnc-enc-zrle.inc.c | 2 +- - ui/vnc.c | 28 ++++--- - ui/vnc.h | 4 +- - 6 files changed, 170 insertions(+), 162 deletions(-) - -diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c -index 9084c22..1e08518 100644 ---- a/ui/vnc-enc-tight.c -+++ b/ui/vnc-enc-tight.c -@@ -116,7 +116,7 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, - - static bool tight_can_send_png_rect(VncState *vs, int w, int h) - { -- if (vs->tight.type != VNC_ENCODING_TIGHT_PNG) { -+ if (vs->tight->type != VNC_ENCODING_TIGHT_PNG) { - return false; - } - -@@ -144,7 +144,7 @@ tight_detect_smooth_image24(VncState *vs, int w, int h) - int pixels = 0; - int pix, left[3]; - unsigned int errors; -- unsigned char *buf = vs->tight.tight.buffer; -+ unsigned char *buf = vs->tight->tight.buffer; - - /* - * If client is big-endian, color samples begin from the second -@@ -215,7 +215,7 @@ tight_detect_smooth_image24(VncState *vs, int w, int h) - int pixels = 0; \ - int sample, sum, left[3]; \ - unsigned int errors; \ -- unsigned char *buf = vs->tight.tight.buffer; \ -+ unsigned char *buf = vs->tight->tight.buffer; \ - \ - endian = 0; /* FIXME */ \ - \ -@@ -296,8 +296,8 @@ static int - tight_detect_smooth_image(VncState *vs, int w, int h) - { - unsigned int errors; -- int compression = vs->tight.compression; -- int quality = vs->tight.quality; -+ int compression = vs->tight->compression; -+ int quality = vs->tight->quality; - - if (!vs->vd->lossy) { - return 0; -@@ -309,7 +309,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h) - return 0; - } - -- if (vs->tight.quality != (uint8_t)-1) { -+ if (vs->tight->quality != (uint8_t)-1) { - if (w * h < VNC_TIGHT_JPEG_MIN_RECT_SIZE) { - return 0; - } -@@ -320,9 +320,9 @@ tight_detect_smooth_image(VncState *vs, int w, int h) - } - - if (vs->client_pf.bytes_per_pixel == 4) { -- if (vs->tight.pixel24) { -+ if (vs->tight->pixel24) { - errors = tight_detect_smooth_image24(vs, w, h); -- if (vs->tight.quality != (uint8_t)-1) { -+ if (vs->tight->quality != (uint8_t)-1) { - return (errors < tight_conf[quality].jpeg_threshold24); - } - return (errors < tight_conf[compression].gradient_threshold24); -@@ -352,7 +352,7 @@ tight_detect_smooth_image(VncState *vs, int w, int h) - uint##bpp##_t c0, c1, ci; \ - int i, n0, n1; \ - \ -- data = (uint##bpp##_t *)vs->tight.tight.buffer; \ -+ data = (uint##bpp##_t *)vs->tight->tight.buffer; \ - \ - c0 = data[0]; \ - i = 1; \ -@@ -423,9 +423,9 @@ static int tight_fill_palette(VncState *vs, int x, int y, - { - int max; - -- max = count / tight_conf[vs->tight.compression].idx_max_colors_divisor; -+ max = count / tight_conf[vs->tight->compression].idx_max_colors_divisor; - if (max < 2 && -- count >= tight_conf[vs->tight.compression].mono_min_rect_size) { -+ count >= tight_conf[vs->tight->compression].mono_min_rect_size) { - max = 2; - } - if (max >= 256) { -@@ -558,7 +558,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h) - int x, y, c; - - buf32 = (uint32_t *)buf; -- memset(vs->tight.gradient.buffer, 0, w * 3 * sizeof(int)); -+ memset(vs->tight->gradient.buffer, 0, w * 3 * sizeof(int)); - - if (1 /* FIXME */) { - shift[0] = vs->client_pf.rshift; -@@ -575,7 +575,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h) - upper[c] = 0; - here[c] = 0; - } -- prev = (int *)vs->tight.gradient.buffer; -+ prev = (int *)vs->tight->gradient.buffer; - for (x = 0; x < w; x++) { - pix32 = *buf32++; - for (c = 0; c < 3; c++) { -@@ -615,7 +615,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h) - int prediction; \ - int x, y, c; \ - \ -- memset (vs->tight.gradient.buffer, 0, w * 3 * sizeof(int)); \ -+ memset(vs->tight->gradient.buffer, 0, w * 3 * sizeof(int)); \ - \ - endian = 0; /* FIXME */ \ - \ -@@ -631,7 +631,7 @@ tight_filter_gradient24(VncState *vs, uint8_t *buf, int w, int h) - upper[c] = 0; \ - here[c] = 0; \ - } \ -- prev = (int *)vs->tight.gradient.buffer; \ -+ prev = (int *)vs->tight->gradient.buffer; \ - for (x = 0; x < w; x++) { \ - pix = *buf; \ - if (endian) { \ -@@ -785,7 +785,7 @@ static void extend_solid_area(VncState *vs, int x, int y, int w, int h, - static int tight_init_stream(VncState *vs, int stream_id, - int level, int strategy) - { -- z_streamp zstream = &vs->tight.stream[stream_id]; -+ z_streamp zstream = &vs->tight->stream[stream_id]; - - if (zstream->opaque == NULL) { - int err; -@@ -803,15 +803,15 @@ static int tight_init_stream(VncState *vs, int stream_id, - return -1; - } - -- vs->tight.levels[stream_id] = level; -+ vs->tight->levels[stream_id] = level; - zstream->opaque = vs; - } - -- if (vs->tight.levels[stream_id] != level) { -+ if (vs->tight->levels[stream_id] != level) { - if (deflateParams(zstream, level, strategy) != Z_OK) { - return -1; - } -- vs->tight.levels[stream_id] = level; -+ vs->tight->levels[stream_id] = level; - } - return 0; - } -@@ -839,11 +839,11 @@ static void tight_send_compact_size(VncState *vs, size_t len) - static int tight_compress_data(VncState *vs, int stream_id, size_t bytes, - int level, int strategy) - { -- z_streamp zstream = &vs->tight.stream[stream_id]; -+ z_streamp zstream = &vs->tight->stream[stream_id]; - int previous_out; - - if (bytes < VNC_TIGHT_MIN_TO_COMPRESS) { -- vnc_write(vs, vs->tight.tight.buffer, vs->tight.tight.offset); -+ vnc_write(vs, vs->tight->tight.buffer, vs->tight->tight.offset); - return bytes; - } - -@@ -852,13 +852,13 @@ static int tight_compress_data(VncState *vs, int stream_id, size_t bytes, - } - - /* reserve memory in output buffer */ -- buffer_reserve(&vs->tight.zlib, bytes + 64); -+ buffer_reserve(&vs->tight->zlib, bytes + 64); - - /* set pointers */ -- zstream->next_in = vs->tight.tight.buffer; -- zstream->avail_in = vs->tight.tight.offset; -- zstream->next_out = vs->tight.zlib.buffer + vs->tight.zlib.offset; -- zstream->avail_out = vs->tight.zlib.capacity - vs->tight.zlib.offset; -+ zstream->next_in = vs->tight->tight.buffer; -+ zstream->avail_in = vs->tight->tight.offset; -+ zstream->next_out = vs->tight->zlib.buffer + vs->tight->zlib.offset; -+ zstream->avail_out = vs->tight->zlib.capacity - vs->tight->zlib.offset; - previous_out = zstream->avail_out; - zstream->data_type = Z_BINARY; - -@@ -868,14 +868,14 @@ static int tight_compress_data(VncState *vs, int stream_id, size_t bytes, - return -1; - } - -- vs->tight.zlib.offset = vs->tight.zlib.capacity - zstream->avail_out; -+ vs->tight->zlib.offset = vs->tight->zlib.capacity - zstream->avail_out; - /* ...how much data has actually been produced by deflate() */ - bytes = previous_out - zstream->avail_out; - - tight_send_compact_size(vs, bytes); -- vnc_write(vs, vs->tight.zlib.buffer, bytes); -+ vnc_write(vs, vs->tight->zlib.buffer, bytes); - -- buffer_reset(&vs->tight.zlib); -+ buffer_reset(&vs->tight->zlib); - - return bytes; - } -@@ -927,16 +927,17 @@ static int send_full_color_rect(VncState *vs, int x, int y, int w, int h) - - vnc_write_u8(vs, stream << 4); /* no flushing, no filter */ - -- if (vs->tight.pixel24) { -- tight_pack24(vs, vs->tight.tight.buffer, w * h, &vs->tight.tight.offset); -+ if (vs->tight->pixel24) { -+ tight_pack24(vs, vs->tight->tight.buffer, w * h, -+ &vs->tight->tight.offset); - bytes = 3; - } else { - bytes = vs->client_pf.bytes_per_pixel; - } - - bytes = tight_compress_data(vs, stream, w * h * bytes, -- tight_conf[vs->tight.compression].raw_zlib_level, -- Z_DEFAULT_STRATEGY); -+ tight_conf[vs->tight->compression].raw_zlib_level, -+ Z_DEFAULT_STRATEGY); - - return (bytes >= 0); - } -@@ -947,14 +948,14 @@ static int send_solid_rect(VncState *vs) - - vnc_write_u8(vs, VNC_TIGHT_FILL << 4); /* no flushing, no filter */ - -- if (vs->tight.pixel24) { -- tight_pack24(vs, vs->tight.tight.buffer, 1, &vs->tight.tight.offset); -+ if (vs->tight->pixel24) { -+ tight_pack24(vs, vs->tight->tight.buffer, 1, &vs->tight->tight.offset); - bytes = 3; - } else { - bytes = vs->client_pf.bytes_per_pixel; - } - -- vnc_write(vs, vs->tight.tight.buffer, bytes); -+ vnc_write(vs, vs->tight->tight.buffer, bytes); - return 1; - } - -@@ -963,7 +964,7 @@ static int send_mono_rect(VncState *vs, int x, int y, - { - ssize_t bytes; - int stream = 1; -- int level = tight_conf[vs->tight.compression].mono_zlib_level; -+ int level = tight_conf[vs->tight->compression].mono_zlib_level; - - #ifdef CONFIG_VNC_PNG - if (tight_can_send_png_rect(vs, w, h)) { -@@ -991,26 +992,26 @@ static int send_mono_rect(VncState *vs, int x, int y, - uint32_t buf[2] = {bg, fg}; - size_t ret = sizeof (buf); - -- if (vs->tight.pixel24) { -+ if (vs->tight->pixel24) { - tight_pack24(vs, (unsigned char*)buf, 2, &ret); - } - vnc_write(vs, buf, ret); - -- tight_encode_mono_rect32(vs->tight.tight.buffer, w, h, bg, fg); -+ tight_encode_mono_rect32(vs->tight->tight.buffer, w, h, bg, fg); - break; - } - case 2: - vnc_write(vs, &bg, 2); - vnc_write(vs, &fg, 2); -- tight_encode_mono_rect16(vs->tight.tight.buffer, w, h, bg, fg); -+ tight_encode_mono_rect16(vs->tight->tight.buffer, w, h, bg, fg); - break; - default: - vnc_write_u8(vs, bg); - vnc_write_u8(vs, fg); -- tight_encode_mono_rect8(vs->tight.tight.buffer, w, h, bg, fg); -+ tight_encode_mono_rect8(vs->tight->tight.buffer, w, h, bg, fg); - break; - } -- vs->tight.tight.offset = bytes; -+ vs->tight->tight.offset = bytes; - - bytes = tight_compress_data(vs, stream, bytes, level, Z_DEFAULT_STRATEGY); - return (bytes >= 0); -@@ -1040,7 +1041,7 @@ static void write_palette(int idx, uint32_t color, void *opaque) - static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h) - { - int stream = 3; -- int level = tight_conf[vs->tight.compression].gradient_zlib_level; -+ int level = tight_conf[vs->tight->compression].gradient_zlib_level; - ssize_t bytes; - - if (vs->client_pf.bytes_per_pixel == 1) { -@@ -1050,23 +1051,23 @@ static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h) - vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4); - vnc_write_u8(vs, VNC_TIGHT_FILTER_GRADIENT); - -- buffer_reserve(&vs->tight.gradient, w * 3 * sizeof (int)); -+ buffer_reserve(&vs->tight->gradient, w * 3 * sizeof(int)); - -- if (vs->tight.pixel24) { -- tight_filter_gradient24(vs, vs->tight.tight.buffer, w, h); -+ if (vs->tight->pixel24) { -+ tight_filter_gradient24(vs, vs->tight->tight.buffer, w, h); - bytes = 3; - } else if (vs->client_pf.bytes_per_pixel == 4) { -- tight_filter_gradient32(vs, (uint32_t *)vs->tight.tight.buffer, w, h); -+ tight_filter_gradient32(vs, (uint32_t *)vs->tight->tight.buffer, w, h); - bytes = 4; - } else { -- tight_filter_gradient16(vs, (uint16_t *)vs->tight.tight.buffer, w, h); -+ tight_filter_gradient16(vs, (uint16_t *)vs->tight->tight.buffer, w, h); - bytes = 2; - } - -- buffer_reset(&vs->tight.gradient); -+ buffer_reset(&vs->tight->gradient); - - bytes = w * h * bytes; -- vs->tight.tight.offset = bytes; -+ vs->tight->tight.offset = bytes; - - bytes = tight_compress_data(vs, stream, bytes, - level, Z_FILTERED); -@@ -1077,7 +1078,7 @@ static int send_palette_rect(VncState *vs, int x, int y, - int w, int h, VncPalette *palette) - { - int stream = 2; -- int level = tight_conf[vs->tight.compression].idx_zlib_level; -+ int level = tight_conf[vs->tight->compression].idx_zlib_level; - int colors; - ssize_t bytes; - -@@ -1104,12 +1105,12 @@ static int send_palette_rect(VncState *vs, int x, int y, - palette_iter(palette, write_palette, &priv); - vnc_write(vs, header, sizeof(header)); - -- if (vs->tight.pixel24) { -+ if (vs->tight->pixel24) { - tight_pack24(vs, vs->output.buffer + old_offset, colors, &offset); - vs->output.offset = old_offset + offset; - } - -- tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette); -+ tight_encode_indexed_rect32(vs->tight->tight.buffer, w * h, palette); - break; - } - case 2: -@@ -1119,7 +1120,7 @@ static int send_palette_rect(VncState *vs, int x, int y, - - palette_iter(palette, write_palette, &priv); - vnc_write(vs, header, sizeof(header)); -- tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette); -+ tight_encode_indexed_rect16(vs->tight->tight.buffer, w * h, palette); - break; - } - default: -@@ -1127,7 +1128,7 @@ static int send_palette_rect(VncState *vs, int x, int y, - break; - } - bytes = w * h; -- vs->tight.tight.offset = bytes; -+ vs->tight->tight.offset = bytes; - - bytes = tight_compress_data(vs, stream, bytes, - level, Z_DEFAULT_STRATEGY); -@@ -1146,7 +1147,7 @@ static int send_palette_rect(VncState *vs, int x, int y, - static void jpeg_init_destination(j_compress_ptr cinfo) - { - VncState *vs = cinfo->client_data; -- Buffer *buffer = &vs->tight.jpeg; -+ Buffer *buffer = &vs->tight->jpeg; - - cinfo->dest->next_output_byte = (JOCTET *)buffer->buffer + buffer->offset; - cinfo->dest->free_in_buffer = (size_t)(buffer->capacity - buffer->offset); -@@ -1156,7 +1157,7 @@ static void jpeg_init_destination(j_compress_ptr cinfo) - static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo) - { - VncState *vs = cinfo->client_data; -- Buffer *buffer = &vs->tight.jpeg; -+ Buffer *buffer = &vs->tight->jpeg; - - buffer->offset = buffer->capacity; - buffer_reserve(buffer, 2048); -@@ -1168,7 +1169,7 @@ static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo) - static void jpeg_term_destination(j_compress_ptr cinfo) - { - VncState *vs = cinfo->client_data; -- Buffer *buffer = &vs->tight.jpeg; -+ Buffer *buffer = &vs->tight->jpeg; - - buffer->offset = buffer->capacity - cinfo->dest->free_in_buffer; - } -@@ -1187,7 +1188,7 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality) - return send_full_color_rect(vs, x, y, w, h); - } - -- buffer_reserve(&vs->tight.jpeg, 2048); -+ buffer_reserve(&vs->tight->jpeg, 2048); - - cinfo.err = jpeg_std_error(&jerr); - jpeg_create_compress(&cinfo); -@@ -1222,9 +1223,9 @@ static int send_jpeg_rect(VncState *vs, int x, int y, int w, int h, int quality) - - vnc_write_u8(vs, VNC_TIGHT_JPEG << 4); - -- tight_send_compact_size(vs, vs->tight.jpeg.offset); -- vnc_write(vs, vs->tight.jpeg.buffer, vs->tight.jpeg.offset); -- buffer_reset(&vs->tight.jpeg); -+ tight_send_compact_size(vs, vs->tight->jpeg.offset); -+ vnc_write(vs, vs->tight->jpeg.buffer, vs->tight->jpeg.offset); -+ buffer_reset(&vs->tight->jpeg); - - return 1; - } -@@ -1240,7 +1241,7 @@ static void write_png_palette(int idx, uint32_t pix, void *opaque) - VncState *vs = priv->vs; - png_colorp color = &priv->png_palette[idx]; - -- if (vs->tight.pixel24) -+ if (vs->tight->pixel24) - { - color->red = (pix >> vs->client_pf.rshift) & vs->client_pf.rmax; - color->green = (pix >> vs->client_pf.gshift) & vs->client_pf.gmax; -@@ -1267,10 +1268,10 @@ static void png_write_data(png_structp png_ptr, png_bytep data, - { - VncState *vs = png_get_io_ptr(png_ptr); - -- buffer_reserve(&vs->tight.png, vs->tight.png.offset + length); -- memcpy(vs->tight.png.buffer + vs->tight.png.offset, data, length); -+ buffer_reserve(&vs->tight->png, vs->tight->png.offset + length); -+ memcpy(vs->tight->png.buffer + vs->tight->png.offset, data, length); - -- vs->tight.png.offset += length; -+ vs->tight->png.offset += length; - } - - static void png_flush_data(png_structp png_ptr) -@@ -1295,8 +1296,8 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, - png_infop info_ptr; - png_colorp png_palette = NULL; - pixman_image_t *linebuf; -- int level = tight_png_conf[vs->tight.compression].png_zlib_level; -- int filters = tight_png_conf[vs->tight.compression].png_filters; -+ int level = tight_png_conf[vs->tight->compression].png_zlib_level; -+ int filters = tight_png_conf[vs->tight->compression].png_filters; - uint8_t *buf; - int dy; - -@@ -1340,21 +1341,23 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, - png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette)); - - if (vs->client_pf.bytes_per_pixel == 4) { -- tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette); -+ tight_encode_indexed_rect32(vs->tight->tight.buffer, w * h, -+ palette); - } else { -- tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette); -+ tight_encode_indexed_rect16(vs->tight->tight.buffer, w * h, -+ palette); - } - } - - png_write_info(png_ptr, info_ptr); - -- buffer_reserve(&vs->tight.png, 2048); -+ buffer_reserve(&vs->tight->png, 2048); - linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w); - buf = (uint8_t *)pixman_image_get_data(linebuf); - for (dy = 0; dy < h; dy++) - { - if (color_type == PNG_COLOR_TYPE_PALETTE) { -- memcpy(buf, vs->tight.tight.buffer + (dy * w), w); -+ memcpy(buf, vs->tight->tight.buffer + (dy * w), w); - } else { - qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, x, y + dy); - } -@@ -1372,27 +1375,27 @@ static int send_png_rect(VncState *vs, int x, int y, int w, int h, - - vnc_write_u8(vs, VNC_TIGHT_PNG << 4); - -- tight_send_compact_size(vs, vs->tight.png.offset); -- vnc_write(vs, vs->tight.png.buffer, vs->tight.png.offset); -- buffer_reset(&vs->tight.png); -+ tight_send_compact_size(vs, vs->tight->png.offset); -+ vnc_write(vs, vs->tight->png.buffer, vs->tight->png.offset); -+ buffer_reset(&vs->tight->png); - return 1; - } - #endif /* CONFIG_VNC_PNG */ - - static void vnc_tight_start(VncState *vs) - { -- buffer_reset(&vs->tight.tight); -+ buffer_reset(&vs->tight->tight); - - // make the output buffer be the zlib buffer, so we can compress it later -- vs->tight.tmp = vs->output; -- vs->output = vs->tight.tight; -+ vs->tight->tmp = vs->output; -+ vs->output = vs->tight->tight; - } - - static void vnc_tight_stop(VncState *vs) - { - // switch back to normal output/zlib buffers -- vs->tight.tight = vs->output; -- vs->output = vs->tight.tmp; -+ vs->tight->tight = vs->output; -+ vs->output = vs->tight->tmp; - } - - static int send_sub_rect_nojpeg(VncState *vs, int x, int y, int w, int h, -@@ -1426,9 +1429,9 @@ static int send_sub_rect_jpeg(VncState *vs, int x, int y, int w, int h, - int ret; - - if (colors == 0) { -- if (force || (tight_jpeg_conf[vs->tight.quality].jpeg_full && -+ if (force || (tight_jpeg_conf[vs->tight->quality].jpeg_full && - tight_detect_smooth_image(vs, w, h))) { -- int quality = tight_conf[vs->tight.quality].jpeg_quality; -+ int quality = tight_conf[vs->tight->quality].jpeg_quality; - - ret = send_jpeg_rect(vs, x, y, w, h, quality); - } else { -@@ -1440,9 +1443,9 @@ static int send_sub_rect_jpeg(VncState *vs, int x, int y, int w, int h, - ret = send_mono_rect(vs, x, y, w, h, bg, fg); - } else if (colors <= 256) { - if (force || (colors > 96 && -- tight_jpeg_conf[vs->tight.quality].jpeg_idx && -+ tight_jpeg_conf[vs->tight->quality].jpeg_idx && - tight_detect_smooth_image(vs, w, h))) { -- int quality = tight_conf[vs->tight.quality].jpeg_quality; -+ int quality = tight_conf[vs->tight->quality].jpeg_quality; - - ret = send_jpeg_rect(vs, x, y, w, h, quality); - } else { -@@ -1480,20 +1483,20 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h) - qemu_thread_atexit_add(&vnc_tight_cleanup_notifier); - } - -- vnc_framebuffer_update(vs, x, y, w, h, vs->tight.type); -+ vnc_framebuffer_update(vs, x, y, w, h, vs->tight->type); - - vnc_tight_start(vs); - vnc_raw_send_framebuffer_update(vs, x, y, w, h); - vnc_tight_stop(vs); - - #ifdef CONFIG_VNC_JPEG -- if (!vs->vd->non_adaptive && vs->tight.quality != (uint8_t)-1) { -+ if (!vs->vd->non_adaptive && vs->tight->quality != (uint8_t)-1) { - double freq = vnc_update_freq(vs, x, y, w, h); - -- if (freq < tight_jpeg_conf[vs->tight.quality].jpeg_freq_min) { -+ if (freq < tight_jpeg_conf[vs->tight->quality].jpeg_freq_min) { - allow_jpeg = false; - } -- if (freq >= tight_jpeg_conf[vs->tight.quality].jpeg_freq_threshold) { -+ if (freq >= tight_jpeg_conf[vs->tight->quality].jpeg_freq_threshold) { - force_jpeg = true; - vnc_sent_lossy_rect(vs, x, y, w, h); - } -@@ -1503,7 +1506,7 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h) - colors = tight_fill_palette(vs, x, y, w * h, &bg, &fg, color_count_palette); - - #ifdef CONFIG_VNC_JPEG -- if (allow_jpeg && vs->tight.quality != (uint8_t)-1) { -+ if (allow_jpeg && vs->tight->quality != (uint8_t)-1) { - ret = send_sub_rect_jpeg(vs, x, y, w, h, bg, fg, colors, - color_count_palette, force_jpeg); - } else { -@@ -1520,7 +1523,7 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h) - - static int send_sub_rect_solid(VncState *vs, int x, int y, int w, int h) - { -- vnc_framebuffer_update(vs, x, y, w, h, vs->tight.type); -+ vnc_framebuffer_update(vs, x, y, w, h, vs->tight->type); - - vnc_tight_start(vs); - vnc_raw_send_framebuffer_update(vs, x, y, w, h); -@@ -1538,8 +1541,8 @@ static int send_rect_simple(VncState *vs, int x, int y, int w, int h, - int rw, rh; - int n = 0; - -- max_size = tight_conf[vs->tight.compression].max_rect_size; -- max_width = tight_conf[vs->tight.compression].max_rect_width; -+ max_size = tight_conf[vs->tight->compression].max_rect_size; -+ max_width = tight_conf[vs->tight->compression].max_rect_width; - - if (split && (w > max_width || w * h > max_size)) { - max_sub_width = (w > max_width) ? max_width : w; -@@ -1648,16 +1651,16 @@ static int tight_send_framebuffer_update(VncState *vs, int x, int y, - - if (vs->client_pf.bytes_per_pixel == 4 && vs->client_pf.rmax == 0xFF && - vs->client_pf.bmax == 0xFF && vs->client_pf.gmax == 0xFF) { -- vs->tight.pixel24 = true; -+ vs->tight->pixel24 = true; - } else { -- vs->tight.pixel24 = false; -+ vs->tight->pixel24 = false; - } - - #ifdef CONFIG_VNC_JPEG -- if (vs->tight.quality != (uint8_t)-1) { -+ if (vs->tight->quality != (uint8_t)-1) { - double freq = vnc_update_freq(vs, x, y, w, h); - -- if (freq > tight_jpeg_conf[vs->tight.quality].jpeg_freq_threshold) { -+ if (freq > tight_jpeg_conf[vs->tight->quality].jpeg_freq_threshold) { - return send_rect_simple(vs, x, y, w, h, false); - } - } -@@ -1669,8 +1672,8 @@ static int tight_send_framebuffer_update(VncState *vs, int x, int y, - - /* Calculate maximum number of rows in one non-solid rectangle. */ - -- max_rows = tight_conf[vs->tight.compression].max_rect_size; -- max_rows /= MIN(tight_conf[vs->tight.compression].max_rect_width, w); -+ max_rows = tight_conf[vs->tight->compression].max_rect_size; -+ max_rows /= MIN(tight_conf[vs->tight->compression].max_rect_width, w); - - return find_large_solid_color_rect(vs, x, y, w, h, max_rows); - } -@@ -1678,33 +1681,33 @@ static int tight_send_framebuffer_update(VncState *vs, int x, int y, - int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y, - int w, int h) - { -- vs->tight.type = VNC_ENCODING_TIGHT; -+ vs->tight->type = VNC_ENCODING_TIGHT; - return tight_send_framebuffer_update(vs, x, y, w, h); - } - - int vnc_tight_png_send_framebuffer_update(VncState *vs, int x, int y, - int w, int h) - { -- vs->tight.type = VNC_ENCODING_TIGHT_PNG; -+ vs->tight->type = VNC_ENCODING_TIGHT_PNG; - return tight_send_framebuffer_update(vs, x, y, w, h); - } - - void vnc_tight_clear(VncState *vs) - { - int i; -- for (i=0; itight.stream); i++) { -- if (vs->tight.stream[i].opaque) { -- deflateEnd(&vs->tight.stream[i]); -+ for (i = 0; i < ARRAY_SIZE(vs->tight->stream); i++) { -+ if (vs->tight->stream[i].opaque) { -+ deflateEnd(&vs->tight->stream[i]); - } - } - -- buffer_free(&vs->tight.tight); -- buffer_free(&vs->tight.zlib); -- buffer_free(&vs->tight.gradient); -+ buffer_free(&vs->tight->tight); -+ buffer_free(&vs->tight->zlib); -+ buffer_free(&vs->tight->gradient); - #ifdef CONFIG_VNC_JPEG -- buffer_free(&vs->tight.jpeg); -+ buffer_free(&vs->tight->jpeg); - #endif - #ifdef CONFIG_VNC_PNG -- buffer_free(&vs->tight.png); -+ buffer_free(&vs->tight->png); - #endif - } -diff --git a/ui/vnc-enc-zlib.c b/ui/vnc-enc-zlib.c -index 33e9df2..900ae5b 100644 ---- a/ui/vnc-enc-zlib.c -+++ b/ui/vnc-enc-zlib.c -@@ -76,7 +76,8 @@ static int vnc_zlib_stop(VncState *vs) - zstream->zalloc = vnc_zlib_zalloc; - zstream->zfree = vnc_zlib_zfree; - -- err = deflateInit2(zstream, vs->tight.compression, Z_DEFLATED, MAX_WBITS, -+ err = deflateInit2(zstream, vs->tight->compression, Z_DEFLATED, -+ MAX_WBITS, - MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); - - if (err != Z_OK) { -@@ -84,16 +85,16 @@ static int vnc_zlib_stop(VncState *vs) - return -1; - } - -- vs->zlib.level = vs->tight.compression; -+ vs->zlib.level = vs->tight->compression; - zstream->opaque = vs; - } - -- if (vs->tight.compression != vs->zlib.level) { -- if (deflateParams(zstream, vs->tight.compression, -+ if (vs->tight->compression != vs->zlib.level) { -+ if (deflateParams(zstream, vs->tight->compression, - Z_DEFAULT_STRATEGY) != Z_OK) { - return -1; - } -- vs->zlib.level = vs->tight.compression; -+ vs->zlib.level = vs->tight->compression; - } - - // reserve memory in output buffer -diff --git a/ui/vnc-enc-zrle.c b/ui/vnc-enc-zrle.c -index 7493a84..17fd28a 100644 ---- a/ui/vnc-enc-zrle.c -+++ b/ui/vnc-enc-zrle.c -@@ -37,18 +37,18 @@ static const int bits_per_packed_pixel[] = { - - static void vnc_zrle_start(VncState *vs) - { -- buffer_reset(&vs->zrle.zrle); -+ buffer_reset(&vs->zrle->zrle); - - /* make the output buffer be the zlib buffer, so we can compress it later */ -- vs->zrle.tmp = vs->output; -- vs->output = vs->zrle.zrle; -+ vs->zrle->tmp = vs->output; -+ vs->output = vs->zrle->zrle; - } - - static void vnc_zrle_stop(VncState *vs) - { - /* switch back to normal output/zlib buffers */ -- vs->zrle.zrle = vs->output; -- vs->output = vs->zrle.tmp; -+ vs->zrle->zrle = vs->output; -+ vs->output = vs->zrle->tmp; - } - - static void *zrle_convert_fb(VncState *vs, int x, int y, int w, int h, -@@ -56,24 +56,24 @@ static void *zrle_convert_fb(VncState *vs, int x, int y, int w, int h, - { - Buffer tmp; - -- buffer_reset(&vs->zrle.fb); -- buffer_reserve(&vs->zrle.fb, w * h * bpp + bpp); -+ buffer_reset(&vs->zrle->fb); -+ buffer_reserve(&vs->zrle->fb, w * h * bpp + bpp); - - tmp = vs->output; -- vs->output = vs->zrle.fb; -+ vs->output = vs->zrle->fb; - - vnc_raw_send_framebuffer_update(vs, x, y, w, h); - -- vs->zrle.fb = vs->output; -+ vs->zrle->fb = vs->output; - vs->output = tmp; -- return vs->zrle.fb.buffer; -+ return vs->zrle->fb.buffer; - } - - static int zrle_compress_data(VncState *vs, int level) - { -- z_streamp zstream = &vs->zrle.stream; -+ z_streamp zstream = &vs->zrle->stream; - -- buffer_reset(&vs->zrle.zlib); -+ buffer_reset(&vs->zrle->zlib); - - if (zstream->opaque != vs) { - int err; -@@ -93,13 +93,13 @@ static int zrle_compress_data(VncState *vs, int level) - } - - /* reserve memory in output buffer */ -- buffer_reserve(&vs->zrle.zlib, vs->zrle.zrle.offset + 64); -+ buffer_reserve(&vs->zrle->zlib, vs->zrle->zrle.offset + 64); - - /* set pointers */ -- zstream->next_in = vs->zrle.zrle.buffer; -- zstream->avail_in = vs->zrle.zrle.offset; -- zstream->next_out = vs->zrle.zlib.buffer + vs->zrle.zlib.offset; -- zstream->avail_out = vs->zrle.zlib.capacity - vs->zrle.zlib.offset; -+ zstream->next_in = vs->zrle->zrle.buffer; -+ zstream->avail_in = vs->zrle->zrle.offset; -+ zstream->next_out = vs->zrle->zlib.buffer + vs->zrle->zlib.offset; -+ zstream->avail_out = vs->zrle->zlib.capacity - vs->zrle->zlib.offset; - zstream->data_type = Z_BINARY; - - /* start encoding */ -@@ -108,8 +108,8 @@ static int zrle_compress_data(VncState *vs, int level) - return -1; - } - -- vs->zrle.zlib.offset = vs->zrle.zlib.capacity - zstream->avail_out; -- return vs->zrle.zlib.offset; -+ vs->zrle->zlib.offset = vs->zrle->zlib.capacity - zstream->avail_out; -+ return vs->zrle->zlib.offset; - } - - /* Try to work out whether to use RLE and/or a palette. We do this by -@@ -259,14 +259,14 @@ static int zrle_send_framebuffer_update(VncState *vs, int x, int y, - size_t bytes; - int zywrle_level; - -- if (vs->zrle.type == VNC_ENCODING_ZYWRLE) { -- if (!vs->vd->lossy || vs->tight.quality == (uint8_t)-1 -- || vs->tight.quality == 9) { -+ if (vs->zrle->type == VNC_ENCODING_ZYWRLE) { -+ if (!vs->vd->lossy || vs->tight->quality == (uint8_t)-1 -+ || vs->tight->quality == 9) { - zywrle_level = 0; -- vs->zrle.type = VNC_ENCODING_ZRLE; -- } else if (vs->tight.quality < 3) { -+ vs->zrle->type = VNC_ENCODING_ZRLE; -+ } else if (vs->tight->quality < 3) { - zywrle_level = 3; -- } else if (vs->tight.quality < 6) { -+ } else if (vs->tight->quality < 6) { - zywrle_level = 2; - } else { - zywrle_level = 1; -@@ -337,30 +337,30 @@ static int zrle_send_framebuffer_update(VncState *vs, int x, int y, - - vnc_zrle_stop(vs); - bytes = zrle_compress_data(vs, Z_DEFAULT_COMPRESSION); -- vnc_framebuffer_update(vs, x, y, w, h, vs->zrle.type); -+ vnc_framebuffer_update(vs, x, y, w, h, vs->zrle->type); - vnc_write_u32(vs, bytes); -- vnc_write(vs, vs->zrle.zlib.buffer, vs->zrle.zlib.offset); -+ vnc_write(vs, vs->zrle->zlib.buffer, vs->zrle->zlib.offset); - return 1; - } - - int vnc_zrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) - { -- vs->zrle.type = VNC_ENCODING_ZRLE; -+ vs->zrle->type = VNC_ENCODING_ZRLE; - return zrle_send_framebuffer_update(vs, x, y, w, h); - } - - int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) - { -- vs->zrle.type = VNC_ENCODING_ZYWRLE; -+ vs->zrle->type = VNC_ENCODING_ZYWRLE; - return zrle_send_framebuffer_update(vs, x, y, w, h); - } - - void vnc_zrle_clear(VncState *vs) - { -- if (vs->zrle.stream.opaque) { -- deflateEnd(&vs->zrle.stream); -+ if (vs->zrle->stream.opaque) { -+ deflateEnd(&vs->zrle->stream); - } -- buffer_free(&vs->zrle.zrle); -- buffer_free(&vs->zrle.fb); -- buffer_free(&vs->zrle.zlib); -+ buffer_free(&vs->zrle->zrle); -+ buffer_free(&vs->zrle->fb); -+ buffer_free(&vs->zrle->zlib); - } -diff --git a/ui/vnc-enc-zrle.inc.c b/ui/vnc-enc-zrle.inc.c -index abf6b86..c107d8a 100644 ---- a/ui/vnc-enc-zrle.inc.c -+++ b/ui/vnc-enc-zrle.inc.c -@@ -96,7 +96,7 @@ static void ZRLE_ENCODE(VncState *vs, int x, int y, int w, int h, - static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h, - int zywrle_level) - { -- VncPalette *palette = &vs->zrle.palette; -+ VncPalette *palette = &vs->zrle->palette; - - int runs = 0; - int single_pixels = 0; -diff --git a/ui/vnc.c b/ui/vnc.c -index bc43c4c..87b8045 100644 ---- a/ui/vnc.c -+++ b/ui/vnc.c -@@ -1307,6 +1307,8 @@ void vnc_disconnect_finish(VncState *vs) - object_unref(OBJECT(vs->sioc)); - vs->sioc = NULL; - vs->magic = 0; -+ g_free(vs->zrle); -+ g_free(vs->tight); - g_free(vs); - } - -@@ -2058,8 +2060,8 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) - - vs->features = 0; - vs->vnc_encoding = 0; -- vs->tight.compression = 9; -- vs->tight.quality = -1; /* Lossless by default */ -+ vs->tight->compression = 9; -+ vs->tight->quality = -1; /* Lossless by default */ - vs->absolute = -1; - - /* -@@ -2127,11 +2129,11 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) - vs->features |= VNC_FEATURE_LED_STATE_MASK; - break; - case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9: -- vs->tight.compression = (enc & 0x0F); -+ vs->tight->compression = (enc & 0x0F); - break; - case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9: - if (vs->vd->lossy) { -- vs->tight.quality = (enc & 0x0F); -+ vs->tight->quality = (enc & 0x0F); - } - break; - default: -@@ -3034,6 +3036,8 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc, - int i; - - trace_vnc_client_connect(vs, sioc); -+ vs->zrle = g_new0(VncZrle, 1); -+ vs->tight = g_new0(VncTight, 1); - vs->magic = VNC_MAGIC; - vs->sioc = sioc; - object_ref(OBJECT(vs->sioc)); -@@ -3045,19 +3049,19 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc, - buffer_init(&vs->output, "vnc-output/%p", sioc); - buffer_init(&vs->jobs_buffer, "vnc-jobs_buffer/%p", sioc); - -- buffer_init(&vs->tight.tight, "vnc-tight/%p", sioc); -- buffer_init(&vs->tight.zlib, "vnc-tight-zlib/%p", sioc); -- buffer_init(&vs->tight.gradient, "vnc-tight-gradient/%p", sioc); -+ buffer_init(&vs->tight->tight, "vnc-tight/%p", sioc); -+ buffer_init(&vs->tight->zlib, "vnc-tight-zlib/%p", sioc); -+ buffer_init(&vs->tight->gradient, "vnc-tight-gradient/%p", sioc); - #ifdef CONFIG_VNC_JPEG -- buffer_init(&vs->tight.jpeg, "vnc-tight-jpeg/%p", sioc); -+ buffer_init(&vs->tight->jpeg, "vnc-tight-jpeg/%p", sioc); - #endif - #ifdef CONFIG_VNC_PNG -- buffer_init(&vs->tight.png, "vnc-tight-png/%p", sioc); -+ buffer_init(&vs->tight->png, "vnc-tight-png/%p", sioc); - #endif - buffer_init(&vs->zlib.zlib, "vnc-zlib/%p", sioc); -- buffer_init(&vs->zrle.zrle, "vnc-zrle/%p", sioc); -- buffer_init(&vs->zrle.fb, "vnc-zrle-fb/%p", sioc); -- buffer_init(&vs->zrle.zlib, "vnc-zrle-zlib/%p", sioc); -+ buffer_init(&vs->zrle->zrle, "vnc-zrle/%p", sioc); -+ buffer_init(&vs->zrle->fb, "vnc-zrle-fb/%p", sioc); -+ buffer_init(&vs->zrle->zlib, "vnc-zrle-zlib/%p", sioc); - - if (skipauth) { - vs->auth = VNC_AUTH_NONE; -diff --git a/ui/vnc.h b/ui/vnc.h -index 8643860..fea79c2 100644 ---- a/ui/vnc.h -+++ b/ui/vnc.h -@@ -338,10 +338,10 @@ struct VncState - /* Encoding specific, if you add something here, don't forget to - * update vnc_async_encoding_start() - */ -- VncTight tight; -+ VncTight *tight; - VncZlib zlib; - VncHextile hextile; -- VncZrle zrle; -+ VncZrle *zrle; - VncZywrle zywrle; - - Notifier mouse_mode_notifier; --- -1.8.3.1 - diff --git a/vpc-Return-0-from-vpc_co_create-on-success.patch b/vpc-Return-0-from-vpc_co_create-on-success.patch deleted file mode 100644 index 46fbd90d1bd39f5549ce5d0185d58bbd437a82aa..0000000000000000000000000000000000000000 --- a/vpc-Return-0-from-vpc_co_create-on-success.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 97c478c355fee96eb2b740313f50561e69b6f305 Mon Sep 17 00:00:00 2001 -From: Max Reitz -Date: Mon, 2 Sep 2019 21:33:16 +0200 -Subject: [PATCH] vpc: Return 0 from vpc_co_create() on success - -blockdev_create_run() directly uses .bdrv_co_create()'s return value as -the job's return value. Jobs must return 0 on success, not just any -nonnegative value. Therefore, using blockdev-create for VPC images may -currently fail as the vpc driver may return a positive integer. - -Because there is no point in returning a positive integer anywhere in -the block layer (all non-negative integers are generally treated as -complete success), we probably do not want to add more such cases. -Therefore, fix this problem by making the vpc driver always return 0 in -case of success. - -Suggested-by: Kevin Wolf -Cc: qemu-stable@nongnu.org -Signed-off-by: Max Reitz -Signed-off-by: Kevin Wolf -(cherry picked from commit 1a37e3124407b5a145d44478d3ecbdb89c63789f) -Signed-off-by: Michael Roth ---- - block/vpc.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/block/vpc.c b/block/vpc.c -index d4776ee8a5..3a88e28e2b 100644 ---- a/block/vpc.c -+++ b/block/vpc.c -@@ -885,6 +885,7 @@ static int create_dynamic_disk(BlockBackend *blk, uint8_t *buf, - goto fail; - } - -+ ret = 0; - fail: - return ret; - } -@@ -908,7 +909,7 @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf, - return ret; - } - -- return ret; -+ return 0; - } - - static int calculate_rounded_image_size(BlockdevCreateOptionsVpc *vpc_opts, --- -2.23.0 diff --git a/vtimer-Drop-vtimer-virtual-timer-adjust.patch b/vtimer-Drop-vtimer-virtual-timer-adjust.patch deleted file mode 100644 index 726498fb6c778f8d5739e9614ae451d54a11bb56..0000000000000000000000000000000000000000 --- a/vtimer-Drop-vtimer-virtual-timer-adjust.patch +++ /dev/null @@ -1,144 +0,0 @@ -From b1782119bcfac96d8a541d8d60ee00f954d721db Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Wed, 27 May 2020 17:48:54 +0800 -Subject: [PATCH] vtimer: Drop vtimer virtual timer adjust - -This patch drops the vtimer virtual timer adjust, cross version migration -from openEuler qemu-4.0.1 to qemu-4.1.0 is not supported as a consequence. - -By default openEuler qemu-4.1.0 use kvm_adjvtime as the virtual timer. - -Signed-off-by: Ying Fang - -diff --git a/cpus.c b/cpus.c -index 6a28bdef..927a00aa 100644 ---- a/cpus.c -+++ b/cpus.c -@@ -1066,34 +1066,6 @@ void cpu_synchronize_all_pre_loadvm(void) - } - } - --#ifdef __aarch64__ --static bool kvm_adjvtime_enabled(CPUState *cs) --{ -- ARMCPU *cpu = ARM_CPU(cs); -- return cpu->kvm_adjvtime == true; --} -- --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, ®); -- 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; -@@ -1101,17 +1073,6 @@ static int do_vm_stop(RunState state, bool send_stop) - if (runstate_is_running()) { - cpu_disable_ticks(); - pause_all_vcpus(); --#ifdef __aarch64__ -- /* vtimer adjust is used in openEuler qemu-4.0.1, however kvm_adjvtime -- * is introduced in openEuler qemu-4.1.0. To maintain the compatibility -- * and enable cross version migration, let's enable vtimer adjust only -- * if kvm_adjvtime is not enabled, otherwise there may be conflicts -- * between vtimer adjust and kvm_adjvtime. -- */ -- if (first_cpu && !kvm_adjvtime_enabled(first_cpu)) { -- get_vcpu_timer_tick(first_cpu); -- } --#endif - runstate_set(state); - vm_state_notify(0, state); - if (send_stop) { -@@ -1957,46 +1918,11 @@ 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) { -- 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, ®); -- 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__ -- /* Enable vtimer adjust only if kvm_adjvtime is not enabled, otherwise -- * there may be conflicts between vtimer adjust and kvm_adjvtime. -- */ -- if (first_cpu && !kvm_adjvtime_enabled(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 aec6a214..86eb79cd 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -262,8 +262,6 @@ typedef struct CPUARMState { - 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 ec28b839..ee3c59a6 100644 ---- a/target/arm/machine.c -+++ b/target/arm/machine.c -@@ -814,7 +814,6 @@ 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.23.0 - diff --git a/vtimer-compat-cross-version-migration-from-v4.0.1.patch b/vtimer-compat-cross-version-migration-from-v4.0.1.patch deleted file mode 100644 index f452948fd29818c9551899e5044de1e3b33bc235..0000000000000000000000000000000000000000 --- a/vtimer-compat-cross-version-migration-from-v4.0.1.patch +++ /dev/null @@ -1,41 +0,0 @@ -From aec34c33730c36b34e4442548885463f57100e13 Mon Sep 17 00:00:00 2001 -From: Ying Fang -Date: Fri, 8 May 2020 11:25:28 +0800 -Subject: [PATCH] vtimer: compat cross version migration from v4.0.1 - -vtimer feature was added to qemu v4.0.1 to record timer tick when vcpu -is stopped. However this feature is discared and the new virtual time -adjustment is introduced. - -This patch add the missing vtimer parameter to ARMCPUState in order -to compat cross version migration fromm v4.0.1 openEuler 2003 lts release. - -Singed-off-by: Ying Fang - -diff --git a/target/arm/cpu.h b/target/arm/cpu.h -index 219c222b..2609113d 100644 ---- a/target/arm/cpu.h -+++ b/target/arm/cpu.h -@@ -261,6 +261,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 is stopped */ -+ - /* System control coprocessor (cp15) */ - struct { - uint32_t c0_cpuid; -diff --git a/target/arm/machine.c b/target/arm/machine.c -index ee3c59a6..ec28b839 100644 ---- a/target/arm/machine.c -+++ b/target/arm/machine.c -@@ -814,6 +814,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.23.0 diff --git a/x86-Intel-AVX512_BF16-feature-enabling.patch b/x86-Intel-AVX512_BF16-feature-enabling.patch deleted file mode 100644 index 175190f10c71a4670f32ab3d16a49fee127e1c29..0000000000000000000000000000000000000000 --- a/x86-Intel-AVX512_BF16-feature-enabling.patch +++ /dev/null @@ -1,179 +0,0 @@ -From e2fdc78f93d61be487c03a782aef6fdd8b26fa7e Mon Sep 17 00:00:00 2001 -From: Jing Liu -Date: Thu, 25 Jul 2019 14:14:16 +0800 -Subject: [PATCH] x86: Intel AVX512_BF16 feature enabling - -Intel CooperLake cpu adds AVX512_BF16 instruction, defining as -CPUID.(EAX=7,ECX=1):EAX[bit 05]. - -The patch adds a property for setting the subleaf of CPUID leaf 7 in -case that people would like to specify it. - -The release spec link as follows, -https://software.intel.com/sites/default/files/managed/c5/15/\ -architecture-instruction-set-extensions-programming-reference.pdf - -Signed-off-by: Jing Liu -Signed-off-by: Paolo Bonzini - -Signed-off-by: Jingyi Wang ---- - target/i386/cpu.c | 39 ++++++++++++++++++++++++++++++++++++++- - target/i386/cpu.h | 7 +++++++ - target/i386/kvm.c | 3 ++- - 3 files changed, 47 insertions(+), 2 deletions(-) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index 19751e37a7..1ade90c28b 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -770,6 +770,7 @@ static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, - /* CPUID_7_0_ECX_OSPKE is dynamic */ \ - CPUID_7_0_ECX_LA57) - #define TCG_7_0_EDX_FEATURES 0 -+#define TCG_7_1_EAX_FEATURES 0 - #define TCG_APM_FEATURES 0 - #define TCG_6_EAX_FEATURES CPUID_6_EAX_ARAT - #define TCG_XSAVE_FEATURES (CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XGETBV1) -@@ -1095,6 +1096,25 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { - }, - .tcg_features = TCG_7_0_EDX_FEATURES, - }, -+ [FEAT_7_1_EAX] = { -+ .type = CPUID_FEATURE_WORD, -+ .feat_names = { -+ NULL, NULL, NULL, NULL, -+ NULL, "avx512-bf16", NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, -+ }, -+ .cpuid = { -+ .eax = 7, -+ .needs_ecx = true, .ecx = 1, -+ .reg = R_EAX, -+ }, -+ .tcg_features = TCG_7_1_EAX_FEATURES, -+ }, - [FEAT_8000_0007_EDX] = { - .type = CPUID_FEATURE_WORD, - .feat_names = { -@@ -4292,13 +4312,19 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, - case 7: - /* Structured Extended Feature Flags Enumeration Leaf */ - if (count == 0) { -- *eax = 0; /* Maximum ECX value for sub-leaves */ -+ /* Maximum ECX value for sub-leaves */ -+ *eax = env->cpuid_level_func7; - *ebx = env->features[FEAT_7_0_EBX]; /* Feature flags */ - *ecx = env->features[FEAT_7_0_ECX]; /* Feature flags */ - if ((*ecx & CPUID_7_0_ECX_PKU) && env->cr[4] & CR4_PKE_MASK) { - *ecx |= CPUID_7_0_ECX_OSPKE; - } - *edx = env->features[FEAT_7_0_EDX]; /* Feature flags */ -+ } else if (count == 1) { -+ *eax = env->features[FEAT_7_1_EAX]; -+ *ebx = 0; -+ *ecx = 0; -+ *edx = 0; - } else { - *eax = 0; - *ebx = 0; -@@ -4948,6 +4974,11 @@ static void x86_cpu_adjust_feat_level(X86CPU *cpu, FeatureWord w) - x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel2, eax); - break; - } -+ -+ if (eax == 7) { -+ x86_cpu_adjust_level(cpu, &env->cpuid_min_level_func7, -+ fi->cpuid.ecx); -+ } - } - - /* Calculate XSAVE components based on the configured CPU feature flags */ -@@ -5066,6 +5097,7 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) - x86_cpu_adjust_feat_level(cpu, FEAT_1_ECX); - x86_cpu_adjust_feat_level(cpu, FEAT_6_EAX); - x86_cpu_adjust_feat_level(cpu, FEAT_7_0_ECX); -+ x86_cpu_adjust_feat_level(cpu, FEAT_7_1_EAX); - x86_cpu_adjust_feat_level(cpu, FEAT_8000_0001_EDX); - x86_cpu_adjust_feat_level(cpu, FEAT_8000_0001_ECX); - x86_cpu_adjust_feat_level(cpu, FEAT_8000_0007_EDX); -@@ -5097,6 +5129,9 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) - } - - /* Set cpuid_*level* based on cpuid_min_*level, if not explicitly set */ -+ if (env->cpuid_level_func7 == UINT32_MAX) { -+ env->cpuid_level_func7 = env->cpuid_min_level_func7; -+ } - if (env->cpuid_level == UINT32_MAX) { - env->cpuid_level = env->cpuid_min_level; - } -@@ -5868,6 +5903,8 @@ static Property x86_cpu_properties[] = { - DEFINE_PROP_BOOL("host-phys-bits", X86CPU, host_phys_bits, false), - DEFINE_PROP_UINT8("host-phys-bits-limit", X86CPU, host_phys_bits_limit, 0), - DEFINE_PROP_BOOL("fill-mtrr-mask", X86CPU, fill_mtrr_mask, true), -+ DEFINE_PROP_UINT32("level-func7", X86CPU, env.cpuid_level_func7, -+ UINT32_MAX), - DEFINE_PROP_UINT32("level", X86CPU, env.cpuid_level, UINT32_MAX), - DEFINE_PROP_UINT32("xlevel", X86CPU, env.cpuid_xlevel, UINT32_MAX), - DEFINE_PROP_UINT32("xlevel2", X86CPU, env.cpuid_xlevel2, UINT32_MAX), -diff --git a/target/i386/cpu.h b/target/i386/cpu.h -index 8b3dc5533e..488b4dc778 100644 ---- a/target/i386/cpu.h -+++ b/target/i386/cpu.h -@@ -479,6 +479,7 @@ typedef enum FeatureWord { - FEAT_7_0_EBX, /* CPUID[EAX=7,ECX=0].EBX */ - FEAT_7_0_ECX, /* CPUID[EAX=7,ECX=0].ECX */ - FEAT_7_0_EDX, /* CPUID[EAX=7,ECX=0].EDX */ -+ FEAT_7_1_EAX, /* CPUID[EAX=7,ECX=1].EAX */ - FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */ - FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */ - FEAT_8000_0007_EDX, /* CPUID[8000_0007].EDX */ -@@ -692,6 +693,8 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; - #define CPUID_7_0_EDX_CORE_CAPABILITY (1U << 30) /*Core Capability*/ - #define CPUID_7_0_EDX_SPEC_CTRL_SSBD (1U << 31) /* Speculative Store Bypass Disable */ - -+#define CPUID_7_1_EAX_AVX512_BF16 (1U << 5) /* AVX512 BFloat16 Instruction */ -+ - #define CPUID_8000_0008_EBX_WBNOINVD (1U << 9) /* Write back and - do not invalidate cache */ - #define CPUID_8000_0008_EBX_IBPB (1U << 12) /* Indirect Branch Prediction Barrier */ -@@ -1322,6 +1325,10 @@ typedef struct CPUX86State { - /* Fields after this point are preserved across CPU reset. */ - - /* processor features (e.g. for CPUID insn) */ -+ /* Minimum cpuid leaf 7 value */ -+ uint32_t cpuid_level_func7; -+ /* Actual cpuid leaf 7 value */ -+ uint32_t cpuid_min_level_func7; - /* Minimum level/xlevel/xlevel2, based on CPU model + features */ - uint32_t cpuid_min_level, cpuid_min_xlevel, cpuid_min_xlevel2; - /* Maximum level/xlevel/xlevel2 value for auto-assignment: */ -diff --git a/target/i386/kvm.c b/target/i386/kvm.c -index dbbb13772a..f55d4b4b97 100644 ---- a/target/i386/kvm.c -+++ b/target/i386/kvm.c -@@ -1497,6 +1497,7 @@ int kvm_arch_init_vcpu(CPUState *cs) - c = &cpuid_data.entries[cpuid_i++]; - } - break; -+ case 0x7: - case 0x14: { - uint32_t times; - -@@ -1509,7 +1510,7 @@ int kvm_arch_init_vcpu(CPUState *cs) - for (j = 1; j <= times; ++j) { - if (cpuid_i == KVM_MAX_CPUID_ENTRIES) { - fprintf(stderr, "cpuid_data is full, no space for " -- "cpuid(eax:0x14,ecx:0x%x)\n", j); -+ "cpuid(eax:0x%x,ecx:0x%x)\n", i, j); - abort(); - } - c = &cpuid_data.entries[cpuid_i++]; --- -2.27.0 - diff --git a/x86-do-not-advertise-die-id-in-query-hotpluggbale-cp.patch b/x86-do-not-advertise-die-id-in-query-hotpluggbale-cp.patch deleted file mode 100644 index fc17f48b7a395bafffaf7ef9763d04bff110af0a..0000000000000000000000000000000000000000 --- a/x86-do-not-advertise-die-id-in-query-hotpluggbale-cp.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 725dfa851f8e1de8653f41a4bd38c7f98757eb40 Mon Sep 17 00:00:00 2001 -From: Igor Mammedov -Date: Mon, 2 Sep 2019 08:02:22 -0400 -Subject: [PATCH] x86: do not advertise die-id in query-hotpluggbale-cpus if - '-smp dies' is not set - -Commit 176d2cda0 (i386/cpu: Consolidate die-id validity in smp context) added -new 'die-id' topology property to CPUs and exposed it via QMP command -query-hotpluggable-cpus, which broke -device/device_add cpu-foo for existing -users that do not support die-id/dies yet. That's would be fine if it happened -to new machine type only but it also happened to old machine types, -which breaks migration from old QEMU to the new one, for example following CLI: - - OLD-QEMU -M pc-i440fx-4.0 -smp 1,max_cpus=2 \ - -device qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id -is not able to start with new QEMU, complaining about invalid die-id. - -After discovering regression, the patch - "pc: Don't make die-id mandatory unless necessary" -makes die-id optional so old CLI would work. - -However it's not enough as new QEMU still exposes die-id via query-hotpluggbale-cpus -QMP command, so the users that started old machine type on new QEMU, using all -properties (including die-id) received from QMP command (as required), won't be -able to start old QEMU using the same properties since it doesn't support die-id. - -Fix it by hiding die-id in query-hotpluggbale-cpus for all machine types in case -'-smp dies' is not provided on CLI or -smp dies = 1', in which case smp_dies == 1 -and APIC ID is calculated in default way (as it was before DIE support) so we won't -need compat code as in both cases the topology provided to guest via CPUID is the same. - -Signed-off-by: Igor Mammedov -Message-Id: <20190902120222.6179-1-imammedo@redhat.com> -Reviewed-by: Eduardo Habkost -Signed-off-by: Eduardo Habkost -(cherry picked from commit c6c1bb89fb46f3b88f832e654cf5a6f7941aac51) -Signed-off-by: Michael Roth ---- - hw/i386/pc.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/hw/i386/pc.c b/hw/i386/pc.c -index 947f81070f..d011733ff7 100644 ---- a/hw/i386/pc.c -+++ b/hw/i386/pc.c -@@ -2887,8 +2887,10 @@ static const CPUArchIdList *pc_possible_cpu_arch_ids(MachineState *ms) - ms->smp.threads, &topo); - ms->possible_cpus->cpus[i].props.has_socket_id = true; - ms->possible_cpus->cpus[i].props.socket_id = topo.pkg_id; -- ms->possible_cpus->cpus[i].props.has_die_id = true; -- ms->possible_cpus->cpus[i].props.die_id = topo.die_id; -+ if (pcms->smp_dies > 1) { -+ ms->possible_cpus->cpus[i].props.has_die_id = true; -+ ms->possible_cpus->cpus[i].props.die_id = topo.die_id; -+ } - ms->possible_cpus->cpus[i].props.has_core_id = true; - ms->possible_cpus->cpus[i].props.core_id = topo.core_id; - ms->possible_cpus->cpus[i].props.has_thread_id = true; --- -2.23.0 diff --git a/xhci-Fix-memory-leak-in-xhci_address_slot.patch b/xhci-Fix-memory-leak-in-xhci_address_slot.patch deleted file mode 100644 index 1d0f858f3e6ea2975aff0a7e89a155083a9695b7..0000000000000000000000000000000000000000 --- a/xhci-Fix-memory-leak-in-xhci_address_slot.patch +++ /dev/null @@ -1,47 +0,0 @@ -From c0de0a04d03183f524c2f60cda8ae1e886197a7d Mon Sep 17 00:00:00 2001 -From: Ying Fang -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 -Signed-off-by: Ying Fang ---- - 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 - diff --git a/xhci-Fix-memory-leak-in-xhci_kick_epctx-when-poweroff.patch b/xhci-Fix-memory-leak-in-xhci_kick_epctx-when-poweroff.patch deleted file mode 100644 index 7d226e65cdc2e6e6e9c19e4791567246e1851787..0000000000000000000000000000000000000000 --- a/xhci-Fix-memory-leak-in-xhci_kick_epctx-when-poweroff.patch +++ /dev/null @@ -1,56 +0,0 @@ -From cf859d444770243fa184019fd4eab135b2653390 Mon Sep 17 00:00:00 2001 -From: Chen Qun -Date: Fri, 10 Jan 2020 18:36:24 +0800 -Subject: [PATCH] xhci: Fix memory leak in xhci_kick_epctx when poweroff - GuestOS -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -start vm with libvirt, when GuestOS running, enter poweroff command using -the xhci keyboard, then ASAN shows memory leak stack: - -Direct leak of 80 byte(s) in 5 object(s) allocated from: - #0 0xfffd1e6431cb in __interceptor_malloc (/lib64/libasan.so.4+0xd31cb) - #1 0xfffd1e107163 in g_malloc (/lib64/libglib-2.0.so.0+0x57163) - #2 0xaaad39051367 in qemu_sglist_init /qemu/dma-helpers.c:43 - #3 0xaaad3947c407 in pci_dma_sglist_init /qemu/include/hw/pci/pci.h:842 - #4 0xaaad3947c407 in xhci_xfer_create_sgl /qemu/hw/usb/hcd-xhci.c:1446 - #5 0xaaad3947c407 in xhci_setup_packet /qemu/hw/usb/hcd-xhci.c:1618 - #6 0xaaad3948625f in xhci_submit /qemu/hw/usb/hcd-xhci.c:1827 - #7 0xaaad3948625f in xhci_fire_transfer /qemu/hw/usb/hcd-xhci.c:1839 - #8 0xaaad3948625f in xhci_kick_epctx /qemu/hw/usb/hcd-xhci.c:1991 - #9 0xaaad3948f537 in xhci_doorbell_write /qemu/hw/usb/hcd-xhci.c:3158 - #10 0xaaad38bcbfc7 in memory_region_write_accessor /qemu/memory.c:483 - #11 0xaaad38bc654f in access_with_adjusted_size /qemu/memory.c:544 - #12 0xaaad38bd1877 in memory_region_dispatch_write /qemu/memory.c:1482 - #13 0xaaad38b1c77f in flatview_write_continue /qemu/exec.c:3167 - #14 0xaaad38b1ca83 in flatview_write /qemu/exec.c:3207 - #15 0xaaad38b268db in address_space_write /qemu/exec.c:3297 - #16 0xaaad38bf909b in kvm_cpu_exec /qemu/accel/kvm/kvm-all.c:2383 - #17 0xaaad38bb063f in qemu_kvm_cpu_thread_fn /qemu/cpus.c:1246 - #18 0xaaad39821c93 in qemu_thread_start /qemu/util/qemu-thread-posix.c:519 - #19 0xfffd1c8378bb (/lib64/libpthread.so.0+0x78bb) - #20 0xfffd1c77616b (/lib64/libc.so.6+0xd616b) - -Reported-by: Euler Robot -Signed-off-by: Chen Qun ---- - 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 80988bb305..0d3d96d05a 100644 ---- a/hw/usb/hcd-xhci.c -+++ b/hw/usb/hcd-xhci.c -@@ -2000,6 +2000,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) - if (xfer != NULL && xfer->running_retry) { - DPRINTF("xhci: xfer nacked, stopping schedule\n"); - epctx->retry = xfer; -+ xhci_xfer_unmap(xfer); - break; - } - if (count++ > TRANSFER_LIMIT) { --- -2.23.0 - diff --git a/xhci-Fix-memory-leak-in-xhci_kick_epctx.patch b/xhci-Fix-memory-leak-in-xhci_kick_epctx.patch deleted file mode 100644 index 398b1bcdd6e784cf1ecd87f41d0f1066d2780c6c..0000000000000000000000000000000000000000 --- a/xhci-Fix-memory-leak-in-xhci_kick_epctx.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 2212f37e0e477d8da0cff02cfc8b7a921ca11bef Mon Sep 17 00:00:00 2001 -From: fangying -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 ---- - 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 - diff --git a/xhci-check-reg-to-avoid-OOB-read.patch b/xhci-check-reg-to-avoid-OOB-read.patch new file mode 100644 index 0000000000000000000000000000000000000000..f6a4c356578e4f686ad8cb0dbbcdd24e6cd8b816 --- /dev/null +++ b/xhci-check-reg-to-avoid-OOB-read.patch @@ -0,0 +1,47 @@ +From a95ada20170af0a71529c1583846e402cdbb850b Mon Sep 17 00:00:00 2001 +From: Yan Wang +Date: Thu, 10 Feb 2022 10:41:40 +0800 +Subject: [PATCH] xhci: check reg to avoid OOB read + +Add a sanity check to fix OOB read access. + +Signed-off-by: Yan Wang +--- + hw/usb/hcd-xhci.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index e01700039b..08cd63e159 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -27,6 +27,7 @@ + #include "hw/qdev-properties.h" + #include "trace.h" + #include "qapi/error.h" ++#include "qemu/log.h" + + #include "hcd-xhci.h" + +@@ -3017,14 +3018,17 @@ static void xhci_runtime_write(void *ptr, hwaddr reg, + XHCIInterrupter *intr; + int v; + +- trace_usb_xhci_runtime_write(reg, val); +- + if (reg < 0x20) { + trace_usb_xhci_unimplemented("runtime write", reg); + return; + } + v = (reg - 0x20) / 0x20; ++ if (v >= xhci->numintrs) { ++ qemu_log("intr nr out of range (%d >= %d)\n", v, xhci->numintrs); ++ return; ++ } + intr = &xhci->intr[v]; ++ trace_usb_xhci_runtime_write(reg, val); + + switch (reg & 0x1f) { + case 0x00: /* IMAN */ +-- +2.27.0 + diff --git a/xhci-fix-valid.max_access_size-to-access-address-reg.patch b/xhci-fix-valid.max_access_size-to-access-address-reg.patch deleted file mode 100644 index 466cbf2667efaf26cc65c160c8223659abb0c288..0000000000000000000000000000000000000000 --- a/xhci-fix-valid.max_access_size-to-access-address-reg.patch +++ /dev/null @@ -1,62 +0,0 @@ -From a71d1847aa780b3c4062e582ab400a7fea0413b3 Mon Sep 17 00:00:00 2001 -From: Laurent Vivier -Date: Tue, 21 Jul 2020 10:33:22 +0200 -Subject: [PATCH 01/11] xhci: fix valid.max_access_size to access address - registers -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -QEMU XHCI advertises AC64 (64-bit addressing) but doesn't allow -64-bit mode access in "runtime" and "operational" MemoryRegionOps. - -Set the max_access_size based on sizeof(dma_addr_t) as AC64 is set. - -XHCI specs: -"If the xHC supports 64-bit addressing (AC64 = ‘1’), then software -should write 64-bit registers using only Qword accesses. If a -system is incapable of issuing Qword accesses, then writes to the -64-bit address fields shall be performed using 2 Dword accesses; -low Dword-first, high-Dword second. If the xHC supports 32-bit -addressing (AC64 = ‘0’), then the high Dword of registers containing -64-bit address fields are unused and software should write addresses -using only Dword accesses" - -The problem has been detected with SLOF, as linux kernel always accesses -registers using 32-bit access even if AC64 is set and revealed by -5d971f9e6725 ("memory: Revert "memory: accept mismatching sizes in memory_region_access_valid"") - -Suggested-by: Alexey Kardashevskiy -Signed-off-by: Laurent Vivier -Message-id: 20200721083322.90651-1-lvivier@redhat.com -Signed-off-by: Gerd Hoffmann -Signed-off-by: BiaoXiang Ye ---- - hw/usb/hcd-xhci.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c -index a21485fe..24565de1 100644 ---- a/hw/usb/hcd-xhci.c -+++ b/hw/usb/hcd-xhci.c -@@ -3171,7 +3171,7 @@ static const MemoryRegionOps xhci_oper_ops = { - .read = xhci_oper_read, - .write = xhci_oper_write, - .valid.min_access_size = 4, -- .valid.max_access_size = 4, -+ .valid.max_access_size = sizeof(dma_addr_t), - .endianness = DEVICE_LITTLE_ENDIAN, - }; - -@@ -3187,7 +3187,7 @@ static const MemoryRegionOps xhci_runtime_ops = { - .read = xhci_runtime_read, - .write = xhci_runtime_write, - .valid.min_access_size = 4, -- .valid.max_access_size = 4, -+ .valid.max_access_size = sizeof(dma_addr_t), - .endianness = DEVICE_LITTLE_ENDIAN, - }; - --- -2.27.0.dirty - diff --git a/xhci-recheck-slot-status.patch b/xhci-recheck-slot-status.patch deleted file mode 100644 index d05c3c8344802c788827334b2f48693ec4b72edb..0000000000000000000000000000000000000000 --- a/xhci-recheck-slot-status.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 33d6a2bc0e432a85962b71bcb2c3b5eec39bf436 Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann -Date: Tue, 7 Jan 2020 09:36:06 +0100 -Subject: [PATCH] xhci: recheck slot status -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Factor out slot status check into a helper function. Add an additional -check after completing transfers. This is needed in case a guest -queues multiple transfers in a row and a device unplug happens while -qemu processes them. - -Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1786413 -Signed-off-by: Gerd Hoffmann -Reviewed-by: Philippe Mathieu-Daudé -Message-id: 20200107083606.12393-1-kraxel@redhat.com ---- - hw/usb/hcd-xhci.c | 15 ++++++++++++--- - 1 file changed, 12 insertions(+), 3 deletions(-) - -diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c -index 24565de1d1..4b42f53b9c 100644 ---- a/hw/usb/hcd-xhci.c -+++ b/hw/usb/hcd-xhci.c -@@ -1860,6 +1860,13 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, - xhci_kick_epctx(epctx, streamid); - } - -+static bool xhci_slot_ok(XHCIState *xhci, int slotid) -+{ -+ return (xhci->slots[slotid - 1].uport && -+ xhci->slots[slotid - 1].uport->dev && -+ xhci->slots[slotid - 1].uport->dev->attached); -+} -+ - static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) - { - XHCIState *xhci = epctx->xhci; -@@ -1877,9 +1884,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) - - /* If the device has been detached, but the guest has not noticed this - yet the 2 above checks will succeed, but we must NOT continue */ -- if (!xhci->slots[epctx->slotid - 1].uport || -- !xhci->slots[epctx->slotid - 1].uport->dev || -- !xhci->slots[epctx->slotid - 1].uport->dev->attached) { -+ if (!xhci_slot_ok(xhci, epctx->slotid)) { - return; - } - -@@ -1986,6 +1991,10 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) - } else { - xhci_fire_transfer(xhci, xfer, epctx); - } -+ if (!xhci_slot_ok(xhci, epctx->slotid)) { -+ /* surprise removal -> stop processing */ -+ break; -+ } - if (xfer->complete) { - /* update ring dequeue ptr */ - xhci_set_ep_state(xhci, epctx, stctx, epctx->state); --- -2.27.0 - diff --git a/xics-Don-t-deassert-outputs.patch b/xics-Don-t-deassert-outputs.patch deleted file mode 100644 index 083a9a2e885cd2b4c2d8fe701c2ad037b5bece00..0000000000000000000000000000000000000000 --- a/xics-Don-t-deassert-outputs.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 5b137b37ef7c4941200798cca99200e80ef17a01 Mon Sep 17 00:00:00 2001 -From: Greg Kurz -Date: Wed, 4 Dec 2019 20:43:43 +0100 -Subject: [PATCH] xics: Don't deassert outputs - -The correct way to do this is to deassert the input pins on the CPU side. -This is the case since a previous change. - -Signed-off-by: Greg Kurz -Message-Id: <157548862298.3650476.1228720391270249433.stgit@bahia.lan> -Signed-off-by: David Gibson ---- - hw/intc/xics.c | 3 --- - 1 file changed, 3 deletions(-) - -diff --git a/hw/intc/xics.c b/hw/intc/xics.c -index faa976e2f8..d2d377fc85 100644 ---- a/hw/intc/xics.c -+++ b/hw/intc/xics.c -@@ -303,9 +303,6 @@ static void icp_reset_handler(void *dev) - icp->pending_priority = 0xff; - icp->mfrr = 0xff; - -- /* Make all outputs are deasserted */ -- qemu_set_irq(icp->output, 0); -- - if (kvm_irqchip_in_kernel()) { - Error *local_err = NULL; - --- -2.27.0 -