Re: [PATCH RFC V2 03/37] hw/arm/virt: Move setting of common CPU properties in a function
On 9/26/23 18:04, Salil Mehta via wrote: Factor out CPU properties code common for {hot,cold}-plugged CPUs. This allows code reuse. Signed-off-by: Salil Mehta --- hw/arm/virt.c | 220 ++ include/hw/arm/virt.h | 4 + 2 files changed, 140 insertions(+), 84 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 57fe97c242..0eb6bf5a18 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2018,16 +2018,130 @@ static void virt_cpu_post_init(VirtMachineState *vms, MemoryRegion *sysmem) } } +static void virt_cpu_set_properties(Object *cpuobj, const CPUArchId *cpu_slot, +Error **errp) +{ Hi Salil, This patch seems break the code, the virt_cpu_set_properties() function being defined but not used in this patch, so those original code in the machvirt_init() just not work. We should use this function in the machvirt_init(). +MachineState *ms = MACHINE(qdev_get_machine()); +VirtMachineState *vms = VIRT_MACHINE(ms); +Error *local_err = NULL; +VirtMachineClass *vmc; + +vmc = VIRT_MACHINE_GET_CLASS(ms); + +/* now, set the cpu object property values */ +numa_cpu_pre_plug(cpu_slot, DEVICE(cpuobj), &local_err); +if (local_err) { +goto out; +} + +object_property_set_int(cpuobj, "mp-affinity", cpu_slot->arch_id, NULL); + +if (!vms->secure) { +object_property_set_bool(cpuobj, "has_el3", false, NULL); +} + +if (!vms->virt && object_property_find(cpuobj, "has_el2")) { +object_property_set_bool(cpuobj, "has_el2", false, NULL); +} + +if (vmc->kvm_no_adjvtime && +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")) { +object_property_set_bool(cpuobj, "pmu", false, NULL); +} + +if (vmc->no_tcg_lpa2 && object_property_find(cpuobj, "lpa2")) { +object_property_set_bool(cpuobj, "lpa2", false, NULL); +} + +if (object_property_find(cpuobj, "reset-cbar")) { +object_property_set_int(cpuobj, "reset-cbar", +vms->memmap[VIRT_CPUPERIPHS].base, +&local_err); +if (local_err) { +goto out; +} +} + +/* link already initialized {secure,tag}-memory regions to this cpu */ +object_property_set_link(cpuobj, "memory", OBJECT(vms->sysmem), &local_err); +if (local_err) { +goto out; +} + +if (vms->secure) { +object_property_set_link(cpuobj, "secure-memory", + OBJECT(vms->secure_sysmem), &local_err); +if (local_err) { +goto out; +} +} + +if (vms->mte) { +if (!object_property_find(cpuobj, "tag-memory")) { +error_setg(&local_err, "MTE requested, but not supported " + "by the guest CPU"); +if (local_err) { +goto out; +} +} + +object_property_set_link(cpuobj, "tag-memory", OBJECT(vms->tag_sysmem), + &local_err); +if (local_err) { +goto out; +} + +if (vms->secure) { +object_property_set_link(cpuobj, "secure-tag-memory", + OBJECT(vms->secure_tag_sysmem), + &local_err); +if (local_err) { +goto out; +} +} +} + +/* + * RFC: Question: this must only be called for the hotplugged cpus. For the + * cold booted secondary cpus this is being taken care in arm_load_kernel() + * in boot.c. Perhaps we should remove that code now? + */ +if (vms->psci_conduit != QEMU_PSCI_CONDUIT_DISABLED) { +object_property_set_int(cpuobj, "psci-conduit", vms->psci_conduit, +NULL); + +/* Secondary CPUs start in PSCI powered-down state */ +if (CPU(cpuobj)->cpu_index > 0) { +object_property_set_bool(cpuobj, "start-powered-off", true, NULL); +} +} Besides, if this patch is just factor out the code, we could move the check psci_conduit to later patch, and keep this patch clean. Thanks, Shaoqin + +out: +if (local_err) { +error_propagate(errp, local_err); +} +return; +} + static void machvirt_init(MachineState *machine) { VirtMachineState *vms = VIRT_MACHINE(machine); VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(machine); MachineClass *mc = MACHINE_GET_CLASS(machine); const CPUArchIdList *possible_cpus; -MemoryRegion *sysmem = get_system_memory(); +MemoryRegion *secure_tag_sysmem
[PATCH] virtio-serial-bus: Discard throttled VirtQueueElement when virtio-serial closed
With commit d4c19cde("virtio-serial: add missing virtio_detach_element() call"), when virtio serial is throttled and closed by host, port->elem should be discard with virtqueue_push, otherwise virtqueue will not rewind, guest will blocked finally and cannot write anymore data. It can be reproduced with following steps: Create a vm with virtio-serial device through libvirt: Host run: watch -n0.5 'timeout 0.5 nc -U /tmp/test' Guest run: hexdump -C -v /dev/zero > /dev/vport1p1 After sometime, guest can not write any data to serial. We can see vq->last_avail_idx - vq->used_idx = 128 with gdb. (gdb) p *(struct VirtQueue *) 0x565161c5c788 $4 = {vring = {num = 128, num_default = 128, align = 4096, desc = 4316049408, avail = 4316051456, used = 4316051776, caches = 0x7fc530067e60}, used_elems = 0x565161c88dc0, last_avail_idx = 7929, last_avail_wrap_counter = true, shadow_avail_idx = 7929, shadow_avail_wrap_counter = true, used_idx = 7801, used_wrap_counter = true, signalled_used = 7801, signalled_used_valid = true, notification = true, queue_index = 5, inuse = 0, vector = 1, handle_output = 0x56515da8aea0 , handle_aio_output = 0x0, vdev = 0x565161c54e30, guest_notifier = {rfd = 0, wfd = 0}, host_notifier = {rfd = 74, wfd = 74}, host_notifier_enabled = true, node = {le_next = 0x565161c5c6f0, le_prev = 0x565161c5c8a8}} Fixes: d4c19cde("virtio-serial: add missing virtio_detach_element() call") Signed-off-by: Sun Feng --- 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 dd619f0..30b00a4 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -151,7 +151,7 @@ static void discard_vq_data(VirtQueue *vq, VirtIODevice *vdev) static void discard_throttle_data(VirtIOSerialPort *port) { if (port->elem) { -virtqueue_detach_element(port->ovq, port->elem, 0); +virtqueue_push(port->ovq, port->elem, 0); g_free(port->elem); port->elem = NULL; } -- 2.7.4
[PATCH] targer/i386/cpu: Fix CPUID_HT exposure
When explicitly booting a multiple vcpus vm with "-cpu +ht", it gets warning of warning: host doesn't support requested feature: CPUID.01H:EDX.ht [bit 28] Make CPUID_HT as supported unconditionally can resolve the warning. However it introduces another issue that it also expose CPUID_HT to guest when "-cpu host/max" with only 1 vcpu. To fix this, need mark CPUID_HT as the no_autoenable_flags. Signed-off-by: Xiaoyao Li --- target/i386/cpu.c | 1 + target/i386/kvm/kvm.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index cec5d2b7b65e..32c077455f04 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -778,6 +778,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { }, .cpuid = {.eax = 1, .reg = R_EDX, }, .tcg_features = TCG_FEATURES, +.no_autoenable_flags = CPUID_HT, }, [FEAT_1_ECX] = { .type = CPUID_FEATURE_WORD, diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index f6c7f7e26869..ab72bcdfad13 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -373,6 +373,8 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, if (function == 1 && reg == R_EDX) { /* KVM before 2.6.30 misreports the following features */ ret |= CPUID_MTRR | CPUID_PAT | CPUID_MCE | CPUID_MCA; +/* KVM never reports CPUID_HT but QEMU can support when vcpus > 1 */ +ret |= CPUID_HT; } else if (function == 1 && reg == R_ECX) { /* We can set the hypervisor flag, even if KVM does not return it on * GET_SUPPORTED_CPUID base-commit: cea3ea670fe265421131aad90c36fbb87bc4d206 -- 2.34.1
Re: [PATCH v2 3/3] target/hexagon: avoid shadowing globals
Philippe Mathieu-Daudé writes: [...] > If we have to clean that for -Wshadow=global, I'm tempted to rename > the typedef as 'vaddr_t' and keep the 'vaddr' variable names. POSIX reserves suffix _t, see https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_02_02 Do we care? > Richard, Anton, what do you think? [...]
Re: [PATCH v12 00/10] migration: Modify 'migrate' and 'migrate-incoming' QAPI commands for migration
On 10/10/2023 2:34 AM, Fabiano Rosas wrote: Het Gala writes: This is v12 patchset of modified 'migrate' and 'migrate-incoming' QAPI design for upstream review. Would like to thank all the maintainers that actively participated in the v11 patchset discussion and gave insightful suggestions to improve the patches. Link to previous upstream community patchset links: v1:https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.gnu.org_archive_html_qemu-2Ddevel_2022-2D12_msg04339.html&d=DwIFaQ&c=s883GpUCOChKOHiocYtGcg&r=-qwZZzrw4EKSsq0BK7MBd3wW1WEpXmJeng3ZUT5uBCg&m=s4FkORPOMqBTxCrkaYO6frUTsbcGM6c3K4FCdGaNAKeCIZ2GS9VaQxJGytQv0mGv&s=OXhp-cq93AZ1ZRIwKL5wXhx5-8ei7RfBdmmbU9KNDfg&e= v2:https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.gnu.org_archive_html_qemu-2Ddevel_2023-2D02_msg02106.html&d=DwIFaQ&c=s883GpUCOChKOHiocYtGcg&r=-qwZZzrw4EKSsq0BK7MBd3wW1WEpXmJeng3ZUT5uBCg&m=s4FkORPOMqBTxCrkaYO6frUTsbcGM6c3K4FCdGaNAKeCIZ2GS9VaQxJGytQv0mGv&s=r7SYaB2fxLcEP2DiHslsbEyaY7ZPrXxageSBRtRZ7TA&e= v3:https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.gnu.org_archive_html_qemu-2Ddevel_2023-2D02_msg02473.html&d=DwIFaQ&c=s883GpUCOChKOHiocYtGcg&r=-qwZZzrw4EKSsq0BK7MBd3wW1WEpXmJeng3ZUT5uBCg&m=s4FkORPOMqBTxCrkaYO6frUTsbcGM6c3K4FCdGaNAKeCIZ2GS9VaQxJGytQv0mGv&s=fnGhJw56ypUavnslnUL6JeK4OLi7xwh7TGsafaSSZvw&e= v4:https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.gnu.org_archive_html_qemu-2Ddevel_2023-2D05_msg03064.html&d=DwIFaQ&c=s883GpUCOChKOHiocYtGcg&r=-qwZZzrw4EKSsq0BK7MBd3wW1WEpXmJeng3ZUT5uBCg&m=s4FkORPOMqBTxCrkaYO6frUTsbcGM6c3K4FCdGaNAKeCIZ2GS9VaQxJGytQv0mGv&s=SA4q18GEE4q3Eh7sy5nhQ8OZO5KM8kfapiBkSPZYDxE&e= v5:https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.gnu.org_archive_html_qemu-2Ddevel_2023-2D05_msg04845.html&d=DwIFaQ&c=s883GpUCOChKOHiocYtGcg&r=-qwZZzrw4EKSsq0BK7MBd3wW1WEpXmJeng3ZUT5uBCg&m=s4FkORPOMqBTxCrkaYO6frUTsbcGM6c3K4FCdGaNAKeCIZ2GS9VaQxJGytQv0mGv&s=QRW_aAGHmTBajBnu1a4jcxQFZ1lf1N3RCyLgOt82Ji4&e= v6:https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.gnu.org_archive_html_qemu-2Ddevel_2023-2D06_msg01251.html&d=DwIFaQ&c=s883GpUCOChKOHiocYtGcg&r=-qwZZzrw4EKSsq0BK7MBd3wW1WEpXmJeng3ZUT5uBCg&m=s4FkORPOMqBTxCrkaYO6frUTsbcGM6c3K4FCdGaNAKeCIZ2GS9VaQxJGytQv0mGv&s=7Dmgm47UdQ0h0Y9-XffsUW_ZdeQ-eCCVzhUkigTMKbc&e= v7:https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.gnu.org_archive_html_qemu-2Ddevel_2023-2D07_msg02027.html&d=DwIFaQ&c=s883GpUCOChKOHiocYtGcg&r=-qwZZzrw4EKSsq0BK7MBd3wW1WEpXmJeng3ZUT5uBCg&m=s4FkORPOMqBTxCrkaYO6frUTsbcGM6c3K4FCdGaNAKeCIZ2GS9VaQxJGytQv0mGv&s=8a3tAfIJ-6st1tlYkbjsRWEv-JvEFxokXzanf0WCqzw&e= v8:https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.gnu.org_archive_html_qemu-2Ddevel_2023-2D07_msg02770.html&d=DwIFaQ&c=s883GpUCOChKOHiocYtGcg&r=-qwZZzrw4EKSsq0BK7MBd3wW1WEpXmJeng3ZUT5uBCg&m=s4FkORPOMqBTxCrkaYO6frUTsbcGM6c3K4FCdGaNAKeCIZ2GS9VaQxJGytQv0mGv&s=4q_F05ZPdhWsPJ0fa850gHS90AsVX7MbsaIHi-3OsMI&e= v9:https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.gnu.org_archive_html_qemu-2Ddevel_2023-2D07_msg04216.html&d=DwIFaQ&c=s883GpUCOChKOHiocYtGcg&r=-qwZZzrw4EKSsq0BK7MBd3wW1WEpXmJeng3ZUT5uBCg&m=s4FkORPOMqBTxCrkaYO6frUTsbcGM6c3K4FCdGaNAKeCIZ2GS9VaQxJGytQv0mGv&s=1wNhJSfSvAoadG06F2JKFHZ2mA4QWSgqvYpt1zRX9qw&e= v10:https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.gnu.org_archive_html_qemu-2Ddevel_2023-2D07_msg05022.html&d=DwIFaQ&c=s883GpUCOChKOHiocYtGcg&r=-qwZZzrw4EKSsq0BK7MBd3wW1WEpXmJeng3ZUT5uBCg&m=s4FkORPOMqBTxCrkaYO6frUTsbcGM6c3K4FCdGaNAKeCIZ2GS9VaQxJGytQv0mGv&s=guEm3FuFn7jutT4ZB4RlgwttD4IMSBJy1MNh2zp3tYY&e= v11:https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.gnu.org_archive_html_qemu-2Ddevel_2023-2D10_msg00740.html&d=DwIFaQ&c=s883GpUCOChKOHiocYtGcg&r=-qwZZzrw4EKSsq0BK7MBd3wW1WEpXmJeng3ZUT5uBCg&m=s4FkORPOMqBTxCrkaYO6frUTsbcGM6c3K4FCdGaNAKeCIZ2GS9VaQxJGytQv0mGv&s=W7rbQhebtuWtT2ydMuG21OOkbqlh9KxMi1ZM5yZP6Ig&e= v11 -> v12 changelog: --- - Resolved double-freeing when using g_autoptr in structures that are nested into another. - Overwriting of pointers to an existing allocated memory is solved at various places. - Use of g_autoptr caused make check errors in non-error path while going out of scope inside function. Added g_steal_pointer() in the non-error paths wherever required. Please run make check before sending: ▶ 242/355 qcow2 181 FAIL You can also push your code to your gitlab and run a pipeline with the branch. I tested on my setup, and it passed all the checks. [root@06f1b38a5d6a build]# make check /rpmbuild/SOURCES/qemu/build/pyvenv/bin/meson test --no-rebuild -t 0 --num-processes 1 --print-errorlogs 1/348 qemu:qtest+qtest-x86_64 / qtest-x86_64/qom-test OK 14.00s 8 subtests passed 2/348 qemu:qtest+qtest-x86_64 / qtest-x86_64/migration-test OK 82.28s 13 subtests passed 3/348 qemu:qtest+qtest-x86_64 / qtest-x86_64/bios-tables-test OK 79.38s 51 subtests passed 4/348 qemu:qtest+qtest-x86_64 / qtest-x8
Re: [PATCH v2 08/58] i386/tdx: Adjust the supported CPUID based on TDX restrictions
On 10/10/2023 9:02 AM, Tina Zhang wrote: Hi, On 8/18/23 17:49, Xiaoyao Li wrote: According to Chapter "CPUID Virtualization" in TDX module spec, CPUID bits of TD can be classified into 6 types: 1 | As configured | configurable by VMM, independent of native value; 2 | As configured | configurable by VMM if the bit is supported natively (if native) | Otherwise it equals as native(0). 3 | Fixed | fixed to 0/1 4 | Native | reflect the native value 5 | Calculated | calculated by TDX module. 6 | Inducing #VE | get #VE exception Note: 1. All the configurable XFAM related features and TD attributes related features fall into type #2. And fixed0/1 bits of XFAM and TD attributes fall into type #3. 2. For CPUID leaves not listed in "CPUID virtualization Overview" table in TDX module spec, TDX module injects #VE to TDs when those are queried. For this case, TDs can request CPUID emulation from VMM via TDVMCALL and the values are fully controlled by VMM. Due to TDX module has its own virtualization policy on CPUID bits, it leads to what reported via KVM_GET_SUPPORTED_CPUID diverges from the supported CPUID bits for TDs. In order to keep a consistent CPUID configuration between VMM and TDs. Adjust supported CPUID for TDs based on TDX restrictions. Currently only focus on the CPUID leaves recognized by QEMU's feature_word_info[] that are indexed by a FeatureWord. Introduce a TDX CPUID lookup table, which maintains 1 entry for each FeatureWord. Each entry has below fields: - tdx_fixed0/1: The bits that are fixed as 0/1; - vmm_fixup: The bits that are configurable from the view of TDX module. But they requires emulation of VMM when they are configured as enabled. For those, they are not supported if VMM doesn't report them as supported. So they need be fixed up by checking if VMM supports them. - inducing_ve: TD gets #VE when querying this CPUID leaf. The result is totally configurable by VMM. - supported_on_ve: It's valid only when @inducing_ve is true. It represents the maximum feature set supported that be emulated for TDs. By applying TDX CPUID lookup table and TDX capabilities reported from TDX module, the supported CPUID for TDs can be obtained from following steps: - get the base of VMM supported feature set; - if the leaf is not a FeatureWord just return VMM's value without modification; - if the leaf is an inducing_ve type, applying supported_on_ve mask and return; - include all native bits, it covers type #2, #4, and parts of type #1. (it also includes some unsupported bits. The following step will correct it.) - apply fixed0/1 to it (it covers #3, and rectifies the previous step); - add configurable bits (it covers the other part of type #1); - fix the ones in vmm_fixup; - filter the one has valid .supported field; (Calculated type is ignored since it's determined at runtime). Co-developed-by: Chenyi Qiang Signed-off-by: Chenyi Qiang Signed-off-by: Xiaoyao Li --- target/i386/cpu.h | 16 +++ target/i386/kvm/kvm.c | 4 + target/i386/kvm/tdx.c | 254 ++ target/i386/kvm/tdx.h | 2 + 4 files changed, 276 insertions(+) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index e0771a10433b..c93dcd274531 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -780,6 +780,8 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, /* Support RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE */ #define CPUID_7_0_EBX_FSGSBASE (1U << 0) +/* Support for TSC adjustment MSR 0x3B */ +#define CPUID_7_0_EBX_TSC_ADJUST (1U << 1) /* Support SGX */ #define CPUID_7_0_EBX_SGX (1U << 2) /* 1st Group of Advanced Bit Manipulation Extensions */ @@ -798,8 +800,12 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, #define CPUID_7_0_EBX_INVPCID (1U << 10) /* Restricted Transactional Memory */ #define CPUID_7_0_EBX_RTM (1U << 11) +/* Cache QoS Monitoring */ +#define CPUID_7_0_EBX_PQM (1U << 12) /* Memory Protection Extension */ #define CPUID_7_0_EBX_MPX (1U << 14) +/* Resource Director Technology Allocation */ +#define CPUID_7_0_EBX_RDT_A (1U << 15) /* AVX-512 Foundation */ #define CPUID_7_0_EBX_AVX512F (1U << 16) /* AVX-512 Doubleword & Quadword Instruction */ @@ -8
Re: [PATCH v2 3/3] target/hexagon: avoid shadowing globals
On 9/10/23 22:53, Brian Cain wrote: On 9/10/23 08:09, Philippe Mathieu-Daudé wrote: On 6/10/23 00:22, Brian Cain wrote: The typedef `vaddr` is shadowed by `vaddr` identifiers, so we rename the identifiers to avoid shadowing the type name. This one surprises me, since we have other occurences: include/exec/memory.h:751:bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr, include/qemu/plugin.h:199:void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr, target/arm/internals.h:643:G_NORETURN void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, target/i386/tcg/helper-tcg.h:70:G_NORETURN void handle_unaligned_access(CPUX86State *env, vaddr vaddr, ... $ git grep -w vaddr, | wc -l 207 What is the error/warning like? OK I could reproduce, I suppose you are building with Clang which doesn't support shadow-local so you get global warnings too (as mentioned in this patch subject...): No -- I generally build with gcc and only double-check the clang results to make sure I don't see any new failures there. But I've not tested "-Wshadow" with clang yet. I found these by adding "-Wshadow=global" to "-Wshadow=local". I thought it might be useful to address these too while we're here. In file included from ../../gdbstub/trace.h:1, from ../../gdbstub/softmmu.c:30: trace/trace-gdbstub.h: In function '_nocheck__trace_gdbstub_hit_watchpoint': trace/trace-gdbstub.h:903:106: error: declaration of 'vaddr' shadows a global declaration [-Werror=shadow] 903 | static inline void _nocheck__trace_gdbstub_hit_watchpoint(const char * type, int cpu_gdb_index, uint64_t vaddr) | ~^ In file included from include/sysemu/accel-ops.h:13, from include/sysemu/cpus.h:4, from ../../gdbstub/softmmu.c:21: include/exec/cpu-common.h:21:18: note: shadowed declaration is here 21 | typedef uint64_t vaddr; | ^ trace/trace-gdbstub.h: In function 'trace_gdbstub_hit_watchpoint': trace/trace-gdbstub.h:923:96: error: declaration of 'vaddr' shadows a global declaration [-Werror=shadow] 923 | static inline void trace_gdbstub_hit_watchpoint(const char * type, int cpu_gdb_index, uint64_t vaddr) | ~^ include/exec/cpu-common.h:21:18: note: shadowed declaration is here 21 | typedef uint64_t vaddr; | ^ If we have to clean that for -Wshadow=global, I'm tempted to rename the typedef as 'vaddr_t' and keep the 'vaddr' variable names. Richard, Anton, what do you think? Clang users got confused by this, IIUC Markus and Thomas idea is to only enable these warnings for GCC, enforcing them for Clang users via CI (until Clang get this option supported). Personally I'd rather enable the warning once for all, waiting for Clang support (or clean/enable global shadowing for GCC too). Hopefully it's helpful or at least benign if we address the shadowed globals under target/hexagon/ for now, even if "-Wshadow=global" is not enabled. See this thread: https://lore.kernel.org/qemu-devel/11abc551-188e-85c0-fe55- b2b58d351...@redhat.com/ Regards, Phil.
Re: [PATCH v11 09/10] migration: Implement MigrateChannelList to hmp migration flow.
On 10/9/2023 8:05 PM, Fabiano Rosas wrote: Het Gala writes: On 10/4/2023 8:55 PM, Fabiano Rosas wrote: Het Gala writes: Integrate MigrateChannelList with all transport backends (socket, exec and rdma) for both src and dest migration endpoints for hmp migration. Suggested-by: Aravind Retnakaran Signed-off-by: Het Gala Reviewed-by: Daniel P. Berrangé --- migration/migration-hmp-cmds.c | 15 +-- migration/migration.c | 5 ++--- migration/migration.h | 3 ++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c index a2e6a5c51e..a1657f3d37 100644 --- a/migration/migration-hmp-cmds.c +++ b/migration/migration-hmp-cmds.c @@ -441,9 +441,14 @@ void hmp_migrate_incoming(Monitor *mon, const QDict *qdict) { Error *err = NULL; const char *uri = qdict_get_str(qdict, "uri"); +MigrationChannelList *caps = NULL; +g_autoptr(MigrationChannel) channel = g_new0(MigrationChannel, 1); Just the pointer here. If I remember correctly the g_autoptr here would cause a double free when freeing the caps. Yes, we'll just have 'g_autoptr(MigrationChannel) channel = NULL'. Is it because inside QAPI_LIST_PREPEND, caps will be refrencing to the same memory as 'channel', we don't need to free channel ? Slightly different scenario here. Here the issue is that we will free the caps with qapi_free_MigrationChannel() before returning. Then, at function exit the g_autoptr will try to free 'channel', which has already been freed along with 'caps'. That's a double free, I think it hits an assert inside glib, if I remember correctly. I am still not sure what is the right place to use g_steal_pointer(), is this a right place to use (non-error paths) ? It doesn't look like we need it here. As long as the qapi list has a reference and we're freeing the caps, then channel should be freed by that function already. Ack. Yes, with the discussion in earlier patches, I also don't think we need g_autoptr too here. Normal pointer is enough as we are freeing the memory after the function is returned. -qmp_migrate_incoming(uri, false, NULL, &err); +migrate_uri_parse(uri, &channel, &err); +QAPI_LIST_PREPEND(caps, channel); +qmp_migrate_incoming(NULL, true, caps, &err); +qapi_free_MigrationChannelList(caps); hmp_handle_error(mon, err); } @@ -730,9 +735,15 @@ void hmp_migrate(Monitor *mon, const QDict *qdict) bool resume = qdict_get_try_bool(qdict, "resume", false); const char *uri = qdict_get_str(qdict, "uri"); Error *err = NULL; +MigrationChannelList *caps = NULL; +g_autoptr(MigrationChannel) channel = g_new0(MigrationChannel, 1); Same here. We free the channel via caps and we attribute it below, no need to allocate. Ack. -qmp_migrate(uri, false, NULL, !!blk, blk, !!inc, inc, +migrate_uri_parse(uri, &channel, &err); +QAPI_LIST_PREPEND(caps, channel); + +qmp_migrate(NULL, true, caps, !!blk, blk, !!inc, inc, false, false, true, resume, &err); +qapi_free_MigrationChannelList(caps); if (hmp_handle_error(mon, err)) { Regards, Het Gala Regards, Het Gala
Re: [PATCH v11 08/10] migration: Implement MigrateChannelList to qmp migration flow.
On 10/9/2023 7:59 PM, Fabiano Rosas wrote: Het Gala writes: On 10/4/2023 8:51 PM, Fabiano Rosas wrote: Het Gala writes: Integrate MigrateChannelList with all transport backends (socket, exec and rdma) for both src and dest migration endpoints for qmp migration. For current series, limit the size of MigrateChannelList to single element (single interface) as runtime check. Suggested-by: Aravind Retnakaran Signed-off-by: Het Gala Reviewed-by: Daniel P. Berrangé --- migration/migration.c | 95 +++ 1 file changed, 52 insertions(+), 43 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index 6f948988ec..3eae32e616 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -432,9 +432,10 @@ void migrate_add_address(SocketAddress *address) } static bool migrate_uri_parse(const char *uri, - MigrationAddress **channel, + MigrationChannel **channel, Error **errp) { +g_autoptr(MigrationChannel) val = g_new0(MigrationChannel, 1); Here val is passed out of scope so it shouldn't be g_autoptr. I guess, same as for 'addr' we need to go with adding g_steal_pointer(&val) here too ? Yes, you cannot give the same pointer to *channel because this one is already being tracked by g_autoptr and it will free the memory when it gets the chance. So we need to steal it from g_autoptr, so to speak. Yes true. Ack. g_autoptr(MigrationAddress) addr = g_new0(MigrationAddress, 1); SocketAddress *saddr = &addr->u.socket; InetSocketAddress *isock = &addr->u.rdma; @@ -471,7 +472,9 @@ static bool migrate_uri_parse(const char *uri, return false; } -*channel = addr; +val->channel_type = MIGRATION_CHANNEL_TYPE_MAIN; +val->addr = addr; +*channel = val; return true; } @@ -479,41 +482,44 @@ static void qemu_start_incoming_migration(const char *uri, bool has_channels, MigrationChannelList *channels, Error **errp) { -g_autoptr(MigrationAddress) channel = g_new0(MigrationAddress, 1); +g_autoptr(MigrationChannel) channel = g_new0(MigrationChannel, 1); +g_autoptr(MigrationAddress) addr = g_new0(MigrationAddress, 1); Here we want just the pointer, no allocation, no freeing. For both channel and addr. Ack, same as channel in patch 2. This is actually one of the cases where we need to think about how we are going to free that memory. You need to make sure no one is using the 'addr' after you call into the *_incoming_migration functions. All users should either use the value and return or make a copy if they intend to pass it forward. If you determine that no one is using 'addr' and 'channel', then we could bring the channel g_autoptr back. Honestly, I think g_autoptr would work here because no one uses addr or channel after *_incoming_migration or *_outgoing_migration functions. But not sure. But that does not make the checks pass, so I have gone forward with simple pointers to pass make checks. /* * Having preliminary checks for uri and channel */ -if (has_channels) { -error_setg(errp, "'channels' argument should not be set yet."); -return; -} - if (uri && has_channels) { error_setg(errp, "'uri' and 'channels' arguments are mutually " "exclusive; exactly one of the two should be present in " "'migrate-incoming' qmp command "); return; -} - -if (!uri && !has_channels) { +} else if (channels) { +/* To verify that Migrate channel list has only item */ +if (channels->next) { +error_setg(errp, "Channel list has more than one entries"); +return; +} +channel = channels->value; +} else if (uri) { +/* caller uses the old URI syntax */ +if (!migrate_uri_parse(uri, &channel, errp)) { +return; +} +} else { error_setg(errp, "neither 'uri' or 'channels' argument are " "specified in 'migrate-incoming' qmp command "); return; } - -if (uri && !migrate_uri_parse(uri, &channel, errp)) { -return; -} +addr = channel->addr; /* transport mechanism not suitable for migration? */ -if (!migration_channels_and_transport_compatible(channel, errp)) { +if (!migration_channels_and_transport_compatible(addr, errp)) { return; } qapi_event_send_migration(MIGRATION_STATUS_SETUP); -if (channel->transport == MIGRATION_ADDRESS_TYPE_SOCKET) { -SocketAddress *saddr = &channel->u.socket; +if (addr->transport == MIGRATION_ADDRESS_TYPE_SOCKET) { +SocketAddress *saddr = &addr->u.socket; if (saddr->type == SOCKET_ADDRESS_TYPE_INET ||
Re: [PATCH] hw/loongarch: remove global loaderparams variable
Hi Thomas, On 9/10/23 23:00, Thomas Weißschuh wrote: Passing the struct around explicitly makes the control-flow more obvious. Signed-off-by: Thomas Weißschuh --- hw/loongarch/virt.c | 50 - 1 file changed, 27 insertions(+), 23 deletions(-) -static void loongarch_direct_kernel_boot(LoongArchMachineState *lams) +static void loongarch_direct_kernel_boot(LoongArchMachineState *lams, + const struct loaderparams *loaderparams) { MachineState *machine = MACHINE(lams); int64_t kernel_addr = 0; LoongArchCPU *lacpu; int i; -kernel_addr = load_kernel_info(); +kernel_addr = load_kernel_info(loaderparams); if (!machine->firmware) { for (i = 0; i < machine->smp.cpus; i++) { lacpu = LOONGARCH_CPU(qemu_get_cpu(i)); @@ -793,6 +796,7 @@ static void loongarch_init(MachineState *machine) MachineClass *mc = MACHINE_GET_CLASS(machine); CPUState *cpu; char *ramName = NULL; +struct loaderparams loaderparams; Please zero-initialize with '= { }', otherwise great! Reviewed-by: Philippe Mathieu-Daudé if (!cpu_model) { cpu_model = LOONGARCH_CPU_TYPE_NAME("la464"); @@ -898,9 +902,9 @@ static void loongarch_init(MachineState *machine) /* load the kernel. */ if (loaderparams.kernel_filename) { if (lams->bios_loaded) { -loongarch_firmware_boot(lams); +loongarch_firmware_boot(lams, &loaderparams); } else { -loongarch_direct_kernel_boot(lams); +loongarch_direct_kernel_boot(lams, &loaderparams); } } fdt_add_flash_node(lams); base-commit: 2f3913f4b2ad74baeb5a6f1d36efbd9ecdf1057d
[PATCH] hw/ufs: Fix incorrect register fields
From: Jeuk Kim This patch fixes invalid ufs register fields. This fixes an issue reported by Bin Meng that caused ufs to fail over riscv. Signed-off-by: Jeuk Kim --- include/block/ufs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/block/ufs.h b/include/block/ufs.h index fd884eb8ce..7631a5af10 100644 --- a/include/block/ufs.h +++ b/include/block/ufs.h @@ -111,14 +111,14 @@ REG32(UECT, offsetof(UfsReg, uect)) REG32(UECDME, offsetof(UfsReg, uecdme)) REG32(UTRIACR, offsetof(UfsReg, utriacr)) REG32(UTRLBA, offsetof(UfsReg, utrlba)) -FIELD(UTRLBA, UTRLBA, 9, 22) +FIELD(UTRLBA, UTRLBA, 10, 22) REG32(UTRLBAU, offsetof(UfsReg, utrlbau)) REG32(UTRLDBR, offsetof(UfsReg, utrldbr)) REG32(UTRLCLR, offsetof(UfsReg, utrlclr)) REG32(UTRLRSR, offsetof(UfsReg, utrlrsr)) REG32(UTRLCNR, offsetof(UfsReg, utrlcnr)) REG32(UTMRLBA, offsetof(UfsReg, utmrlba)) -FIELD(UTMRLBA, UTMRLBA, 9, 22) +FIELD(UTMRLBA, UTMRLBA, 10, 22) REG32(UTMRLBAU, offsetof(UfsReg, utmrlbau)) REG32(UTMRLDBR, offsetof(UfsReg, utmrldbr)) REG32(UTMRLCLR, offsetof(UfsReg, utmrlclr)) -- 2.34.1
Re: [PATCH v2 3/3] target/hexagon: avoid shadowing globals
Philippe Mathieu-Daudé writes: > On 9/10/23 08:09, Philippe Mathieu-Daudé wrote: >> Hi Brian, >> On 6/10/23 00:22, Brian Cain wrote: >>> The typedef `vaddr` is shadowed by `vaddr` identifiers, so we rename the >>> identifiers to avoid shadowing the type name. >> This one surprises me, since we have other occurences: >> include/exec/memory.h:751:bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, >> void **vaddr, >> include/qemu/plugin.h:199:void qemu_plugin_vcpu_mem_cb(CPUState *cpu, >> uint64_t vaddr, >> target/arm/internals.h:643:G_NORETURN void >> arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, >> target/i386/tcg/helper-tcg.h:70:G_NORETURN void >> handle_unaligned_access(CPUX86State *env, vaddr vaddr, >> ... >> $ git grep -w vaddr, | wc -l >> 207 >> What is the error/warning like? > > OK I could reproduce, I suppose you are building with Clang which > doesn't support shadow-local so you get global warnings too (as > mentioned in this patch subject...): > > In file included from ../../gdbstub/trace.h:1, > from ../../gdbstub/softmmu.c:30: > trace/trace-gdbstub.h: In function '_nocheck__trace_gdbstub_hit_watchpoint': > trace/trace-gdbstub.h:903:106: error: declaration of 'vaddr' shadows a global > declaration [-Werror=shadow] > 903 | static inline void _nocheck__trace_gdbstub_hit_watchpoint(const char > * type, int cpu_gdb_index, uint64_t vaddr) > | ~^ > In file included from include/sysemu/accel-ops.h:13, > from include/sysemu/cpus.h:4, > from ../../gdbstub/softmmu.c:21: > include/exec/cpu-common.h:21:18: note: shadowed declaration is here >21 | typedef uint64_t vaddr; > | ^ > trace/trace-gdbstub.h: In function 'trace_gdbstub_hit_watchpoint': > trace/trace-gdbstub.h:923:96: error: declaration of 'vaddr' shadows a global > declaration [-Werror=shadow] > 923 | static inline void trace_gdbstub_hit_watchpoint(const char * type, > int cpu_gdb_index, uint64_t vaddr) > |~^ > include/exec/cpu-common.h:21:18: note: shadowed declaration is here >21 | typedef uint64_t vaddr; > | ^ > > Clang users got confused by this, IIUC Markus and Thomas idea is > to only enable these warnings for GCC, enforcing them for Clang > users via CI (until Clang get this option supported). Personally > I'd rather enable the warning once for all, waiting for Clang > support (or clean/enable global shadowing for GCC too). > > See this thread: > https://lore.kernel.org/qemu-devel/11abc551-188e-85c0-fe55-b2b58d351...@redhat.com/ The idea to enable some variation of -Wshadow goes back to this thread: Subject: Re: [RFC PATCH] docs/style: permit inline loop variables Date: Thu, 24 Aug 2023 14:18:53 +0100 Message-ID: https://lore.kernel.org/qemu-devel/cafeaca8wobo5f16vyhbqcjeadfn5zwx5cq7l4vq3fh8c_6n...@mail.gmail.com/ I've been aiming at -Wshadow=local because (1) it seemed more practical (a lot less cleanup needed before we can enable the warning), and (2) local shadowing is basically always foolish and fully our own fault. No objection to additional -Wshadow work as long as I'm not the one doing it :)
Re: [Virtio-fs] (no subject)
On 10/9/2023 5:13 PM, Hanna Czenczek wrote: External email: Use caution opening links or attachments On 09.10.23 11:07, Hanna Czenczek wrote: On 09.10.23 10:21, Hanna Czenczek wrote: On 07.10.23 04:22, Yajun Wu wrote: [...] The main motivation of adding VHOST_USER_SET_STATUS is to let backend DPDK know when DRIVER_OK bit is valid. It's an indication of all VQ configuration has sent, otherwise DPDK has to rely on first queue pair is ready, then receiving/applying VQ configuration one by one. During live migration, configuring VQ one by one is very time consuming. One question I have here is why it wasn’t then introduced in the live migration code, but in the general VM stop/cont code instead. It does seem time-consuming to do this every time the VM is paused and resumed. Yes, VM stop/cont will call vhost_net_stop/vhost_net_start. Maybe because there's no device level stop/cont vhost message? For VIRTIO net vDPA, HW needs to know how many VQs are enabled to set RSS(Receive-Side Scaling). If you don’t want SET_STATUS message, backend can remove protocol feature bit VHOST_USER_PROTOCOL_F_STATUS. The problem isn’t back-ends that don’t want the message, the problem is that qemu uses the message wrongly, which prevents well-behaving back-ends from implementing the message. DPDK is ignoring SET_STATUS 0, but using GET_VRING_BASE to do device close/reset. So the right thing to do for back-ends is to announce STATUS support and then not implement it correctly? GET_VRING_BASE should not reset the close or reset the device, by the way. It should stop that one vring, not more. We have a RESET_DEVICE command for resetting. I believe dpdk uses GET_VRING_BASE long before qemu has RESET_DEVICE? It's a compatible issue. For new backend implements, we can have better solution, right? I'm not involved in discussion about adding SET_STATUS in Vhost protocol. This feature is essential for vDPA(same as vhost-vdpa implements VHOST_VDPA_SET_STATUS). So from what I gather from your response is that there is only a single use for SET_STATUS, which is the DRIVER_OK bit. If so, documenting that all other bits are to be ignored by both back-end and front-end would be fine by me. I’m not fully serious about that suggestion, but I hear the strong implication that nothing but DRIVER_OK was of any concern, and this is really important to note when we talk about the status of the STATUS feature in vhost today. It seems to me now that it was not intended to be the virtio-level status byte, but just a DRIVER_OK signalling path from front-end to back-end. That makes it a vhost-level protocol feature to me. On second thought, it just is a pure vhost-level protocol feature, and has nothing to do with the virtio status byte as-is. The only stated purpose is for the front-end to send DRIVER_OK after migration, but migration is transparent to the guest, so the guest would never change the status byte during migration. Therefore, if this feature is essential, we will never be able to have a status byte that is transparently shared between guest and back-end device, i.e. the virtio status byte. On third thought, scratch that. The guest wouldn’t set it, but naturally, after migration, the front-end will need to restore the status byte from the source, so the front-end will always need to set it, even if it were otherwise used controlled only by the guest and the back-end device. So technically, this doesn’t prevent such a use case. (In practice, it isn’t controlled by the guest right now, but that could be fixed.) I only tested the feature with DPDK(the only backend use it today?). Max defined the protocol and added the corresponding code in DPDK before I added QEMU support. If other backend or different device type want to use this, we can have further discussion? Cc-ing Alex on this mail, because to me, this seems like an important detail when he plans on using the byte in the future. If we need a virtio status byte, I can’t see how we could use the existing F_STATUS for it. Hanna
[PATCH v1 0/6] linux-user/loongarch64: Add LSX/LASX sigcontext
Hi, All. This series adds save/restore sigcontext. We use extctx_flags to choces which sigcontext need save/restore. The extctx_flags default value is EXTCTX_FLAGS_FPU, we need save/restore fpu context. After a LSX/LASX instruction is execed, extctx_flags value change to EXTCTX_FLAGS_LSX/LASX, we always need save/restore lsx/lasx context. The test_signal.c is a simple test. The default vreg len is 64. After execed a LSX instruction, the vreg len is 128, and then we exec a FPU instruction, the vreg len is also 128. After execed a LASX instruction, the vreg len is 256, and then we exec a FPU instruction, the vreg len is also 256. test_signal.c: #include #include #include #include #include #include #include #include #include static sigjmp_buf jmpbuf; struct _ctx_layout { struct sctx_info *addr; unsigned int size; }; struct extctx_layout { unsigned long size; unsigned int flags; struct _ctx_layout fpu; struct _ctx_layout lsx; struct _ctx_layout lasx; struct _ctx_layout end; }; static int parse_extcontext(struct sigcontext *sc, struct extctx_layout *extctx) { uint32_t magic, size; struct sctx_info *info = (struct sctx_info *)&sc->sc_extcontext; while(1) { magic = (uint32_t)info->magic; size = (uint32_t)info->size; printf("magic is %lx\n", magic); printf("size is %lx\n", size); switch (magic) { case 0: /* END*/ return 0; case FPU_CTX_MAGIC: if (size < (sizeof(struct sctx_info) + sizeof(struct fpu_context))) { return -1; } extctx->fpu.addr = info; break; case LSX_CTX_MAGIC: if (size < (sizeof(struct sctx_info) + sizeof(struct lsx_context))) { return -1; } extctx->lsx.addr = info; break; case LASX_CTX_MAGIC: if (size < (sizeof(struct sctx_info) + sizeof(struct lasx_context))) { return -1; } extctx->lasx.addr = info; break; default: return -1; } info = (struct sctx_info *)((char *)info +size); } return 0; } static int n = 0; static void do_signal(int sig, siginfo_t *info, void *ucontext) { int i; struct ucontext *uc = (struct ucontext *)ucontext; struct extctx_layout extctx; memset(&extctx, 0, sizeof(struct extctx_layout)); printf("pc: %016lx\n", uc->uc_mcontext.sc_pc); parse_extcontext(&uc->uc_mcontext, &extctx); if (n < 5) { printf("extctx.lasx.addr is %lx\n", extctx.lasx.addr); printf("extctx.lsx.addr is %lx\n", extctx.lsx.addr); printf("extctx.fpu.addr is %lx\n", extctx.fpu.addr); if (extctx.lasx.addr) { struct sctx_info *info = extctx.lasx.addr; struct lasx_context *lasx_ctx = (struct lasx_context *)((char *)info + sizeof(struct sctx_info)); printf("vl: %016lx\n", 256); } else if (extctx.lsx.addr) { struct sctx_info *info = extctx.lsx.addr; struct lsx_context *lsx_ctx = (struct lsx_context *)((char *)info + sizeof(struct sctx_info)); printf("vl: %016lx\n", 128); } else if (extctx.fpu.addr) { struct sctx_info *info = extctx.fpu.addr; struct fpu_context *fpu_ctx = (struct fpu_context *)((char *)info + sizeof(struct sctx_info)); printf("vl: %016lx\n", 64); } } n++; printf("n is -- %d\n", n); if (n == 1) { // vaddwev.w.hu$vr27, $vr22, $vr29 asm volatile(".word 0x702ef6db"); printf("After execed LSX instructons vaddwev.w.hu\n"); } if (n == 2) { // 0101395efadd.d $fs6, $ft2, $ft6 asm volatile(".word 0x0101395e"); printf("After execed FPU instructions fadd\n"); } if (n == 3) { // xvextrins.d $xr13, $xr15, 0x59 asm volatile(".word 0x778165ed"); printf("After execed LASX instructions xvextrins.d\n"); } if (n == 4) { // 0101395efadd.d $fs6, $ft2, $ft6 asm volatile(".word 0x0101395e"); printf("After execed FPU instructions fadd\n"); } if (n == 5) { exit(0); } siglongjmp(jmpbuf, 1); } static int setup_signal(int sig, void (*fn) (int, siginfo_t *, void *)) { struct sigaction my_act; int ret; my_act.sa_sigaction = fn; my_act.sa_flags = SA_SIGINFO; sigemptyset(&my_act.sa_mask); ret = sigaction(sig, &my_act, NULL); if (ret != 0) { printf("FAIL: signal %d\n", sig); return SIG_ERR; } } int main() { setup_signal(SIGSE
[PATCH v1 5/6] linux-user/loongarch64: Add LSX sigcontext save/restore
Signed-off-by: Song Gao --- linux-user/loongarch64/signal.c | 107 ++-- 1 file changed, 87 insertions(+), 20 deletions(-) diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c index 277e9f5757..4b09e50a5f 100644 --- a/linux-user/loongarch64/signal.c +++ b/linux-user/loongarch64/signal.c @@ -33,6 +33,14 @@ struct target_fpu_context { uint32_t fcsr; } QEMU_ALIGNED(FPU_CTX_ALIGN); +#define LSX_CTX_MAGIC 0x53580001 +#define LSX_CTX_ALIGN 16 +struct target_lsx_context { +uint64_t regs[2 * 32]; +uint64_t fcc; +uint32_t fcsr; +} QEMU_ALIGNED(LSX_CTX_ALIGN); + #define CONTEXT_INFO_ALIGN 16 struct target_sctx_info { uint32_t magic; @@ -66,9 +74,10 @@ struct ctx_layout { }; struct extctx_layout { -unsigned int size; +unsigned long size; unsigned int flags; struct ctx_layout fpu; +struct ctx_layout lsx; struct ctx_layout end; }; @@ -90,7 +99,8 @@ static abi_ptr extframe_alloc(struct extctx_layout *extctx, return sp; } -static abi_ptr setup_extcontext(struct extctx_layout *extctx, abi_ptr sp) +static abi_ptr setup_extcontext(CPULoongArchState *env, +struct extctx_layout *extctx, abi_ptr sp) { memset(extctx, 0, sizeof(struct extctx_layout)); @@ -99,8 +109,15 @@ static abi_ptr setup_extcontext(struct extctx_layout *extctx, abi_ptr sp) /* For qemu, there is no lazy fp context switch, so fp always present. */ extctx->flags = SC_USED_FP; -sp = extframe_alloc(extctx, &extctx->fpu, + +if (env->extctx_flags & EXTCTX_FLAGS_LSX) { +sp = extframe_alloc(extctx, &extctx->lsx, +sizeof(struct target_lsx_context), LSX_CTX_ALIGN, sp); + +} else if (env->extctx_flags & EXTCTX_FLAGS_FPU) { +sp = extframe_alloc(extctx, &extctx->fpu, sizeof(struct target_fpu_context), FPU_CTX_ALIGN, sp); +} return sp; } @@ -110,7 +127,6 @@ static void setup_sigframe(CPULoongArchState *env, struct extctx_layout *extctx) { struct target_sctx_info *info; -struct target_fpu_context *fpu_ctx; int i; __put_user(extctx->flags, &sc->sc_flags); @@ -121,18 +137,39 @@ static void setup_sigframe(CPULoongArchState *env, } /* - * Set fpu context + * Set extension context */ -info = extctx->fpu.haddr; -__put_user(FPU_CTX_MAGIC, &info->magic); -__put_user(extctx->fpu.size, &info->size); -fpu_ctx = (struct target_fpu_context *)(info + 1); -for (i = 0; i < 32; ++i) { -__put_user(env->fpr[i].vreg.D(0), &fpu_ctx->regs[i]); +if (env->extctx_flags & EXTCTX_FLAGS_LSX) { +struct target_lsx_context *lsx_ctx; +info = extctx->lsx.haddr; + +__put_user(LSX_CTX_MAGIC, &info->magic); +__put_user(extctx->lsx.size, &info->size); + +lsx_ctx = (struct target_lsx_context *)(info + 1); + +for (i = 0; i < 32; ++i) { +__put_user(env->fpr[i].vreg.UD(0), &lsx_ctx->regs[2 * i]); +__put_user(env->fpr[i].vreg.UD(1), &lsx_ctx->regs[2 * i + 1]); +} +__put_user(read_fcc(env), &lsx_ctx->fcc); +__put_user(env->fcsr0, &lsx_ctx->fcsr); +} else if (env->extctx_flags & EXTCTX_FLAGS_FPU) { +struct target_fpu_context *fpu_ctx; +info = extctx->fpu.haddr; + +__put_user(FPU_CTX_MAGIC, &info->magic); +__put_user(extctx->fpu.size, &info->size); + +fpu_ctx = (struct target_fpu_context *)(info + 1); + +for (i = 0; i < 32; ++i) { +__put_user(env->fpr[i].vreg.UD(0), &fpu_ctx->regs[i]); +} +__put_user(read_fcc(env), &fpu_ctx->fcc); +__put_user(env->fcsr0, &fpu_ctx->fcsr); } -__put_user(read_fcc(env), &fpu_ctx->fcc); -__put_user(env->fcsr0, &fpu_ctx->fcsr); /* * Set end context @@ -169,6 +206,15 @@ static bool parse_extcontext(struct extctx_layout *extctx, abi_ptr frame) extctx->fpu.size = size; extctx->size += size; break; +case LSX_CTX_MAGIC: +if (size < (sizeof(struct target_sctx_info) + +sizeof(struct target_lsx_context))) { +return false; +} +extctx->lsx.gaddr = frame; +extctx->lsx.size = size; +extctx->size += size; +break; default: return false; } @@ -182,19 +228,31 @@ static void restore_sigframe(CPULoongArchState *env, struct extctx_layout *extctx) { int i; +uint64_t fcc; __get_user(env->pc, &sc->sc_pc); for (i = 1; i < 32; ++i) { __get_user(env->gpr[i], &sc->sc_regs[i]); } -if (extctx->fpu.haddr) { +if (extctx->lsx.haddr) { +struct target_lsx_context *lsx_ctx = +extctx->lsx.haddr + sizeof(struct target_sctx_info); + +for
[PATCH v1 2/6] target/loongarch: Add set_vec_extctx to set LSX/LASX instructions extctx_flags
Signed-off-by: Song Gao --- target/loongarch/insn_trans/trans_vec.c.inc | 12 target/loongarch/internals.h| 2 ++ 2 files changed, 14 insertions(+) diff --git a/target/loongarch/insn_trans/trans_vec.c.inc b/target/loongarch/insn_trans/trans_vec.c.inc index 98f856bb29..aef16ef44a 100644 --- a/target/loongarch/insn_trans/trans_vec.c.inc +++ b/target/loongarch/insn_trans/trans_vec.c.inc @@ -23,8 +23,20 @@ static bool check_vec(DisasContext *ctx, uint32_t oprsz) #else +static void set_vec_extctx(DisasContext *ctx, uint32_t oprsz) +{ +if (oprsz == 16) { +ctx->extctx_flags |= EXTCTX_FLAGS_LSX; +} + +if (oprsz == 32) { +ctx->extctx_flags |= EXTCTX_FLAGS_LASX; +} +} + static bool check_vec(DisasContext *ctx, uint32_t oprsz) { +set_vec_extctx(ctx, oprsz); return true; } diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h index 01d98ac2fc..2efba9b859 100644 --- a/target/loongarch/internals.h +++ b/target/loongarch/internals.h @@ -22,6 +22,8 @@ #define LOONGARCH_HGLOBAL_SHIFT 12 #define EXTCTX_FLAGS_FPU 0b01 +#define EXTCTX_FLAGS_LSX 0b10 +#define EXTCTX_FLAGS_LASX 0b100 void loongarch_translate_init(void); -- 2.25.1
[PATCH v1 4/6] linux-user/loongarch64: setup_sigframe() set 'end' context size 0
See: https://github.com/torvalds/linux/blob/master/arch/loongarch/kernel/signal.c The kernel setup_sigcontext() set end context size 0. Signed-off-by: Song Gao --- linux-user/loongarch64/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c index d97aa7db7f..277e9f5757 100644 --- a/linux-user/loongarch64/signal.c +++ b/linux-user/loongarch64/signal.c @@ -139,7 +139,7 @@ static void setup_sigframe(CPULoongArchState *env, */ info = extctx->end.haddr; __put_user(0, &info->magic); -__put_user(extctx->end.size, &info->size); +__put_user(0, &info->size); } static bool parse_extcontext(struct extctx_layout *extctx, abi_ptr frame) -- 2.25.1
[PATCH v1 3/6] linux-user/loongarch64: Fix setup_extcontext alloc wrong fpu_context size
See: https://github.com/torvalds/linux/blob/master/arch/loongarch/kernel/signal.c The alloc size is sizeof(struct target_fpu_context). Signed-off-by: Song Gao --- linux-user/loongarch64/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c index 39572c1190..d97aa7db7f 100644 --- a/linux-user/loongarch64/signal.c +++ b/linux-user/loongarch64/signal.c @@ -100,7 +100,7 @@ static abi_ptr setup_extcontext(struct extctx_layout *extctx, abi_ptr sp) /* For qemu, there is no lazy fp context switch, so fp always present. */ extctx->flags = SC_USED_FP; sp = extframe_alloc(extctx, &extctx->fpu, -sizeof(struct target_rt_sigframe), FPU_CTX_ALIGN, sp); +sizeof(struct target_fpu_context), FPU_CTX_ALIGN, sp); return sp; } -- 2.25.1
[PATCH v1 1/6] target/loongarch: Add env->extctx_flags for user-mode setup extcontext
extctx_flags only for user-mode, and the default value is EXTCTX_FLAGS_FPU, We only need save/restore fpu context, After a LSX or LASX instruction is execed, the value change to EXTCTX_FLAGS_LSX/LASX, and we need save/restore lsx/lasx context. So if the binary no LSX/LASX instruction We only need save/restore fpu context. Signed-off-by: Song Gao --- target/loongarch/cpu.c | 2 ++ target/loongarch/cpu.h | 2 ++ target/loongarch/internals.h | 2 ++ target/loongarch/translate.c | 3 +++ target/loongarch/translate.h | 1 + 5 files changed, 10 insertions(+) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 2bea7ca5d5..32dd1b624b 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -546,6 +546,8 @@ static void loongarch_cpu_reset_hold(Object *obj) memset(env->tlb, 0, sizeof(env->tlb)); #endif +env->extctx_flags = EXTCTX_FLAGS_FPU; + restore_fp_status(env); cs->exception_index = -1; } diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index 40e70a8119..7a94963e5f 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -295,6 +295,8 @@ typedef struct CPUArchState { uint64_t lladdr; /* LL virtual address compared against SC */ uint64_t llval; +uint64_t extctx_flags; /* Use for user-mode setup extcontext */ + /* LoongArch CSRs */ uint64_t CSR_CRMD; uint64_t CSR_PRMD; diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h index c492863cc5..01d98ac2fc 100644 --- a/target/loongarch/internals.h +++ b/target/loongarch/internals.h @@ -21,6 +21,8 @@ /* Global bit for huge page */ #define LOONGARCH_HGLOBAL_SHIFT 12 +#define EXTCTX_FLAGS_FPU 0b01 + void loongarch_translate_init(void); void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags); diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index 21f4db6fbd..9b82295542 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -147,6 +147,8 @@ static void loongarch_tr_init_disas_context(DisasContextBase *dcbase, ctx->cpucfg1 = env->cpucfg[1]; ctx->cpucfg2 = env->cpucfg[2]; + +ctx->extctx_flags = env->extctx_flags; } static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) @@ -294,6 +296,7 @@ static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) generate_exception(ctx, EXCCODE_INE); } +env->extctx_flags |= ctx->extctx_flags; ctx->base.pc_next += 4; if (ctx->va32) { diff --git a/target/loongarch/translate.h b/target/loongarch/translate.h index 195f53573a..3bf1a1df86 100644 --- a/target/loongarch/translate.h +++ b/target/loongarch/translate.h @@ -40,6 +40,7 @@ typedef enum { typedef struct DisasContext { DisasContextBase base; target_ulong page_start; +uint64_t extctx_flags; uint32_t opcode; uint16_t mem_idx; uint16_t plv; -- 2.25.1
[PATCH v1 6/6] linux-user/loongarch64: Add LASX sigcontext save/restore
Signed-off-by: Song Gao --- linux-user/loongarch64/signal.c | 67 ++--- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c index 4b09e50a5f..e5b7688a2e 100644 --- a/linux-user/loongarch64/signal.c +++ b/linux-user/loongarch64/signal.c @@ -41,6 +41,14 @@ struct target_lsx_context { uint32_t fcsr; } QEMU_ALIGNED(LSX_CTX_ALIGN); +#define LASX_CTX_MAGIC 0x41535801 +#define LASX_CTX_ALIGN 32 +struct target_lasx_context { +uint64_t regs[4 * 32]; +uint64_t fcc; +uint32_t fcsr; +} QEMU_ALIGNED(LASX_CTX_ALIGN); + #define CONTEXT_INFO_ALIGN 16 struct target_sctx_info { uint32_t magic; @@ -78,6 +86,7 @@ struct extctx_layout { unsigned int flags; struct ctx_layout fpu; struct ctx_layout lsx; +struct ctx_layout lasx; struct ctx_layout end; }; @@ -110,7 +119,10 @@ static abi_ptr setup_extcontext(CPULoongArchState *env, /* For qemu, there is no lazy fp context switch, so fp always present. */ extctx->flags = SC_USED_FP; -if (env->extctx_flags & EXTCTX_FLAGS_LSX) { +if (env->extctx_flags & EXTCTX_FLAGS_LASX) { +sp = extframe_alloc(extctx, &extctx->lasx, +sizeof(struct target_lasx_context), LASX_CTX_ALIGN, sp); +} else if (env->extctx_flags & EXTCTX_FLAGS_LSX) { sp = extframe_alloc(extctx, &extctx->lsx, sizeof(struct target_lsx_context), LSX_CTX_ALIGN, sp); @@ -140,7 +152,24 @@ static void setup_sigframe(CPULoongArchState *env, * Set extension context */ -if (env->extctx_flags & EXTCTX_FLAGS_LSX) { +if (env->extctx_flags & EXTCTX_FLAGS_LASX) { +struct target_lasx_context *lasx_ctx; +info = extctx->lasx.haddr; + +__put_user(LASX_CTX_MAGIC, &info->magic); +__put_user(extctx->lasx.size, &info->size); + +lasx_ctx = (struct target_lasx_context *)(info + 1); + +for (i = 0; i < 32; ++i) { +__put_user(env->fpr[i].vreg.UD(0), &lasx_ctx->regs[4 * i]); +__put_user(env->fpr[i].vreg.UD(1), &lasx_ctx->regs[4 * i + 1]); +__put_user(env->fpr[i].vreg.UD(2), &lasx_ctx->regs[4 * i + 2]); +__put_user(env->fpr[i].vreg.UD(3), &lasx_ctx->regs[4 * i + 3]); +} +__put_user(read_fcc(env), &lasx_ctx->fcc); +__put_user(env->fcsr0, &lasx_ctx->fcsr); +} else if (env->extctx_flags & EXTCTX_FLAGS_LSX) { struct target_lsx_context *lsx_ctx; info = extctx->lsx.haddr; @@ -215,6 +244,15 @@ static bool parse_extcontext(struct extctx_layout *extctx, abi_ptr frame) extctx->lsx.size = size; extctx->size += size; break; +case LASX_CTX_MAGIC: +if (size < (sizeof(struct target_sctx_info) + +sizeof(struct target_lasx_context))) { +return false; +} +extctx->lasx.gaddr = frame; +extctx->lasx.size = size; +extctx->size += size; +break; default: return false; } @@ -235,7 +273,21 @@ static void restore_sigframe(CPULoongArchState *env, __get_user(env->gpr[i], &sc->sc_regs[i]); } -if (extctx->lsx.haddr) { +if (extctx->lasx.haddr) { +struct target_lasx_context *lasx_ctx = +extctx->lasx.haddr + sizeof(struct target_sctx_info); + +for (i = 0; i < 32; ++i) { +__get_user(env->fpr[i].vreg.UD(0), &lasx_ctx->regs[4 * i]); +__get_user(env->fpr[i].vreg.UD(1), &lasx_ctx->regs[4 * i + 1]); +__get_user(env->fpr[i].vreg.UD(2), &lasx_ctx->regs[4 * i + 2]); +__get_user(env->fpr[i].vreg.UD(3), &lasx_ctx->regs[4 * i + 3]); +} +__get_user(fcc, &lasx_ctx->fcc); +write_fcc(env, fcc); +__get_user(env->fcsr0, &lasx_ctx->fcsr); +restore_fp_status(env); +} else if (extctx->lsx.haddr) { struct target_lsx_context *lsx_ctx = extctx->lsx.haddr + sizeof(struct target_sctx_info); @@ -299,7 +351,10 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, return; } -if (env->extctx_flags & EXTCTX_FLAGS_LSX) { +if (env->extctx_flags & EXTCTX_FLAGS_LASX) { +extctx.lasx.haddr = (void *)frame + (extctx.lasx.gaddr - frame_addr); +extctx.end.haddr = (void *)frame + (extctx.end.gaddr - frame_addr); +} else if (env->extctx_flags & EXTCTX_FLAGS_LSX) { extctx.lsx.haddr = (void *)frame + (extctx.lsx.gaddr - frame_addr); extctx.end.haddr = (void *)frame + (extctx.end.gaddr - frame_addr); } else if (env->extctx_flags & EXTCTX_FLAGS_FPU) { @@ -349,7 +404,9 @@ long do_rt_sigreturn(CPULoongArchState *env) goto badframe; } -if (extctx.lsx.gaddr) { +if (extctx.lasx.gaddr) { +extctx.lasx.haddr = (void *)frame + (extctx.lasx.gaddr - frame
Re: [Virtio-fs] (no subject)
On 10/9/2023 6:28 PM, German Maglione wrote: External email: Use caution opening links or attachments On Sat, Oct 7, 2023 at 4:23 AM Yajun Wu wrote: On 10/6/2023 6:34 PM, Michael S. Tsirkin wrote: External email: Use caution opening links or attachments On Fri, Oct 06, 2023 at 11:47:55AM +0200, Hanna Czenczek wrote: On 06.10.23 11:26, Michael S. Tsirkin wrote: On Fri, Oct 06, 2023 at 11:15:55AM +0200, Hanna Czenczek wrote: On 06.10.23 10:45, Michael S. Tsirkin wrote: On Fri, Oct 06, 2023 at 09:48:14AM +0200, Hanna Czenczek wrote: On 05.10.23 19:15, Michael S. Tsirkin wrote: On Thu, Oct 05, 2023 at 01:08:52PM -0400, Stefan Hajnoczi wrote: On Wed, Oct 04, 2023 at 02:58:57PM +0200, Hanna Czenczek wrote: There is no clearly defined purpose for the virtio status byte in vhost-user: For resetting, we already have RESET_DEVICE; and for virtio feature negotiation, we have [GS]ET_FEATURES. With the REPLY_ACK protocol extension, it is possible for SET_FEATURES to return errors (SET_PROTOCOL_FEATURES may be called before SET_FEATURES). As for implementations, SET_STATUS is not widely implemented. dpdk does implement it, but only uses it to signal feature negotiation failure. While it does log reset requests (SET_STATUS 0) as such, it effectively ignores them, in contrast to RESET_OWNER (which is deprecated, and today means the same thing as RESET_DEVICE). While qemu superficially has support for [GS]ET_STATUS, it does not forward the guest-set status byte, but instead just makes it up internally, and actually completely ignores what the back-end returns, only using it as the template for a subsequent SET_STATUS to add single bits to it. Notably, after setting FEATURES_OK, it never reads it back to see whether the flag is still set, which is the only way in which dpdk uses the status byte. As-is, no front-end or back-end can rely on the other side handling this field in a useful manner, and it also provides no practical use over other mechanisms the vhost-user protocol has, which are more clearly defined. Deprecate it. Suggested-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- docs/interop/vhost-user.rst | 28 +--- 1 file changed, 21 insertions(+), 7 deletions(-) Reviewed-by: Stefan Hajnoczi SET_STATUS is the only way to signal failure to acknowledge FEATURES_OK. The fact current backends never check errors does not mean they never will. So no, not applying this. Can this not be done with REPLY_ACK? I.e., with the following message order: 1. GET_FEATURES to find out whether VHOST_USER_F_PROTOCOL_FEATURES is present 2. GET_PROTOCOL_FEATURES to hopefully get VHOST_USER_PROTOCOL_F_REPLY_ACK 3. SET_PROTOCOL_FEATURES to set VHOST_USER_PROTOCOL_F_REPLY_ACK 4. SET_FEATURES with need_reply If not, the problem is that qemu has sent SET_STATUS 0 for a while when the vCPUs are stopped, which generally seems to request a device reset. If we don’t state at least that SET_STATUS 0 is to be ignored, back-ends that will implement SET_STATUS later may break with at least these qemu versions. But documenting that a particular use of the status byte is to be ignored would be really strange. Hanna Hmm I guess. Though just following virtio spec seems cleaner to me... vhost-user reconfigures the state fully on start. Not the internal device state, though. virtiofsd has internal state, and other devices like vhost-gpu back-ends would probably, too. Stefan has recently sent a series (https://lists.nongnu.org/archive/html/qemu-devel/2023-10/msg00709.html) to put the reset (RESET_DEVICE) into virtio_reset() (when we really need a reset). I really don’t like our current approach with the status byte. Following the virtio specification to me would mean that the guest directly controls this byte, which it does not. qemu makes up values as it deems appropriate, and this includes sending a SET_STATUS 0 when the guest is just paused, i.e. when the guest really doesn’t want a device reset. That means that qemu does not treat this as a virtio device field (because that would mean exposing it to the guest driver), but instead treats it as part of the vhost(-user) protocol. It doesn’t feel right to me that we use a virtio-defined feature for communication on the vhost level, i.e. between front-end and back-end, and not between guest driver and device. I think all vhost-level protocol features should be fully defined in the vhost-user specification, which REPLY_ACK is. Hmm that makes sense. Maybe we should have done what stefan's patch is doing. Do look at the original commit that introduced it to understand why it was added. I don’t understand why this was added to the stop/cont code, though. If it is time consuming to make these changes, why are they done every time the VM is paused and resumed? It makes sense that this would be done for the initial configuration (where a reset also wouldn’t hurt), but here it seems wrong. (To be clear, a reset in the stop/co
[PATCH v2 5/7] virtio-net: Return an error when vhost cannot enable RSS
vhost requires eBPF for RSS. Even when eBPF is not available, virtio-net reported RSS availability, and raised a warning only after the guest requested RSS, and the guest could not know that RSS is not available. Check RSS availability during device realization and return an error if RSS is requested but not available. Assert RSS availability when the guest actually requests the feature. Signed-off-by: Akihiko Odaki --- ebpf/ebpf_rss.h | 2 +- ebpf/ebpf_rss-stub.c | 4 +- ebpf/ebpf_rss.c | 68 +- hw/net/virtio-net.c | 114 +-- 4 files changed, 82 insertions(+), 106 deletions(-) diff --git a/ebpf/ebpf_rss.h b/ebpf/ebpf_rss.h index bf3f2572c7..1128173572 100644 --- a/ebpf/ebpf_rss.h +++ b/ebpf/ebpf_rss.h @@ -36,7 +36,7 @@ bool ebpf_rss_is_loaded(struct EBPFRSSContext *ctx); bool ebpf_rss_load(struct EBPFRSSContext *ctx); -bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *config, +void ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *config, uint16_t *indirections_table, uint8_t *toeplitz_key); void ebpf_rss_unload(struct EBPFRSSContext *ctx); diff --git a/ebpf/ebpf_rss-stub.c b/ebpf/ebpf_rss-stub.c index e71e229190..525b358597 100644 --- a/ebpf/ebpf_rss-stub.c +++ b/ebpf/ebpf_rss-stub.c @@ -28,10 +28,10 @@ bool ebpf_rss_load(struct EBPFRSSContext *ctx) return false; } -bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *config, +void ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *config, uint16_t *indirections_table, uint8_t *toeplitz_key) { -return false; +g_assert_not_reached(); } void ebpf_rss_unload(struct EBPFRSSContext *ctx) diff --git a/ebpf/ebpf_rss.c b/ebpf/ebpf_rss.c index cee658c158..6cdf82d059 100644 --- a/ebpf/ebpf_rss.c +++ b/ebpf/ebpf_rss.c @@ -74,42 +74,32 @@ error: return false; } -static bool ebpf_rss_set_config(struct EBPFRSSContext *ctx, +static void ebpf_rss_set_config(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *config) { uint32_t map_key = 0; -if (!ebpf_rss_is_loaded(ctx)) { -return false; -} -if (bpf_map_update_elem(ctx->map_configuration, -&map_key, config, 0) < 0) { -return false; -} -return true; +assert(ebpf_rss_is_loaded(ctx)); +assert(!bpf_map_update_elem(ctx->map_configuration, &map_key, config, 0)); } -static bool ebpf_rss_set_indirections_table(struct EBPFRSSContext *ctx, +static void ebpf_rss_set_indirections_table(struct EBPFRSSContext *ctx, uint16_t *indirections_table, size_t len) { uint32_t i = 0; -if (!ebpf_rss_is_loaded(ctx) || indirections_table == NULL || - len > VIRTIO_NET_RSS_MAX_TABLE_LEN) { -return false; -} +assert(ebpf_rss_is_loaded(ctx)); +assert(indirections_table); +assert(len <= VIRTIO_NET_RSS_MAX_TABLE_LEN); for (; i < len; ++i) { -if (bpf_map_update_elem(ctx->map_indirections_table, &i, -indirections_table + i, 0) < 0) { -return false; -} +assert(!bpf_map_update_elem(ctx->map_indirections_table, &i, +indirections_table + i, 0)); } -return true; } -static bool ebpf_rss_set_toepliz_key(struct EBPFRSSContext *ctx, +static void ebpf_rss_set_toepliz_key(struct EBPFRSSContext *ctx, uint8_t *toeplitz_key) { uint32_t map_key = 0; @@ -117,41 +107,29 @@ static bool ebpf_rss_set_toepliz_key(struct EBPFRSSContext *ctx, /* prepare toeplitz key */ uint8_t toe[VIRTIO_NET_RSS_MAX_KEY_SIZE] = {}; -if (!ebpf_rss_is_loaded(ctx) || toeplitz_key == NULL) { -return false; -} +assert(ebpf_rss_is_loaded(ctx)); +assert(toeplitz_key); + memcpy(toe, toeplitz_key, VIRTIO_NET_RSS_MAX_KEY_SIZE); *(uint32_t *)toe = ntohl(*(uint32_t *)toe); -if (bpf_map_update_elem(ctx->map_toeplitz_key, &map_key, toe, -0) < 0) { -return false; -} -return true; +assert(!bpf_map_update_elem(ctx->map_toeplitz_key, &map_key, toe, 0)); } -bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *config, +void ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *config, uint16_t *indirections_table, uint8_t *toeplitz_key) { -if (!ebpf_rss_is_loaded(ctx) || config == NULL || -indirections_table == NULL || toeplitz_key == NULL) { -return false; -} - -if (!ebpf_rss_set_config(ctx, config)) { -return false; -} +assert(ebpf_rss_is_loaded(ctx)); +assert(config); +assert(indirections_table); +assert(toeplitz_key); -if (!ebpf_rss_set_indirections_
[PATCH v2 7/7] ebpf: Fix RSS error handling
calculate_rss_hash() was using hash value 0 to tell if it calculated a hash, but the hash value may be 0 on a rare occasion. Have a distinct bool value for correctness. Fixes: f3fa412de2 ("ebpf: Added eBPF RSS program.") Signed-off-by: Akihiko Odaki --- tools/ebpf/rss.bpf.c | 20 +++- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tools/ebpf/rss.bpf.c b/tools/ebpf/rss.bpf.c index 20f227e2ac..667ea6899e 100644 --- a/tools/ebpf/rss.bpf.c +++ b/tools/ebpf/rss.bpf.c @@ -377,18 +377,19 @@ error: return err; } -static inline __u32 calculate_rss_hash(struct __sk_buff *skb, -struct rss_config_t *config, struct toeplitz_key_data_t *toe) +static inline bool calculate_rss_hash(struct __sk_buff *skb, + struct rss_config_t *config, + struct toeplitz_key_data_t *toe, + __u32 *result) { __u8 rss_input[HASH_CALCULATION_BUFFER_SIZE] = {}; size_t bytes_written = 0; -__u32 result = 0; int err = 0; struct packet_hash_info_t packet_info = {}; err = parse_packet(skb, &packet_info); if (err) { -return 0; +return false; } if (packet_info.is_ipv4) { @@ -521,11 +522,13 @@ static inline __u32 calculate_rss_hash(struct __sk_buff *skb, } } -if (bytes_written) { -net_toeplitz_add(&result, rss_input, bytes_written, toe); +if (!bytes_written) { +return false; } -return result; +net_toeplitz_add(result, rss_input, bytes_written, toe); + +return true; } SEC("tun_rss_steering") @@ -546,8 +549,7 @@ int tun_rss_steering_prog(struct __sk_buff *skb) return config->default_queue; } -hash = calculate_rss_hash(skb, config, toe); -if (hash) { +if (calculate_rss_hash(skb, config, toe, &hash)) { __u32 table_idx = hash % config->indirections_len; __u16 *queue = 0; -- 2.42.0
[PATCH v2 0/7] virtio-net RSS/hash report fixes
This series contains fixes and improvements for virtio-net RSS and hash reporting feature. V1 -> V2: Added patch "ebpf: Fix RSS error handling". Akihiko Odaki (7): tap: Fix virtio-net header buffer size virtio-net: Copy header only when necessary virtio-net: Disable RSS on reset virtio-net: Unify the logic to update NIC state for RSS virtio-net: Return an error when vhost cannot enable RSS virtio-net: Do not clear VIRTIO_NET_F_RSS ebpf: Fix RSS error handling ebpf/ebpf_rss.h | 2 +- ebpf/ebpf_rss-stub.c | 4 +- ebpf/ebpf_rss.c | 68 --- hw/net/virtio-net.c | 277 --- net/tap.c| 4 +- tools/ebpf/rss.bpf.c | 20 ++-- 6 files changed, 166 insertions(+), 209 deletions(-) -- 2.42.0
[PATCH v2 3/7] virtio-net: Disable RSS on reset
RSS is disabled by default. Fixes: 590790297c ("virtio-net: implement RSS configuration command") Signed-off-by: Akihiko Odaki --- hw/net/virtio-net.c | 70 +++-- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 1ba748c964..83bac9a98a 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -601,40 +601,6 @@ static void virtio_net_queue_enable(VirtIODevice *vdev, uint32_t queue_index) } } -static void virtio_net_reset(VirtIODevice *vdev) -{ -VirtIONet *n = VIRTIO_NET(vdev); -int i; - -/* Reset back to compatibility mode */ -n->promisc = 1; -n->allmulti = 0; -n->alluni = 0; -n->nomulti = 0; -n->nouni = 0; -n->nobcast = 0; -/* multiqueue is disabled by default */ -n->curr_queue_pairs = 1; -timer_del(n->announce_timer.tm); -n->announce_timer.round = 0; -n->status &= ~VIRTIO_NET_S_ANNOUNCE; - -/* Flush any MAC and VLAN filter table state */ -n->mac_table.in_use = 0; -n->mac_table.first_multi = 0; -n->mac_table.multi_overflow = 0; -n->mac_table.uni_overflow = 0; -memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN); -memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac)); -qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); -memset(n->vlans, 0, MAX_VLAN >> 3); - -/* Flush any async TX */ -for (i = 0; i < n->max_queue_pairs; i++) { -flush_or_purge_queued_packets(qemu_get_subqueue(n->nic, i)); -} -} - static void peer_test_vnet_hdr(VirtIONet *n) { NetClientState *nc = qemu_get_queue(n->nic); @@ -3789,6 +3755,42 @@ static void virtio_net_device_unrealize(DeviceState *dev) virtio_cleanup(vdev); } +static void virtio_net_reset(VirtIODevice *vdev) +{ +VirtIONet *n = VIRTIO_NET(vdev); +int i; + +/* Reset back to compatibility mode */ +n->promisc = 1; +n->allmulti = 0; +n->alluni = 0; +n->nomulti = 0; +n->nouni = 0; +n->nobcast = 0; +/* multiqueue is disabled by default */ +n->curr_queue_pairs = 1; +timer_del(n->announce_timer.tm); +n->announce_timer.round = 0; +n->status &= ~VIRTIO_NET_S_ANNOUNCE; + +/* Flush any MAC and VLAN filter table state */ +n->mac_table.in_use = 0; +n->mac_table.first_multi = 0; +n->mac_table.multi_overflow = 0; +n->mac_table.uni_overflow = 0; +memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN); +memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac)); +qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); +memset(n->vlans, 0, MAX_VLAN >> 3); + +/* Flush any async TX */ +for (i = 0; i < n->max_queue_pairs; i++) { +flush_or_purge_queued_packets(qemu_get_subqueue(n->nic, i)); +} + +virtio_net_disable_rss(n); +} + static void virtio_net_instance_init(Object *obj) { VirtIONet *n = VIRTIO_NET(obj); -- 2.42.0
[PATCH v2 1/7] tap: Fix virtio-net header buffer size
The largest possible virtio-net header is struct virtio_net_hdr_v1_hash. Fixes: fbbdbddec0 ("tap: allow extended virtio header with hash info") Signed-off-by: Akihiko Odaki --- net/tap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/tap.c b/net/tap.c index c6639d9f20..ea46feeaa8 100644 --- a/net/tap.c +++ b/net/tap.c @@ -118,7 +118,7 @@ static ssize_t tap_receive_iov(NetClientState *nc, const struct iovec *iov, TAPState *s = DO_UPCAST(TAPState, nc, nc); const struct iovec *iovp = iov; struct iovec iov_copy[iovcnt + 1]; -struct virtio_net_hdr_mrg_rxbuf hdr = { }; +struct virtio_net_hdr_v1_hash hdr = { }; if (s->host_vnet_hdr_len && !s->using_vnet_hdr) { iov_copy[0].iov_base = &hdr; @@ -136,7 +136,7 @@ static ssize_t tap_receive_raw(NetClientState *nc, const uint8_t *buf, size_t si TAPState *s = DO_UPCAST(TAPState, nc, nc); struct iovec iov[2]; int iovcnt = 0; -struct virtio_net_hdr_mrg_rxbuf hdr = { }; +struct virtio_net_hdr_v1_hash hdr = { }; if (s->host_vnet_hdr_len) { iov[iovcnt].iov_base = &hdr; -- 2.42.0
[PATCH v2 4/7] virtio-net: Unify the logic to update NIC state for RSS
The code to attach or detach the eBPF program to RSS were duplicated so unify them into one function to save some code. Signed-off-by: Akihiko Odaki --- hw/net/virtio-net.c | 90 ++--- 1 file changed, 36 insertions(+), 54 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 83bac9a98a..3c3440ab72 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -1212,18 +1212,6 @@ static int virtio_net_handle_announce(VirtIONet *n, uint8_t cmd, } } -static void virtio_net_detach_epbf_rss(VirtIONet *n); - -static void virtio_net_disable_rss(VirtIONet *n) -{ -if (n->rss_data.enabled) { -trace_virtio_net_rss_disable(); -} -n->rss_data.enabled = false; - -virtio_net_detach_epbf_rss(n); -} - static bool virtio_net_attach_ebpf_to_backend(NICState *nic, int prog_fd) { NetClientState *nc = qemu_get_peer(qemu_get_queue(nic), 0); @@ -1271,6 +1259,40 @@ static void virtio_net_detach_epbf_rss(VirtIONet *n) virtio_net_attach_ebpf_to_backend(n->nic, -1); } +static void virtio_net_commit_rss_config(VirtIONet *n) +{ +if (n->rss_data.enabled) { +n->rss_data.enabled_software_rss = n->rss_data.populate_hash; +if (n->rss_data.populate_hash) { +virtio_net_detach_epbf_rss(n); +} else if (!virtio_net_attach_epbf_rss(n)) { +if (get_vhost_net(qemu_get_queue(n->nic)->peer)) { +warn_report("Can't use eBPF RSS for vhost"); +} else { +warn_report("Can't use eBPF RSS - fallback to software RSS"); +n->rss_data.enabled_software_rss = true; +} +} + +trace_virtio_net_rss_enable(n->rss_data.hash_types, +n->rss_data.indirections_len, +sizeof(n->rss_data.key)); +} else { +virtio_net_detach_epbf_rss(n); +trace_virtio_net_rss_disable(); +} +} + +static void virtio_net_disable_rss(VirtIONet *n) +{ +if (!n->rss_data.enabled) { +return; +} + +n->rss_data.enabled = false; +virtio_net_commit_rss_config(n); +} + static bool virtio_net_load_ebpf(VirtIONet *n) { if (!virtio_net_attach_ebpf_to_backend(n->nic, -1)) { @@ -1399,28 +1421,7 @@ static uint16_t virtio_net_handle_rss(VirtIONet *n, goto error; } n->rss_data.enabled = true; - -if (!n->rss_data.populate_hash) { -if (!virtio_net_attach_epbf_rss(n)) { -/* EBPF must be loaded for vhost */ -if (get_vhost_net(qemu_get_queue(n->nic)->peer)) { -warn_report("Can't load eBPF RSS for vhost"); -goto error; -} -/* fallback to software RSS */ -warn_report("Can't load eBPF RSS - fallback to software RSS"); -n->rss_data.enabled_software_rss = true; -} -} else { -/* use software RSS for hash populating */ -/* and detach eBPF if was loaded before */ -virtio_net_detach_epbf_rss(n); -n->rss_data.enabled_software_rss = true; -} - -trace_virtio_net_rss_enable(n->rss_data.hash_types, -n->rss_data.indirections_len, -temp.b); +virtio_net_commit_rss_config(n); return queue_pairs; error: trace_virtio_net_rss_error(err_msg, err_value); @@ -3016,26 +3017,7 @@ static int virtio_net_post_load_device(void *opaque, int version_id) } } -if (n->rss_data.enabled) { -n->rss_data.enabled_software_rss = n->rss_data.populate_hash; -if (!n->rss_data.populate_hash) { -if (!virtio_net_attach_epbf_rss(n)) { -if (get_vhost_net(qemu_get_queue(n->nic)->peer)) { -warn_report("Can't post-load eBPF RSS for vhost"); -} else { -warn_report("Can't post-load eBPF RSS - " -"fallback to software RSS"); -n->rss_data.enabled_software_rss = true; -} -} -} - -trace_virtio_net_rss_enable(n->rss_data.hash_types, -n->rss_data.indirections_len, -sizeof(n->rss_data.key)); -} else { -trace_virtio_net_rss_disable(); -} +virtio_net_commit_rss_config(n); return 0; } -- 2.42.0
[PATCH v2 2/7] virtio-net: Copy header only when necessary
It is necessary to copy the header only for byte swapping. Worse, when byte swapping is not needed, the header can be larger than the buffer due to VIRTIO_NET_F_HASH_REPORT, which results in buffer overflow. Copy the header only when byte swapping is needed. Fixes: e22f0603fb ("virtio-net: reference implementation of hash report") Signed-off-by: Akihiko Odaki --- hw/net/virtio-net.c | 26 -- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 9a93a2df01..1ba748c964 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -361,7 +361,8 @@ static void virtio_net_vnet_endian_status(VirtIONet *n, uint8_t status) * can't do it, we fallback onto fixing the headers in the core * virtio-net code. */ -n->needs_vnet_hdr_swap = virtio_net_set_vnet_endian(vdev, n->nic->ncs, +n->needs_vnet_hdr_swap = n->has_vnet_hdr && + virtio_net_set_vnet_endian(vdev, n->nic->ncs, queue_pairs, true); } else if (virtio_net_started(n, vdev->status)) { /* After using the device, we need to reset the network backend to @@ -2690,7 +2691,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) return -EINVAL; } -if (n->has_vnet_hdr) { +if (n->needs_vnet_hdr_swap) { if (iov_to_buf(out_sg, out_num, 0, &mhdr, n->guest_hdr_len) < n->guest_hdr_len) { virtio_error(vdev, "virtio-net header incorrect"); @@ -2698,19 +2699,16 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) g_free(elem); return -EINVAL; } -if (n->needs_vnet_hdr_swap) { -virtio_net_hdr_swap(vdev, (void *) &mhdr); -sg2[0].iov_base = &mhdr; -sg2[0].iov_len = n->guest_hdr_len; -out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1, - out_sg, out_num, - n->guest_hdr_len, -1); -if (out_num == VIRTQUEUE_MAX_SIZE) { -goto drop; -} -out_num += 1; -out_sg = sg2; +virtio_net_hdr_swap(vdev, (void *) &mhdr); +sg2[0].iov_base = &mhdr; +sg2[0].iov_len = n->guest_hdr_len; +out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1, out_sg, out_num, + n->guest_hdr_len, -1); +if (out_num == VIRTQUEUE_MAX_SIZE) { +goto drop; } +out_num += 1; +out_sg = sg2; } /* * If host wants to see the guest header as is, we can -- 2.42.0
[PATCH v2 6/7] virtio-net: Do not clear VIRTIO_NET_F_RSS
Even if eBPF is not available, virtio-net can perform RSS on the user-space if vhost is disabled although such a configuration results in a warning. If vhost is enabled, the configuration will be rejected when realizing the device. Therefore, VIRTIO_NET_F_RSS should not be cleared even if eBPF is not loaded. Signed-off-by: Akihiko Odaki --- hw/net/virtio-net.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 05f9abdbcd..3bb4bf136d 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -775,9 +775,6 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features, return features; } -if (!ebpf_rss_is_loaded(&n->ebpf_rss)) { -virtio_clear_feature(&features, VIRTIO_NET_F_RSS); -} features = vhost_net_get_features(get_vhost_net(nc->peer), features); vdev->backend_features = features; -- 2.42.0
Re: [PULL v2 0/6] vfio queue
Applied, thanks. Please update the changelog at https://wiki.qemu.org/ChangeLog/8.2 for any user-visible changes. signature.asc Description: PGP signature
Re: [PULL v2 00/25] Audio, source reorg, HVF changes for 2023-10-06
Applied, thanks. Please update the changelog at https://wiki.qemu.org/ChangeLog/8.2 for any user-visible changes. signature.asc Description: PGP signature
Re: [PULL 00/20] Q800 for 8.2 patches
Applied, thanks. Please update the changelog at https://wiki.qemu.org/ChangeLog/8.2 for any user-visible changes. signature.asc Description: PGP signature
Re: [PULL 00/15] NBD patches through 2023-10-05
Applied, thanks. Please update the changelog at https://wiki.qemu.org/ChangeLog/8.2 for any user-visible changes. signature.asc Description: PGP signature
Re: [PULL 00/32] -Wshadow=local patches patches for 2023-10-06
Applied, thanks. Please update the changelog at https://wiki.qemu.org/ChangeLog/8.2 for any user-visible changes. signature.asc Description: PGP signature
Re: qemu direct kernel boot on LoongArch
Thomas, Thanks for reporting this issue. It is the problem of QEMU for LoongArch system, QEMU does not support booting vmlinux with elf format without UEFI bios now. We will add support to boot vmlinux directly on QEMU LoongArch side. Regards Bibo Mao 在 2023/10/10 上午4:13, Thomas Weißschuh 写道: Hi, I'm trying to boot a LoongArch Linux via the direct kernel mode of qemu. ( qemu -kernel vmlinux -append "verbose" ) This doesn't work so well. A few problems I encoutered: * Linux reads the cmdline from $a1 during boot, but qemu doesn't place it there. * Qemu puts a FDT at 1MiB but Linux doesn't use it. * Qemu does not put the cmdline into the FDT. * Linux panics in memory_present() because memblock_init() in arch/loongarch/kernel/mem.c did not set up any memblocks. * Qemu has no support for initrds in direct kernel mode on LoongArch. (All observations based on current git versions) For the other architectures I'm using Linux/qemu with the direct kernel mode works nicely including cmdline and initrds. Are these restrictions by design/intentional or is it just for somebody to do the necessary legwork? The direct kernel mode is nice because it does not require the installation of the additional EFI binary. Thanks, Thomas
[PULL 2/2] migration/dirtyrate: use QEMU_CLOCK_HOST to report start-time
From: Andrei Gudkov Currently query-dirty-rate uses QEMU_CLOCK_REALTIME as the source for start-time field. This translates to clock_gettime(CLOCK_MONOTONIC), i.e. number of seconds since host boot. This is not very useful. The only reasonable use case of start-time I can imagine is to check whether previously completed measurements are too old or not. But this makes sense only if start-time is reported as host wall-clock time. This patch replaces source of start-time from QEMU_CLOCK_REALTIME to QEMU_CLOCK_HOST. Signed-off-by: Andrei Gudkov Reviewed-by: Hyman Huang Message-Id: <399861531e3b24a1ecea2ba453fb2c3d129fb03a.1693905328.git.gudkov.and...@huawei.com> Signed-off-by: Hyman Huang --- migration/dirtyrate.c | 15 ++- qapi/migration.json | 4 ++-- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c index a461b28bb5..036ac017fc 100644 --- a/migration/dirtyrate.c +++ b/migration/dirtyrate.c @@ -293,11 +293,10 @@ query_dirty_rate_info(TimeUnit calc_time_unit) return info; } -static void init_dirtyrate_stat(int64_t start_time, -struct DirtyRateConfig config) +static void init_dirtyrate_stat(struct DirtyRateConfig config) { DirtyStat.dirty_rate = -1; -DirtyStat.start_time = start_time; +DirtyStat.start_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000; DirtyStat.calc_time_ms = config.calc_time_ms; DirtyStat.sample_pages = config.sample_pages_per_gigabytes; @@ -633,7 +632,7 @@ static void calculate_dirtyrate_dirty_bitmap(struct DirtyRateConfig config) record_dirtypages_bitmap(&dirty_pages, true); start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); -DirtyStat.start_time = start_time / 1000; +DirtyStat.start_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000; DirtyStat.calc_time_ms = dirty_stat_wait(config.calc_time_ms, start_time); @@ -659,7 +658,7 @@ static void calculate_dirtyrate_dirty_ring(struct DirtyRateConfig config) /* start log sync */ global_dirty_log_change(GLOBAL_DIRTY_DIRTY_RATE, true); -DirtyStat.start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000; +DirtyStat.start_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000; /* calculate vcpu dirtyrate */ DirtyStat.calc_time_ms = vcpu_calculate_dirtyrate(config.calc_time_ms, @@ -685,6 +684,7 @@ static void calculate_dirtyrate_sample_vm(struct DirtyRateConfig config) rcu_read_lock(); initial_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); +DirtyStat.start_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) / 1000; if (!record_ramblock_hash_info(&block_dinfo, config, &block_count)) { goto out; } @@ -692,7 +692,6 @@ static void calculate_dirtyrate_sample_vm(struct DirtyRateConfig config) DirtyStat.calc_time_ms = dirty_stat_wait(config.calc_time_ms, initial_time); -DirtyStat.start_time = initial_time / 1000; rcu_read_lock(); if (!compare_page_hash_info(block_dinfo, block_count)) { @@ -756,7 +755,6 @@ void qmp_calc_dirty_rate(int64_t calc_time, static struct DirtyRateConfig config; QemuThread thread; int ret; -int64_t start_time; /* * If the dirty rate is already being measured, don't attempt to start. @@ -833,8 +831,7 @@ void qmp_calc_dirty_rate(int64_t calc_time, **/ dirtyrate_mode = mode; -start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) / 1000; -init_dirtyrate_stat(start_time, config); +init_dirtyrate_stat(config); qemu_thread_create(&thread, "get_dirtyrate", get_dirtyrate_thread, (void *)&config, QEMU_THREAD_DETACHED); diff --git a/qapi/migration.json b/qapi/migration.json index 1717aa4bbd..d8f3bbd7b0 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -1974,13 +1974,13 @@ # 1. Measurement is in progress: # # <- {"status": "measuring", "sample-pages": 512, -# "mode": "page-sampling", "start-time": 3665220, "calc-time": 10, +# "mode": "page-sampling", "start-time": 1693900454, "calc-time": 10, # "calc-time-unit": "second"} # # 2. Measurement has been completed: # # <- {"status": "measured", "sample-pages": 512, "dirty-rate": 108, -# "mode": "page-sampling", "start-time": 3665220, "calc-time": 10, +# "mode": "page-sampling", "start-time": 1693900454, "calc-time": 10, # "calc-time-unit": "second"} ## { 'command': 'query-dirty-rate', 'data': {'*calc-time-unit': 'TimeUnit' }, -- 2.39.1
[PULL 0/2] Dirty page rate and dirty page limit 20231010 patches
The following changes since commit 2f3913f4b2ad74baeb5a6f1d36efbd9ecdf1057d: Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging (2023-10-05 09:01:01 -0400) are available in the Git repository at: https://github.com/newfriday/qemu.git tags/dirtylimit-dirtyrate-pull-request-20231010 for you to fetch changes up to 320a6ccc769dc09ae7ad0b4838e322018f334bf4: migration/dirtyrate: use QEMU_CLOCK_HOST to report start-time (2023-10-10 08:04:12 +0800) Dirtylimit and dirtyrate 20231010 patches PULL request Dirty page rate measurement optimization. Please apply, thanks, Yong. Andrei Gudkov (2): migration/calc-dirty-rate: millisecond-granularity period migration/dirtyrate: use QEMU_CLOCK_HOST to report start-time migration/dirtyrate.c | 122 +++--- migration/dirtyrate.h | 12 +++-- qapi/migration.json | 58 3 files changed, 134 insertions(+), 58 deletions(-) -- 2.39.1
[PULL 1/2] migration/calc-dirty-rate: millisecond-granularity period
From: Andrei Gudkov This patch allows to measure dirty page rate for sub-second intervals of time. An optional argument is introduced -- calc-time-unit. For example: {"execute": "calc-dirty-rate", "arguments": {"calc-time": 500, "calc-time-unit": "millisecond"} } Millisecond granularity allows to make predictions whether migration will succeed or not. To do this, calculate dirty rate with calc-time set to max allowed downtime (e.g. 300ms), convert measured rate into volume of dirtied memory, and divide by network throughput. If the value is lower than max allowed downtime, then migration will converge. Measurement results for single thread randomly writing to a 1/4/24GiB memory region: ++---+ | calc-time |dirty rate MiB/s | | (milliseconds) ++---+--+ || theoretical| page-sampling | dirty-bitmap | || (at 3M wr/sec) | | | +++---+--+ | 1GiB | +++---+--+ |100 | 6996 | 7100 | 3192 | |200 | 4606 | 4660 | 2655 | |300 | 3305 | 3280 | 2371 | |400 | 2534 | 2525 | 2154 | |500 | 2041 | 2044 | 1871 | |750 | 1365 | 1341 | 1358 | | 1000 | 1024 | 1052 | 1025 | | 1500 |683 | 678 | 684 | | 2000 |512 | 507 | 513 | +++---+--+ | 4GiB | +++---+--+ |100 | 10232 | 8880 | 4070 | |200 | 8954 | 8049 | 3195 | |300 | 7889 | 7193 | 2881 | |400 | 6996 | 6530 | 2700 | |500 | 6245 | 5772 | 2312 | |750 | 4829 | 4586 | 2465 | | 1000 | 3865 | 3780 | 2178 | | 1500 | 2694 | 2633 | 2004 | | 2000 | 2041 | 2031 | 1789 | +++---+--+ | 24GiB| +++---+--+ |100 | 11495 | 8640 | 5597 | |200 | 11226 | 8616 | 3527 | |300 | 10965 | 8386 | 2355 | |400 | 10713 | 8370 | 2179 | |500 | 10469 | 8196 | 2098 | |750 | 9890 | 7885 | 2556 | | 1000 | 9354 | 7506 | 2084 | | 1500 | 8397 | 6944 | 2075 | | 2000 | 7574 | 6402 | 2062 | +++---+--+ Theoretical values are computed according to the following formula: size * (1 - (1-(4096/size))^(time*wps)) / (time * 2^20), where size is in bytes, time is in seconds, and wps is number of writes per second. Signed-off-by: Andrei Gudkov Reviewed-by: Hyman Huang Message-Id: Signed-off-by: Hyman Huang --- migration/dirtyrate.c | 107 +- migration/dirtyrate.h | 12 +++-- qapi/migration.json | 58 ++- 3 files changed, 128 insertions(+), 49 deletions(-) diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c index bccb3515e3..a461b28bb5 100644 --- a/migration/dirtyrate.c +++ b/migration/dirtyrate.c @@ -189,10 +189,9 @@ retry: return duration; } -static bool is_sample_period_valid(int64_t sec) +static bool is_calc_time_valid(int64_t msec) { -if (sec < MIN_FETCH_DIRTYRATE_TIME_SEC || -sec > MAX_FETCH_DIRTYRATE_TIME_SEC) { +if ((msec < MIN_CALC_TIME_MS) || (msec > MAX_CALC_TIME_MS)) { return false; } @@ -216,7 +215,39 @@ static int dirtyrate_set_state(int *state, int old_state, int new_state) } } -static struct DirtyRateInfo *query_dirty_rate_info(void) +/* Decimal power of given time unit relative to one second */ +static int time_unit_to_power(TimeUnit time_unit) +{ +switch (time_unit) { +case TIME_UNIT_SECOND: +return 0; +case TIME_UNIT_MILLISECOND: +return -3; +default: +assert(false); /* unreachabl
Re: [QEMU][PATCH v1 2/7] xen: add pseudo RAM region for grant mappings
On Mon, 9 Oct 2023, Stefano Stabellini wrote: > On Thu, 5 Oct 2023, Vikram Garhwal wrote: > > From: Juergen Gross > > > > Add a memory region which can be used to automatically map granted > > memory. It is starting at 0x8000ULL in order to be able to > > distinguish it from normal RAM. > > > > For this reason the xen.ram memory region is expanded, which has no > > further impact as it is used just as a container of the real RAM > > regions and now the grant region. > > > > Signed-off-by: Juergen Gross > > Signed-off-by: Vikram Garhwal > > This patch doesn't apply to staging anymore > > > > --- > > hw/i386/xen/xen-hvm.c | 3 ++ > > hw/xen/xen-hvm-common.c | 4 +-- > > hw/xen/xen-mapcache.c | 27 ++ > > include/exec/ram_addr.h | 1 + > > include/hw/xen/xen-hvm-common.h | 2 ++ > > include/hw/xen/xen_pvdev.h | 3 ++ > > include/sysemu/xen-mapcache.h | 3 ++ > > softmmu/physmem.c | 62 + > > 8 files changed, 80 insertions(+), 25 deletions(-) > > > > diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c > > index f42621e674..67a8a6 100644 > > --- a/hw/i386/xen/xen-hvm.c > > +++ b/hw/i386/xen/xen-hvm.c > > @@ -172,6 +172,9 @@ static void xen_ram_init(PCMachineState *pcms, > > x86ms->above_4g_mem_size); > > memory_region_add_subregion(sysmem, 0x1ULL, &ram_hi); > > } > > + > > +/* Add grant mappings as a pseudo RAM region. */ > > +ram_grants = *xen_init_grant_ram(); > > } > > > > static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size) > > diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c > > index 565dc39c8f..b7255977a5 100644 > > --- a/hw/xen/xen-hvm-common.c > > +++ b/hw/xen/xen-hvm-common.c > > @@ -9,7 +9,7 @@ > > #include "hw/boards.h" > > #include "hw/xen/arch_hvm.h" > > > > -MemoryRegion ram_memory; > > +MemoryRegion ram_memory, ram_grants; > > > > void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr, > > Error **errp) > > @@ -26,7 +26,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, > > MemoryRegion *mr, > > return; > > } > > > > -if (mr == &ram_memory) { > > +if (mr == &ram_memory || mr == &ram_grants) { > > return; > > } > > > > diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c > > index f7d974677d..8115c44c00 100644 > > --- a/hw/xen/xen-mapcache.c > > +++ b/hw/xen/xen-mapcache.c > > @@ -14,7 +14,9 @@ > > > > #include > > > > +#include "hw/xen/xen-hvm-common.h" > > #include "hw/xen/xen_native.h" > > +#include "hw/xen/xen_pvdev.h" > > #include "qemu/bitmap.h" > > > > #include "sysemu/runstate.h" > > @@ -597,3 +599,28 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr, > > mapcache_unlock(); > > return p; > > } > > + > > +MemoryRegion *xen_init_grant_ram(void) > > +{ > > +RAMBlock *block; > > + > > +memory_region_init(&ram_grants, NULL, "xen.grants", > > + XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE); > > +block = g_malloc0(sizeof(*block)); > > +block->mr = &ram_grants; > > +block->used_length = XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE; > > +block->max_length = XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE; > > +block->fd = -1; > > +block->page_size = XC_PAGE_SIZE; > > +block->host = (void *)XEN_GRANT_ADDR_OFF; > > +block->offset = XEN_GRANT_ADDR_OFF; > > +block->flags = RAM_PREALLOC; > > +ram_grants.ram_block = block; > > +ram_grants.ram = true; > > +ram_grants.terminates = true; > > +ram_block_add_list(block); > > +memory_region_add_subregion(get_system_memory(), XEN_GRANT_ADDR_OFF, > > +&ram_grants); > > + > > +return &ram_grants; > > It doesn't look like xen_init_grant_ram has anything to do with the > mapcache. It should be in another file. Maybe ./hw/xen/xen-hvm-common.c > or ./hw/i386/xen/xen-hvm.c (but this is x86 specific and we need grants > on ARM too) Now having seen all the other patches, it might be OK to keep this here. I am OK with this patch once it is rebased on the latest staging. I would still advise to split the physdev.c changes to a separate patch.
Re: [QEMU][PATCH v1 7/7] hw: arm: Add grant mapping.
On Thu, 5 Oct 2023, Vikram Garhwal wrote: > Enable grant ram mapping support for Xenpvh machine on ARM. > > Signed-off-by: Vikram Garhwal Reviewed-by: Stefano Stabellini > --- > hw/arm/xen_arm.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c > index f83b983ec5..553c289720 100644 > --- a/hw/arm/xen_arm.c > +++ b/hw/arm/xen_arm.c > @@ -125,6 +125,9 @@ static void xen_init_ram(MachineState *machine) > DPRINTF("Initialized region xen.ram.hi: base 0x%llx size 0x%lx\n", > GUEST_RAM1_BASE, ram_size[1]); > } > + > +DPRINTF("init grant ram mapping for XEN\n"); > +ram_grants = *xen_init_grant_ram(); > } > > void arch_handle_ioreq(XenIOState *state, ioreq_t *req) > -- > 2.17.1 >
Re: [QEMU][PATCH v1 6/7] xen: add map and unmap callbacks for grant region
On Thu, 5 Oct 2023, Vikram Garhwal wrote: > From: Juergen Gross > > Add the callbacks for mapping/unmapping guest memory via grants to the > special grant memory region. > > Signed-off-by: Juergen Gross > Signed-off-by: Vikram Garhwal This looks good. We need to add a check to make sure we don't exceed XEN_MAX_VIRTIO_GRANTS. > --- > hw/xen/xen-mapcache.c | 167 +- > softmmu/physmem.c | 11 ++- > 2 files changed, 173 insertions(+), 5 deletions(-) > > diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c > index 8a61c7dde6..52844a6a9d 100644 > --- a/hw/xen/xen-mapcache.c > +++ b/hw/xen/xen-mapcache.c > @@ -9,6 +9,8 @@ > */ > > #include "qemu/osdep.h" > +#include "qemu/queue.h" > +#include "qemu/thread.h" > #include "qemu/units.h" > #include "qemu/error-report.h" > > @@ -23,6 +25,8 @@ > #include "sysemu/xen-mapcache.h" > #include "trace.h" > > +#include > +#include > > //#define MAPCACHE_DEBUG > > @@ -385,7 +389,7 @@ uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size, > return p; > } > > -ram_addr_t xen_ram_addr_from_mapcache(void *ptr) > +static ram_addr_t xen_ram_addr_from_mapcache_try(void *ptr) > { > MapCacheEntry *entry = NULL; > MapCacheRev *reventry; > @@ -594,10 +598,170 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr, > return p; > } > > +struct XENMappedGrantRegion { > +void *addr; > +unsigned int pages; > +unsigned int refs; > +unsigned int prot; > +uint32_t idx; > +QLIST_ENTRY(XENMappedGrantRegion) list; > +}; > + > +static xengnttab_handle *xen_region_gnttabdev; > +static QLIST_HEAD(GrantRegionList, XENMappedGrantRegion) xen_grant_mappings = > +QLIST_HEAD_INITIALIZER(xen_grant_mappings); > +static QemuMutex xen_map_mutex; > + > +static void *xen_map_grant_dyn(MemoryRegion **mr, hwaddr addr, hwaddr *plen, > + bool is_write, MemTxAttrs attrs) > +{ > +unsigned int page_off = addr & (XC_PAGE_SIZE - 1); > +unsigned int i; > +unsigned int nrefs = (page_off + *plen + XC_PAGE_SIZE - 1) >> > XC_PAGE_SHIFT; > +uint32_t ref = (addr - XEN_GRANT_ADDR_OFF) >> XC_PAGE_SHIFT; > +uint32_t *refs = NULL; > +unsigned int prot = PROT_READ; > +struct XENMappedGrantRegion *mgr = NULL; > + > +if (is_write) { > +prot |= PROT_WRITE; > +} > + > +qemu_mutex_lock(&xen_map_mutex); > + > +QLIST_FOREACH(mgr, &xen_grant_mappings, list) { > +if (mgr->idx == ref && > +mgr->pages == nrefs && > +(mgr->prot & prot) == prot) { > +break; > +} > +} > +if (!mgr) { > +mgr = g_new(struct XENMappedGrantRegion, 1); > + > +if (nrefs == 1) { > +refs = &ref; > +} else { > +refs = g_new(uint32_t, nrefs); > +for (i = 0; i < nrefs; i++) { > +refs[i] = ref + i; > +} > +} > +mgr->addr = xengnttab_map_domain_grant_refs(xen_region_gnttabdev, > nrefs, > +xen_domid, refs, prot); > +if (mgr->addr) { > +mgr->pages = nrefs; > +mgr->refs = 1; > +mgr->prot = prot; > +mgr->idx = ref; > + > +QLIST_INSERT_HEAD(&xen_grant_mappings, mgr, list); > +} else { > +g_free(mgr); > +mgr = NULL; > +} > +} else { > +mgr->refs++; > +} > + > +qemu_mutex_unlock(&xen_map_mutex); > + > +if (nrefs > 1) { > +g_free(refs); > +} > + > +return mgr ? mgr->addr + page_off : NULL; > +} > + > +static void xen_unmap_grant_dyn(MemoryRegion *mr, void *buffer, ram_addr_t > addr, > +hwaddr len, bool is_write, hwaddr access_len) > +{ > +unsigned int page_off = (unsigned long)buffer & (XC_PAGE_SIZE - 1); > +unsigned int nrefs = (page_off + len + XC_PAGE_SIZE - 1) >> > XC_PAGE_SHIFT; > +unsigned int prot = PROT_READ; > +struct XENMappedGrantRegion *mgr = NULL; > + > +if (is_write) { > +prot |= PROT_WRITE; > +} > + > +qemu_mutex_lock(&xen_map_mutex); > + > +QLIST_FOREACH(mgr, &xen_grant_mappings, list) { > +if (mgr->addr == buffer - page_off && > +mgr->pages == nrefs && > +(mgr->prot & prot) == prot) { > +break; > +} > +} > +if (mgr) { > +mgr->refs--; > +if (!mgr->refs) { > +xengnttab_unmap(xen_region_gnttabdev, mgr->addr, nrefs); > + > +QLIST_REMOVE(mgr, list); > +g_free(mgr); > +} > +} else { > +error_report("xen_unmap_grant_dyn() trying to unmap unknown buffer"); > +} > + > +qemu_mutex_unlock(&xen_map_mutex); > +} > + > +static ram_addr_t xen_ram_addr_from_grant_cache(void *ptr) > +{ > +unsigned int page_off = (unsigned long)ptr & (XC_PAGE_SIZE - 1); > +struct XENMappedGrantRegion *mgr = NUL
Re: [QEMU][PATCH v1 5/7] memory: add MemoryRegion map and unmap callbacks
On Thu, 5 Oct 2023, Vikram Garhwal wrote: > From: Juergen Gross > > In order to support mapping and unmapping guest memory dynamically to > and from qemu during address_space_[un]map() operations add the map() > and unmap() callbacks to MemoryRegionOps. > > Those will be used e.g. for Xen grant mappings when performing guest > I/Os. > > Signed-off-by: Juergen Gross > Signed-off-by: Vikram Garhwal Can't we just use the existing Xen hooks in qemu_ram_ptr_length and xen_invalidate_map_cache_entry? Do we really need new ones? > --- > include/exec/memory.h | 21 ++ > softmmu/physmem.c | 50 +-- > 2 files changed, 60 insertions(+), 11 deletions(-) > > diff --git a/include/exec/memory.h b/include/exec/memory.h > index c99842d2fc..f3c62d2883 100644 > --- a/include/exec/memory.h > +++ b/include/exec/memory.h > @@ -280,6 +280,27 @@ struct MemoryRegionOps { > unsigned size, > MemTxAttrs attrs); > > +/* > + * Dynamically create mapping. @addr is the guest address to map; @plen > + * is the pointer to the usable length of the buffer. > + * @mr contents can be changed in case a new memory region is created for > + * the mapping. > + * Returns the buffer address for accessing the data. > + */ > +void *(*map)(MemoryRegion **mr, > + hwaddr addr, > + hwaddr *plen, > + bool is_write, > + MemTxAttrs attrs); > + > +/* Unmap an area obtained via map() before. */ > +void (*unmap)(MemoryRegion *mr, > + void *buffer, > + ram_addr_t addr, > + hwaddr len, > + bool is_write, > + hwaddr access_len); > + > enum device_endian endianness; > /* Guest-visible constraints: */ > struct { > diff --git a/softmmu/physmem.c b/softmmu/physmem.c > index 6e5e379dd0..5f425bea1c 100644 > --- a/softmmu/physmem.c > +++ b/softmmu/physmem.c > @@ -3135,6 +3135,7 @@ void *address_space_map(AddressSpace *as, > hwaddr len = *plen; > hwaddr l, xlat; > MemoryRegion *mr; > +void *ptr = NULL; > FlatView *fv; > > if (len == 0) { > @@ -3168,12 +3169,20 @@ void *address_space_map(AddressSpace *as, > return bounce.buffer; > } > > - > memory_region_ref(mr); > + > +if (mr->ops && mr->ops->map) { > +ptr = mr->ops->map(&mr, addr, plen, is_write, attrs); > +} > + > *plen = flatview_extend_translation(fv, addr, len, mr, xlat, > l, is_write, attrs); > fuzz_dma_read_cb(addr, *plen, mr); > -return qemu_ram_ptr_length(mr->ram_block, xlat, plen, true); > +if (ptr == NULL) { > +ptr = qemu_ram_ptr_length(mr->ram_block, xlat, plen, true); > +} > + > +return ptr; > } > > /* Unmaps a memory region previously mapped by address_space_map(). > @@ -3189,11 +3198,16 @@ void address_space_unmap(AddressSpace *as, void > *buffer, hwaddr len, > > mr = memory_region_from_host(buffer, &addr1); > assert(mr != NULL); > -if (is_write) { > -invalidate_and_set_dirty(mr, addr1, access_len); > -} > -if (xen_enabled()) { > -xen_invalidate_map_cache_entry(buffer); > + > +if (mr->ops && mr->ops->unmap) { > +mr->ops->unmap(mr, buffer, addr1, len, is_write, access_len); > +} else { > +if (is_write) { > +invalidate_and_set_dirty(mr, addr1, access_len); > +} > +if (xen_enabled()) { > +xen_invalidate_map_cache_entry(buffer); > +} > } > memory_region_unref(mr); > return; > @@ -3266,10 +3280,18 @@ int64_t address_space_cache_init(MemoryRegionCache > *cache, > * doing this if we found actual RAM, which behaves the same > * regardless of attributes; so UNSPECIFIED is fine. > */ > +if (mr->ops && mr->ops->map) { > +cache->ptr = mr->ops->map(&mr, addr, &l, is_write, > + MEMTXATTRS_UNSPECIFIED); > +} > + > l = flatview_extend_translation(cache->fv, addr, len, mr, > cache->xlat, l, is_write, > MEMTXATTRS_UNSPECIFIED); > -cache->ptr = qemu_ram_ptr_length(mr->ram_block, cache->xlat, &l, > true); > +if (!cache->ptr) { > +cache->ptr = qemu_ram_ptr_length(mr->ram_block, cache->xlat, &l, > + true); > +} > } else { > cache->ptr = NULL; > } > @@ -3291,14 +3313,20 @@ void address_space_cache_invalidate(MemoryRegionCache > *cache, > > void address_space_cache_destroy(MemoryRegionCache *cache) > { > -if (!cache->mrs.mr) { > +MemoryRegion *mr =
Re: [QEMU][PATCH v1 4/7] xen: let xen_ram_addr_from_mapcache() return -1 in case of not found entry
On Thu, 5 Oct 2023, Vikram Garhwal wrote: > From: Juergen Gross > > Today xen_ram_addr_from_mapcache() will either abort() or return 0 in > case it can't find a matching entry for a pointer value. Both cases > are bad, so change that to return an invalid address instead. > > Signed-off-by: Juergen Gross Reviewed-by: Stefano Stabellini > --- > hw/xen/xen-mapcache.c | 12 +++- > 1 file changed, 3 insertions(+), 9 deletions(-) > > diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c > index 8115c44c00..8a61c7dde6 100644 > --- a/hw/xen/xen-mapcache.c > +++ b/hw/xen/xen-mapcache.c > @@ -404,13 +404,8 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr) > } > } > if (!found) { > -fprintf(stderr, "%s, could not find %p\n", __func__, ptr); > -QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) { > -DPRINTF(" "HWADDR_FMT_plx" -> %p is present\n", > reventry->paddr_index, > -reventry->vaddr_req); > -} > -abort(); > -return 0; > +mapcache_unlock(); > +return RAM_ADDR_INVALID; > } > > entry = &mapcache->entry[paddr_index % mapcache->nr_buckets]; > @@ -418,8 +413,7 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr) > entry = entry->next; > } > if (!entry) { > -DPRINTF("Trying to find address %p that is not in the mapcache!\n", > ptr); > -raddr = 0; > +raddr = RAM_ADDR_INVALID; > } else { > raddr = (reventry->paddr_index << MCACHE_BUCKET_SHIFT) + > ((unsigned long) ptr - (unsigned long) entry->vaddr_base); > -- > 2.17.1 >
Re: [QEMU][PATCH v1 3/7] softmmu: let qemu_map_ram_ptr() use qemu_ram_ptr_length()
On Thu, 5 Oct 2023, Vikram Garhwal wrote: > From: Juergen Gross > > qemu_map_ram_ptr() and qemu_ram_ptr_length() share quite some code, so > modify qemu_ram_ptr_length() a little bit and use it for > qemu_map_ram_ptr(), too. > > Signed-off-by: Juergen Gross > Signed-off-by: Vikram Garhwal This patch also doesn't apply due to code movement. Other than that, the patch looks good to me > --- > softmmu/physmem.c | 58 +++ > 1 file changed, 23 insertions(+), 35 deletions(-) > > diff --git a/softmmu/physmem.c b/softmmu/physmem.c > index e182a2fa07..6e5e379dd0 100644 > --- a/softmmu/physmem.c > +++ b/softmmu/physmem.c > @@ -2163,38 +2163,8 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) > } > #endif /* !_WIN32 */ > > -/* Return a host pointer to ram allocated with qemu_ram_alloc. > - * This should not be used for general purpose DMA. Use address_space_map > - * or address_space_rw instead. For local memory (e.g. video ram) that the > - * device owns, use memory_region_get_ram_ptr. > - * > - * Called within RCU critical section. > - */ > -void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr) > -{ > -RAMBlock *block = ram_block; > - > -if (block == NULL) { > -block = qemu_get_ram_block(addr); > -addr -= block->offset; > -} > - > -if (xen_enabled() && block->host == NULL) { > -/* We need to check if the requested address is in the RAM > - * because we don't want to map the entire memory in QEMU. > - * In that case just map until the end of the page. > - */ > -if (block->offset == 0) { > -return xen_map_cache(addr, 0, 0, false); > -} > - > -block->host = xen_map_cache(block->offset, block->max_length, 1, > false); > -} > -return ramblock_ptr(block, addr); > -} > - > -/* Return a host pointer to guest's ram. Similar to qemu_map_ram_ptr > - * but takes a size argument. > +/* > + * Return a host pointer to guest's ram. > * > * Called within RCU critical section. > */ > @@ -2202,7 +2172,9 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, > ram_addr_t addr, > hwaddr *size, bool lock) > { > RAMBlock *block = ram_block; > -if (*size == 0) { > +hwaddr len = 0; > + > +if (size && *size == 0) { > return NULL; > } > > @@ -2210,7 +2182,10 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, > ram_addr_t addr, > block = qemu_get_ram_block(addr); > addr -= block->offset; > } > -*size = MIN(*size, block->max_length - addr); > +if (size) { > +*size = MIN(*size, block->max_length - addr); > +len = *size; > +} > > if (xen_enabled() && block->host == NULL) { > /* We need to check if the requested address is in the RAM > @@ -2218,7 +2193,7 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, > ram_addr_t addr, > * In that case just map the requested area. > */ > if (block->offset == 0) { > -return xen_map_cache(addr, *size, lock, lock); > +return xen_map_cache(addr, len, lock, lock); > } > > block->host = xen_map_cache(block->offset, block->max_length, 1, > lock); > @@ -2227,6 +2202,19 @@ static void *qemu_ram_ptr_length(RAMBlock *ram_block, > ram_addr_t addr, > return ramblock_ptr(block, addr); > } > > +/* > + * Return a host pointer to ram allocated with qemu_ram_alloc. > + * This should not be used for general purpose DMA. Use address_space_map > + * or address_space_rw instead. For local memory (e.g. video ram) that the > + * device owns, use memory_region_get_ram_ptr. > + * > + * Called within RCU critical section. > + */ > +void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr) > +{ > +return qemu_ram_ptr_length(ram_block, addr, NULL, false); > +} > + > /* Return the offset of a hostpointer within a ramblock */ > ram_addr_t qemu_ram_block_host_offset(RAMBlock *rb, void *host) > { > -- > 2.17.1 >
Re: [PATCH v17 6/9] gfxstream + rutabaga: add initial support for gfxstream
On Mon, Oct 9, 2023 at 12:11 AM Marc-André Lureau < marcandre.lur...@redhat.com> wrote: > On Fri, Oct 6, 2023 at 5:09 AM Gurchetan Singh > wrote: > > > > This adds initial support for gfxstream and cross-domain. Both > > features rely on virtio-gpu blob resources and context types, which > > are also implemented in this patch. > > > > gfxstream has a long and illustrious history in Android graphics > > paravirtualization. It has been powering graphics in the Android > > Studio Emulator for more than a decade, which is the main developer > > platform. > > > > Originally conceived by Jesse Hall, it was first known as "EmuGL" [a]. > > The key design characteristic was a 1:1 threading model and > > auto-generation, which fit nicely with the OpenGLES spec. It also > > allowed easy layering with ANGLE on the host, which provides the GLES > > implementations on Windows or MacOS enviroments. > > > > gfxstream has traditionally been maintained by a single engineer, and > > between 2015 to 2021, the goldfish throne passed to Frank Yang. > > Historians often remark this glorious reign ("pax gfxstreama" is the > > academic term) was comparable to that of Augustus and both Queen > > Elizabeths. Just to name a few accomplishments in a resplendent > > panoply: higher versions of GLES, address space graphics, snapshot > > support and CTS compliant Vulkan [b]. > > > > One major drawback was the use of out-of-tree goldfish drivers. > > Android engineers didn't know much about DRM/KMS and especially TTM so > > a simple guest to host pipe was conceived. > > > > Luckily, virtio-gpu 3D started to emerge in 2016 due to the work of > > the Mesa/virglrenderer communities. In 2018, the initial virtio-gpu > > port of gfxstream was done by Cuttlefish enthusiast Alistair Delva. > > It was a symbol compatible replacement of virglrenderer [c] and named > > "AVDVirglrenderer". This implementation forms the basis of the > > current gfxstream host implementation still in use today. > > > > cross-domain support follows a similar arc. Originally conceived by > > Wayland aficionado David Reveman and crosvm enjoyer Zach Reizner in > > 2018, it initially relied on the downstream "virtio-wl" device. > > > > In 2020 and 2021, virtio-gpu was extended to include blob resources > > and multiple timelines by yours truly, features gfxstream/cross-domain > > both require to function correctly. > > > > Right now, we stand at the precipice of a truly fantastic possibility: > > the Android Emulator powered by upstream QEMU and upstream Linux > > kernel. gfxstream will then be packaged properfully, and app > > developers can even fix gfxstream bugs on their own if they encounter > > them. > > > > It's been quite the ride, my friends. Where will gfxstream head next, > > nobody really knows. I wouldn't be surprised if it's around for > > another decade, maintained by a new generation of Android graphics > > enthusiasts. > > > > Technical details: > > - Very simple initial display integration: just used Pixman > > - Largely, 1:1 mapping of virtio-gpu hypercalls to rutabaga function > > calls > > > > Next steps for Android VMs: > > - The next step would be improving display integration and UI > interfaces > > with the goal of the QEMU upstream graphics being in an emulator > > release [d]. > > > > Next steps for Linux VMs for display virtualization: > > - For widespread distribution, someone needs to package Sommelier or > the > > wayland-proxy-virtwl [e] ideally into Debian main. In addition, newer > > versions of the Linux kernel come with DRM_VIRTIO_GPU_KMS option, > > which allows disabling KMS hypercalls. If anyone cares enough, it'll > > probably be possible to build a custom VM variant that uses this > display > > virtualization strategy. > > > > [a] > https://android-review.googlesource.com/c/platform/development/+/34470 > > [b] > https://android-review.googlesource.com/q/topic:%22vulkan-hostconnection-start%22 > > [c] > https://android-review.googlesource.com/c/device/generic/goldfish-opengl/+/761927 > > [d] https://developer.android.com/studio/releases/emulator > > [e] https://github.com/talex5/wayland-proxy-virtwl > > > > Signed-off-by: Gurchetan Singh > > Tested-by: Alyssa Ross > > Tested-by: Emmanouil Pitsidianakis > > Tested-by: Akihiko Odaki > > Reviewed-by: Emmanouil Pitsidianakis > > Reviewed-by: Antonio Caggiano > > Reviewed-by: Akihiko Odaki > > --- > > hw/display/virtio-gpu-pci-rutabaga.c | 47 ++ > > hw/display/virtio-gpu-rutabaga.c | 1113 ++ > > hw/display/virtio-vga-rutabaga.c | 50 ++ > > 3 files changed, 1210 insertions(+) > > create mode 100644 hw/display/virtio-gpu-pci-rutabaga.c > > create mode 100644 hw/display/virtio-gpu-rutabaga.c > > create mode 100644 hw/display/virtio-vga-rutabaga.c > > > > diff --git a/hw/display/virtio-gpu-pci-rutabaga.c > b/hw/display/virtio-gpu-pci-rutabaga.c > > new file mode 100644 > > index 00..c
Re: [QEMU][PATCH v1 2/7] xen: add pseudo RAM region for grant mappings
On Thu, 5 Oct 2023, Vikram Garhwal wrote: > From: Juergen Gross > > Add a memory region which can be used to automatically map granted > memory. It is starting at 0x8000ULL in order to be able to > distinguish it from normal RAM. > > For this reason the xen.ram memory region is expanded, which has no > further impact as it is used just as a container of the real RAM > regions and now the grant region. > > Signed-off-by: Juergen Gross > Signed-off-by: Vikram Garhwal This patch doesn't apply to staging anymore > --- > hw/i386/xen/xen-hvm.c | 3 ++ > hw/xen/xen-hvm-common.c | 4 +-- > hw/xen/xen-mapcache.c | 27 ++ > include/exec/ram_addr.h | 1 + > include/hw/xen/xen-hvm-common.h | 2 ++ > include/hw/xen/xen_pvdev.h | 3 ++ > include/sysemu/xen-mapcache.h | 3 ++ > softmmu/physmem.c | 62 + > 8 files changed, 80 insertions(+), 25 deletions(-) > > diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c > index f42621e674..67a8a6 100644 > --- a/hw/i386/xen/xen-hvm.c > +++ b/hw/i386/xen/xen-hvm.c > @@ -172,6 +172,9 @@ static void xen_ram_init(PCMachineState *pcms, > x86ms->above_4g_mem_size); > memory_region_add_subregion(sysmem, 0x1ULL, &ram_hi); > } > + > +/* Add grant mappings as a pseudo RAM region. */ > +ram_grants = *xen_init_grant_ram(); > } > > static XenPhysmap *get_physmapping(hwaddr start_addr, ram_addr_t size) > diff --git a/hw/xen/xen-hvm-common.c b/hw/xen/xen-hvm-common.c > index 565dc39c8f..b7255977a5 100644 > --- a/hw/xen/xen-hvm-common.c > +++ b/hw/xen/xen-hvm-common.c > @@ -9,7 +9,7 @@ > #include "hw/boards.h" > #include "hw/xen/arch_hvm.h" > > -MemoryRegion ram_memory; > +MemoryRegion ram_memory, ram_grants; > > void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr, > Error **errp) > @@ -26,7 +26,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, > MemoryRegion *mr, > return; > } > > -if (mr == &ram_memory) { > +if (mr == &ram_memory || mr == &ram_grants) { > return; > } > > diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c > index f7d974677d..8115c44c00 100644 > --- a/hw/xen/xen-mapcache.c > +++ b/hw/xen/xen-mapcache.c > @@ -14,7 +14,9 @@ > > #include > > +#include "hw/xen/xen-hvm-common.h" > #include "hw/xen/xen_native.h" > +#include "hw/xen/xen_pvdev.h" > #include "qemu/bitmap.h" > > #include "sysemu/runstate.h" > @@ -597,3 +599,28 @@ uint8_t *xen_replace_cache_entry(hwaddr old_phys_addr, > mapcache_unlock(); > return p; > } > + > +MemoryRegion *xen_init_grant_ram(void) > +{ > +RAMBlock *block; > + > +memory_region_init(&ram_grants, NULL, "xen.grants", > + XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE); > +block = g_malloc0(sizeof(*block)); > +block->mr = &ram_grants; > +block->used_length = XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE; > +block->max_length = XEN_MAX_VIRTIO_GRANTS * XC_PAGE_SIZE; > +block->fd = -1; > +block->page_size = XC_PAGE_SIZE; > +block->host = (void *)XEN_GRANT_ADDR_OFF; > +block->offset = XEN_GRANT_ADDR_OFF; > +block->flags = RAM_PREALLOC; > +ram_grants.ram_block = block; > +ram_grants.ram = true; > +ram_grants.terminates = true; > +ram_block_add_list(block); > +memory_region_add_subregion(get_system_memory(), XEN_GRANT_ADDR_OFF, > +&ram_grants); > + > +return &ram_grants; It doesn't look like xen_init_grant_ram has anything to do with the mapcache. It should be in another file. Maybe ./hw/xen/xen-hvm-common.c or ./hw/i386/xen/xen-hvm.c (but this is x86 specific and we need grants on ARM too) > +} > diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h > index 90676093f5..c0b5f9a7d0 100644 > --- a/include/exec/ram_addr.h > +++ b/include/exec/ram_addr.h > @@ -139,6 +139,7 @@ void qemu_ram_free(RAMBlock *block); > int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp); > > void qemu_ram_msync(RAMBlock *block, ram_addr_t start, ram_addr_t length); > +void ram_block_add_list(RAMBlock *new_block); > > /* Clear whole block of mem */ > static inline void qemu_ram_block_writeback(RAMBlock *block) > diff --git a/include/hw/xen/xen-hvm-common.h b/include/hw/xen/xen-hvm-common.h > index 4e9904f1a6..0d300ba898 100644 > --- a/include/hw/xen/xen-hvm-common.h > +++ b/include/hw/xen/xen-hvm-common.h > @@ -17,6 +17,8 @@ > #include > > extern MemoryRegion ram_memory; > + > +extern MemoryRegion ram_grants; > extern MemoryListener xen_io_listener; > extern DeviceListener xen_device_listener; > > diff --git a/include/hw/xen/xen_pvdev.h b/include/hw/xen/xen_pvdev.h > index ddad4b9f36..0f1b5edfa9 100644 > --- a/include/hw/xen/xen_pvdev.h > +++ b/include/hw/xen/xen_pvdev.h > @@ -80,4 +80,7 @@ int xen_pv_send_noti
Re: [PATCH 1/3] via-ide: Fix legacy mode emulation
On Mon, 9 Oct 2023, Mark Cave-Ayland wrote: On 09/10/2023 23:23, BALATON Zoltan wrote: On Mon, 9 Oct 2023, Mark Cave-Ayland wrote: On 08/10/2023 12:08, BALATON Zoltan wrote: On Sun, 8 Oct 2023, Mark Cave-Ayland wrote: On 05/10/2023 23:13, BALATON Zoltan wrote: The initial value for BARs were set in reset method for emulating legacy mode at start but this does not work because PCI code resets BARs after calling device reset method. This is certainly something I've noticed when testing previous versions of the VIA patches. Perhaps it's worth a separate thread to the PCI devs? I think I brought up this back then but was told current PCI code won't change and since that could break everything else that makes sense so this is something that we should take as given and accomodate that. I don't remember the details of that thread, but that's not too much of an issue here as the values won't be used. Additionally the values written to BARs were also wrong. I don't believe this is correct: according to the datasheet the values on reset are the ones given in the current reset code, so even if the reset function is overridden at a later data during PCI bus reset, I would leave these for now since it is a different issue. Those values are missing the IO space bit for one so they can't be correct as a BAR value no matter what the datasheet says. And since they are ineffective now I think it's best to remove them to avoid confusion. Maybe, or perhaps just fix up the missing IO space bit and add a comment pointing out these are the defaults, but currently they are erased on PCI bus reset? I have found it useful to have the values around to save having to reference the datasheet. The data sheet does not list the io space bits so fixing that would lead to values not matching data sheet any more. Also the defaults in the data sheet don't make much sense even with io space but as some of them match legacy ports while others don't. I can either drop this hunk leaving the current values there or add a FIXME comment saying they are ineffective but because they are overwritten (either by PCI code now or firmware/guest later) I think it's best to remove them any maybe only bring them back if we find they would be needed for any guest and what would be the correct default valuss here. I don't trust the data sheet on that and getting it from real hardware is also not really possible because the firmware could have overwritten them by the time you can get them. So I don't think keeping these here would help anybody, just cause confusion. We can check the values on real hardware given the Forth in my previous reply which will then tell us the correct values for once and for all. My guess is that since the address is a separate field to the BAR type in the datasheet, the IO bit was simply missed. I only have device tree dump from real pegasos2 but it has BARs so you can see here: package 0xFC5CE70 /pci/ide: parent=0xFC58E08 children=0xFC5D418 link=0xFC5D948 dict=0xFC5CEA0: open func[0x11F4] close func[0x11F5] dma-alloc func[0x11F6] dma-free func[0x11F7] decode-unit func[0x11F8] encode-unit func[0x11F9] selftest func[0x11FA] props=0xFC5CEB8: vendor-id 0x1106 (4358) device-id 0x571 (1393) revision-id 0x6 (6) class-code0x1018F (65935) subsystem-id 0x0 (0) subsystem-vendor-id 0x0 (0) .vendor-name "VIA" .part-number "VT82C586/596/686" .description "PCI IDE Controller" interrupts0x1 (1) devsel-speed 0x1 (1) fast-back-to-back min-grant 0x0 (0) max-latency 0x0 (0) name "ide" reg C,1:0 iC,1,10,0:8 iC,1,14,0:4 iC,1,18,0:8 iC,1,1C,0:4 iC,1,20,0:10 device_type "spi" assigned-addressesiC,1,10,FE001000:8 iC,1,14,FE00100C:4 iC,1,18,FE001010:8 iC,1,1C,FE00101C:4 iC,1,20,FE001020:10 That means by the time you could run your Forth the firmware already set the IDE device up se we get the same values as in Linux. If you want to see how the firmware progrems it you can find out with the emulated pegasos2 using -bios pegasos2.rom and enabling pci traces, but we can't find out what are the default values on real machine before this without replacing firmware that likely nobody dares to try. So just let it go and accept that whatever defaults are the
Re: [QEMU][PATCH v1 1/7] xen: when unplugging emulated devices skip virtio devices
On Thu, 5 Oct 2023, Vikram Garhwal wrote: > From: Juergen Gross > > Virtio devices should never be unplugged at boot time, as they are > similar to pci passthrough devices. > > Signed-off-by: Juergen Gross > Signed-off-by: Vikram Garhwal > --- > hw/i386/xen/xen_platform.c | 8 +++- > 1 file changed, 7 insertions(+), 1 deletion(-) > > diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c > index 17457ff3de..3560eaf8c8 100644 > --- a/hw/i386/xen/xen_platform.c > +++ b/hw/i386/xen/xen_platform.c > @@ -28,6 +28,7 @@ > #include "hw/ide/pci.h" > #include "hw/pci/pci.h" > #include "migration/vmstate.h" > +#include "hw/virtio/virtio-bus.h" > #include "net/net.h" > #include "trace.h" > #include "sysemu/xen.h" > @@ -132,7 +133,8 @@ static void unplug_nic(PCIBus *b, PCIDevice *d, void *o) > /* We have to ignore passthrough devices */ > if (pci_get_word(d->config + PCI_CLASS_DEVICE) == > PCI_CLASS_NETWORK_ETHERNET > -&& !pci_device_is_passthrough(d)) { > +&& !pci_device_is_passthrough(d) > +&& !qdev_get_child_bus(&d->qdev, TYPE_VIRTIO_BUS)) { Please update the in-code comment above to say "ignore passthrough devices and virtio devices" > object_unparent(OBJECT(d)); > } > } > @@ -208,6 +210,10 @@ static void unplug_disks(PCIBus *b, PCIDevice *d, void > *opaque) > /* We have to ignore passthrough devices */ > if (pci_device_is_passthrough(d)) > return; > +/* Ignore virtio devices */ > +if (qdev_get_child_bus(&d->qdev, TYPE_VIRTIO_BUS)) { > +return; > +} > > switch (pci_get_word(d->config + PCI_CLASS_DEVICE)) { > case PCI_CLASS_STORAGE_IDE: > -- > 2.17.1 >
Re: [PATCH 1/3] via-ide: Fix legacy mode emulation
On 09/10/2023 23:23, BALATON Zoltan wrote: On Mon, 9 Oct 2023, Mark Cave-Ayland wrote: On 08/10/2023 12:08, BALATON Zoltan wrote: On Sun, 8 Oct 2023, Mark Cave-Ayland wrote: On 05/10/2023 23:13, BALATON Zoltan wrote: The initial value for BARs were set in reset method for emulating legacy mode at start but this does not work because PCI code resets BARs after calling device reset method. This is certainly something I've noticed when testing previous versions of the VIA patches. Perhaps it's worth a separate thread to the PCI devs? I think I brought up this back then but was told current PCI code won't change and since that could break everything else that makes sense so this is something that we should take as given and accomodate that. I don't remember the details of that thread, but that's not too much of an issue here as the values won't be used. Additionally the values written to BARs were also wrong. I don't believe this is correct: according to the datasheet the values on reset are the ones given in the current reset code, so even if the reset function is overridden at a later data during PCI bus reset, I would leave these for now since it is a different issue. Those values are missing the IO space bit for one so they can't be correct as a BAR value no matter what the datasheet says. And since they are ineffective now I think it's best to remove them to avoid confusion. Maybe, or perhaps just fix up the missing IO space bit and add a comment pointing out these are the defaults, but currently they are erased on PCI bus reset? I have found it useful to have the values around to save having to reference the datasheet. The data sheet does not list the io space bits so fixing that would lead to values not matching data sheet any more. Also the defaults in the data sheet don't make much sense even with io space but as some of them match legacy ports while others don't. I can either drop this hunk leaving the current values there or add a FIXME comment saying they are ineffective but because they are overwritten (either by PCI code now or firmware/guest later) I think it's best to remove them any maybe only bring them back if we find they would be needed for any guest and what would be the correct default valuss here. I don't trust the data sheet on that and getting it from real hardware is also not really possible because the firmware could have overwritten them by the time you can get them. So I don't think keeping these here would help anybody, just cause confusion. We can check the values on real hardware given the Forth in my previous reply which will then tell us the correct values for once and for all. My guess is that since the address is a separate field to the BAR type in the datasheet, the IO bit was simply missed. Move setting the BARs to a callback on writing the PCI config regsiter that sets the compatibility mode (which firmwares needing this mode seem to do) and fix their values to program it to use legacy port numbers. As noted in a comment, we only do this when the BARs were unset before, because logs from real machine show this is how real chip works, even if it contradicts the data sheet which is not very clear about this. Signed-off-by: BALATON Zoltan --- hw/ide/via.c | 35 ++- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/hw/ide/via.c b/hw/ide/via.c index fff23803a6..8186190207 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -132,11 +132,6 @@ static void via_ide_reset(DeviceState *dev) pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, 0x01f0); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_1, 0x03f4); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_2, 0x0170); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_3, 0x0374); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_4, 0xcc01); /* BMIBA: 20-23h */ pci_set_long(pci_conf + PCI_INTERRUPT_LINE, 0x010e); /* IDE chip enable, IDE configuration 1/2, IDE FIFO Configuration*/ @@ -159,6 +154,35 @@ static void via_ide_reset(DeviceState *dev) pci_set_long(pci_conf + 0xc0, 0x00020001); } +static void via_ide_cfg_write(PCIDevice *pd, uint32_t addr, + uint32_t val, int len) +{ + pci_default_write_config(pd, addr, val, len); + /* + * Only set BARs if they are unset. Logs from real hardware show that + * writing class_prog to enable compatibility mode after BARs were set + * (possibly by firmware) it will use ports set by BARs not ISA ports + * (e.g. pegasos2 Linux does this and calls it non-100% native mode). Can you remind me again where the references are to non-100% native mode? The only thing I can find in Linux is https://github.com/torvalds/linux/blob/master/arch/powerpc/platforms/chrp/pci.c#L360 but that simply forces a switch to leg
Re: [PATCH 2/3] hw/pci-host: Add emulation of Mai Logic Articia S
On Mon, 9 Oct 2023, Mark Cave-Ayland wrote: On 09/10/2023 22:57, BALATON Zoltan wrote: On Mon, 9 Oct 2023, Mark Cave-Ayland wrote: On 08/10/2023 19:08, BALATON Zoltan wrote: On Sun, 8 Oct 2023, Mark Cave-Ayland wrote: On 05/10/2023 23:13, BALATON Zoltan wrote: The Articia S is a generic chipset supporting several different CPUs that were used on some PPC boards. This is a minimal emulation of the parts needed for emulating the AmigaOne board. Signed-off-by: BALATON Zoltan --- hw/pci-host/Kconfig | 5 + hw/pci-host/articia.c | 266 ++ hw/pci-host/meson.build | 2 + include/hw/pci-host/articia.h | 17 +++ 4 files changed, 290 insertions(+) create mode 100644 hw/pci-host/articia.c create mode 100644 include/hw/pci-host/articia.h diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig index a07070eddf..33014c80a4 100644 --- a/hw/pci-host/Kconfig +++ b/hw/pci-host/Kconfig @@ -73,6 +73,11 @@ config SH_PCI bool select PCI +config ARTICIA + bool + select PCI + select I8259 + config MV64361 bool select PCI diff --git a/hw/pci-host/articia.c b/hw/pci-host/articia.c new file mode 100644 index 00..80558e1c47 --- /dev/null +++ b/hw/pci-host/articia.c @@ -0,0 +1,266 @@ +/* + * Mai Logic Articia S emulation + * + * Copyright (c) 2023 BALATON Zoltan + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/pci/pci_device.h" +#include "hw/pci/pci_host.h" +#include "hw/irq.h" +#include "hw/i2c/bitbang_i2c.h" +#include "hw/intc/i8259.h" +#include "hw/pci-host/articia.h" + +OBJECT_DECLARE_SIMPLE_TYPE(ArticiaState, ARTICIA) + +OBJECT_DECLARE_SIMPLE_TYPE(ArticiaHostState, ARTICIA_PCI_HOST) +struct ArticiaHostState { + PCIDevice parent_obj; + + ArticiaState *as; +}; + +/* TYPE_ARTICIA */ + +struct ArticiaState { + PCIHostState parent_obj; + + qemu_irq irq[PCI_NUM_PINS]; + MemoryRegion io; + MemoryRegion mem; + MemoryRegion reg; + + bitbang_i2c_interface smbus; + uint32_t gpio; /* bits 0-7 in, 8-15 out, 16-23 direction (0 in, 1 out) */ + hwaddr gpio_base; + MemoryRegion gpio_reg; +}; These types above should be in the header file and not in the C file, as per our current QOM guidelines. I don't think there's such a guideline, at least I did not find any mention of it in style and qom docs. It was necessary to move some type declarations to headers for types that are embedded in other objects because C needs the struct size for that, but I don't think that should be a general thing when it's not needed. The reason for that is that moving these to the header exposes internal object structure to users that should not need to know that so it breaks object encapsulation and also needs moving a bunch of includes to the header which then makes the users of this type also include those headers when they don't really need them but only need the type defines to instantiate the object and that's all they should have access to. So I think declaring types in the header should only be done for types that aren't full devices and are meant to be embedded as part of another device or a SoC but otherwise it's better to keep implementation closed and local to the object and not expose it unless really needed, that's why these are here. If you insist I can move these but I don't think there's really such recommendation and I don't think that's a good idea because of the above. Maybe it was something that was missed out of the recent documentation updates, but you can clearly see this has been the standard pattern for some time, including for recent devices such as the xlnx-versal. If there are any devices that don't follow this pattern then it is likely because they are based on older code. If you disagree with this, then start a new thread on qemu-devel with a new proposal and if everyone is agreement then that will be become the new standard. I think you should start a thread with a patch to style or qom docs about this to document this standard and if that's accepted then I also accept it as a real recommendation as my understanding of it was as above that it was needed for some deviecs to allow embedding them but not a general recommendation for all devices and I don't think it should be beacuse of braeaking encapsulation and introduces a lot of unneded includes so I'd keep it to those devices where it'e really needed which is what the docs currently say. Oh is there already a mention of this somewhere in the docs? Can you provide a link so we can check the wording? Certainly that's the way my own patches (and other people's patches) have been reviewed historically over the years. The only mention I could find is in docs/devel/qom.rst, section "Standard type declaration and definition macros" which says: "In types which do
Re: [PATCH 2/3] hw/pci-host: Add emulation of Mai Logic Articia S
On 09/10/2023 22:57, BALATON Zoltan wrote: On Mon, 9 Oct 2023, Mark Cave-Ayland wrote: On 08/10/2023 19:08, BALATON Zoltan wrote: On Sun, 8 Oct 2023, Mark Cave-Ayland wrote: On 05/10/2023 23:13, BALATON Zoltan wrote: The Articia S is a generic chipset supporting several different CPUs that were used on some PPC boards. This is a minimal emulation of the parts needed for emulating the AmigaOne board. Signed-off-by: BALATON Zoltan --- hw/pci-host/Kconfig | 5 + hw/pci-host/articia.c | 266 ++ hw/pci-host/meson.build | 2 + include/hw/pci-host/articia.h | 17 +++ 4 files changed, 290 insertions(+) create mode 100644 hw/pci-host/articia.c create mode 100644 include/hw/pci-host/articia.h diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig index a07070eddf..33014c80a4 100644 --- a/hw/pci-host/Kconfig +++ b/hw/pci-host/Kconfig @@ -73,6 +73,11 @@ config SH_PCI bool select PCI +config ARTICIA + bool + select PCI + select I8259 + config MV64361 bool select PCI diff --git a/hw/pci-host/articia.c b/hw/pci-host/articia.c new file mode 100644 index 00..80558e1c47 --- /dev/null +++ b/hw/pci-host/articia.c @@ -0,0 +1,266 @@ +/* + * Mai Logic Articia S emulation + * + * Copyright (c) 2023 BALATON Zoltan + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/pci/pci_device.h" +#include "hw/pci/pci_host.h" +#include "hw/irq.h" +#include "hw/i2c/bitbang_i2c.h" +#include "hw/intc/i8259.h" +#include "hw/pci-host/articia.h" + +OBJECT_DECLARE_SIMPLE_TYPE(ArticiaState, ARTICIA) + +OBJECT_DECLARE_SIMPLE_TYPE(ArticiaHostState, ARTICIA_PCI_HOST) +struct ArticiaHostState { + PCIDevice parent_obj; + + ArticiaState *as; +}; + +/* TYPE_ARTICIA */ + +struct ArticiaState { + PCIHostState parent_obj; + + qemu_irq irq[PCI_NUM_PINS]; + MemoryRegion io; + MemoryRegion mem; + MemoryRegion reg; + + bitbang_i2c_interface smbus; + uint32_t gpio; /* bits 0-7 in, 8-15 out, 16-23 direction (0 in, 1 out) */ + hwaddr gpio_base; + MemoryRegion gpio_reg; +}; These types above should be in the header file and not in the C file, as per our current QOM guidelines. I don't think there's such a guideline, at least I did not find any mention of it in style and qom docs. It was necessary to move some type declarations to headers for types that are embedded in other objects because C needs the struct size for that, but I don't think that should be a general thing when it's not needed. The reason for that is that moving these to the header exposes internal object structure to users that should not need to know that so it breaks object encapsulation and also needs moving a bunch of includes to the header which then makes the users of this type also include those headers when they don't really need them but only need the type defines to instantiate the object and that's all they should have access to. So I think declaring types in the header should only be done for types that aren't full devices and are meant to be embedded as part of another device or a SoC but otherwise it's better to keep implementation closed and local to the object and not expose it unless really needed, that's why these are here. If you insist I can move these but I don't think there's really such recommendation and I don't think that's a good idea because of the above. Maybe it was something that was missed out of the recent documentation updates, but you can clearly see this has been the standard pattern for some time, including for recent devices such as the xlnx-versal. If there are any devices that don't follow this pattern then it is likely because they are based on older code. If you disagree with this, then start a new thread on qemu-devel with a new proposal and if everyone is agreement then that will be become the new standard. I think you should start a thread with a patch to style or qom docs about this to document this standard and if that's accepted then I also accept it as a real recommendation as my understanding of it was as above that it was needed for some deviecs to allow embedding them but not a general recommendation for all devices and I don't think it should be beacuse of braeaking encapsulation and introduces a lot of unneded includes so I'd keep it to those devices where it'e really needed which is what the docs currently say. Oh is there already a mention of this somewhere in the docs? Can you provide a link so we can check the wording? Certainly that's the way my own patches (and other people's patches) have been reviewed historically over the years. But I also said I can change this if you insist as for just this devices only used once it does not matter much so I take that as you still want this chnage so I can send another version but wait
Re: [PATCH 1/3] via-ide: Fix legacy mode emulation
On Mon, 9 Oct 2023, Mark Cave-Ayland wrote: On 08/10/2023 12:08, BALATON Zoltan wrote: On Sun, 8 Oct 2023, Mark Cave-Ayland wrote: On 05/10/2023 23:13, BALATON Zoltan wrote: The initial value for BARs were set in reset method for emulating legacy mode at start but this does not work because PCI code resets BARs after calling device reset method. This is certainly something I've noticed when testing previous versions of the VIA patches. Perhaps it's worth a separate thread to the PCI devs? I think I brought up this back then but was told current PCI code won't change and since that could break everything else that makes sense so this is something that we should take as given and accomodate that. I don't remember the details of that thread, but that's not too much of an issue here as the values won't be used. Additionally the values written to BARs were also wrong. I don't believe this is correct: according to the datasheet the values on reset are the ones given in the current reset code, so even if the reset function is overridden at a later data during PCI bus reset, I would leave these for now since it is a different issue. Those values are missing the IO space bit for one so they can't be correct as a BAR value no matter what the datasheet says. And since they are ineffective now I think it's best to remove them to avoid confusion. Maybe, or perhaps just fix up the missing IO space bit and add a comment pointing out these are the defaults, but currently they are erased on PCI bus reset? I have found it useful to have the values around to save having to reference the datasheet. The data sheet does not list the io space bits so fixing that would lead to values not matching data sheet any more. Also the defaults in the data sheet don't make much sense even with io space but as some of them match legacy ports while others don't. I can either drop this hunk leaving the current values there or add a FIXME comment saying they are ineffective but because they are overwritten (either by PCI code now or firmware/guest later) I think it's best to remove them any maybe only bring them back if we find they would be needed for any guest and what would be the correct default valuss here. I don't trust the data sheet on that and getting it from real hardware is also not really possible because the firmware could have overwritten them by the time you can get them. So I don't think keeping these here would help anybody, just cause confusion. Move setting the BARs to a callback on writing the PCI config regsiter that sets the compatibility mode (which firmwares needing this mode seem to do) and fix their values to program it to use legacy port numbers. As noted in a comment, we only do this when the BARs were unset before, because logs from real machine show this is how real chip works, even if it contradicts the data sheet which is not very clear about this. Signed-off-by: BALATON Zoltan --- hw/ide/via.c | 35 ++- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/hw/ide/via.c b/hw/ide/via.c index fff23803a6..8186190207 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -132,11 +132,6 @@ static void via_ide_reset(DeviceState *dev) pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, 0x01f0); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_1, 0x03f4); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_2, 0x0170); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_3, 0x0374); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_4, 0xcc01); /* BMIBA: 20-23h */ pci_set_long(pci_conf + PCI_INTERRUPT_LINE, 0x010e); /* IDE chip enable, IDE configuration 1/2, IDE FIFO Configuration*/ @@ -159,6 +154,35 @@ static void via_ide_reset(DeviceState *dev) pci_set_long(pci_conf + 0xc0, 0x00020001); } +static void via_ide_cfg_write(PCIDevice *pd, uint32_t addr, + uint32_t val, int len) +{ + pci_default_write_config(pd, addr, val, len); + /* + * Only set BARs if they are unset. Logs from real hardware show that + * writing class_prog to enable compatibility mode after BARs were set + * (possibly by firmware) it will use ports set by BARs not ISA ports + * (e.g. pegasos2 Linux does this and calls it non-100% native mode). Can you remind me again where the references are to non-100% native mode? The only thing I can find in Linux is https://github.com/torvalds/linux/blob/master/arch/powerpc/platforms/chrp/pci.c#L360 but that simply forces a switch to legacy mode, with no mention of "non-100% native mode". It was discussed somewhere in the via-ide thread we had when this was last touched for pegasos2 in March 2020. Basically the non-100% native mode is when ports are set by BARs but IRQs are still hard coded to 14-15. Linux can work with all 3 p
Re: [PATCH v4 03/10] hw/fsi: Introduce IBM's cfam,fsi-slave
Hello Cedric, Thanks for the review. On 9/11/23 07:19, Cédric Le Goater wrote: On 9/9/23 00:28, Ninad Palsule wrote: This is a part of patchset where IBM's Flexible Service Interface is introduced. The Common FRU Access Macro (CFAM), an address space containing various "engines" that drive accesses on busses internal and external to the POWER chip. Examples include the SBEFIFO and I2C masters. The engines hang off of an internal Local Bus (LBUS) which is described by the CFAM configuration block. The FSI slave: The slave is the terminal point of the FSI bus for FSI symbols addressed to it. Slaves can be cascaded off of one another. The slave's configuration registers appear in address space of the CFAM to which it is attached. Signed-off-by: Andrew Jeffery Signed-off-by: Cédric Le Goater Signed-off-by: Ninad Palsule --- v2: - Incorporated Joel's review comments. v3: - Incorporated Thomas Huth's review comments. --- hw/fsi/Kconfig | 9 ++ hw/fsi/cfam.c | 238 + hw/fsi/fsi-slave.c | 109 + hw/fsi/meson.build | 2 + hw/fsi/trace-events | 5 + include/hw/fsi/cfam.h | 61 ++ include/hw/fsi/fsi-slave.h | 29 + 7 files changed, 453 insertions(+) create mode 100644 hw/fsi/cfam.c create mode 100644 hw/fsi/fsi-slave.c create mode 100644 hw/fsi/trace-events create mode 100644 include/hw/fsi/cfam.h create mode 100644 include/hw/fsi/fsi-slave.h diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig index 2a9c49f2c9..087980be22 100644 --- a/hw/fsi/Kconfig +++ b/hw/fsi/Kconfig @@ -1,3 +1,12 @@ +config CFAM + bool + select FSI + select SCRATCHPAD + select LBUS + +config FSI + bool + config SCRATCHPAD bool select LBUS diff --git a/hw/fsi/cfam.c b/hw/fsi/cfam.c new file mode 100644 index 00..9a9e65d33f --- /dev/null +++ b/hw/fsi/cfam.c @@ -0,0 +1,238 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2023 IBM Corp. + * + * IBM Common FRU Access Macro + */ + +#include "qemu/osdep.h" + +#include "qapi/error.h" +#include "qemu/log.h" +#include "trace.h" + +#include "hw/fsi/bits.h" +#include "hw/fsi/cfam.h" +#include "hw/fsi/engine-scratchpad.h" + +#include "hw/qdev-properties.h" + +#define TO_REG(x) ((x) >> 2) + +#define CFAM_ENGINE_CONFIG TO_REG(0x04) + +#define CFAM_CONFIG_CHIP_ID TO_REG(0x00) +#define CFAM_CONFIG_CHIP_ID_P9 0xc0022d15 +#define CFAM_CONFIG_CHIP_ID_BREAK 0xc0de + +static uint64_t cfam_config_read(void *opaque, hwaddr addr, unsigned size) +{ + CFAMConfig *config; + CFAMState *cfam; + LBusNode *node; + int i; + + config = CFAM_CONFIG(opaque); + cfam = container_of(config, CFAMState, config); + + trace_cfam_config_read(addr, size); + + assert(size == 4); + assert(!(addr & 3)); These checks are useless if the MemoryRegionOps is defined accordingly. Good suggestion. Updated MemoryRegionOps registration and removed these asserts. + + switch (addr) { + case 0x00: + return CFAM_CONFIG_CHIP_ID_P9; + case 0x04: + return ENGINE_CONFIG_NEXT + | 0x0001 /* slots */ + | 0x1000 /* version */ + | ENGINE_CONFIG_TYPE_PEEK /* type */ + | 0x000c; /* crc */ + case 0x08: + return ENGINE_CONFIG_NEXT + | 0x0001 /* slots */ + | 0x5000 /* version */ + | ENGINE_CONFIG_TYPE_FSI /* type */ + | 0x000a; /* crc */ + break; + default: + /* FIXME: Improve this */ This looks hacky. What is it suppose to do ? Yes, This is kind of work in progress. Looks like it is expecting address 0xc onwards devices and if we find any device then it will return config data for that device otherwise its a bad things and sends a break to reset. + i = 0xc; + QLIST_FOREACH(node, &cfam->lbus.devices, next) { + if (i == addr) { + return LBUS_DEVICE_GET_CLASS(node->ldev)->config; + } + i += size; + } + + if (i == addr) { + return 0; + } + + /* + * As per FSI specification, This is a magic value at address 0 of + * given FSI port. This causes FSI master to send BREAK command for + * initialization and recovery. + */ + return 0xc0de; we could use a definition. Fixed + } +} + +static void cfam_config_write(void *opaque, hwaddr addr, uint64_t data, + unsigned size) +{ + CFAMConfig *s = CFAM_CONFIG(opaque); + + trace_cfam_config_write(addr, size, data); + + assert(size == 4); + assert(!(addr & 3)); These checks are useless if the MemoryRegionOps is defined accordingly. Remove
Re: [PATCH 2/3] hw/pci-host: Add emulation of Mai Logic Articia S
On Mon, 9 Oct 2023, Mark Cave-Ayland wrote: On 08/10/2023 19:08, BALATON Zoltan wrote: On Sun, 8 Oct 2023, Mark Cave-Ayland wrote: On 05/10/2023 23:13, BALATON Zoltan wrote: The Articia S is a generic chipset supporting several different CPUs that were used on some PPC boards. This is a minimal emulation of the parts needed for emulating the AmigaOne board. Signed-off-by: BALATON Zoltan --- hw/pci-host/Kconfig | 5 + hw/pci-host/articia.c | 266 ++ hw/pci-host/meson.build | 2 + include/hw/pci-host/articia.h | 17 +++ 4 files changed, 290 insertions(+) create mode 100644 hw/pci-host/articia.c create mode 100644 include/hw/pci-host/articia.h diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig index a07070eddf..33014c80a4 100644 --- a/hw/pci-host/Kconfig +++ b/hw/pci-host/Kconfig @@ -73,6 +73,11 @@ config SH_PCI bool select PCI +config ARTICIA + bool + select PCI + select I8259 + config MV64361 bool select PCI diff --git a/hw/pci-host/articia.c b/hw/pci-host/articia.c new file mode 100644 index 00..80558e1c47 --- /dev/null +++ b/hw/pci-host/articia.c @@ -0,0 +1,266 @@ +/* + * Mai Logic Articia S emulation + * + * Copyright (c) 2023 BALATON Zoltan + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/pci/pci_device.h" +#include "hw/pci/pci_host.h" +#include "hw/irq.h" +#include "hw/i2c/bitbang_i2c.h" +#include "hw/intc/i8259.h" +#include "hw/pci-host/articia.h" + +OBJECT_DECLARE_SIMPLE_TYPE(ArticiaState, ARTICIA) + +OBJECT_DECLARE_SIMPLE_TYPE(ArticiaHostState, ARTICIA_PCI_HOST) +struct ArticiaHostState { + PCIDevice parent_obj; + + ArticiaState *as; +}; + +/* TYPE_ARTICIA */ + +struct ArticiaState { + PCIHostState parent_obj; + + qemu_irq irq[PCI_NUM_PINS]; + MemoryRegion io; + MemoryRegion mem; + MemoryRegion reg; + + bitbang_i2c_interface smbus; + uint32_t gpio; /* bits 0-7 in, 8-15 out, 16-23 direction (0 in, 1 out) */ + hwaddr gpio_base; + MemoryRegion gpio_reg; +}; These types above should be in the header file and not in the C file, as per our current QOM guidelines. I don't think there's such a guideline, at least I did not find any mention of it in style and qom docs. It was necessary to move some type declarations to headers for types that are embedded in other objects because C needs the struct size for that, but I don't think that should be a general thing when it's not needed. The reason for that is that moving these to the header exposes internal object structure to users that should not need to know that so it breaks object encapsulation and also needs moving a bunch of includes to the header which then makes the users of this type also include those headers when they don't really need them but only need the type defines to instantiate the object and that's all they should have access to. So I think declaring types in the header should only be done for types that aren't full devices and are meant to be embedded as part of another device or a SoC but otherwise it's better to keep implementation closed and local to the object and not expose it unless really needed, that's why these are here. If you insist I can move these but I don't think there's really such recommendation and I don't think that's a good idea because of the above. Maybe it was something that was missed out of the recent documentation updates, but you can clearly see this has been the standard pattern for some time, including for recent devices such as the xlnx-versal. If there are any devices that don't follow this pattern then it is likely because they are based on older code. If you disagree with this, then start a new thread on qemu-devel with a new proposal and if everyone is agreement then that will be become the new standard. I think you should start a thread with a patch to style or qom docs about this to document this standard and if that's accepted then I also accept it as a real recommendation as my understanding of it was as above that it was needed for some deviecs to allow embedding them but not a general recommendation for all devices and I don't think it should be beacuse of braeaking encapsulation and introduces a lot of unneded includes so I'd keep it to those devices where it'e really needed which is what the docs currently say. But I also said I can change this if you insist as for just this devices only used once it does not matter much so I take that as you still want this chnage so I can send another version but wait for the opinion of the maintainers if they want anything else changed so I cah do all remaining changes in next version. Regards, BALATON Zoltan
Re: [PATCH] target/sparc: Clean up global variable shadowing
On 09/10/2023 10:24, Philippe Mathieu-Daudé wrote: Fix: target/sparc/translate.c:2823:66: error: declaration shadows a variable in the global scope [-Werror,-Wshadow] static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_env tcg_env) ^ include/tcg/tcg.h:579:17: note: previous declaration is here extern TCGv_env tcg_env; ^ Signed-off-by: Philippe Mathieu-Daudé --- target/sparc/translate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/sparc/translate.c b/target/sparc/translate.c index f92ff80ac8..26ed371109 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -2820,19 +2820,19 @@ static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs) } #ifndef CONFIG_USER_ONLY -static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_env tcg_env) +static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_env env) { TCGv_i32 r_tl = tcg_temp_new_i32(); /* load env->tl into r_tl */ -tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl)); +tcg_gen_ld_i32(r_tl, env, offsetof(CPUSPARCState, tl)); /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */ tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK); /* calculate offset to current trap state from env->ts, reuse r_tl */ tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state)); -tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts)); +tcg_gen_addi_ptr(r_tsptr, env, offsetof(CPUSPARCState, ts)); /* tsptr = env->ts[env->tl & MAXTL_MASK] */ { Reviewed-by: Mark Cave-Ayland ATB, Mark.
Re: [PATCH 2/3] hw/pci-host: Add emulation of Mai Logic Articia S
On 08/10/2023 19:08, BALATON Zoltan wrote: On Sun, 8 Oct 2023, Mark Cave-Ayland wrote: On 05/10/2023 23:13, BALATON Zoltan wrote: The Articia S is a generic chipset supporting several different CPUs that were used on some PPC boards. This is a minimal emulation of the parts needed for emulating the AmigaOne board. Signed-off-by: BALATON Zoltan --- hw/pci-host/Kconfig | 5 + hw/pci-host/articia.c | 266 ++ hw/pci-host/meson.build | 2 + include/hw/pci-host/articia.h | 17 +++ 4 files changed, 290 insertions(+) create mode 100644 hw/pci-host/articia.c create mode 100644 include/hw/pci-host/articia.h diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig index a07070eddf..33014c80a4 100644 --- a/hw/pci-host/Kconfig +++ b/hw/pci-host/Kconfig @@ -73,6 +73,11 @@ config SH_PCI bool select PCI +config ARTICIA + bool + select PCI + select I8259 + config MV64361 bool select PCI diff --git a/hw/pci-host/articia.c b/hw/pci-host/articia.c new file mode 100644 index 00..80558e1c47 --- /dev/null +++ b/hw/pci-host/articia.c @@ -0,0 +1,266 @@ +/* + * Mai Logic Articia S emulation + * + * Copyright (c) 2023 BALATON Zoltan + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/pci/pci_device.h" +#include "hw/pci/pci_host.h" +#include "hw/irq.h" +#include "hw/i2c/bitbang_i2c.h" +#include "hw/intc/i8259.h" +#include "hw/pci-host/articia.h" + +OBJECT_DECLARE_SIMPLE_TYPE(ArticiaState, ARTICIA) + +OBJECT_DECLARE_SIMPLE_TYPE(ArticiaHostState, ARTICIA_PCI_HOST) +struct ArticiaHostState { + PCIDevice parent_obj; + + ArticiaState *as; +}; + +/* TYPE_ARTICIA */ + +struct ArticiaState { + PCIHostState parent_obj; + + qemu_irq irq[PCI_NUM_PINS]; + MemoryRegion io; + MemoryRegion mem; + MemoryRegion reg; + + bitbang_i2c_interface smbus; + uint32_t gpio; /* bits 0-7 in, 8-15 out, 16-23 direction (0 in, 1 out) */ + hwaddr gpio_base; + MemoryRegion gpio_reg; +}; These types above should be in the header file and not in the C file, as per our current QOM guidelines. I don't think there's such a guideline, at least I did not find any mention of it in style and qom docs. It was necessary to move some type declarations to headers for types that are embedded in other objects because C needs the struct size for that, but I don't think that should be a general thing when it's not needed. The reason for that is that moving these to the header exposes internal object structure to users that should not need to know that so it breaks object encapsulation and also needs moving a bunch of includes to the header which then makes the users of this type also include those headers when they don't really need them but only need the type defines to instantiate the object and that's all they should have access to. So I think declaring types in the header should only be done for types that aren't full devices and are meant to be embedded as part of another device or a SoC but otherwise it's better to keep implementation closed and local to the object and not expose it unless really needed, that's why these are here. If you insist I can move these but I don't think there's really such recommendation and I don't think that's a good idea because of the above. Maybe it was something that was missed out of the recent documentation updates, but you can clearly see this has been the standard pattern for some time, including for recent devices such as the xlnx-versal. If there are any devices that don't follow this pattern then it is likely because they are based on older code. If you disagree with this, then start a new thread on qemu-devel with a new proposal and if everyone is agreement then that will be become the new standard. ATB, Mark.
Re: [PATCH 1/3] via-ide: Fix legacy mode emulation
On 08/10/2023 12:08, BALATON Zoltan wrote: On Sun, 8 Oct 2023, Mark Cave-Ayland wrote: On 05/10/2023 23:13, BALATON Zoltan wrote: The initial value for BARs were set in reset method for emulating legacy mode at start but this does not work because PCI code resets BARs after calling device reset method. This is certainly something I've noticed when testing previous versions of the VIA patches. Perhaps it's worth a separate thread to the PCI devs? I think I brought up this back then but was told current PCI code won't change and since that could break everything else that makes sense so this is something that we should take as given and accomodate that. I don't remember the details of that thread, but that's not too much of an issue here as the values won't be used. Additionally the values written to BARs were also wrong. I don't believe this is correct: according to the datasheet the values on reset are the ones given in the current reset code, so even if the reset function is overridden at a later data during PCI bus reset, I would leave these for now since it is a different issue. Those values are missing the IO space bit for one so they can't be correct as a BAR value no matter what the datasheet says. And since they are ineffective now I think it's best to remove them to avoid confusion. Maybe, or perhaps just fix up the missing IO space bit and add a comment pointing out these are the defaults, but currently they are erased on PCI bus reset? I have found it useful to have the values around to save having to reference the datasheet. Move setting the BARs to a callback on writing the PCI config regsiter that sets the compatibility mode (which firmwares needing this mode seem to do) and fix their values to program it to use legacy port numbers. As noted in a comment, we only do this when the BARs were unset before, because logs from real machine show this is how real chip works, even if it contradicts the data sheet which is not very clear about this. Signed-off-by: BALATON Zoltan --- hw/ide/via.c | 35 ++- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/hw/ide/via.c b/hw/ide/via.c index fff23803a6..8186190207 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -132,11 +132,6 @@ static void via_ide_reset(DeviceState *dev) pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, 0x01f0); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_1, 0x03f4); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_2, 0x0170); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_3, 0x0374); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_4, 0xcc01); /* BMIBA: 20-23h */ pci_set_long(pci_conf + PCI_INTERRUPT_LINE, 0x010e); /* IDE chip enable, IDE configuration 1/2, IDE FIFO Configuration*/ @@ -159,6 +154,35 @@ static void via_ide_reset(DeviceState *dev) pci_set_long(pci_conf + 0xc0, 0x00020001); } +static void via_ide_cfg_write(PCIDevice *pd, uint32_t addr, + uint32_t val, int len) +{ + pci_default_write_config(pd, addr, val, len); + /* + * Only set BARs if they are unset. Logs from real hardware show that + * writing class_prog to enable compatibility mode after BARs were set + * (possibly by firmware) it will use ports set by BARs not ISA ports + * (e.g. pegasos2 Linux does this and calls it non-100% native mode). Can you remind me again where the references are to non-100% native mode? The only thing I can find in Linux is https://github.com/torvalds/linux/blob/master/arch/powerpc/platforms/chrp/pci.c#L360 but that simply forces a switch to legacy mode, with no mention of "non-100% native mode". It was discussed somewhere in the via-ide thread we had when this was last touched for pegasos2 in March 2020. Basically the non-100% native mode is when ports are set by BARs but IRQs are still hard coded to 14-15. Linux can work with all 3 possible modes: legacy (both ports and IRQs are hard coded to ISA values), native (using BARs and PCI config 0x3c for a single interrupt for both channels, vt82c686 data sheet does not document this but vt8231 has a comment saying native mode only) and non-100% native mode where BARs are effective to set port addresses but IRQs don't respect 0x3c but use 14-15 as in legacy mode. Some machines only work in non-100% native mode such as pegasos2 and Linux has some quirks for this. Other OSes running on this machine work with what the firmware has set up and can't work with anything else so we need to emulate what those OSes want (which matches real hardware) because Linux can usually cope anyway. On pegasso2 MorphOS uses BARs but expects IRQ 14-15 which is what the firmware also sets up by setting mode to native in the PCI config of the IDE func yet IRQs are fixed at 14-15. Linux forces its driver to use legacy i
Re: [PATCH v2 3/3] qom: Link multiple numa nodes to device using a new object
On Mon, 9 Oct 2023 13:30:48 +0100 Jonathan Cameron wrote: > On Sun, 8 Oct 2023 01:47:40 +0530 > wrote: > > > From: Ankit Agrawal > > > > NVIDIA GPU's support MIG (Mult-Instance GPUs) feature [1], which allows > > partitioning of the GPU device resources (including device memory) into > > several (upto 8) isolated instances. Each of the partitioned memory needs > > a dedicated NUMA node to operate. The partitions are not fixed and they > > can be created/deleted at runtime. > > > > Unfortunately Linux OS does not provide a means to dynamically > > create/destroy > > NUMA nodes and such feature implementation is not expected to be trivial. > > The > > nodes that OS discovers at the boot time while parsing SRAT remains fixed. > > So > > we utilize the GI Affinity structures that allows association between nodes > > and devices. Multiple GI structures per BDF is possible, allowing creation > > of > > multiple nodes by exposing unique PXM in each of these structures. > > > > Introducing a new nvidia-acpi-generic-initiator object, which inherits from > > the generic acpi-generic-initiator object to allow a BDF to be associated > > with > > more than 1 nodes. > > > > An admin can provide the range of nodes using numa-node-start and > > numa-node-count and link it to a device by providing its id. The following > > sample creates 8 nodes and link them to the device dev0: > > > > -numa node,nodeid=2 \ > > -numa node,nodeid=3 \ > > -numa node,nodeid=4 \ > > -numa node,nodeid=5 \ > > -numa node,nodeid=6 \ > > -numa node,nodeid=7 \ > > -numa node,nodeid=8 \ > > -numa node,nodeid=9 \ > > -device > > vfio-pci-nohotplug,host=0009:01:00.0,bus=pcie.0,addr=04.0,rombar=0,id=dev0 \ > > -object > > nvidia-acpi-generic-initiator,id=gi0,device=dev0,numa-node-start=2,numa-node-count=8 > > \ > > If you go this way, use an array of references to the numa nodes instead of a > start and number. > There is no obvious reason why they should be contiguous that I can see. Yup, I was looking for other places we allow a list syntax, I only found fds=a:b:...:z, which is also used for vhostfds=. I didn't find a property beyond the string type to hold this though. > I think it is simpler the other way around though - so have the numa nodes > point at the > vfio-pci-nohotplug device. Do you have a syntax you'd propose for this? I'm having trouble seeing how it makes things simpler. Thanks, Alex > > [1] https://www.nvidia.com/en-in/technologies/multi-instance-gpu > > > > Signed-off-by: Ankit Agrawal > > --- > > hw/acpi/acpi-generic-initiator.c | 61 > > include/hw/acpi/acpi-generic-initiator.h | 12 + > > qapi/qom.json| 24 +- > > 3 files changed, 95 insertions(+), 2 deletions(-) > > > > diff --git a/hw/acpi/acpi-generic-initiator.c > > b/hw/acpi/acpi-generic-initiator.c > > index 1ae79639be..8ef887c3a4 100644 > > --- a/hw/acpi/acpi-generic-initiator.c > > +++ b/hw/acpi/acpi-generic-initiator.c > > @@ -150,3 +150,64 @@ void build_srat_generic_initiator(GArray *table_data) > > } > > g_slist_free(list); > > } > > + > > +static void > > +nvidia_acpi_generic_initiator_set_node_start(Object *obj, Visitor *v, > > + const char *name, void > > *opaque, > > + Error **errp) > > +{ > > +AcpiGenericInitiator *gi = ACPI_GENERIC_INITIATOR(obj); > > +uint32_t value; > > + > > +if (!visit_type_uint32(v, name, &value, errp)) { > > +return; > > +} > > + > > +if (value >= MAX_NODES) { > > +return; > > +} > > + > > +gi->node = value; > > +} > > + > > +static void > > +nvidia_acpi_generic_initiator_set_node_count(Object *obj, Visitor *v, > > + const char *name, void > > *opaque, > > + Error **errp) > > +{ > > +AcpiGenericInitiator *gi = ACPI_GENERIC_INITIATOR(obj); > > +uint32_t value; > > + > > +if (!visit_type_uint32(v, name, &value, errp)) { > > +return; > > +} > > + > > +gi->node_count = value; > > +} > > + > > +static void nvidia_acpi_generic_initiator_class_init(ObjectClass *oc, void > > *data) > > +{ > > +object_class_property_add(oc, > > NVIDIA_ACPI_GENERIC_INITIATOR_NODE_START_PROP, > > + "uint32", NULL, > > + nvidia_acpi_generic_initiator_set_node_start, > > + NULL, NULL); > > +object_class_property_add(oc, > > NVIDIA_ACPI_GENERIC_INITIATOR_NODE_COUNT_PROP, > > + "uint32", NULL, > > + nvidia_acpi_generic_initiator_set_node_count, > > + NULL, NULL); > > +} > > + > > +static const TypeInfo nvidia_acpi_generic_initiator_info = { > > +
Re: [PATCH v12 09/10] migration: Implement MigrateChannelList to hmp migration flow.
Het Gala writes: > Integrate MigrateChannelList with all transport backends > (socket, exec and rdma) for both src and dest migration > endpoints for hmp migration. > > Suggested-by: Aravind Retnakaran > Signed-off-by: Het Gala > --- > migration/migration-hmp-cmds.c | 15 +-- > migration/migration.c | 5 ++--- > migration/migration.h | 3 ++- > 3 files changed, 17 insertions(+), 6 deletions(-) > > diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c > index a2e6a5c51e..21b57f7ed8 100644 > --- a/migration/migration-hmp-cmds.c > +++ b/migration/migration-hmp-cmds.c > @@ -441,9 +441,14 @@ void hmp_migrate_incoming(Monitor *mon, const QDict > *qdict) > { > Error *err = NULL; > const char *uri = qdict_get_str(qdict, "uri"); > +MigrationChannelList *caps = NULL; > +g_autoptr(MigrationChannel) channel = NULL; No g_autoptr here because the list code will already free the channel. > > -qmp_migrate_incoming(uri, false, NULL, &err); > +migrate_uri_parse(uri, &channel, &err); Need to check the return value of this function. $ (echo "migrate -d unix:") | ./qemu-system-x86_64 -monitor stdio -display none QEMU 8.1.50 monitor - type 'help' for more information (qemu) migrate -d unix: Segmentation fault (core dumped) > +QAPI_LIST_PREPEND(caps, channel); > > +qmp_migrate_incoming(NULL, true, caps, &err); > +qapi_free_MigrationChannelList(caps); > hmp_handle_error(mon, err); > } > > @@ -730,9 +735,15 @@ void hmp_migrate(Monitor *mon, const QDict *qdict) > bool resume = qdict_get_try_bool(qdict, "resume", false); > const char *uri = qdict_get_str(qdict, "uri"); > Error *err = NULL; > +MigrationChannelList *caps = NULL; > +g_autoptr(MigrationChannel) channel = NULL; > > -qmp_migrate(uri, false, NULL, !!blk, blk, !!inc, inc, > +migrate_uri_parse(uri, &channel, &err); > +QAPI_LIST_PREPEND(caps, channel); > + > +qmp_migrate(NULL, true, caps, !!blk, blk, !!inc, inc, > false, false, true, resume, &err); > +qapi_free_MigrationChannelList(caps); > if (hmp_handle_error(mon, err)) { > return; > }
Re: [PATCH v2] misc/pca9552: Fix for pca9552 not getting reset
Hello Glenn, On 10/5/23 23:10, Glenn Miles wrote: Testing of the pca9552 device on the powernv platform showed that the reset method was not being called when an instance of the device was realized. This was causing the INPUT0/INPUT1 POR values to be incorrect. Fixed by overriding the parent pca955x_realize method with a new pca9552_realize method which first calls the parent pca955x_realize method followed by the pca9552_reset function. Signed-off-by: Glenn Miles --- hw/misc/pca9552.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hw/misc/pca9552.c b/hw/misc/pca9552.c index fff19e369a..bc12dced7f 100644 --- a/hw/misc/pca9552.c +++ b/hw/misc/pca9552.c @@ -384,6 +384,12 @@ static void pca955x_realize(DeviceState *dev, Error **errp) qdev_init_gpio_out(dev, s->gpio, k->pin_count); } +static void pca9552_realize(DeviceState *dev, Error **errp) +{ +pca955x_realize(dev, errp); +pca9552_reset(dev); +} This looks wrong. You need both handlers, a realize and a reset. Thanks, C. + static Property pca955x_properties[] = { DEFINE_PROP_STRING("description", PCA955xState, description), DEFINE_PROP_END_OF_LIST(), @@ -416,7 +422,7 @@ static void pca9552_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); PCA955xClass *pc = PCA955X_CLASS(oc); -dc->reset = pca9552_reset; +dc->realize = pca9552_realize; dc->vmsd = &pca9552_vmstate; pc->max_reg = PCA9552_LS3; pc->pin_count = 16;
Re: [PATCH v12 00/10] migration: Modify 'migrate' and 'migrate-incoming' QAPI commands for migration
Het Gala writes: > This is v12 patchset of modified 'migrate' and 'migrate-incoming' QAPI design > for upstream review. > > Would like to thank all the maintainers that actively participated in the v11 > patchset discussion and gave insightful suggestions to improve the patches. > > Link to previous upstream community patchset links: > v1: https://lists.gnu.org/archive/html/qemu-devel/2022-12/msg04339.html > v2: https://lists.gnu.org/archive/html/qemu-devel/2023-02/msg02106.html > v3: https://lists.gnu.org/archive/html/qemu-devel/2023-02/msg02473.html > v4: https://lists.gnu.org/archive/html/qemu-devel/2023-05/msg03064.html > v5: https://lists.gnu.org/archive/html/qemu-devel/2023-05/msg04845.html > v6: https://lists.gnu.org/archive/html/qemu-devel/2023-06/msg01251.html > v7: https://lists.gnu.org/archive/html/qemu-devel/2023-07/msg02027.html > v8: https://lists.gnu.org/archive/html/qemu-devel/2023-07/msg02770.html > v9: https://lists.gnu.org/archive/html/qemu-devel/2023-07/msg04216.html > v10: https://lists.gnu.org/archive/html/qemu-devel/2023-07/msg05022.html > v11: https://lists.gnu.org/archive/html/qemu-devel/2023-10/msg00740.html > > v11 -> v12 changelog: > --- > - Resolved double-freeing when using g_autoptr in structures that are > nested into another. > - Overwriting of pointers to an existing allocated memory is solved at > various places. > - Use of g_autoptr caused make check errors in non-error path while going > out of scope inside function. Added g_steal_pointer() in the non-error > paths wherever required. Please run make check before sending: ▶ 242/355 qcow2 181 FAIL You can also push your code to your gitlab and run a pipeline with the branch.
[PATCH] hw/loongarch: remove global loaderparams variable
Passing the struct around explicitly makes the control-flow more obvious. Signed-off-by: Thomas Weißschuh --- hw/loongarch/virt.c | 50 - 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 2629128aeda4..ea7eb408c071 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -47,6 +47,13 @@ #include "qemu/error-report.h" +struct loaderparams { +uint64_t ram_size; +const char *kernel_filename; +const char *kernel_cmdline; +const char *initrd_filename; +}; + static void virt_flash_create(LoongArchMachineState *lams) { DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01); @@ -411,24 +418,17 @@ static const MemoryRegionOps loongarch_virt_pm_ops = { } }; -static struct _loaderparams { -uint64_t ram_size; -const char *kernel_filename; -const char *kernel_cmdline; -const char *initrd_filename; -} loaderparams; - static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr) { return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS); } -static int64_t load_kernel_info(void) +static int64_t load_kernel_info(const struct loaderparams *loaderparams) { uint64_t kernel_entry, kernel_low, kernel_high; ssize_t kernel_size; -kernel_size = load_elf(loaderparams.kernel_filename, NULL, +kernel_size = load_elf(loaderparams->kernel_filename, NULL, cpu_loongarch_virt_to_phys, NULL, &kernel_entry, &kernel_low, &kernel_high, NULL, 0, @@ -436,7 +436,7 @@ static int64_t load_kernel_info(void) if (kernel_size < 0) { error_report("could not load kernel '%s': %s", - loaderparams.kernel_filename, + loaderparams->kernel_filename, load_elf_strerror(kernel_size)); exit(1); } @@ -728,7 +728,8 @@ static void reset_load_elf(void *opaque) } } -static void fw_cfg_add_kernel_info(FWCfgState *fw_cfg) +static void fw_cfg_add_kernel_info(const struct loaderparams *loaderparams, + FWCfgState *fw_cfg) { /* * Expose the kernel, the command line, and the initrd in fw_cfg. @@ -737,36 +738,38 @@ static void fw_cfg_add_kernel_info(FWCfgState *fw_cfg) */ load_image_to_fw_cfg(fw_cfg, FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA, - loaderparams.kernel_filename, + loaderparams->kernel_filename, false); -if (loaderparams.initrd_filename) { +if (loaderparams->initrd_filename) { load_image_to_fw_cfg(fw_cfg, FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA, - loaderparams.initrd_filename, false); + loaderparams->initrd_filename, false); } -if (loaderparams.kernel_cmdline) { +if (loaderparams->kernel_cmdline) { fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, - strlen(loaderparams.kernel_cmdline) + 1); + strlen(loaderparams->kernel_cmdline) + 1); fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, - loaderparams.kernel_cmdline); + loaderparams->kernel_cmdline); } } -static void loongarch_firmware_boot(LoongArchMachineState *lams) +static void loongarch_firmware_boot(LoongArchMachineState *lams, +const struct loaderparams *loaderparams) { -fw_cfg_add_kernel_info(lams->fw_cfg); +fw_cfg_add_kernel_info(loaderparams, lams->fw_cfg); } -static void loongarch_direct_kernel_boot(LoongArchMachineState *lams) +static void loongarch_direct_kernel_boot(LoongArchMachineState *lams, + const struct loaderparams *loaderparams) { MachineState *machine = MACHINE(lams); int64_t kernel_addr = 0; LoongArchCPU *lacpu; int i; -kernel_addr = load_kernel_info(); +kernel_addr = load_kernel_info(loaderparams); if (!machine->firmware) { for (i = 0; i < machine->smp.cpus; i++) { lacpu = LOONGARCH_CPU(qemu_get_cpu(i)); @@ -793,6 +796,7 @@ static void loongarch_init(MachineState *machine) MachineClass *mc = MACHINE_GET_CLASS(machine); CPUState *cpu; char *ramName = NULL; +struct loaderparams loaderparams; if (!cpu_model) { cpu_model = LOONGARCH_CPU_TYPE_NAME("la464"); @@ -898,9 +902,9 @@ static void loongarch_init(MachineState *machine) /* load the kernel. */ if (loaderparams.kernel_filename) { if (lams->bios_loaded) { -loongarch_firmware_boot(lams); +loongarch_firmware_boot(lams, &loaderparams); } else { -loongarch_direct_kernel_boot(lams); +loongarch_direct_kernel_boot(lams, &loaderparams);
RE: [PATCH V4 10/10] target/arm/kvm: Write CPU state back to KVM on reset
Hello, Perhaps I need to drop this patch from this patch-set as it is ARM specific. I pulled this from RFC V2 of Virtual CPU Hotplug Support on ARMv8 and is not required by other architectures trying to implement Virtual CPU Hotplug Support. https://lore.kernel.org/qemu-devel/20230926103654.34424-2-salil.me...@huawei.com/ I will retain the Reviewed-by's collected here in the RFC V3 patch-set. Sorry, for the noise. Thanks Salil. > From: Salil Mehta > Sent: Monday, October 9, 2023 9:36 PM > To: qemu-devel@nongnu.org; qemu-...@nongnu.org > Cc: Salil Mehta ; m...@kernel.org; jean- > phili...@linaro.org; Jonathan Cameron ; > lpieral...@kernel.org; peter.mayd...@linaro.org; > richard.hender...@linaro.org; imamm...@redhat.com; andrew.jo...@linux.dev; > da...@redhat.com; phi...@linaro.org; eric.au...@redhat.com; > oliver.up...@linux.dev; pbonz...@redhat.com; m...@redhat.com; > w...@kernel.org; gs...@redhat.com; raf...@kernel.org; > alex.ben...@linaro.org; li...@armlinux.org.uk; > dar...@os.amperecomputing.com; il...@os.amperecomputing.com; > vis...@os.amperecomputing.com; karl.heub...@oracle.com; > miguel.l...@oracle.com; salil.me...@opnsrc.net; zhukeqian > ; wangxiongfeng (C) ; > wangyanan (Y) ; jiakern...@gmail.com; > maob...@loongson.cn; lixiang...@loongson.cn; Linuxarm > Subject: [PATCH V4 10/10] target/arm/kvm: Write CPU state back to KVM on > reset > > From: Jean-Philippe Brucker > > When a KVM vCPU is reset following a PSCI CPU_ON call, its power state > is not synchronized with KVM at the moment. Because the vCPU is not > marked dirty, we miss the call to kvm_arch_put_registers() that writes > to KVM's MP_STATE. Force mp_state synchronization. > > Signed-off-by: Jean-Philippe Brucker > Signed-off-by: Salil Mehta > Reviewed-by: Alex Bennée > Reviewed-by: Gavin Shan > --- > target/arm/kvm.c | 8 +++- > 1 file changed, 7 insertions(+), 1 deletion(-) > > diff --git a/target/arm/kvm.c b/target/arm/kvm.c > index b66b936a95..8cb70b9e7c 100644 > --- a/target/arm/kvm.c > +++ b/target/arm/kvm.c > @@ -642,11 +642,12 @@ void kvm_arm_cpu_post_load(ARMCPU *cpu) > void kvm_arm_reset_vcpu(ARMCPU *cpu) > { > int ret; > +CPUState *cs = CPU(cpu); > > /* Re-init VCPU so that all registers are set to > * their respective reset values. > */ > -ret = kvm_arm_vcpu_init(CPU(cpu)); > +ret = kvm_arm_vcpu_init(cs); > if (ret < 0) { > fprintf(stderr, "kvm_arm_vcpu_init failed: %s\n", strerror(-ret)); > abort(); > @@ -663,6 +664,11 @@ void kvm_arm_reset_vcpu(ARMCPU *cpu) > * for the same reason we do so in kvm_arch_get_registers(). > */ > write_list_to_cpustate(cpu); > +/* > + * Ensure we call kvm_arch_put_registers(). The vCPU isn't marked > dirty if > + * it was parked in KVM and is now booting from a PSCI CPU_ON call. > + */ > +cs->vcpu_dirty = true; > } > > /* > -- > 2.34.1
Re: [PATCH 3/3] vfio/ccw: Remove redundant definition of TYPE_VFIO_CCW
On 10/9/23 20:58, Eric Farman wrote: On Mon, 2023-10-09 at 10:20 +0800, Zhenzhong Duan wrote: No functional changes. Signed-off-by: Zhenzhong Duan I see Cedric has already queued this, but FWIW: Reviewed-by: Eric Farman I will take the new tags when I rebase. Thanks, C. --- include/hw/s390x/vfio-ccw.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/hw/s390x/vfio-ccw.h b/include/hw/s390x/vfio- ccw.h index 63a909eb7e..4209d27657 100644 --- a/include/hw/s390x/vfio-ccw.h +++ b/include/hw/s390x/vfio-ccw.h @@ -22,6 +22,4 @@ #define TYPE_VFIO_CCW "vfio-ccw" OBJECT_DECLARE_SIMPLE_TYPE(VFIOCCWDevice, VFIO_CCW) -#define TYPE_VFIO_CCW "vfio-ccw" - #endif
RE: [PATCH v2 3/3] target/hexagon: avoid shadowing globals
> -Original Message- > From: Philippe Mathieu-Daudé > Sent: Monday, October 9, 2023 1:43 AM > To: Brian Cain ; qemu-devel@nongnu.org > Cc: arm...@redhat.com; richard.hender...@linaro.org; > peter.mayd...@linaro.org; Matheus Bernardino (QUIC) > ; stefa...@redhat.com; a...@rev.ng; > a...@rev.ng; Marco Liebel (QUIC) ; > ltaylorsimp...@gmail.com; Thomas Huth ; Daniel P. > Berrangé > Subject: Re: [PATCH v2 3/3] target/hexagon: avoid shadowing globals > > WARNING: This email originated from outside of Qualcomm. Please be wary of > any links or attachments, and do not enable macros. > > On 9/10/23 08:09, Philippe Mathieu-Daudé wrote: > > Hi Brian, > > > > On 6/10/23 00:22, Brian Cain wrote: > >> The typedef `vaddr` is shadowed by `vaddr` identifiers, so we rename the > >> identifiers to avoid shadowing the type name. > > > > This one surprises me, since we have other occurences: > > > > include/exec/memory.h:751:bool memory_get_xlat_addr(IOMMUTLBEntry > > *iotlb, void **vaddr, > > include/qemu/plugin.h:199:void qemu_plugin_vcpu_mem_cb(CPUState > > *cpu, uint64_t vaddr, > > target/arm/internals.h:643:G_NORETURN void > > arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, > > target/i386/tcg/helper-tcg.h:70:G_NORETURN void > > handle_unaligned_access(CPUX86State *env, vaddr vaddr, > > ... > > > > $ git grep -w vaddr, | wc -l > > 207 > > > > What is the error/warning like? > > OK I could reproduce, I suppose you are building with Clang which > doesn't support shadow-local so you get global warnings too (as > mentioned in this patch subject...): No -- I generally build with gcc and only double-check the clang results to make sure I don't see any new failures there. But I've not tested "-Wshadow" with clang yet. I found these by adding "-Wshadow=global" to "-Wshadow=local". I thought it might be useful to address these too while we're here. > In file included from ../../gdbstub/trace.h:1, > from ../../gdbstub/softmmu.c:30: > trace/trace-gdbstub.h: In function '_nocheck__trace_gdbstub_hit_watchpoint': > trace/trace-gdbstub.h:903:106: error: declaration of 'vaddr' shadows a > global declaration [-Werror=shadow] >903 | static inline void _nocheck__trace_gdbstub_hit_watchpoint(const > char * type, int cpu_gdb_index, uint64_t vaddr) >| > ~^ > In file included from include/sysemu/accel-ops.h:13, > from include/sysemu/cpus.h:4, > from ../../gdbstub/softmmu.c:21: > include/exec/cpu-common.h:21:18: note: shadowed declaration is here > 21 | typedef uint64_t vaddr; >| ^ > trace/trace-gdbstub.h: In function 'trace_gdbstub_hit_watchpoint': > trace/trace-gdbstub.h:923:96: error: declaration of 'vaddr' shadows a > global declaration [-Werror=shadow] >923 | static inline void trace_gdbstub_hit_watchpoint(const char * > type, int cpu_gdb_index, uint64_t vaddr) >| >~^ > include/exec/cpu-common.h:21:18: note: shadowed declaration is here > 21 | typedef uint64_t vaddr; >| ^ > > Clang users got confused by this, IIUC Markus and Thomas idea is > to only enable these warnings for GCC, enforcing them for Clang > users via CI (until Clang get this option supported). Personally > I'd rather enable the warning once for all, waiting for Clang > support (or clean/enable global shadowing for GCC too). Hopefully it's helpful or at least benign if we address the shadowed globals under target/hexagon/ for now, even if "-Wshadow=global" is not enabled. > See this thread: > https://lore.kernel.org/qemu-devel/11abc551-188e-85c0-fe55- > b2b58d351...@redhat.com/ > > Regards, > > Phil.
Re: [PATCH] ppc/pnv: Add an I2C master controller model
Hello Glenn, On 10/9/23 20:05, Glenn Miles wrote: From: Cédric Le Goater Not supported : . 10 bit addresses . multimaster . slave Signed-off-by: Cédric Le Goater Signed-off-by: Glenn Miles [milesg: fixed formatting warning] Overall it looks good ;) Some suggestions for the respin : * Please split the model implementation from the wiring in the board. Adding a cover letter would be nice. * In the commit log, please add more details on the unit being modeled, how this I2C unit interacts with the rest of the machine, what is modeled, what is not, etc. A simple intro in short. * Add a SPDX-License-Identifier tag in new files. Thanks, C. PS: I am not getting your emails for some (corporate) reasons. --- hw/ppc/meson.build | 1 + hw/ppc/pnv.c | 26 ++ hw/ppc/pnv_i2c.c | 678 + include/hw/ppc/pnv_chip.h | 4 + include/hw/ppc/pnv_i2c.h | 39 +++ include/hw/ppc/pnv_xscom.h | 3 + 6 files changed, 751 insertions(+) create mode 100644 hw/ppc/pnv_i2c.c create mode 100644 include/hw/ppc/pnv_i2c.h diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build index 7c2c52434a..87b756a701 100644 --- a/hw/ppc/meson.build +++ b/hw/ppc/meson.build @@ -43,6 +43,7 @@ ppc_ss.add(when: 'CONFIG_POWERNV', if_true: files( 'pnv.c', 'pnv_xscom.c', 'pnv_core.c', + 'pnv_i2c.c', 'pnv_lpc.c', 'pnv_psi.c', 'pnv_occ.c', diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index eb54f93986..32b6d9889d 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1438,6 +1438,10 @@ static void pnv_chip_power9_instance_init(Object *obj) object_initialize_child(obj, "pec[*]", &chip9->pecs[i], TYPE_PNV_PHB4_PEC); } + +for (i = 0; i < PNV9_CHIP_MAX_I2C; i++) { +object_initialize_child(obj, "i2c[*]", &chip9->i2c[i], TYPE_PNV_I2C); +} } static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq, @@ -1510,6 +1514,7 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) PnvChip *chip = PNV_CHIP(dev); Pnv9Psi *psi9 = &chip9->psi; Error *local_err = NULL; +int i; /* XSCOM bridge is first */ pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); @@ -1613,6 +1618,27 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) error_propagate(errp, local_err); return; } + +/* + * I2C + * TODO: The number of busses is specific to each platform + */ +for (i = 0; i < PNV9_CHIP_MAX_I2C; i++) { +Object *obj = OBJECT(&chip9->i2c[i]); + +object_property_set_int(obj, "engine", i + 1, &error_fatal); +object_property_set_int(obj, "num-busses", 1, &error_fatal); +object_property_set_link(obj, "chip", OBJECT(chip), &error_abort); +if (!qdev_realize(DEVICE(obj), NULL, errp)) { +return; +} +pnv_xscom_add_subregion(chip, PNV9_XSCOM_I2CM_BASE + + chip9->i2c[i].engine * PNV9_XSCOM_I2CM_SIZE, +&chip9->i2c[i].xscom_regs); +qdev_connect_gpio_out(DEVICE(&chip9->i2c[i]), 0, + qdev_get_gpio_in(DEVICE(&chip9->psi), + PSIHB9_IRQ_SBE_I2C)); +} } static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr) diff --git a/hw/ppc/pnv_i2c.c b/hw/ppc/pnv_i2c.c new file mode 100644 index 00..8c191912bf --- /dev/null +++ b/hw/ppc/pnv_i2c.c @@ -0,0 +1,678 @@ +/* + * QEMU PowerPC PowerNV Processor I2C model + * + * Copyright (c) 2019-2021, IBM Corporation. + * + * 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/module.h" +#include "qemu/log.h" +#include "sysemu/reset.h" + +#include "hw/irq.h" +#include "hw/qdev-properties.h" + +#include "hw/ppc/pnv.h" +#include "hw/ppc/pnv_chip.h" +#include "hw/ppc/pnv_i2c.h" +#include "hw/ppc/pnv_xscom.h" +#include "hw/ppc/fdt.h" + +#include + +/* I2C FIFO register */ +#define I2C_FIFO_REG0x4 +#define I2C_FIFOPPC_BITMASK(0, 7) + +/* I2C command register */ +#define I2C_CMD_REG 0x5 +#define I2C_CMD_WITH_START PPC_BIT(0) +#define I2C_CMD_WITH_ADDR PPC_BIT(1) +#define I2C_CMD_READ_CONT PPC_BIT(2) +#define I2C_CMD_WITH_STOP PPC_BIT(3) +#define I2C_CMD_INTR_STEERING PPC_BITMASK(6, 7) /* P9 */ +#define I2C_CMD_INTR_STEER_HOST 1 +#define I2C_CMD_INTR_STEER_OCC2 +#define I2C_CMD_DEV_ADDRPPC_BITMASK(8, 14) +#define I2C_CMD_READ_NOT_WRITE PPC_BIT(15) +#define I2C_CMD_LEN_BYTES PPC_BITMASK(16, 31) +#define I2C_MAX_TFR_LEN 0xfff0ull + +/* I2C mode register */ +#define I2C_MODE_REG0x6 +#define I2C_MO
[PATCH V4 10/10] target/arm/kvm: Write CPU state back to KVM on reset
From: Jean-Philippe Brucker When a KVM vCPU is reset following a PSCI CPU_ON call, its power state is not synchronized with KVM at the moment. Because the vCPU is not marked dirty, we miss the call to kvm_arch_put_registers() that writes to KVM's MP_STATE. Force mp_state synchronization. Signed-off-by: Jean-Philippe Brucker Signed-off-by: Salil Mehta Reviewed-by: Alex Bennée Reviewed-by: Gavin Shan --- target/arm/kvm.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/target/arm/kvm.c b/target/arm/kvm.c index b66b936a95..8cb70b9e7c 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -642,11 +642,12 @@ void kvm_arm_cpu_post_load(ARMCPU *cpu) void kvm_arm_reset_vcpu(ARMCPU *cpu) { int ret; +CPUState *cs = CPU(cpu); /* Re-init VCPU so that all registers are set to * their respective reset values. */ -ret = kvm_arm_vcpu_init(CPU(cpu)); +ret = kvm_arm_vcpu_init(cs); if (ret < 0) { fprintf(stderr, "kvm_arm_vcpu_init failed: %s\n", strerror(-ret)); abort(); @@ -663,6 +664,11 @@ void kvm_arm_reset_vcpu(ARMCPU *cpu) * for the same reason we do so in kvm_arch_get_registers(). */ write_list_to_cpustate(cpu); +/* + * Ensure we call kvm_arch_put_registers(). The vCPU isn't marked dirty if + * it was parked in KVM and is now booting from a PSCI CPU_ON call. + */ +cs->vcpu_dirty = true; } /* -- 2.34.1
[PATCH V4 09/10] gdbstub: Add helper function to unregister GDB register space
Add common function to help unregister the GDB Register Space. This shall be done in context to the CPU unrealization. Signed-off-by: Salil Mehta --- gdbstub/gdbstub.c | 15 +++ include/exec/gdbstub.h | 5 + 2 files changed, 20 insertions(+) diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index 349d348c7b..97b89e2d00 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -491,6 +491,21 @@ void gdb_register_coprocessor(CPUState *cpu, } } +void gdb_unregister_coprocessor_all(CPUState *cpu) +{ +GDBRegisterState *s, *p; + +p = cpu->gdb_regs; +while (p) { +s = p; +p = p->next; +/* s->xml is static const char so isn't freed */ +g_free(s); +} +cpu->gdb_regs = NULL; +cpu->gdb_num_g_regs = 0; +} + static void gdb_process_breakpoint_remove_all(GDBProcess *p) { CPUState *cpu = gdb_get_first_cpu_in_process(p); diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h index 16a139043f..7d1368d377 100644 --- a/include/exec/gdbstub.h +++ b/include/exec/gdbstub.h @@ -27,6 +27,11 @@ typedef int (*gdb_set_reg_cb)(CPUArchState *env, uint8_t *buf, int reg); void gdb_register_coprocessor(CPUState *cpu, gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg, int num_regs, const char *xml, int g_pos); +/** + * gdb_unregister_coprocessor_all() - unregisters supplemental set of registers + * @cpu - the CPU associated with registers + */ +void gdb_unregister_coprocessor_all(CPUState *cpu); /** * gdbserver_start: start the gdb server -- 2.34.1
[PATCH V4 08/10] physmem: Add helper function to destroy CPU AddressSpace
Virtual CPU Hot-unplug leads to unrealization of a CPU object. This also involves destruction of the CPU AddressSpace. Add common function to help destroy the CPU AddressSpace. Signed-off-by: Salil Mehta --- include/exec/cpu-common.h | 8 include/hw/core/cpu.h | 1 + softmmu/physmem.c | 25 + 3 files changed, 34 insertions(+) diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 41788c0bdd..eb56a228a2 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -120,6 +120,14 @@ size_t qemu_ram_pagesize_largest(void); */ void cpu_address_space_init(CPUState *cpu, int asidx, const char *prefix, MemoryRegion *mr); +/** + * cpu_address_space_destroy: + * @cpu: CPU for which address space needs to be destroyed + * @asidx: integer index of this address space + * + * Note that with KVM only one address space is supported. + */ +void cpu_address_space_destroy(CPUState *cpu, int asidx); void cpu_physical_memory_rw(hwaddr addr, void *buf, hwaddr len, bool is_write); diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 648b5b3586..65d2ae4581 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -355,6 +355,7 @@ struct CPUState { QSIMPLEQ_HEAD(, qemu_work_item) work_list; CPUAddressSpace *cpu_ases; +int cpu_ases_count; int num_ases; AddressSpace *as; MemoryRegion *memory; diff --git a/softmmu/physmem.c b/softmmu/physmem.c index 4f6ca653b3..4dfa0ca66f 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -761,6 +761,7 @@ void cpu_address_space_init(CPUState *cpu, int asidx, if (!cpu->cpu_ases) { cpu->cpu_ases = g_new0(CPUAddressSpace, cpu->num_ases); +cpu->cpu_ases_count = cpu->num_ases; } newas = &cpu->cpu_ases[asidx]; @@ -774,6 +775,30 @@ void cpu_address_space_init(CPUState *cpu, int asidx, } } +void cpu_address_space_destroy(CPUState *cpu, int asidx) +{ +CPUAddressSpace *cpuas; + +assert(asidx < cpu->num_ases); +assert(asidx == 0 || !kvm_enabled()); +assert(cpu->cpu_ases); + +cpuas = &cpu->cpu_ases[asidx]; +if (tcg_enabled()) { +memory_listener_unregister(&cpuas->tcg_as_listener); +} + +address_space_destroy(cpuas->as); +g_free_rcu(cpuas->as, rcu); + +if (cpu->cpu_ases_count == 1) { +g_free(cpu->cpu_ases); +cpu->cpu_ases = NULL; +} + +cpu->cpu_ases_count--; +} + AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx) { /* Return the AddressSpace corresponding to the specified index */ -- 2.34.1
[PATCH V4 07/10] hw/acpi: Update ACPI GED framework to support vCPU Hotplug
ACPI GED shall be used to convey to the guest kernel about any CPU hot-(un)plug events. Therefore, existing ACPI GED framework inside QEMU needs to be enhanced to support CPU hotplug state and events. Co-developed-by: Keqian Zhu Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta Reviewed-by: Jonathan Cameron Reviewed-by: Gavin Shan --- hw/acpi/generic_event_device.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c index 62d504d231..0d5f0140e5 100644 --- a/hw/acpi/generic_event_device.c +++ b/hw/acpi/generic_event_device.c @@ -12,6 +12,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/acpi/acpi.h" +#include "hw/acpi/cpu.h" #include "hw/acpi/generic_event_device.h" #include "hw/irq.h" #include "hw/mem/pc-dimm.h" @@ -239,6 +240,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))); @@ -253,6 +256,8 @@ static void acpi_ged_unplug_request_cb(HotplugHandler *hotplug_dev, if ((object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) && !(object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM { acpi_memory_unplug_request_cb(hotplug_dev, &s->memhp_state, dev, errp); +} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { +acpi_cpu_unplug_request_cb(hotplug_dev, &s->cpuhp_state, dev, errp); } else { error_setg(errp, "acpi: device unplug request for unsupported device" " type: %s", object_get_typename(OBJECT(dev))); @@ -266,6 +271,8 @@ static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev, if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { acpi_memory_unplug_cb(&s->memhp_state, dev, errp); +} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { +acpi_cpu_unplug_cb(&s->cpuhp_state, dev, errp); } else { error_setg(errp, "acpi: device unplug for unsupported device" " type: %s", object_get_typename(OBJECT(dev))); @@ -277,6 +284,7 @@ static void acpi_ged_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list) AcpiGedState *s = ACPI_GED(adev); acpi_memory_ospm_status(&s->memhp_state, list); +acpi_cpu_ospm_status(&s->cpuhp_state, list); } static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) @@ -291,6 +299,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); -- 2.34.1
[PATCH V4 06/10] hw/acpi: Update GED _EVT method AML with CPU scan
OSPM evaluates _EVT method to map the event. The CPU hotplug event eventually results in start of the CPU scan. Scan figures out the CPU and the kind of event(plug/unplug) and notifies it back to the guest. Update the GED AML _EVT method with the call to \\_SB.CPUS.CSCN Also, macro CPU_SCAN_METHOD might be referred in other places like during GED intialization so it makes sense to have its definition placed in some common header file like cpu_hotplug.h. But doing this can cause compilation break because of the conflicting macro definitions present in cpu.c and cpu_hotplug.c and because both these files get compiled due to historic reasons of x86 world i.e. decision to use legacy(GPE.2)/modern(GED) CPU hotplug interface happens during runtime [1]. To mitigate above, for now, declare a new common macro ACPI_CPU_SCAN_METHOD for CPU scan method instead. (This needs a separate discussion later on for clean-up) Reference: [1] https://lore.kernel.org/qemu-devel/1463496205-251412-24-git-send-email-imamm...@redhat.com/ Co-developed-by: Keqian Zhu Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta Reviewed-by: Jonathan Cameron Reviewed-by: Gavin Shan --- hw/acpi/cpu.c | 2 +- hw/acpi/generic_event_device.c | 4 include/hw/acpi/cpu_hotplug.h | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c index 66a71660ec..d7d7b5b8d2 100644 --- a/hw/acpi/cpu.c +++ b/hw/acpi/cpu.c @@ -322,7 +322,7 @@ const VMStateDescription vmstate_cpu_hotplug = { #define CPUHP_RES_DEVICE "PRES" #define CPU_LOCK "CPLK" #define CPU_STS_METHOD"CSTA" -#define CPU_SCAN_METHOD "CSCN" +#define CPU_SCAN_METHOD ACPI_CPU_SCAN_METHOD #define CPU_NOTIFY_METHOD "CTFY" #define CPU_EJECT_METHOD "CEJ0" #define CPU_OST_METHOD"COST" diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c index d2fa1d0e4a..62d504d231 100644 --- a/hw/acpi/generic_event_device.c +++ b/hw/acpi/generic_event_device.c @@ -108,6 +108,10 @@ 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_CPU_HOTPLUG_EVT: +aml_append(if_ctx, aml_call0(ACPI_CPU_CONTAINER "." + ACPI_CPU_SCAN_METHOD)); +break; case ACPI_GED_PWR_DOWN_EVT: aml_append(if_ctx, aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE), diff --git a/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h index 48b291e45e..ef631750b4 100644 --- a/include/hw/acpi/cpu_hotplug.h +++ b/include/hw/acpi/cpu_hotplug.h @@ -20,6 +20,8 @@ #include "hw/acpi/cpu.h" #define ACPI_CPU_HOTPLUG_REG_LEN 12 +#define ACPI_CPU_SCAN_METHOD "CSCN" +#define ACPI_CPU_CONTAINER "\\_SB.CPUS" typedef struct AcpiCpuHotplug { Object *device; -- 2.34.1
[PATCH V4 05/10] hw/acpi: Update CPUs AML with cpu-(ctrl)dev change
CPUs Control device(\\_SB.PCI0) register interface for the x86 arch is based on PCI and is IO port based and hence existing CPUs AML code assumes _CRS objects would evaluate to a system resource which describes IO Port address. But on ARM arch CPUs control device(\\_SB.PRES) register interface is memory-mapped hence _CRS object should evaluate to system resource which describes memory-mapped base address. Update build CPUs AML function to accept both IO/MEMORY region spaces and accordingly update the _CRS object. Legacy CPU Hotplug uses Generic ACPI GPE Block Bit 2 (GPE.2) event handler to notify OSPM about any CPU hot(un)plug events. GED framework uses new register interface for cpu-(ctrl)dev. Make AML for GPE.2 event handler conditional. Co-developed-by: Keqian Zhu Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta Reviewed-by: Gavin Shan --- hw/acpi/cpu.c | 23 --- hw/i386/acpi-build.c | 2 +- include/hw/acpi/cpu.h | 5 +++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c index 45defdc0e2..66a71660ec 100644 --- a/hw/acpi/cpu.c +++ b/hw/acpi/cpu.c @@ -338,9 +338,10 @@ const VMStateDescription vmstate_cpu_hotplug = { #define CPU_FW_EJECT_EVENT "CEJF" void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, -hwaddr io_base, +hwaddr base_addr, const char *res_root, -const char *event_handler_method) +const char *event_handler_method, +AmlRegionSpace rs) { Aml *ifctx; Aml *field; @@ -367,13 +368,19 @@ 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, +if (rs == AML_SYSTEM_IO) { +aml_append(crs, aml_io(AML_DECODE16, base_addr, base_addr, 1, ACPI_CPU_HOTPLUG_REG_LEN)); +} else { +aml_append(crs, aml_memory32_fixed(base_addr, + 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(base_addr), ACPI_CPU_HOTPLUG_REG_LEN)); field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, @@ -699,9 +706,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); +if (event_handler_method) { +method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED); +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 4d2d40bab5..611d3d044d 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1550,7 +1550,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 999caaf510..b87ebfdf4b 100644 --- a/include/hw/acpi/cpu.h +++ b/include/hw/acpi/cpu.h @@ -56,9 +56,10 @@ typedef struct CPUHotplugFeatures { } CPUHotplugFeatures; void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts, -hwaddr io_base, +hwaddr base_addr, 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.34.1
[PATCH V4 02/10] hw/acpi: Move CPU ctrl-dev MMIO region len macro to common header file
CPU ctrl-dev MMIO region length could be used in ACPI GED and various other architecture specific places. Move ACPI_CPU_HOTPLUG_REG_LEN macro to more appropriate common header file. Signed-off-by: Salil Mehta Reviewed-by: Alex Bennée Reviewed-by: Jonathan Cameron Reviewed-by: Gavin Shan Reviewed-by: David Hildenbrand --- hw/acpi/cpu.c | 2 +- include/hw/acpi/cpu_hotplug.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c index 19c154d78f..45defdc0e2 100644 --- a/hw/acpi/cpu.c +++ b/hw/acpi/cpu.c @@ -1,12 +1,12 @@ #include "qemu/osdep.h" #include "migration/vmstate.h" #include "hw/acpi/cpu.h" +#include "hw/acpi/cpu_hotplug.h" #include "qapi/error.h" #include "qapi/qapi-events-acpi.h" #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/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h index 3b932a..48b291e45e 100644 --- a/include/hw/acpi/cpu_hotplug.h +++ b/include/hw/acpi/cpu_hotplug.h @@ -19,6 +19,8 @@ #include "hw/hotplug.h" #include "hw/acpi/cpu.h" +#define ACPI_CPU_HOTPLUG_REG_LEN 12 + typedef struct AcpiCpuHotplug { Object *device; MemoryRegion io; -- 2.34.1
[PATCH V4 03/10] hw/acpi: Add ACPI CPU hotplug init stub
ACPI CPU hotplug related initialization should only happen if ACPI_CPU_HOTPLUG support has been enabled for particular architecture. Add cpu_hotplug_hw_init() stub to avoid compilation break. Signed-off-by: Salil Mehta Reviewed-by: Jonathan Cameron Reviewed-by: Gavin Shan --- hw/acpi/acpi-cpu-hotplug-stub.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/hw/acpi/acpi-cpu-hotplug-stub.c b/hw/acpi/acpi-cpu-hotplug-stub.c index 3fc4b14c26..c6c61bb9cd 100644 --- a/hw/acpi/acpi-cpu-hotplug-stub.c +++ b/hw/acpi/acpi-cpu-hotplug-stub.c @@ -19,6 +19,12 @@ void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner, return; } +void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner, + CPUHotplugState *state, hwaddr base_addr) +{ +return; +} + void acpi_cpu_ospm_status(CPUHotplugState *cpu_st, ACPIOSTInfoList ***list) { return; -- 2.34.1
[PATCH V4 04/10] hw/acpi: Init GED framework with CPU hotplug events
ACPI GED(as described in the ACPI 6.2 spec) can be used to generate ACPI events when OSPM/guest receives an interrupt listed in the _CRS object of GED. OSPM then maps or demultiplexes the event by evaluating _EVT method. This change adds the support of CPU hotplug event initialization in the existing GED framework. Co-developed-by: Keqian Zhu Signed-off-by: Keqian Zhu Signed-off-by: Salil Mehta Reviewed-by: Jonathan Cameron Reviewed-by: Gavin Shan Reviewed-by: David Hildenbrand --- hw/acpi/generic_event_device.c | 8 include/hw/acpi/generic_event_device.h | 5 + 2 files changed, 13 insertions(+) diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c index a3d31631fe..d2fa1d0e4a 100644 --- a/hw/acpi/generic_event_device.c +++ b/hw/acpi/generic_event_device.c @@ -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, }; /* @@ -400,6 +401,13 @@ 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); + +s->cpuhp.device = OBJECT(s); +memory_region_init(&s->container_cpuhp, OBJECT(dev), "cpuhp container", + ACPI_CPU_HOTPLUG_REG_LEN); +sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container_cpuhp); +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/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h index d831bbd889..d0a5a43abf 100644 --- a/include/hw/acpi/generic_event_device.h +++ b/include/hw/acpi/generic_event_device.h @@ -60,6 +60,7 @@ #define HW_ACPI_GENERIC_EVENT_DEVICE_H #include "hw/sysbus.h" +#include "hw/acpi/cpu_hotplug.h" #include "hw/acpi/memory_hotplug.h" #include "hw/acpi/ghes.h" #include "qom/object.h" @@ -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_NVDIMM_HOTPLUG_EVT 0x4 +#define ACPI_GED_CPU_HOTPLUG_EVT0x8 typedef struct GEDState { MemoryRegion evt; @@ -108,6 +110,9 @@ struct AcpiGedState { SysBusDevice parent_obj; MemHotplugState memhp_state; MemoryRegion container_memhp; +CPUHotplugState cpuhp_state; +MemoryRegion container_cpuhp; +AcpiCpuHotplug cpuhp; GEDState ged_state; uint32_t ged_event_bitmap; qemu_irq irq; -- 2.34.1
[PATCH V4 01/10] accel/kvm: Extract common KVM vCPU {creation, parking} code
KVM vCPU creation is done once during the initialization of the VM when Qemu thread is spawned. This is common to all the architectures. Hot-unplug of vCPU results in destruction of the vCPU object in QOM but the corresponding KVM vCPU object in the Host KVM is not destroyed and its representative KVM vCPU object/context in Qemu is parked. Refactor common logic so that some APIs could be reused by vCPU Hotplug code. Signed-off-by: Salil Mehta --- accel/kvm/kvm-all.c| 64 -- accel/kvm/trace-events | 4 +++ include/sysemu/kvm.h | 16 +++ 3 files changed, 69 insertions(+), 15 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index ff1578bb32..0dcaa15276 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -137,6 +137,7 @@ static QemuMutex kml_slots_lock; #define kvm_slots_unlock() qemu_mutex_unlock(&kml_slots_lock) static void kvm_slot_init_dirty_bitmap(KVMSlot *mem); +static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id); static inline void kvm_resample_fd_remove(int gsi) { @@ -320,14 +321,53 @@ err: return ret; } +void kvm_park_vcpu(CPUState *cpu) +{ +struct KVMParkedVcpu *vcpu; + +trace_kvm_park_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); + +vcpu = g_malloc0(sizeof(*vcpu)); +vcpu->vcpu_id = kvm_arch_vcpu_id(cpu); +vcpu->kvm_fd = cpu->kvm_fd; +QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node); +} + +int kvm_create_vcpu(CPUState *cpu) +{ +unsigned long vcpu_id = kvm_arch_vcpu_id(cpu); +KVMState *s = kvm_state; +int kvm_fd; + +trace_kvm_create_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); + +/* check if the KVM vCPU already exist but is parked */ +kvm_fd = kvm_get_vcpu(s, vcpu_id); +if (kvm_fd < 0) { +/* vCPU not parked: create a new KVM vCPU */ +kvm_fd = kvm_vm_ioctl(s, KVM_CREATE_VCPU, vcpu_id); +if (kvm_fd < 0) { +error_report("KVM_CREATE_VCPU IOCTL failed for vCPU %lu", vcpu_id); +return kvm_fd; +} +} + +cpu->kvm_fd = kvm_fd; +cpu->kvm_state = s; +cpu->vcpu_dirty = true; +cpu->dirty_pages = 0; +cpu->throttle_us_per_full = 0; + +return 0; +} + static int do_kvm_destroy_vcpu(CPUState *cpu) { KVMState *s = kvm_state; long mmap_size; -struct KVMParkedVcpu *vcpu = NULL; int ret = 0; -DPRINTF("kvm_destroy_vcpu\n"); +trace_kvm_destroy_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); ret = kvm_arch_destroy_vcpu(cpu); if (ret < 0) { @@ -353,10 +393,7 @@ static int do_kvm_destroy_vcpu(CPUState *cpu) } } -vcpu = g_malloc0(sizeof(*vcpu)); -vcpu->vcpu_id = kvm_arch_vcpu_id(cpu); -vcpu->kvm_fd = cpu->kvm_fd; -QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node); +kvm_park_vcpu(cpu); err: return ret; } @@ -377,6 +414,8 @@ static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id) if (cpu->vcpu_id == vcpu_id) { int kvm_fd; +trace_kvm_get_vcpu(vcpu_id); + QLIST_REMOVE(cpu, node); kvm_fd = cpu->kvm_fd; g_free(cpu); @@ -384,7 +423,7 @@ static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id) } } -return kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id); +return -ENOENT; } int kvm_init_vcpu(CPUState *cpu, Error **errp) @@ -395,19 +434,14 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp) trace_kvm_init_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu)); -ret = kvm_get_vcpu(s, kvm_arch_vcpu_id(cpu)); +ret = kvm_create_vcpu(cpu); if (ret < 0) { -error_setg_errno(errp, -ret, "kvm_init_vcpu: kvm_get_vcpu failed (%lu)", +error_setg_errno(errp, -ret, + "kvm_init_vcpu: kvm_create_vcpu failed (%lu)", kvm_arch_vcpu_id(cpu)); goto err; } -cpu->kvm_fd = ret; -cpu->kvm_state = s; -cpu->vcpu_dirty = true; -cpu->dirty_pages = 0; -cpu->throttle_us_per_full = 0; - mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0); if (mmap_size < 0) { ret = mmap_size; diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events index 399aaeb0ec..08e2dc253f 100644 --- a/accel/kvm/trace-events +++ b/accel/kvm/trace-events @@ -9,6 +9,10 @@ kvm_device_ioctl(int fd, int type, void *arg) "dev fd %d, type 0x%x, arg %p" kvm_failed_reg_get(uint64_t id, const char *msg) "Warning: Unable to retrieve ONEREG %" PRIu64 " from KVM: %s" kvm_failed_reg_set(uint64_t id, const char *msg) "Warning: Unable to set ONEREG %" PRIu64 " to KVM: %s" kvm_init_vcpu(int cpu_index, unsigned long arch_cpu_id) "index: %d id: %lu" +kvm_create_vcpu(int cpu_index, unsigned long arch_cpu_id) "creating KVM cpu: cpu_index: %d arch vcpu-id: %lu" +kvm_get_vcpu(unsigned long arch_cpu_id) "unparking KVM vcpu: arch vcpu-id: %lu" +kvm_destroy_vcpu(int cpu_index, unsigned long arch_cpu_id) "destroy vcpu: cpu_index:
[PATCH V4 00/10] Add architecture agnostic code to support vCPU Hotplug
Virtual CPU hotplug support is being added across various architectures[1][3]. This series adds various code bits common across all architectures: 1. vCPU creation and Parking code refactor [Patch 1] 2. Update ACPI GED framework to support vCPU Hotplug [Patch 4,6,7] 3. ACPI CPUs AML code change [Patch 5] 4. Helper functions to support unrealization of CPU objects [Patch 8,9] 5. Misc [Patch 2,3,10] Repository: [*] https://github.com/salil-mehta/qemu.git virt-cpuhp-armv8/rfc-v2.common.v4 Revision History: RFC V3 -> RFC V4 1. Addressed David Hilderbrand's comments - Fixed the wrong doc comment of kvm_park_vcpu API prototype - Added Reviewed-by tags for patches {2,4} Link: https://lore.kernel.org/qemu-devel/20231009112812.10612-1-salil.me...@huawei.com/ RFC V2 -> RFC V3 1. Addressed Jonathan Cameron's comments - Fixed 'vcpu-id' type wrongly changed from 'unsigned long' to 'integer' - Removed unnecessary use of variable 'vcpu_id' in kvm_park_vcpu - Updated [Patch V2 03/10] commit-log with details of ACPI_CPU_SCAN_METHOD macro - Updated [Patch V2 05/10] commit-log with details of conditional event handler method - Added Reviewed-by tags for patches {2,3,4,6,7} 2. Addressed Gavin Shan's comments - Remove unnecessary use of variable 'vcpu_id' in kvm_par_vcpu - Fixed return value in kvm_get_vcpu from -1 to -ENOENT - Reset the value of 'gdb_num_g_regs' in gdb_unregister_coprocessor_all - Fixed the kvm_{create,park}_vcpu prototypes docs - Added Reviewed-by tags for patches {2,3,4,5,6,7,9,10} 3. Addressed one earlier missed comment by Alex Bennée in RFC V1 - Added traces instead of DPRINTF in the newly added and some existing functions Link: https://lore.kernel.org/qemu-devel/20230930001933.2660-1-salil.me...@huawei.com/ RFC V1 -> RFC V2 1. Addressed Alex Bennée's comments - Refactored the kvm_create_vcpu logic to get rid of goto - Added the docs for kvm_{create,park}_vcpu prototypes - Splitted the gdbstub and AddressSpace destruction change into separate patches - Added Reviewed-by tags for patches {2,10} Link: https://lore.kernel.org/qemu-devel/20230929124304.13672-1-salil.me...@huawei.com/ References: [1] https://lore.kernel.org/qemu-devel/20230926100436.28284-1-salil.me...@huawei.com/ [2] https://lore.kernel.org/all/20230913163823.7880-1-james.mo...@arm.com/ [3] https://lore.kernel.org/qemu-devel/cover.1695697701.git.lixiang...@loongson.cn/ Jean-Philippe Brucker (1): target/arm/kvm: Write CPU state back to KVM on reset Salil Mehta (9): accel/kvm: Extract common KVM vCPU {creation,parking} code hw/acpi: Move CPU ctrl-dev MMIO region len macro to common header file hw/acpi: Add ACPI CPU hotplug init stub hw/acpi: Init GED framework with CPU hotplug events hw/acpi: Update CPUs AML with cpu-(ctrl)dev change hw/acpi: Update GED _EVT method AML with CPU scan hw/acpi: Update ACPI GED framework to support vCPU Hotplug physmem: Add helper function to destroy CPU AddressSpace gdbstub: Add helper function to unregister GDB register space accel/kvm/kvm-all.c| 64 -- accel/kvm/trace-events | 4 ++ gdbstub/gdbstub.c | 15 ++ hw/acpi/acpi-cpu-hotplug-stub.c| 6 +++ hw/acpi/cpu.c | 27 +++ hw/acpi/generic_event_device.c | 22 + hw/i386/acpi-build.c | 2 +- include/exec/cpu-common.h | 8 include/exec/gdbstub.h | 5 ++ include/hw/acpi/cpu.h | 5 +- include/hw/acpi/cpu_hotplug.h | 4 ++ include/hw/acpi/generic_event_device.h | 5 ++ include/hw/core/cpu.h | 1 + include/sysemu/kvm.h | 16 +++ softmmu/physmem.c | 25 ++ target/arm/kvm.c | 8 +++- 16 files changed, 189 insertions(+), 28 deletions(-) -- 2.34.1
[PATCH v2 2/3] hw/pci-host: Add emulation of Mai Logic Articia S
The Articia S is a generic chipset supporting several different CPUs that were among others used on some PPC boards. This is a minimal emulation of the parts needed for emulating the AmigaOne board. Signed-off-by: BALATON Zoltan --- hw/pci-host/Kconfig | 5 + hw/pci-host/articia.c | 293 ++ hw/pci-host/meson.build | 2 + include/hw/pci-host/articia.h | 17 ++ 4 files changed, 317 insertions(+) create mode 100644 hw/pci-host/articia.c create mode 100644 include/hw/pci-host/articia.h diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig index a07070eddf..33014c80a4 100644 --- a/hw/pci-host/Kconfig +++ b/hw/pci-host/Kconfig @@ -73,6 +73,11 @@ config SH_PCI bool select PCI +config ARTICIA +bool +select PCI +select I8259 + config MV64361 bool select PCI diff --git a/hw/pci-host/articia.c b/hw/pci-host/articia.c new file mode 100644 index 00..f3fcc49f81 --- /dev/null +++ b/hw/pci-host/articia.c @@ -0,0 +1,293 @@ +/* + * Mai Logic Articia S emulation + * + * Copyright (c) 2023 BALATON Zoltan + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/pci/pci_device.h" +#include "hw/pci/pci_host.h" +#include "hw/irq.h" +#include "hw/i2c/bitbang_i2c.h" +#include "hw/intc/i8259.h" +#include "hw/pci-host/articia.h" + +/* + * This is a minimal emulation of this chip as used in AmigaOne board. + * Most features are missing but those are not needed by firmware and guests. + */ + +OBJECT_DECLARE_SIMPLE_TYPE(ArticiaState, ARTICIA) + +OBJECT_DECLARE_SIMPLE_TYPE(ArticiaHostState, ARTICIA_PCI_HOST) +struct ArticiaHostState { +PCIDevice parent_obj; + +ArticiaState *as; +}; + +/* TYPE_ARTICIA */ + +struct ArticiaState { +PCIHostState parent_obj; + +qemu_irq irq[PCI_NUM_PINS]; +MemoryRegion io; +MemoryRegion mem; +MemoryRegion reg; + +bitbang_i2c_interface smbus; +uint32_t gpio; /* bits 0-7 in, 8-15 out, 16-23 direction (0 in, 1 out) */ +hwaddr gpio_base; +MemoryRegion gpio_reg; +}; + +static uint64_t articia_gpio_read(void *opaque, hwaddr addr, unsigned int size) +{ +ArticiaState *s = opaque; + +return (s->gpio >> (addr * 8)) & 0xff; +} + +static void articia_gpio_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) +{ +ArticiaState *s = opaque; +uint32_t sh = addr * 8; + +if (addr == 0) { +/* in bits read only? */ +return; +} + +if ((s->gpio & (0xff << sh)) != (val & 0xff) << sh) { +s->gpio &= ~(0xff << sh | 0xff); +s->gpio |= (val & 0xff) << sh; +s->gpio |= bitbang_i2c_set(&s->smbus, BITBANG_I2C_SDA, + s->gpio & BIT(16) ? + !!(s->gpio & BIT(8)) : 1); +if ((s->gpio & BIT(17))) { +s->gpio &= ~BIT(0); +s->gpio |= bitbang_i2c_set(&s->smbus, BITBANG_I2C_SCL, + !!(s->gpio & BIT(9))); +} +} +} + +static const MemoryRegionOps articia_gpio_ops = { +.read = articia_gpio_read, +.write = articia_gpio_write, +.valid.min_access_size = 1, +.valid.max_access_size = 1, +.endianness = DEVICE_LITTLE_ENDIAN, +}; + +static uint64_t articia_reg_read(void *opaque, hwaddr addr, unsigned int size) +{ +ArticiaState *s = opaque; +uint64_t ret = UINT_MAX; + +switch (addr) { +case 0xc00cf8: +ret = pci_host_conf_le_ops.read(PCI_HOST_BRIDGE(s), 0, size); +break; +case 0xe00cfc ... 0xe00cff: +ret = pci_host_data_le_ops.read(PCI_HOST_BRIDGE(s), addr - 0xe00cfc, size); +break; +case 0xf0: +ret = pic_read_irq(isa_pic); +break; +default: +qemu_log_mask(LOG_UNIMP, "%s: Unimplemented register read 0x%" + HWADDR_PRIx " %d\n", __func__, addr, size); +break; +} +return ret; +} + +static void articia_reg_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) +{ +ArticiaState *s = opaque; + +switch (addr) { +case 0xc00cf8: +pci_host_conf_le_ops.write(PCI_HOST_BRIDGE(s), 0, val, size); +break; +case 0xe00cfc ... 0xe00cff: +pci_host_data_le_ops.write(PCI_HOST_BRIDGE(s), addr, val, size); +break; +default: +qemu_log_mask(LOG_UNIMP, "%s: Unimplemented register write 0x%" + HWADDR_PRIx " %d <- %"PRIx64"\n", __func__, addr, size, val); +break; +} +} + +static const MemoryRegionOps articia_reg_ops = { +.read = articia_reg_read, +.write = articia_reg_write, +.valid.min_access_size = 1, +.valid.max_access_size = 4, +.endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void articia_pcihost_set_irq(void *opaque, int n, int level) +{ +ArticiaState *s = opaque;
[PATCH v2 3/3] hw/ppc: Add emulation of AmigaOne XE board
The AmigaOne is a rebranded MAI Teron board that uses U-Boot firmware with patches to support AmigaOS and is very similar to pegasos2 so can be easily emulated sharing most code with pegasos2. The reason to emulate it is that AmigaOS comes in different versions for AmigaOne and PegasosII which only have drivers for one machine and firmware so these only run on the specific machine. Adding this board allows another AmigaOS version to be used reusing already existing peagasos2 emulation. (The AmigaOne was the first of these boards so likely most widespread which then inspired Pegasos that was later replaced with PegasosII due to problems with Articia S, so these have a lot of similarity. Pegasos mainly ran MorphOS while the PegasosII version of AmigaOS was added later and therefore less common than the AmigaOne version.) Signed-off-by: BALATON Zoltan --- MAINTAINERS | 8 ++ configs/devices/ppc-softmmu/default.mak | 1 + hw/ppc/Kconfig | 7 + hw/ppc/amigaone.c | 164 hw/ppc/meson.build | 2 + 5 files changed, 182 insertions(+) create mode 100644 hw/ppc/amigaone.c diff --git a/MAINTAINERS b/MAINTAINERS index 7f0e20fde6..03f908c153 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1490,6 +1490,14 @@ F: hw/pci-host/mv64361.c F: hw/pci-host/mv643xx.h F: include/hw/pci-host/mv64361.h +amigaone +M: BALATON Zoltan +L: qemu-...@nongnu.org +S: Maintained +F: hw/ppc/amigaone.c +F: hw/pci-host/articia.c +F: include/hw/pci-host/articia.h + Virtual Open Firmware (VOF) M: Alexey Kardashevskiy R: David Gibson diff --git a/configs/devices/ppc-softmmu/default.mak b/configs/devices/ppc-softmmu/default.mak index a887f5438b..b85fd2bcd7 100644 --- a/configs/devices/ppc-softmmu/default.mak +++ b/configs/devices/ppc-softmmu/default.mak @@ -14,6 +14,7 @@ CONFIG_SAM460EX=y CONFIG_MAC_OLDWORLD=y CONFIG_MAC_NEWWORLD=y +CONFIG_AMIGAONE=y CONFIG_PEGASOS2=y # For PReP diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig index 5dfbf47ef5..56f0475a8e 100644 --- a/hw/ppc/Kconfig +++ b/hw/ppc/Kconfig @@ -69,6 +69,13 @@ config SAM460EX select USB_OHCI select FDT_PPC +config AMIGAONE +bool +imply ATI_VGA +select ARTICIA +select VT82C686 +select SMBUS_EEPROM + config PEGASOS2 bool imply ATI_VGA diff --git a/hw/ppc/amigaone.c b/hw/ppc/amigaone.c new file mode 100644 index 00..3589924c8a --- /dev/null +++ b/hw/ppc/amigaone.c @@ -0,0 +1,164 @@ +/* + * QEMU Eyetech AmigaOne/Mai Logic Teron emulation + * + * Copyright (c) 2023 BALATON Zoltan + * + * This work is licensed under the GNU GPL license version 2 or later. + * + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qemu/datadir.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/ppc/ppc.h" +#include "hw/boards.h" +#include "hw/loader.h" +#include "hw/pci-host/articia.h" +#include "hw/isa/vt82c686.h" +#include "hw/ide/pci.h" +#include "hw/i2c/smbus_eeprom.h" +#include "hw/ppc/ppc.h" +#include "sysemu/reset.h" +#include "kvm_ppc.h" + +#define BUS_FREQ_HZ 1 + +/* + * Firmware binary available at + * https://www.hyperion-entertainment.com/index.php/downloads?view=files&parent=28 + * then "tail -c 524288 updater.image >u-boot-amigaone.bin" + * + * BIOS emulator in firmware cannot run QEMU vgabios and hangs on it, use + * -device VGA,romfile=VGABIOS-lgpl-latest.bin + * from http://www.nongnu.org/vgabios/ instead. + */ +#define PROM_FILENAME "u-boot-amigaone.bin" +#define PROM_ADDR 0xfff0 +#define PROM_SIZE (512 * KiB) + +static void amigaone_cpu_reset(void *opaque) +{ +PowerPCCPU *cpu = opaque; + +cpu_reset(CPU(cpu)); +cpu_ppc_tb_reset(&cpu->env); +} + +static void fix_spd_data(uint8_t *spd) +{ +uint32_t bank_size = 4 * MiB * spd[31]; +uint32_t rows = bank_size / spd[13] / spd[17]; +spd[3] = ctz32(rows) - spd[4]; +} + +static void amigaone_init(MachineState *machine) +{ +PowerPCCPU *cpu; +CPUPPCState *env; +MemoryRegion *rom, *pci_mem, *mr; +const char *fwname = machine->firmware ?: PROM_FILENAME; +char *filename; +ssize_t sz; +PCIBus *pci_bus; +Object *via; +DeviceState *dev; +I2CBus *i2c_bus; +uint8_t *spd_data; +int i; + +/* init CPU */ +cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); +env = &cpu->env; +if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) { +error_report("Incompatible CPU, only 6xx bus supported"); +exit(1); +} +cpu_ppc_tb_init(env, BUS_FREQ_HZ / 4); +qemu_register_reset(amigaone_cpu_reset, cpu); + +/* RAM */ +if (machine->ram_size > 2 * GiB) { +error_report("RAM size more than 2 GiB is not supported"); +exit(1); +} +memory_region_add_subregion(get_system_memory(), 0, machine->ram); +if (machine->ram_size < 1 * GiB + 32 * KiB) { +/* Firmware uses this area for startup *
[PATCH v2 0/3] Add emulation of AmigaOne XE board
Changes in v2: - Update comment and commit message in patch 1 (Mark) - Fix irq mapping in patch 2 (Volker) Regards, BALATON Zoltan BALATON Zoltan (3): via-ide: Fix legacy mode emulation hw/pci-host: Add emulation of Mai Logic Articia S hw/ppc: Add emulation of AmigaOne XE board MAINTAINERS | 8 + configs/devices/ppc-softmmu/default.mak | 1 + hw/ide/via.c| 41 +++- hw/pci-host/Kconfig | 5 + hw/pci-host/articia.c | 293 hw/pci-host/meson.build | 2 + hw/ppc/Kconfig | 7 + hw/ppc/amigaone.c | 164 + hw/ppc/meson.build | 2 + include/hw/pci-host/articia.h | 17 ++ 10 files changed, 535 insertions(+), 5 deletions(-) create mode 100644 hw/pci-host/articia.c create mode 100644 hw/ppc/amigaone.c create mode 100644 include/hw/pci-host/articia.h -- 2.30.9
[PATCH v2 1/3] via-ide: Fix legacy mode emulation
The initial value for BARs were set in reset method for emulating legacy mode at start but this does not work because PCI code resets BARs after calling device reset method. Remove this ineffective default to avoid confusion. Instead move setting the BARs to a callback on writing the PCI config regsiter that sets legacy mode (which firmwares needing this mode seem to do) and fix their values to program it to use legacy port numbers in this case. This does not fully emulate what the data sheet says (which is not very clear on this) but it implements enogh to allow both modes as used by firmwares of machines we emulate. Signed-off-by: BALATON Zoltan --- hw/ide/via.c | 41 - 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/hw/ide/via.c b/hw/ide/via.c index fff23803a6..43e8af8d69 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -132,11 +132,6 @@ static void via_ide_reset(DeviceState *dev) pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM); -pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, 0x01f0); -pci_set_long(pci_conf + PCI_BASE_ADDRESS_1, 0x03f4); -pci_set_long(pci_conf + PCI_BASE_ADDRESS_2, 0x0170); -pci_set_long(pci_conf + PCI_BASE_ADDRESS_3, 0x0374); -pci_set_long(pci_conf + PCI_BASE_ADDRESS_4, 0xcc01); /* BMIBA: 20-23h */ pci_set_long(pci_conf + PCI_INTERRUPT_LINE, 0x010e); /* IDE chip enable, IDE configuration 1/2, IDE FIFO Configuration*/ @@ -159,6 +154,41 @@ static void via_ide_reset(DeviceState *dev) pci_set_long(pci_conf + 0xc0, 0x00020001); } +static void via_ide_cfg_write(PCIDevice *pd, uint32_t addr, + uint32_t val, int len) +{ +pci_default_write_config(pd, addr, val, len); +/* + * Bits 0 and 2 of the PCI programming interface register select between + * legacy and native mode for the two IDE channels. We don't emulate this + * because we cannot easily switch between ISA and PCI in QEMU so instead + * when guest selects legacy mode we set the PCI BARs to legacy ports which + * works the same. We also don't care about setting each channel separately + * as no guest is known to do or need that. We only do this when BARs are + * unset when writing this register as logs from real hardware show that + * setting legacy mode after BARs were set it will still use ports set by + * BARs not ISA ports (e.g. pegasos2 Linux does this after firmware set + * native mode and programmed BARs and calls it non-100% native mode). + * But if 0x8a is written righr after reset without setting BARs then we + * want legacy ports (this is done by the AmigaOne firmware). + */ +if (addr == PCI_CLASS_PROG && val == 0x8a && +pci_get_long(pd->config + PCI_BASE_ADDRESS_0) == +PCI_BASE_ADDRESS_SPACE_IO) { +pci_set_long(pd->config + PCI_BASE_ADDRESS_0, 0x1f0 + | PCI_BASE_ADDRESS_SPACE_IO); +pci_set_long(pd->config + PCI_BASE_ADDRESS_1, 0x3f6 + | PCI_BASE_ADDRESS_SPACE_IO); +pci_set_long(pd->config + PCI_BASE_ADDRESS_2, 0x170 + | PCI_BASE_ADDRESS_SPACE_IO); +pci_set_long(pd->config + PCI_BASE_ADDRESS_3, 0x376 + | PCI_BASE_ADDRESS_SPACE_IO); +/* BMIBA: 20-23h */ +pci_set_long(pd->config + PCI_BASE_ADDRESS_4, 0xcc00 + | PCI_BASE_ADDRESS_SPACE_IO); +} +} + static void via_ide_realize(PCIDevice *dev, Error **errp) { PCIIDEState *d = PCI_IDE(dev); @@ -221,6 +251,7 @@ static void via_ide_class_init(ObjectClass *klass, void *data) /* Reason: only works as function of VIA southbridge */ dc->user_creatable = false; +k->config_write = via_ide_cfg_write; k->realize = via_ide_realize; k->exit = via_ide_exitfn; k->vendor_id = PCI_VENDOR_ID_VIA; -- 2.30.9
Re: [PATCH] docs/about: Deprecate the 'next-cube' m68k machine
On 07/10/2023 08:23, Thomas Huth wrote: (added Natalia who was the GSoC mentor for the NeXT cube work) The machine is incomplete, and unfortunately the hoped-for improvements never happened. So it's maybe best if we mark this machine as deprecated and finally remove it again in case it gets into the way of a code refactoring or other reasons. Signed-off-by: Thomas Huth --- docs/about/deprecated.rst | 8 1 file changed, 8 insertions(+) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 3b074b9ed4..2f6dadd12f 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -253,6 +253,14 @@ deprecated; use the new name ``dtb-randomness`` instead. The new name better reflects the way this property affects all random data within the device tree blob, not just the ``kaslr-seed`` node. +``next-cube`` m68k machine (since 8.2) +'' + +The machine never got fully implemented and can only show the firmware prompt. +Given the incomplete state and slow progress on improvements, it might get +removed again without replacement. + + Backend options --- I'm torn a bit by this one - on the one hand the NeXT code could do with some love, but then given that the code already uses qdev/QOM then there isn't really much in the way of maintenance burden. The main concern for me at the moment is the use of the old-style memory accessors that pre-date the memory API. With my latest ESP patches I think it shouldn't be too hard to update the NeXT DMA controller to get SCSI working, so perhaps we can leave it for now if it doesn't cause too many problems? Natalia, any comments from your side? In particular what sources did you point Bryce towards in order to reverse engineer the NeXT hardware? ATB, Mark.
RE: [PATCH v2 3/3] target/hexagon: avoid shadowing globals
> -Original Message- > From: Brian Cain > Sent: Sunday, October 8, 2023 7:50 AM > To: ltaylorsimp...@gmail.com; qemu-devel@nongnu.org > Cc: arm...@redhat.com; richard.hender...@linaro.org; phi...@linaro.org; > peter.mayd...@linaro.org; Matheus Bernardino (QUIC) > ; stefa...@redhat.com; a...@rev.ng; > a...@rev.ng; Marco Liebel (QUIC) > Subject: RE: [PATCH v2 3/3] target/hexagon: avoid shadowing globals > > > > > -Original Message- > > From: ltaylorsimp...@gmail.com > > Sent: Friday, October 6, 2023 11:01 AM > > To: Brian Cain ; qemu-devel@nongnu.org > > Cc: arm...@redhat.com; richard.hender...@linaro.org; > > phi...@linaro.org; peter.mayd...@linaro.org; Matheus Bernardino (QUIC) > > ; stefa...@redhat.com; a...@rev.ng; > > a...@rev.ng; Marco Liebel (QUIC) > > Subject: RE: [PATCH v2 3/3] target/hexagon: avoid shadowing globals > > > > WARNING: This email originated from outside of Qualcomm. Please be > > wary of any links or attachments, and do not enable macros. > > > > > -Original Message- > > > From: Brian Cain > > > Sent: Thursday, October 5, 2023 4:22 PM > > > To: qemu-devel@nongnu.org > > > Cc: bc...@quicinc.com; arm...@redhat.com; > > > richard.hender...@linaro.org; phi...@linaro.org; > > > peter.mayd...@linaro.org; quic_mathb...@quicinc.com; > > > stefa...@redhat.com; a...@rev.ng; a...@rev.ng; > > > quic_mlie...@quicinc.com; ltaylorsimp...@gmail.com > > > Subject: [PATCH v2 3/3] target/hexagon: avoid shadowing globals > > > > > > The typedef `vaddr` is shadowed by `vaddr` identifiers, so we rename > > > the identifiers to avoid shadowing the type name. > > > > > > The global `cpu_env` is shadowed by local `cpu_env` arguments, so we > > > rename the function arguments to avoid shadowing the global. > > > > > > Signed-off-by: Brian Cain > > > --- > > > target/hexagon/genptr.c | 56 - > > > target/hexagon/genptr.h | 18 > > > target/hexagon/mmvec/system_ext_mmvec.c | 4 +- > > > target/hexagon/mmvec/system_ext_mmvec.h | 2 +- > > > target/hexagon/op_helper.c | 4 +- > > > 5 files changed, 42 insertions(+), 42 deletions(-) > > > > > > diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c index > > > 217bc7bb5a..11377ac92b 100644 > > > --- a/target/hexagon/genptr.c > > > +++ b/target/hexagon/genptr.c > > > @@ -334,28 +334,28 @@ void gen_set_byte_i64(int N, TCGv_i64 result, > > TCGv > > > src) > > > tcg_gen_deposit_i64(result, result, src64, N * 8, 8); } > > > > > > -static inline void gen_load_locked4u(TCGv dest, TCGv vaddr, int > > > mem_index) > > > +static inline void gen_load_locked4u(TCGv dest, TCGv v_addr, int > > > +mem_index) > > > > I'd recommend moving both the type and the arg name to the new line, > > also indent the new line. > > static inline void gen_load_locked4u(TCGv dest, TCGv v_addr, > > int > > mem_index) > > > > > I could be mistaken but AFAICT none of these lines are wrapped in the way > they're quoted above in my patch (nor the baseline). I don't think any of > these lines exceed 80 columns, so they shouldn't need wrapping, either. > > I double checked how it's displayed at the archive > https://lists.gnu.org/archive/html/qemu-devel/2023-10/msg01667.html to > make sure that it wasn't a misconfiguration of my mailer. For another > perspective - refer to the commit used to create this patch: > https://github.com/quic/qemu/commit/7f20565d403d16337ab6d69ee663121 > a3eef71e6 > > Is your review comment that "these lines should be wrapped and when you > do, make sure you do it like this"? Or "if you are going to wrap them, wrap > them like this"? Or something else? Yes. It looked like some adding the v_ would sometimes put the line over the 80 character size. If so, wrap them as described. If not, no wrapping is needed. > > > Otherwise, > > Reviewed-by: Taylor Simpson > >
Re: [PATCH 3/3] vfio/ccw: Remove redundant definition of TYPE_VFIO_CCW
On Mon, 2023-10-09 at 10:20 +0800, Zhenzhong Duan wrote: > No functional changes. > > Signed-off-by: Zhenzhong Duan I see Cedric has already queued this, but FWIW: Reviewed-by: Eric Farman > --- > include/hw/s390x/vfio-ccw.h | 2 -- > 1 file changed, 2 deletions(-) > > diff --git a/include/hw/s390x/vfio-ccw.h b/include/hw/s390x/vfio- > ccw.h > index 63a909eb7e..4209d27657 100644 > --- a/include/hw/s390x/vfio-ccw.h > +++ b/include/hw/s390x/vfio-ccw.h > @@ -22,6 +22,4 @@ > #define TYPE_VFIO_CCW "vfio-ccw" > OBJECT_DECLARE_SIMPLE_TYPE(VFIOCCWDevice, VFIO_CCW) > > -#define TYPE_VFIO_CCW "vfio-ccw" > - > #endif
[PATCH v2 0/6] scripts/migration: Fix analyze-migration.py and add a test
was: [PATCH] qtest/migration: Add a test for the analyze-migration script https://lore.kernel.org/r/20230927214756.14117-1-faro...@suse.de The analyze-migration.py script should be kept in sync with the code that generates the migration stream. The addition/removal of sections and flags from the stream can cause the script to break. Issues when parsing the stream mostly manifest in the form of cryptic python errors such as: Looking at git log, it seems that this is a fairly useful script for people debugging issues with the migration stream. Let's add a test for it to catch bugs early avoid keeping a broken script in the tree. People suggested putting this in avocado or a dedicated shell script. I hope looking at the patches it becomes clear that it's best to have this along with migration-test. Mostly to avoid duplicating capabilities code and arch-specific flags. CI run: https://gitlab.com/farosas/qemu/-/pipelines/1030789937 Fabiano Rosas (5): migration: Fix analyze-migration.py 'configuration' parsing migration: Add capability parsing to analyze-migration.py migration: Fix analyze-migration.py when ignore-shared is used migration: Fix analyze-migration read operation signedness tests/qtest/migration: Add a test for the analyze-migration script Nikolay Borisov (1): migration: Add the configuration vmstate to the json writer migration/migration.c| 1 + migration/savevm.c | 20 --- scripts/analyze-migration.py | 67 tests/qtest/meson.build | 2 ++ tests/qtest/migration-test.c | 60 5 files changed, 139 insertions(+), 11 deletions(-) -- 2.35.3
[PATCH v2 3/6] migration: Add capability parsing to analyze-migration.py
The script is broken when the configuration/capabilities section is present. Add support for parsing the capabilities so we can fix it in the next patch. Signed-off-by: Fabiano Rosas --- scripts/analyze-migration.py | 38 1 file changed, 38 insertions(+) diff --git a/scripts/analyze-migration.py b/scripts/analyze-migration.py index 24687db497..c700fed64d 100755 --- a/scripts/analyze-migration.py +++ b/scripts/analyze-migration.py @@ -264,6 +264,24 @@ class ConfigurationSection(object): def __init__(self, file, desc): self.file = file self.desc = desc +self.caps = [] + +def parse_capabilities(self, vmsd_caps): +if not vmsd_caps: +return + +ncaps = vmsd_caps.data['caps_count'].data +self.caps = vmsd_caps.data['capabilities'] + +if type(self.caps) != list: +self.caps = [self.caps] + +if len(self.caps) != ncaps: +raise Exception("Number of capabilities doesn't match " +"caps_count field") + +def has_capability(self, cap): +return any([str(c) == cap for c in self.caps]) def read(self): if self.desc: @@ -271,6 +289,8 @@ def read(self): section = VMSDSection(self.file, version_id, self.desc, 'configuration') section.read() +self.parse_capabilities( +section.data.get("configuration/capabilities")) else: # backward compatibility for older streams that don't have # the configuration section in the json @@ -297,6 +317,23 @@ def read(self): self.data = self.file.readvar(size) return self.data +class VMSDFieldCap(object): +def __init__(self, desc, file): +self.file = file +self.desc = desc +self.data = "" + +def __repr__(self): +return self.data + +def __str__(self): +return self.data + +def read(self): +len = self.file.read8() +self.data = self.file.readstr(len) + + class VMSDFieldInt(VMSDFieldGeneric): def __init__(self, desc, file): super(VMSDFieldInt, self).__init__(desc, file) @@ -471,6 +508,7 @@ def getDict(self): "unused_buffer" : VMSDFieldGeneric, "bitmap" : VMSDFieldGeneric, "struct" : VMSDFieldStruct, +"capability": VMSDFieldCap, "unknown" : VMSDFieldGeneric, } -- 2.35.3
[PATCH v2 1/6] migration: Add the configuration vmstate to the json writer
From: Nikolay Borisov Make the migration json writer part of MigrationState struct, allowing the 'configuration' object be serialized to json. This will facilitate the parsing of the 'configuration' object in the next patch that fixes analyze-migration.py for arm. Signed-off-by: Nikolay Borisov Signed-off-by: Fabiano Rosas --- farosas: rewrote the commit message. The previous one was tied to fixed-ram. --- migration/migration.c | 1 + migration/savevm.c| 20 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index 585d3c8f55..dde8471f83 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1430,6 +1430,7 @@ int migrate_init(MigrationState *s, Error **errp) error_free(s->error); s->error = NULL; s->hostname = NULL; +s->vmdesc = NULL; migrate_set_state(&s->state, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP); diff --git a/migration/savevm.c b/migration/savevm.c index 60eec7c31f..5343cbc234 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1217,13 +1217,27 @@ void qemu_savevm_non_migratable_list(strList **reasons) void qemu_savevm_state_header(QEMUFile *f) { +MigrationState *s = migrate_get_current(); + +s->vmdesc = json_writer_new(false); + trace_savevm_state_header(); qemu_put_be32(f, QEMU_VM_FILE_MAGIC); qemu_put_be32(f, QEMU_VM_FILE_VERSION); -if (migrate_get_current()->send_configuration) { +if (s->send_configuration) { qemu_put_byte(f, QEMU_VM_CONFIGURATION); -vmstate_save_state(f, &vmstate_configuration, &savevm_state, 0); + +/* + * This starts the main json object and is paired with the + * json_writer_end_object in + * qemu_savevm_state_complete_precopy_non_iterable + */ +json_writer_start_object(s->vmdesc, NULL); + +json_writer_start_object(s->vmdesc, "configuration"); +vmstate_save_state(f, &vmstate_configuration, &savevm_state, s->vmdesc); +json_writer_end_object(s->vmdesc); } } @@ -1272,8 +1286,6 @@ void qemu_savevm_state_setup(QEMUFile *f) Error *local_err = NULL; int ret; -ms->vmdesc = json_writer_new(false); -json_writer_start_object(ms->vmdesc, NULL); json_writer_int64(ms->vmdesc, "page_size", qemu_target_page_size()); json_writer_start_array(ms->vmdesc, "devices"); -- 2.35.3
[PATCH v2 2/6] migration: Fix analyze-migration.py 'configuration' parsing
The 'configuration' state subsections are currently not being parsed and the script fails when analyzing an aarch64 stream: Traceback (most recent call last): File "./scripts/analyze-migration.py", line 625, in dump.read(dump_memory = args.memory) File "./scripts/analyze-migration.py", line 571, in read raise Exception("Unknown section type: %d" % section_type) Exception: Unknown section type: 5 Signed-off-by: Fabiano Rosas --- scripts/analyze-migration.py | 18 ++ 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/scripts/analyze-migration.py b/scripts/analyze-migration.py index 082424558b..24687db497 100755 --- a/scripts/analyze-migration.py +++ b/scripts/analyze-migration.py @@ -261,12 +261,21 @@ def getDict(self): class ConfigurationSection(object): -def __init__(self, file): +def __init__(self, file, desc): self.file = file +self.desc = desc def read(self): -name_len = self.file.read32() -name = self.file.readstr(len = name_len) +if self.desc: +version_id = self.desc['version'] +section = VMSDSection(self.file, version_id, self.desc, + 'configuration') +section.read() +else: +# backward compatibility for older streams that don't have +# the configuration section in the json +name_len = self.file.read32() +name = self.file.readstr(len = name_len) class VMSDFieldGeneric(object): def __init__(self, desc, file): @@ -532,7 +541,8 @@ def read(self, desc_only = False, dump_memory = False, write_memory = False): if section_type == self.QEMU_VM_EOF: break elif section_type == self.QEMU_VM_CONFIGURATION: -section = ConfigurationSection(file) +config_desc = self.vmsd_desc.get('configuration') +section = ConfigurationSection(file, config_desc) section.read() elif section_type == self.QEMU_VM_SECTION_START or section_type == self.QEMU_VM_SECTION_FULL: section_id = file.read32() -- 2.35.3
[PATCH v2 6/6] tests/qtest/migration: Add a test for the analyze-migration script
Add a smoke test that migrates to a file and gives it to the script. It should catch the most annoying errors such as changes in the ram flags. After code has been merged it becomes way harder to figure out what is causing the script to fail, the person making the change is the most likely to know right away what the problem is. Signed-off-by: Fabiano Rosas --- tests/qtest/meson.build | 2 ++ tests/qtest/migration-test.c | 60 2 files changed, 62 insertions(+) diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 1fba07f4ed..5e82eccb62 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -356,6 +356,8 @@ foreach dir : target_dirs test_deps += [qsd] endif + qtest_env.set('PYTHON', python.full_path()) + foreach test : target_qtests # Executables are shared across targets, declare them only the first time we # encounter them diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 46f1c275a2..cb1b6e890c 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -66,6 +66,8 @@ static bool got_dst_resume; */ #define DIRTYLIMIT_TOLERANCE_RANGE 25 /* MB/s */ +#define ANALYZE_SCRIPT "scripts/analyze-migration.py" + #if defined(__linux__) #include #include @@ -1510,6 +1512,61 @@ static void test_baddest(void) test_migrate_end(from, to, false); } +#ifndef _WIN32 +static void test_analyze_script(void) +{ +MigrateStart args = { +.opts_source = "-uuid ----", +}; +QTestState *from, *to; +g_autofree char *uri = NULL; +g_autofree char *file = NULL; +int pid, wstatus; +const char *python = g_getenv("PYTHON"); + +if (!python) { +g_test_skip("PYTHON variable not set"); +return; +} + +/* dummy url */ +if (test_migrate_start(&from, &to, "tcp:127.0.0.1:0", &args)) { +return; +} + +/* + * Setting these two capabilities causes the "configuration" + * vmstate to include subsections for them. The script needs to + * parse those subsections properly. + */ +migrate_set_capability(from, "validate-uuid", true); +migrate_set_capability(from, "x-ignore-shared", true); + +file = g_strdup_printf("%s/migfile", tmpfs); +uri = g_strdup_printf("exec:cat > %s", file); + +migrate_ensure_converge(from); +migrate_qmp(from, uri, "{}"); +wait_for_migration_complete(from); + +pid = fork(); +if (!pid) { +close(1); +open("/dev/null", O_WRONLY); +execl(python, python, ANALYZE_SCRIPT, "-f", file, NULL); +g_assert_not_reached(); +} + +g_assert(waitpid(pid, &wstatus, 0) == pid); +if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0) { +g_test_message("Failed to analyze the migration stream"); +g_test_fail(); +} +test_migrate_end(from, to, false); +cleanup("migfile"); +} +#endif + static void test_precopy_common(MigrateCommon *args) { QTestState *from, *to; @@ -2844,6 +2901,9 @@ int main(int argc, char **argv) } qtest_add_func("/migration/bad_dest", test_baddest); +#ifndef _WIN32 +qtest_add_func("/migration/analyze-script", test_analyze_script); +#endif qtest_add_func("/migration/precopy/unix/plain", test_precopy_unix_plain); qtest_add_func("/migration/precopy/unix/xbzrle", test_precopy_unix_xbzrle); /* -- 2.35.3
[PATCH v2 4/6] migration: Fix analyze-migration.py when ignore-shared is used
The script is currently broken when the x-ignore-shared capability is used: Traceback (most recent call last): File "./scripts/analyze-migration.py", line 656, in dump.read(dump_memory = args.memory) File "./scripts/analyze-migration.py", line 593, in read section.read() File "./scripts/analyze-migration.py", line 163, in read self.name = self.file.readstr(len = namelen) File "./scripts/analyze-migration.py", line 53, in readstr return self.readvar(len).decode('utf-8') UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 55: invalid start byte We're currently adding data to the middle of the ram section depending on the presence of the capability. As a consequence, any code loading the ram section needs to know about capabilities so it can interpret the stream. Skip the byte that's added when x-ignore-shared is used to fix the script. Signed-off-by: Fabiano Rosas --- scripts/analyze-migration.py | 5 + 1 file changed, 5 insertions(+) diff --git a/scripts/analyze-migration.py b/scripts/analyze-migration.py index c700fed64d..56ab04dd2d 100755 --- a/scripts/analyze-migration.py +++ b/scripts/analyze-migration.py @@ -123,6 +123,7 @@ def __init__(self, file, version_id, ramargs, section_key): self.TARGET_PAGE_SIZE = ramargs['page_size'] self.dump_memory = ramargs['dump_memory'] self.write_memory = ramargs['write_memory'] +self.ignore_shared = ramargs['ignore_shared'] self.sizeinfo = collections.OrderedDict() self.data = collections.OrderedDict() self.data['section sizes'] = self.sizeinfo @@ -169,6 +170,8 @@ def read(self): f.truncate(0) f.truncate(len) self.files[self.name] = f +if self.ignore_shared: +mr_addr = self.file.read64() flags &= ~self.RAM_SAVE_FLAG_MEM_SIZE if flags & self.RAM_SAVE_FLAG_COMPRESS: @@ -572,6 +575,7 @@ def read(self, desc_only = False, dump_memory = False, write_memory = False): ramargs['page_size'] = self.vmsd_desc['page_size'] ramargs['dump_memory'] = dump_memory ramargs['write_memory'] = write_memory +ramargs['ignore_shared'] = False self.section_classes[('ram',0)][1] = ramargs while True: @@ -582,6 +586,7 @@ def read(self, desc_only = False, dump_memory = False, write_memory = False): config_desc = self.vmsd_desc.get('configuration') section = ConfigurationSection(file, config_desc) section.read() +ramargs['ignore_shared'] = section.has_capability('x-ignore-shared') elif section_type == self.QEMU_VM_SECTION_START or section_type == self.QEMU_VM_SECTION_FULL: section_id = file.read32() name = file.readstr() -- 2.35.3
[PATCH v2 5/6] migration: Fix analyze-migration read operation signedness
The migration code uses unsigned values for 16, 32 and 64-bit operations. Fix the script to do the same. This was causing an issue when parsing the migration stream generated on the ppc64 target because one of instance_ids was larger than the 32bit signed maximum: Traceback (most recent call last): File "/home/fabiano/kvm/qemu/build/scripts/analyze-migration.py", line 658, in dump.read(dump_memory = args.memory) File "/home/fabiano/kvm/qemu/build/scripts/analyze-migration.py", line 592, in read classdesc = self.section_classes[section_key] KeyError: ('spapr_iommu', -2147483648) Signed-off-by: Fabiano Rosas --- scripts/analyze-migration.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/analyze-migration.py b/scripts/analyze-migration.py index 56ab04dd2d..de506cb8bf 100755 --- a/scripts/analyze-migration.py +++ b/scripts/analyze-migration.py @@ -38,13 +38,13 @@ def __init__(self, filename): self.file = open(self.filename, "rb") def read64(self): -return int.from_bytes(self.file.read(8), byteorder='big', signed=True) +return int.from_bytes(self.file.read(8), byteorder='big', signed=False) def read32(self): -return int.from_bytes(self.file.read(4), byteorder='big', signed=True) +return int.from_bytes(self.file.read(4), byteorder='big', signed=False) def read16(self): -return int.from_bytes(self.file.read(2), byteorder='big', signed=True) +return int.from_bytes(self.file.read(2), byteorder='big', signed=False) def read8(self): return int.from_bytes(self.file.read(1), byteorder='big', signed=True) -- 2.35.3
[PATCH] ppc/pnv: Add an I2C master controller model
From: Cédric Le Goater Not supported : . 10 bit addresses . multimaster . slave Signed-off-by: Cédric Le Goater Signed-off-by: Glenn Miles [milesg: fixed formatting warning] --- hw/ppc/meson.build | 1 + hw/ppc/pnv.c | 26 ++ hw/ppc/pnv_i2c.c | 678 + include/hw/ppc/pnv_chip.h | 4 + include/hw/ppc/pnv_i2c.h | 39 +++ include/hw/ppc/pnv_xscom.h | 3 + 6 files changed, 751 insertions(+) create mode 100644 hw/ppc/pnv_i2c.c create mode 100644 include/hw/ppc/pnv_i2c.h diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build index 7c2c52434a..87b756a701 100644 --- a/hw/ppc/meson.build +++ b/hw/ppc/meson.build @@ -43,6 +43,7 @@ ppc_ss.add(when: 'CONFIG_POWERNV', if_true: files( 'pnv.c', 'pnv_xscom.c', 'pnv_core.c', + 'pnv_i2c.c', 'pnv_lpc.c', 'pnv_psi.c', 'pnv_occ.c', diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index eb54f93986..32b6d9889d 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1438,6 +1438,10 @@ static void pnv_chip_power9_instance_init(Object *obj) object_initialize_child(obj, "pec[*]", &chip9->pecs[i], TYPE_PNV_PHB4_PEC); } + +for (i = 0; i < PNV9_CHIP_MAX_I2C; i++) { +object_initialize_child(obj, "i2c[*]", &chip9->i2c[i], TYPE_PNV_I2C); +} } static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq, @@ -1510,6 +1514,7 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) PnvChip *chip = PNV_CHIP(dev); Pnv9Psi *psi9 = &chip9->psi; Error *local_err = NULL; +int i; /* XSCOM bridge is first */ pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); @@ -1613,6 +1618,27 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) error_propagate(errp, local_err); return; } + +/* + * I2C + * TODO: The number of busses is specific to each platform + */ +for (i = 0; i < PNV9_CHIP_MAX_I2C; i++) { +Object *obj = OBJECT(&chip9->i2c[i]); + +object_property_set_int(obj, "engine", i + 1, &error_fatal); +object_property_set_int(obj, "num-busses", 1, &error_fatal); +object_property_set_link(obj, "chip", OBJECT(chip), &error_abort); +if (!qdev_realize(DEVICE(obj), NULL, errp)) { +return; +} +pnv_xscom_add_subregion(chip, PNV9_XSCOM_I2CM_BASE + + chip9->i2c[i].engine * PNV9_XSCOM_I2CM_SIZE, +&chip9->i2c[i].xscom_regs); +qdev_connect_gpio_out(DEVICE(&chip9->i2c[i]), 0, + qdev_get_gpio_in(DEVICE(&chip9->psi), + PSIHB9_IRQ_SBE_I2C)); +} } static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr) diff --git a/hw/ppc/pnv_i2c.c b/hw/ppc/pnv_i2c.c new file mode 100644 index 00..8c191912bf --- /dev/null +++ b/hw/ppc/pnv_i2c.c @@ -0,0 +1,678 @@ +/* + * QEMU PowerPC PowerNV Processor I2C model + * + * Copyright (c) 2019-2021, IBM Corporation. + * + * 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/module.h" +#include "qemu/log.h" +#include "sysemu/reset.h" + +#include "hw/irq.h" +#include "hw/qdev-properties.h" + +#include "hw/ppc/pnv.h" +#include "hw/ppc/pnv_chip.h" +#include "hw/ppc/pnv_i2c.h" +#include "hw/ppc/pnv_xscom.h" +#include "hw/ppc/fdt.h" + +#include + +/* I2C FIFO register */ +#define I2C_FIFO_REG0x4 +#define I2C_FIFOPPC_BITMASK(0, 7) + +/* I2C command register */ +#define I2C_CMD_REG 0x5 +#define I2C_CMD_WITH_START PPC_BIT(0) +#define I2C_CMD_WITH_ADDR PPC_BIT(1) +#define I2C_CMD_READ_CONT PPC_BIT(2) +#define I2C_CMD_WITH_STOP PPC_BIT(3) +#define I2C_CMD_INTR_STEERING PPC_BITMASK(6, 7) /* P9 */ +#define I2C_CMD_INTR_STEER_HOST 1 +#define I2C_CMD_INTR_STEER_OCC2 +#define I2C_CMD_DEV_ADDRPPC_BITMASK(8, 14) +#define I2C_CMD_READ_NOT_WRITE PPC_BIT(15) +#define I2C_CMD_LEN_BYTES PPC_BITMASK(16, 31) +#define I2C_MAX_TFR_LEN 0xfff0ull + +/* I2C mode register */ +#define I2C_MODE_REG0x6 +#define I2C_MODE_BIT_RATE_DIV PPC_BITMASK(0, 15) +#define I2C_MODE_PORT_NUM PPC_BITMASK(16, 21) +#define I2C_MODE_ENHANCED PPC_BIT(28) +#define I2C_MODE_DIAGNOSTIC PPC_BIT(29) +#define I2C_MODE_PACING_ALLOW PPC_BIT(30) +#define I2C_MODE_WRAP PPC_BIT(31) + +/* I2C watermark register */ +#define I2C_WATERMARK_REG 0x7 +#define I2C_WATERMARK_HIGH PPC_BITMASK(16, 19) +#define I2C_WATERMARK_LOW PPC_BITMASK(24, 27) + +/* + * I2C interrupt mask and condition registers + * + * NB: The funct
Re: [PATCH 2/3] target/riscv: Support discontinuous PMU counters
On Sun, Oct 8, 2023 at 5:58 PM Alistair Francis wrote: > > On Wed, Oct 4, 2023 at 7:36 PM Rob Bradford wrote: > > > > Hi Atish, > > > > On Tue, 2023-10-03 at 13:25 -0700, Atish Kumar Patra wrote: > > > On Tue, Oct 3, 2023 at 5:51 AM Rob Bradford > > > wrote: > > > > > > > > There is no requirement that the enabled counters in the platform > > > > are > > > > continuously numbered. Add a "pmu-mask" property that, if > > > > specified, can > > > > be used to specify the enabled PMUs. In order to avoid ambiguity if > > > > "pmu-mask" is specified then "pmu-num" must also match the number > > > > of > > > > bits set in the mask. > > > > > > > > Signed-off-by: Rob Bradford > > > > --- > > > > target/riscv/cpu.c | 1 + > > > > target/riscv/cpu_cfg.h | 1 + > > > > target/riscv/pmu.c | 15 +-- > > > > 3 files changed, 15 insertions(+), 2 deletions(-) > > > > > > > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > > > > index 9d79c20c1a..b89b006a76 100644 > > > > --- a/target/riscv/cpu.c > > > > +++ b/target/riscv/cpu.c > > > > @@ -1817,6 +1817,7 @@ static void > > > > riscv_cpu_add_misa_properties(Object *cpu_obj) > > > > static Property riscv_cpu_extensions[] = { > > > > /* Defaults for standard extensions */ > > > > DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), > > > > +DEFINE_PROP_UINT32("pmu-mask", RISCVCPU, cfg.pmu_mask, 0), > > > > DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, > > > > false), > > > > DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), > > > > DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), > > > > diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h > > > > index 0e6a0f245c..40f7d970bc 100644 > > > > --- a/target/riscv/cpu_cfg.h > > > > +++ b/target/riscv/cpu_cfg.h > > > > @@ -124,6 +124,7 @@ struct RISCVCPUConfig { > > > > bool ext_XVentanaCondOps; > > > > > > > > uint8_t pmu_num; > > > > +uint32_t pmu_mask; > > > > char *priv_spec; > > > > char *user_spec; > > > > char *bext_spec; > > > > diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c > > > > index 13801ccb78..f97e25a1f6 100644 > > > > --- a/target/riscv/pmu.c > > > > +++ b/target/riscv/pmu.c > > > > @@ -437,6 +437,13 @@ int riscv_pmu_setup_timer(CPURISCVState *env, > > > > uint64_t value, uint32_t ctr_idx) > > > > void riscv_pmu_init(RISCVCPU *cpu, Error **errp) > > > > { > > > > uint8_t pmu_num = cpu->cfg.pmu_num; > > > > +uint32_t pmu_mask = cpu->cfg.pmu_mask; > > > > + > > > > +if (pmu_mask && ctpop32(pmu_mask) != pmu_num) { > > > > +error_setg(errp, "Mismatch between number of enabled > > > > counters in " > > > > + "\"pmu-mask\" and \"pmu-num\""); > > > > +return; > > > > +} > > > > > > > > > > Is that necessary for the default case? I am thinking of marking > > > pmu-num as deprecated and pmu-mask > > > as the preferred way of doing things as it is more flexible. There is > > > no real benefit carrying both. > > > The default pmu-mask value will change in that case. > > > We can just overwrite pmu-num with ctpop32(pmu_mask) if pmu-mask is > > > available. Thoughts ? > > > > > > > I agree it makes sense to me that there is only one way for the user to > > adjust the PMU count. However i'm not sure how we can handle the > > transition if we choose to deprecate "pmu-num". > > > > If we change the default "pmu-mask" to MAKE_32BIT_MASK(3, 16) then that > > value in the config will always be set - you propose that we overwrite > > "pmu-num" with the popcount of that property. But that will break if > > Couldn't we deprecate "pmu-num" and then throw an error if both are > set? Then we can migrate away from "pmu-num" > Yeah. pmu-num should be only available as a command line property and marked deprecated. If only pmu-num is set, it gets converted to a mask and throws a warning that this is a deprecated property. If only the pmu-mask is set, nothing additional is needed. These patches are sufficient. If nothing is set, the pmu-mask will be set to MAKE_32BIT_MASK(3, 16). If a CPU init code uses pmu-num, we should change it to mask. The upstream code doesn't have any other usage. Any downstream user will have to move away from pmu-num once this series is merged. > Alistair > > > the user has an existing setup that changes the value of "pmu-num" > > (either as a property at runtime or in the CPU init code). > > > > One option would be to not make the mask configurable as property and > > make choosing the layout of the counters something that the specialised > > CPU init can choose to do. > > > > Cheers, > > > > Rob > > > > > > if (pmu_num > (RV_MAX_MHPMCOUNTERS - 3)) { > > > > error_setg(errp, "Number of counters exceeds maximum > > > > available"); > > > > @@ -449,6 +456,10 @@ void riscv_pmu_init(RISCVCPU *cpu, Error > > > > **errp) > > > > return; > > > > } > > > > > > > > -/* Create a bitmask of avail
Re: [PATCH v4 02/10] hw/fsi: Introduce IBM's scratchpad
Hello Cedric, On 9/11/23 07:19, Cédric Le Goater wrote: On 9/9/23 00:28, Ninad Palsule wrote: This is a part of patchset where IBM's Flexible Service Interface is introduced. The LBUS device is embeded inside the scratchpad. The scratchpad provides a non-functional registers. There is a 1-1 relation between scratchpad and LBUS devices. Each LBUS device has 1K memory mapped in the LBUS. The commit log is a bit confusing. I have improved it in my next patch. Please check and let me know. Thanks for the review. ~Ninad C. Signed-off-by: Andrew Jeffery Signed-off-by: Cédric Le Goater Signed-off-by: Ninad Palsule --- v2: - Incorporated Joel's review comments. --- hw/fsi/Kconfig | 4 ++ hw/fsi/engine-scratchpad.c | 100 + hw/fsi/meson.build | 1 + include/hw/fsi/engine-scratchpad.h | 33 ++ 4 files changed, 138 insertions(+) create mode 100644 hw/fsi/engine-scratchpad.c create mode 100644 include/hw/fsi/engine-scratchpad.h diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig index 687449e14e..2a9c49f2c9 100644 --- a/hw/fsi/Kconfig +++ b/hw/fsi/Kconfig @@ -1,2 +1,6 @@ +config SCRATCHPAD + bool + select LBUS + config LBUS bool diff --git a/hw/fsi/engine-scratchpad.c b/hw/fsi/engine-scratchpad.c new file mode 100644 index 00..15a8f8cc66 --- /dev/null +++ b/hw/fsi/engine-scratchpad.c @@ -0,0 +1,100 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2023 IBM Corp. + * + * IBM scratchpad engine + */ + +#include "qemu/osdep.h" + +#include "qapi/error.h" +#include "qemu/log.h" + +#include "hw/fsi/engine-scratchpad.h" + +static uint64_t scratchpad_read(void *opaque, hwaddr addr, unsigned size) +{ + ScratchPad *s = SCRATCHPAD(opaque); + + qemu_log_mask(LOG_UNIMP, "%s: read @0x%" HWADDR_PRIx " size=%d\n", + __func__, addr, size); + + if (addr) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n", + __func__, addr, size); + return 0; + } + + return s->reg; +} + +static void scratchpad_write(void *opaque, hwaddr addr, uint64_t data, + unsigned size) +{ + ScratchPad *s = SCRATCHPAD(opaque); + + qemu_log_mask(LOG_UNIMP, "%s: write @0x%" HWADDR_PRIx " size=%d " + "value=%"PRIx64"\n", __func__, addr, size, data); + + if (addr) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out of bounds write: 0x%"HWADDR_PRIx" for %u\n", + __func__, addr, size); + return; + } + + s->reg = data; +} + +static const struct MemoryRegionOps scratchpad_ops = { + .read = scratchpad_read, + .write = scratchpad_write, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static void scratchpad_realize(DeviceState *dev, Error **errp) +{ + LBusDevice *ldev = LBUS_DEVICE(dev); + + memory_region_init_io(&ldev->iomem, OBJECT(ldev), &scratchpad_ops, + ldev, TYPE_SCRATCHPAD, 0x400); +} + +static void scratchpad_reset(DeviceState *dev) +{ + ScratchPad *s = SCRATCHPAD(dev); + + s->reg = 0; +} + +static void scratchpad_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + LBusDeviceClass *ldc = LBUS_DEVICE_CLASS(klass); + + dc->realize = scratchpad_realize; + dc->reset = scratchpad_reset; + + ldc->config = + ENGINE_CONFIG_NEXT /* valid */ + | 0x0001 /* slots */ + | 0x1000 /* version */ + | ENGINE_CONFIG_TYPE_SCRATCHPAD /* type */ + | 0x0007; /* crc */ +} + +static const TypeInfo scratchpad_info = { + .name = TYPE_SCRATCHPAD, + .parent = TYPE_LBUS_DEVICE, + .instance_size = sizeof(ScratchPad), + .class_init = scratchpad_class_init, + .class_size = sizeof(LBusDeviceClass), +}; + +static void scratchpad_register_types(void) +{ + type_register_static(&scratchpad_info); +} + +type_init(scratchpad_register_types); diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build index e1007d5fea..f90e09ddab 100644 --- a/hw/fsi/meson.build +++ b/hw/fsi/meson.build @@ -1 +1,2 @@ system_ss.add(when: 'CONFIG_LBUS', if_true: files('lbus.c')) +system_ss.add(when: 'CONFIG_SCRATCHPAD', if_true: files('engine-scratchpad.c')) diff --git a/include/hw/fsi/engine-scratchpad.h b/include/hw/fsi/engine-scratchpad.h new file mode 100644 index 00..63bf89ac5a --- /dev/null +++ b/include/hw/fsi/engine-scratchpad.h @@ -0,0 +1,33 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2023 IBM Corp. + * + * IBM scratchpad engne + */ +#ifndef FSI_ENGINE_SCRATCHPAD_H +#define FSI_ENGINE_SCRATCHPAD_H + +#include "qemu/bitops.h" + +#include "hw/fsi/lbus.h" + +#define ENGINE_CONFIG_NEXT BE_BIT(0) +#define ENGINE_CONFIG_VPD BE_BIT(1) +#define ENGINE_CONF
Re: [PATCH v3 10/10] tests/migration-test: Add a test for postcopy hangs during RECOVER
Fabiano Rosas writes: > Peter Xu writes: > >> On Thu, Oct 05, 2023 at 06:10:20PM -0300, Fabiano Rosas wrote: >>> Peter Xu writes: >>> >>> > On Thu, Oct 05, 2023 at 10:37:56AM -0300, Fabiano Rosas wrote: >>> >> >> +/* >>> >> >> + * Make sure both QEMU instances will go into RECOVER stage, >>> >> >> then test >>> >> >> + * kicking them out using migrate-pause. >>> >> >> + */ >>> >> >> +wait_for_postcopy_status(from, "postcopy-recover"); >>> >> >> +wait_for_postcopy_status(to, "postcopy-recover"); >>> >> > >>> >> > Is this wait out of place? I think we're trying to resume too fast >>> >> > after >>> >> > migrate_recover(): >>> >> > >>> >> > # { >>> >> > # "error": { >>> >> > # "class": "GenericError", >>> >> > # "desc": "Cannot resume if there is no paused migration" >>> >> > # } >>> >> > # } >>> >> > >>> >> >>> >> Ugh, sorry about the long lines: >>> >> >>> >> { >>> >> "error": { >>> >> "class": "GenericError", >>> >> "desc": "Cannot resume if there is no paused migration" >>> >> } >>> >> } >>> > >>> > Sorry I didn't get you here. Could you elaborate your question? >>> > >>> >>> The test is sometimes failing with the above message. >>> >>> But indeed my question doesn't make sense. I forgot migrate_recover >>> happens on the destination. Nevermind. >>> >>> The bug is still present nonetheless. We're going into migrate_prepare >>> in some state other than POSTCOPY_PAUSED. >> >> Oh I see. Interestingly I cannot reproduce on my host, just like last >> time.. >> >> What is your setup for running the test? Anything special? Here's my >> cmdline: > > The crudest oneliner: > > for i in $(seq 1 ); do echo "$i ="; \ > QTEST_QEMU_BINARY=./qemu-system-x86_64 \ > ./tests/qtest/migration-test -r /x86_64/migration/postcopy/recovery || break > ; done > > I suspect my system has something specific to it that affects the timing > of the tests. But I have no idea what it could be. > > $ lscpu > Architecture:x86_64 > CPU op-mode(s):32-bit, 64-bit > Address sizes: 39 bits physical, 48 bits virtual > Byte Order:Little Endian > CPU(s): 16 > On-line CPU(s) list: 0-15 > Vendor ID: GenuineIntel > Model name:11th Gen Intel(R) Core(TM) i7-11850H @ 2.50GHz > CPU family: 6 > Model: 141 > Thread(s) per core: 2 > Core(s) per socket: 8 > Socket(s): 1 > Stepping:1 > CPU max MHz: 4800. > CPU min MHz: 800. > BogoMIPS:4992.00 > >> >> $ cat reproduce.sh >> index=$1 >> loop=0 >> >> while :; do >> echo "Starting loop=$loop..." >> QTEST_QEMU_BINARY=./qemu-system-x86_64 ./tests/qtest/migration-test >> -p /x86_64/migration/postcopy/recovery/double-failures >> if [[ $? != 0 ]]; then >> echo "index $index REPRODUCED (loop=$loop) !" >> break >> fi >> loop=$(( loop + 1 )) >> done >> >> Survives 200+ loops and kept going. >> >> However I think I saw what's wrong here, could you help try below fixup? >> > > Sure. I won't get to it until tomorrow though. It seems to have fixed the issue. 3500 iterations and still going.
Re: [PATCH v4 02/10] hw/fsi: Introduce IBM's scratchpad
Hello Cedric, On 9/9/23 03:37, Cédric Le Goater wrote: On 9/9/23 00:28, Ninad Palsule wrote: This is a part of patchset where IBM's Flexible Service Interface is introduced. The LBUS device is embeded inside the scratchpad. The scratchpad embedded Fixed provides a non-functional registers. There is a 1-1 relation between scratchpad and LBUS devices. Each LBUS device has 1K memory mapped in the LBUS. Signed-off-by: Andrew Jeffery Signed-off-by: Cédric Le Goater Signed-off-by: Ninad Palsule --- v2: - Incorporated Joel's review comments. --- hw/fsi/Kconfig | 4 ++ hw/fsi/engine-scratchpad.c | 100 + hw/fsi/meson.build | 1 + include/hw/fsi/engine-scratchpad.h | 33 ++ 4 files changed, 138 insertions(+) create mode 100644 hw/fsi/engine-scratchpad.c create mode 100644 include/hw/fsi/engine-scratchpad.h diff --git a/hw/fsi/Kconfig b/hw/fsi/Kconfig index 687449e14e..2a9c49f2c9 100644 --- a/hw/fsi/Kconfig +++ b/hw/fsi/Kconfig @@ -1,2 +1,6 @@ +config SCRATCHPAD + bool + select LBUS + config LBUS bool diff --git a/hw/fsi/engine-scratchpad.c b/hw/fsi/engine-scratchpad.c new file mode 100644 index 00..15a8f8cc66 --- /dev/null +++ b/hw/fsi/engine-scratchpad.c @@ -0,0 +1,100 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2023 IBM Corp. + * + * IBM scratchpad engine + */ + +#include "qemu/osdep.h" + +#include "qapi/error.h" +#include "qemu/log.h" + +#include "hw/fsi/engine-scratchpad.h" + +static uint64_t scratchpad_read(void *opaque, hwaddr addr, unsigned size) +{ + ScratchPad *s = SCRATCHPAD(opaque); + + qemu_log_mask(LOG_UNIMP, "%s: read @0x%" HWADDR_PRIx " size=%d\n", + __func__, addr, size); This should be a trace event. The comment applies to all similar usage. Fixed all required places. + + if (addr) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out of bounds read: 0x%"HWADDR_PRIx" for %u\n", + __func__, addr, size); + return 0; if the MMIO region is correctly sized, this should not be necessary. Do you plans to add support for registers ? If required I am going to implement registers. Current plan is to get initial changes in and then add more stuff. + } + + return s->reg; +} + +static void scratchpad_write(void *opaque, hwaddr addr, uint64_t data, + unsigned size) +{ + ScratchPad *s = SCRATCHPAD(opaque); + + qemu_log_mask(LOG_UNIMP, "%s: write @0x%" HWADDR_PRIx " size=%d " + "value=%"PRIx64"\n", __func__, addr, size, data); trace event Fixed + + if (addr) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Out of bounds write: 0x%"HWADDR_PRIx" for %u\n", + __func__, addr, size); + return; + } + + s->reg = data; +} + +static const struct MemoryRegionOps scratchpad_ops = { + .read = scratchpad_read, + .write = scratchpad_write, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static void scratchpad_realize(DeviceState *dev, Error **errp) +{ + LBusDevice *ldev = LBUS_DEVICE(dev); + + memory_region_init_io(&ldev->iomem, OBJECT(ldev), &scratchpad_ops, + ldev, TYPE_SCRATCHPAD, 0x400); +} + +static void scratchpad_reset(DeviceState *dev) +{ + ScratchPad *s = SCRATCHPAD(dev); + + s->reg = 0; +} + +static void scratchpad_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + LBusDeviceClass *ldc = LBUS_DEVICE_CLASS(klass); + + dc->realize = scratchpad_realize; + dc->reset = scratchpad_reset; + + ldc->config = + ENGINE_CONFIG_NEXT /* valid */ + | 0x0001 /* slots */ + | 0x1000 /* version */ + | ENGINE_CONFIG_TYPE_SCRATCHPAD /* type */ + | 0x0007; /* crc */ where is ->config used ? Yes, Its not but I am thinking of keeping it as next step we may need it. Thanks for the review. ~ Ninad +} + +static const TypeInfo scratchpad_info = { + .name = TYPE_SCRATCHPAD, + .parent = TYPE_LBUS_DEVICE, + .instance_size = sizeof(ScratchPad), + .class_init = scratchpad_class_init, + .class_size = sizeof(LBusDeviceClass), +}; + +static void scratchpad_register_types(void) +{ + type_register_static(&scratchpad_info); +} + +type_init(scratchpad_register_types); diff --git a/hw/fsi/meson.build b/hw/fsi/meson.build index e1007d5fea..f90e09ddab 100644 --- a/hw/fsi/meson.build +++ b/hw/fsi/meson.build @@ -1 +1,2 @@ system_ss.add(when: 'CONFIG_LBUS', if_true: files('lbus.c')) +system_ss.add(when: 'CONFIG_SCRATCHPAD', if_true: files('engine-scratchpad.c')) diff --git a/include/hw/fsi/engine-scratchpad.h b/include/hw/fsi/engine-scratchpad.h new file mode 100644 index 00..63bf89ac5a --- /dev/null +++ b/include/hw/fsi/engine-scratchpad.h
[PATCH 2/3] hw/misc/mips_itu: Declare itc_reconfigure() in 'hw/misc/mips_itu.h'
We already provide "hw/misc/mips_itu.h" to declare prototype related to MIPSITUState. Move itc_reconfigure() declaration there. Signed-off-by: Philippe Mathieu-Daudé --- include/hw/misc/mips_itu.h | 2 ++ target/mips/cpu.h | 3 --- target/mips/tcg/sysemu/cp0_helper.c | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/hw/misc/mips_itu.h b/include/hw/misc/mips_itu.h index 35218b2d14..a413789151 100644 --- a/include/hw/misc/mips_itu.h +++ b/include/hw/misc/mips_itu.h @@ -79,4 +79,6 @@ struct MIPSITUState { /* Get ITC Configuration Tag memory region. */ MemoryRegion *mips_itu_get_tag_region(MIPSITUState *itu); +void itc_reconfigure(struct MIPSITUState *tag); + #endif /* MIPS_ITU_H */ diff --git a/target/mips/cpu.h b/target/mips/cpu.h index fb44defc93..5fddceff3a 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1350,9 +1350,6 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level); void cpu_mips_irq_init_cpu(MIPSCPU *cpu); void cpu_mips_clock_init(MIPSCPU *cpu); -/* mips_itu.c */ -void itc_reconfigure(struct MIPSITUState *tag); - #endif /* !CONFIG_USER_ONLY */ /* helper.c */ diff --git a/target/mips/tcg/sysemu/cp0_helper.c b/target/mips/tcg/sysemu/cp0_helper.c index 5da1124589..d349548743 100644 --- a/target/mips/tcg/sysemu/cp0_helper.c +++ b/target/mips/tcg/sysemu/cp0_helper.c @@ -28,6 +28,7 @@ #include "qemu/host-utils.h" #include "exec/helper-proto.h" #include "exec/exec-all.h" +#include "hw/misc/mips_itu.h" /* SMP helpers. */ -- 2.41.0
[PATCH 3/3] hw/misc/mips_itu: Make MIPSITUState target agnostic
When prototyping a heterogenous machine including the ITU, we get: include/hw/misc/mips_itu.h:76:5: error: unknown type name 'MIPSCPU' MIPSCPU *cpu0; ^ MIPSCPU is declared in the target specific "cpu.h" header, but we don't want to include it, because "cpu.h" is target specific and its inclusion taints all files including "mips_itu.h", which become target specific too. We can however use the 'ArchCPU *' type in the public header. By keeping the TYPE_MIPS_CPU QOM type check in the link property declaration, QOM core code will still check the property is a correct MIPS CPU. TYPE_MIPS_ITU is still built per-(MIPS)target, but its header can now be included by other targets. Signed-off-by: Philippe Mathieu-Daudé --- include/hw/misc/mips_itu.h | 2 +- hw/misc/mips_itu.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/hw/misc/mips_itu.h b/include/hw/misc/mips_itu.h index a413789151..5caed6cc36 100644 --- a/include/hw/misc/mips_itu.h +++ b/include/hw/misc/mips_itu.h @@ -73,7 +73,7 @@ struct MIPSITUState { /* SAAR */ uint64_t *saar; -MIPSCPU *cpu0; +ArchCPU *cpu0; }; /* Get ITC Configuration Tag memory region. */ diff --git a/hw/misc/mips_itu.c b/hw/misc/mips_itu.c index 0eda302db4..5a83ccc4e8 100644 --- a/hw/misc/mips_itu.c +++ b/hw/misc/mips_itu.c @@ -532,7 +532,7 @@ static void mips_itu_realize(DeviceState *dev, Error **errp) return; } -env = &s->cpu0->env; +env = &MIPS_CPU(s->cpu0)->env; if (env->saarp) { s->saar = env->CP0_SAAR; } @@ -563,7 +563,7 @@ static Property mips_itu_properties[] = { ITC_FIFO_NUM_MAX), DEFINE_PROP_UINT32("num-semaphores", MIPSITUState, num_semaphores, ITC_SEMAPH_NUM_MAX), -DEFINE_PROP_LINK("cpu[0]", MIPSITUState, cpu0, TYPE_MIPS_CPU, MIPSCPU *), +DEFINE_PROP_LINK("cpu[0]", MIPSITUState, cpu0, TYPE_MIPS_CPU, ArchCPU *), DEFINE_PROP_END_OF_LIST(), }; -- 2.41.0
[PATCH 1/3] hw/mips: Merge 'hw/mips/cpudevs.h' with 'target/mips/cpu.h'
"hw/mips/cpudevs.h" contains declarations which are specific to the MIPS architecture; it doesn't make sense for these to be called from a non-MIPS architecture. Move the declarations to "target/mips/cpu.h". Signed-off-by: Philippe Mathieu-Daudé --- include/hw/mips/cpudevs.h | 14 -- target/mips/cpu.h | 4 +++- hw/mips/cps.c | 1 - hw/mips/fuloong2e.c | 1 - hw/mips/jazz.c | 1 - hw/mips/loongson3_virt.c| 1 - hw/mips/malta.c | 1 - hw/mips/mips_int.c | 1 - hw/mips/mipssim.c | 1 - target/mips/sysemu/cp0_timer.c | 1 - target/mips/tcg/sysemu/tlb_helper.c | 1 - 11 files changed, 3 insertions(+), 24 deletions(-) delete mode 100644 include/hw/mips/cpudevs.h diff --git a/include/hw/mips/cpudevs.h b/include/hw/mips/cpudevs.h deleted file mode 100644 index f7c9728fa9..00 --- a/include/hw/mips/cpudevs.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef HW_MIPS_CPUDEVS_H -#define HW_MIPS_CPUDEVS_H - -#include "target/mips/cpu-qom.h" - -/* Definitions for MIPS CPU internal devices. */ - -/* mips_int.c */ -void cpu_mips_irq_init_cpu(MIPSCPU *cpu); - -/* mips_timer.c */ -void cpu_mips_clock_init(MIPSCPU *cpu); - -#endif diff --git a/target/mips/cpu.h b/target/mips/cpu.h index 67f8e8b988..fb44defc93 100644 --- a/target/mips/cpu.h +++ b/target/mips/cpu.h @@ -1345,8 +1345,10 @@ uint64_t cpu_mips_phys_to_kseg1(void *opaque, uint64_t addr); #if !defined(CONFIG_USER_ONLY) -/* mips_int.c */ +/* HW declaration specific to the MIPS target */ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level); +void cpu_mips_irq_init_cpu(MIPSCPU *cpu); +void cpu_mips_clock_init(MIPSCPU *cpu); /* mips_itu.c */ void itc_reconfigure(struct MIPSITUState *tag); diff --git a/hw/mips/cps.c b/hw/mips/cps.c index 2b5269ebf1..b6612c1762 100644 --- a/hw/mips/cps.c +++ b/hw/mips/cps.c @@ -24,7 +24,6 @@ #include "hw/mips/mips.h" #include "hw/qdev-clock.h" #include "hw/qdev-properties.h" -#include "hw/mips/cpudevs.h" #include "sysemu/kvm.h" #include "sysemu/reset.h" diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c index c6109633fe..97b2c8ed8e 100644 --- a/hw/mips/fuloong2e.c +++ b/hw/mips/fuloong2e.c @@ -30,7 +30,6 @@ #include "hw/block/flash.h" #include "hw/mips/mips.h" #include "hw/mips/bootloader.h" -#include "hw/mips/cpudevs.h" #include "hw/pci/pci.h" #include "hw/loader.h" #include "hw/ide/pci.h" diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index c32d2b0b0a..86dfe05ea8 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -26,7 +26,6 @@ #include "qemu/datadir.h" #include "hw/clock.h" #include "hw/mips/mips.h" -#include "hw/mips/cpudevs.h" #include "hw/intc/i8259.h" #include "hw/dma/i8257.h" #include "hw/char/serial.h" diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index b74b358874..33eae01eca 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -32,7 +32,6 @@ #include "hw/char/serial.h" #include "hw/intc/loongson_liointc.h" #include "hw/mips/mips.h" -#include "hw/mips/cpudevs.h" #include "hw/mips/fw_cfg.h" #include "hw/mips/loongson3_bootp.h" #include "hw/misc/unimp.h" diff --git a/hw/mips/malta.c b/hw/mips/malta.c index dac27fad9d..b0110c4da6 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -37,7 +37,6 @@ #include "hw/block/flash.h" #include "hw/mips/mips.h" #include "hw/mips/bootloader.h" -#include "hw/mips/cpudevs.h" #include "hw/pci/pci.h" #include "hw/pci/pci_bus.h" #include "qemu/log.h" diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c index 73437cd90f..6c32e466a3 100644 --- a/hw/mips/mips_int.c +++ b/hw/mips/mips_int.c @@ -23,7 +23,6 @@ #include "qemu/osdep.h" #include "qemu/main-loop.h" #include "hw/irq.h" -#include "hw/mips/cpudevs.h" #include "sysemu/kvm.h" #include "kvm_mips.h" diff --git a/hw/mips/mipssim.c b/hw/mips/mipssim.c index 2f951f7fc6..4f743f37eb 100644 --- a/hw/mips/mipssim.c +++ b/hw/mips/mipssim.c @@ -30,7 +30,6 @@ #include "qemu/datadir.h" #include "hw/clock.h" #include "hw/mips/mips.h" -#include "hw/mips/cpudevs.h" #include "hw/char/serial.h" #include "hw/isa/isa.h" #include "net/net.h" diff --git a/target/mips/sysemu/cp0_timer.c b/target/mips/sysemu/cp0_timer.c index 9d2bcb0dea..62de502caa 100644 --- a/target/mips/sysemu/cp0_timer.c +++ b/target/mips/sysemu/cp0_timer.c @@ -22,7 +22,6 @@ #include "qemu/osdep.h" #include "hw/irq.h" -#include "hw/mips/cpudevs.h" #include "qemu/timer.h" #include "sysemu/kvm.h" #include "internal.h" diff --git a/target/mips/tcg/sysemu/tlb_helper.c b/target/mips/tcg/sysemu/tlb_helper.c index 7dbc2e24c4..4ede904800 100644 --- a/target/mips/tcg/sysemu/tlb_helper.c +++ b/target/mips/tcg/sysemu/tlb_helper.c @@ -24,7 +24,6 @@ #include "exec/exec-all.h" #include "exec/cpu_ldst.h" #include "exec/log.h" -#include "hw/mips/cpudevs.h" #include "exec/helper-proto.h" /* TLB management */ -- 2.41.0
[PATCH 0/3] hw/mips: Cleanup in preparation of heterogenous prototype
Prepare few MIPS hardware to be integrated in a heterogeneous machine: - Restrict MIPS-specific HW declaration to target/mips/ - Replace MIPSCPU by ArchCPU in common HW Philippe Mathieu-Daudé (3): hw/mips: Merge 'hw/mips/cpudevs.h' with 'target/mips/cpu.h' hw/misc/mips_itu: Declare itc_reconfigure() in 'hw/misc/mips_itu.h' hw/misc/mips_itu: Make MIPSITUState target agnostic include/hw/mips/cpudevs.h | 14 -- include/hw/misc/mips_itu.h | 4 +++- target/mips/cpu.h | 7 +++ hw/mips/cps.c | 1 - hw/mips/fuloong2e.c | 1 - hw/mips/jazz.c | 1 - hw/mips/loongson3_virt.c| 1 - hw/mips/malta.c | 1 - hw/mips/mips_int.c | 1 - hw/mips/mipssim.c | 1 - hw/misc/mips_itu.c | 4 ++-- target/mips/sysemu/cp0_timer.c | 1 - target/mips/tcg/sysemu/cp0_helper.c | 1 + target/mips/tcg/sysemu/tlb_helper.c | 1 - 14 files changed, 9 insertions(+), 30 deletions(-) delete mode 100644 include/hw/mips/cpudevs.h -- 2.41.0