Compare commits

..
62 Commits
Author SHA1 Message Date
Michael Tokarev b2995afed2 Update version for 9.2.4 release
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-26 10:33:13 +03:00
Helge Deller 0befc056f3 target/hppa: Fix FPE exceptions
Implement FP exception register #1 (lower 32-bits of 64-bit fr[0]).
A proper implementation is necessary to allow the Linux kernel in
system mode and the qemu linux-user to send proper si_code values
on SIGFPE signal.

Always set the T-bit on taken exception, and merge over- and underflow
in system mode to just set overflow bit to mimic the behaviour I tested
on a physical machine.

The test program below can be used to verify correct behaviour. Note
that behaviour on SIGFPE may vary on different platforms. The program
should always detect the correct signal, but it may or may not be able
to sucessfully continue afterwards.

 #define _GNU_SOURCE
 #include <signal.h>
 #include <stdio.h>
 #include <fenv.h>
 #include <float.h>

 static void fpe_func(int sig, siginfo_t *i, void *v) {
    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGFPE);
    sigprocmask(SIG_UNBLOCK, &set, NULL);
    printf("GOT signal %d with si_code %ld\n", sig, i->si_code);
 }

 int main(int argc, char *argv[]) {
    struct sigaction action = {
        .sa_sigaction = fpe_func,
        .sa_flags = SA_RESTART|SA_SIGINFO };
    sigaction(SIGFPE, &action, 0);
    feenableexcept(FE_OVERFLOW | FE_UNDERFLOW);
    double x = DBL_MIN;
    return printf("%lf\n", argc > 1
        ? 1.7976931348623158E308*1.7976931348623158E308
        : x / 10);
 }

Signed-off-by: Helge Deller <deller@gmx.de>
(cherry picked from commit ebd394948d)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-25 13:14:52 +03:00
Helge Deller 148eb79f57 linux-user/hppa: Send proper si_code on SIGFPE exception
Improve the linux-user emulation to send the correct si_code depending
on overflow (TARGET_FPE_FLTOVF), underflow (TARGET_FPE_FLTUND), ...
Note that the hardware stores the relevant flags in FP exception
register #1, which is actually the lower 32-bits of the 64-bit fr[0]
register in qemu.

Signed-off-by: Helge Deller <deller@gmx.de>
(cherry picked from commit b4b49cf39d)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-25 13:14:52 +03:00
Helge Deller b1ff64ba4e target/hppa: Copy instruction code into fr1 on FPU assist fault
The hardware stores the instruction code in the lower bits of the FP
exception register #1 on FP assist traps.
This fixes the FP exception handler on Linux, as the Linux kernel uses
the value to decide on the correct signal which should be pushed into
userspace (see decode_fpu() in Linux kernel).

Signed-off-by: Helge Deller <deller@gmx.de>
(cherry picked from commit 923976dfe3)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-25 13:14:52 +03:00
Peter Xu 53a4bf6830 migration: Allow caps to be set when preempt or multifd cap enabled
With commit 82137e6c8c ("migration: enforce multifd and postcopy preempt to
be set before incoming"), and if postcopy preempt / multifd is enabled, one
cannot setup any capability because these checks would always fail.

(qemu) migrate_set_capability xbzrle off
Error: Postcopy preempt must be set before incoming starts

To fix it, check existing cap and only raise an error if the specific cap
changed.

Fixes: 82137e6c8c ("migration: enforce multifd and postcopy preempt to be set before incoming")
Reviewed-by: Dr. David Alan Gilbert <dave@treblig.org>
Reviewed-by: Juraj Marcin <jmarcin@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
(cherry picked from commit 17bec9235b)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-25 13:14:52 +03:00
Zhao Liu 5a1414313b qapi/misc-target: Fix the doc to distinguish query-sgx and query-sgx-capabilities
There're 2 QMP commands: query-sgx and query-sgx-capabilities, but
their outputs are very similar and the documentation lacks clear
differentiation.

From the codes, query-sgx is used to gather guest's SGX capabilities
(including SGX related CPUIDs and EPC sections' size, in SGXInfo), and
if guest doesn't have SGX, then QEMU will report the error message.

On the other hand, query-sgx-capabilities is used to gather host's SGX
capabilities (descripted by SGXInfo as well). And if host doesn't
support SGX, then QEMU will also report the error message.

Considering that SGXInfo is already documented and both these 2 commands
have enough error messages (for the exception case in their codes).

Therefore the QAPI documentation for these two commands only needs to
emphasize that one of them applies to the guest and the other to the
host.

Fix their documentation to reflect this difference.

Reported-by: Markus Armbruster <armbru@redhat.com>
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
Acked-by: Markus Armbruster <armbru@redhat.com>
Link: https://lore.kernel.org/r/20250513143131.2008078-3-zhao1.liu@intel.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 7f2131c35c)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-25 13:14:52 +03:00
Rakesh Jeyasingh 361bd5efe4 hw/pci-host: Remove unused pci_host_data_be_ops
pci_host_data_be_ops became unused after endianness fixes

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Rakesh Jeyasingh <rakeshjb010@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Thomas Huth <thuth@redhat.com>
Link: https://lore.kernel.org/r/20250429170354.150581-3-rakeshjb010@gmail.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 560375cff3)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-25 13:14:52 +03:00
Rakesh Jeyasingh 5d139247e9 hw/pci-host/gt64120: Fix endianness handling
The GT-64120 PCI controller requires special handling where:
1. Host bridge(bus 0 ,device 0) must never be byte-swapped
2. Other devices follow MByteSwap bit in GT_PCI0_CMD

The previous implementation incorrectly  swapped all accesses, breaking
host bridge detection (lspci -d 11ab:4620).

Changes made:
1. Removed gt64120_update_pci_cfgdata_mapping() and moved data_mem initialization
  to gt64120_realize() for cleaner setup
2. Implemented custom read/write handlers that:
   - Preserve host bridge accesses (extract32(config_reg,11,13)==0)
   - apply swapping only for non-bridge devices in big-endian mode

Fixes: 145e2198 ("hw/mips/gt64xxx_pci: Endian-swap using PCI_HOST_BRIDGE MemoryRegionOps")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2826

Signed-off-by: Rakesh Jeyasingh <rakeshjb010@gmail.com>
Tested-by: Thomas Huth <thuth@redhat.com>
Link: https://lore.kernel.org/r/20250429170354.150581-2-rakeshjb010@gmail.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit e5894fd6f4)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-25 13:14:52 +03:00
Daniel Henrique Barboza 289dcab554 target/riscv/kvm: add kvm_csr_cfgs[]
At this moment we're not checking if the host has support for any
specific CSR before doing get/put regs. This will cause problems if the
host KVM doesn't support it (see [1] as an example).

We'll use the same approach done with the CPU extensions: read all known
KVM CSRs during init() to check for availability, then read/write them
if they are present. This will be made by either using get-reglist or by
directly reading the CSRs.

For now we'll just convert the CSRs to use a kvm_csr_cfg[] array,
reusing the same KVMCPUConfig abstraction we use for extensions, and use
the array in (get|put)_csr_regs() instead of manually listing them. A
lot of boilerplate will be added but at least we'll automate the get/put
procedure for CSRs, i.e. adding a new CSR in the future will be a matter
of adding it in kvm_csr_regs[] and everything else will be taken care
of.

Despite all the code changes no behavioral change is made.

[1] https://lore.kernel.org/qemu-riscv/CABJz62OfUDHYkQ0T3rGHStQprf1c7_E0qBLbLKhfv=+jb0SYAw@mail.gmail.com/

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20250429124421.223883-6-dbarboza@ventanamicro.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit d3b6f1742c)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-25 13:14:52 +03:00
Daniel Henrique Barboza e2d4d3c2ac target/riscv/kvm: turn kvm_riscv_reg_id_ulong() into a macro
We need the reg_id_ulong() helper to be a macro to be able to create a
static array of KVMCPUConfig that will hold CSR information.

Despite the amount of changes all of them are tedious/trivial:

- replace instances of "kvm_riscv_reg_id_ulong" with
  "KVM_RISCV_REG_ID_ULONG";

- RISCV_CORE_REG(), RISCV_CSR_REG(), RISCV_CONFIG_REG() and
  RISCV_VECTOR_CSR_REG() only receives one 'name' arg. Remove unneeded
  'env' variables when applicable.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20250429124421.223883-5-dbarboza@ventanamicro.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit 11766e1761)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-25 13:14:52 +03:00
Daniel Henrique Barboza 6b10b25ddd target/riscv/kvm: turn u32/u64 reg functions into macros
This change is motivated by a future change w.r.t CSRs management. We
want to handle them the same way as KVM extensions, i.e. a static array
with KVMCPUConfig objs that will be read/write during init and so on.
But to do that properly we must be able to declare a static array that
hold KVM regs.

C does not allow to init static arrays and use functions as
initializers, e.g. we can't do:

.kvm_reg_id = kvm_riscv_reg_id_ulong(...)

When instantiating the array. We can do that with macros though, so our
goal is turn kvm_riscv_reg_ulong() in a macro. It is cleaner to turn
every other reg_id_*() function in macros, and ulong will end up using
the macros for u32 and u64, so we'll start with them.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20250429124421.223883-4-dbarboza@ventanamicro.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit b609610349)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-25 13:14:52 +03:00
Daniel Henrique Barboza 800495a394 target/riscv/kvm: fix leak in kvm_riscv_init_multiext_cfg()
'reglist' is being g-malloc'ed but never freed.

Reported-by: Andrew Jones <ajones@ventanamicro.com>
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20250429124421.223883-3-dbarboza@ventanamicro.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit 906af6de94)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-25 13:14:52 +03:00
Anton Blanchard ac053657f0 target/riscv: Fix vslidedown with rvv_ta_all_1s
vslidedown always zeroes elements past vl, where it should use the
tail policy.

Signed-off-by: Anton Blanchard <antonb@tenstorrent.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20250414213006.3509058-1-antonb@tenstorrent.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit 2669b696e2)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-20 09:59:28 +03:00
Max Chou 41c984df66 target/riscv: Fix the rvv reserved encoding of unmasked instructions
According to the v spec, the encodings of vcomoress.vm and vector
mask-register logical instructions with vm=0 are reserved.

Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
Message-ID: <20250408103938.3623486-11-max.chou@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit 8539a1244b)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-20 09:59:14 +03:00
Max Chou 84dd432553 target/riscv: rvv: Apply vext_check_input_eew to vector indexed load/store instructions
Handle the overlap of source registers with different EEWs.

Co-authored-by: Anton Blanchard <antonb@tenstorrent.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
Message-ID: <20250408103938.3623486-10-max.chou@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit db21c3eb05)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-20 09:59:09 +03:00
Max Chou dec1f0b924 target/riscv: rvv: Apply vext_check_input_eew to vector narrow/widen instructions
Handle the overlap of source registers with different EEWs.
The vd of vector widening mul-add instructions is one of the input
operands.

Co-authored-by: Anton Blanchard <antonb@tenstorrent.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
Message-ID: <20250408103938.3623486-9-max.chou@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit 1f090a229f)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-20 09:59:03 +03:00
Max Chou 32f8a2b429 target/riscv: rvv: Apply vext_check_input_eew to vector integer extension instructions(OPMVV)
Handle the overlap of source registers with different EEWs.

Co-authored-by: Anton Blanchard <antonb@tenstorrent.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
Message-ID: <20250408103938.3623486-8-max.chou@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit 411eefd56a)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-20 09:58:56 +03:00
Max Chou d5166dad55 target/riscv: rvv: Apply vext_check_input_eew to vector slide instructions(OPIVI/OPIVX)
Handle the overlap of source registers with different EEWs.

Co-authored-by: Anton Blanchard <antonb@tenstorrent.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
Message-ID: <20250408103938.3623486-7-max.chou@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit b5480a693e)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-20 09:58:08 +03:00
Max Chou 80eebc00f9 target/riscv: rvv: Apply vext_check_input_eew to OPIVV/OPFVV(vext_check_sss) instructions
Handle the overlap of source registers with different EEWs.

Co-authored-by: Anton Blanchard <antonb@tenstorrent.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
Message-ID: <20250408103938.3623486-6-max.chou@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit fda68acb77)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-20 09:57:23 +03:00
Max Chou fd0fc3eb48 target/riscv: rvv: Apply vext_check_input_eew to OPIVI/OPIVX/OPFVF(vext_check_ss) instructions
Handle the overlap of source registers with different EEWs.

Co-authored-by: Anton Blanchard <antonb@tenstorrent.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
Message-ID: <20250408103938.3623486-5-max.chou@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit fbeaf35838)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-20 09:57:07 +03:00
Max Chou 28ee50bbe9 target/riscv: rvv: Apply vext_check_input_eew to vrgather instructions to check mismatched input EEWs encoding constraint
According to the v spec, a vector register cannot be used to provide source
operands with more than one EEW for a single instruction.
The vs1 EEW of vrgatherei16.vv is 16.

Co-authored-by: Anton Blanchard <antonb@tenstorrent.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
Message-ID: <20250408103938.3623486-4-max.chou@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit 629c2a8dd7)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-20 09:56:55 +03:00
Anton Blanchard 6c4ddafa0d target/riscv: rvv: Add CHECK arg to GEN_OPFVF_WIDEN_TRANS
Signed-off-by: Anton Blanchard <antonb@tenstorrent.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Max Chou <max.chou@sifive.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
Message-ID: <20250408103938.3623486-3-max.chou@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit b0450a101d)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-20 09:56:46 +03:00
Anton Blanchard 10bfc8d45e target/riscv: rvv: Source vector registers cannot overlap mask register
Add the relevant ISA paragraphs explaining why source (and destination)
registers cannot overlap the mask register.

Signed-off-by: Anton Blanchard <antonb@tenstorrent.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Max Chou <max.chou@sifive.com>
Signed-off-by: Max Chou <max.chou@sifive.com>
Message-ID: <20250408103938.3623486-2-max.chou@sifive.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit 3e8d1e4a62)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-20 09:56:38 +03:00
Icenowy fb1f88ee29 common-user/host/riscv: use tail pseudoinstruction for calling tail
The j pseudoinstruction maps to a JAL instruction, which can only handle
a jump to somewhere with a signed 20-bit destination. In case of static
linking and LTO'ing this easily leads to "relocation truncated to fit"
error.

Switch to use tail pseudoinstruction, which is the standard way to
tail-call a function in medium code model (emits AUIPC+JALR).

Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20250417072206.364008-1-uwu@icenowy.me>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit 22b448ccc6)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-20 09:56:01 +03:00
Ziqiao Kong 82c0f4946a target/riscv: fix endless translation loop on big endian systems
On big endian systems, pte and updated_pte hold big endian host data
while pte_pa points to little endian target data. This means the branch
at cpu_helper.c:1669 will be always satisfied and restart translation,
causing an endless translation loop.

The correctness of this patch can be deduced by:

old_pte will hold value either from cpu_to_le32/64(pte) or
cpu_to_le32/64(updated_pte), both of wich is litte endian. After that,
an in-place conversion by le32/64_to_cpu(old_pte) ensures that old_pte
now is in native endian, same with pte. Therefore, the endianness of the
both side of if (old_pte != pte) is correct.

Signed-off-by: Ziqiao Kong <ziqiaokong@gmail.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20250415080254.3667878-2-ziqiaokong@gmail.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit ad63158bdb)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-20 09:55:46 +03:00
Loïc Lefort d6258d62cf target/riscv: pmp: move Smepmp operation conversion into a function
Signed-off-by: Loïc Lefort <loic@rivosinc.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Message-ID: <20250313193011.720075-3-loic@rivosinc.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Cc: qemu-stable@nongnu.org
(cherry picked from commit 915b203745)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-20 09:54:28 +03:00
Akihiko Odaki 0b8c7cdeff virtio: Call set_features during reset
virtio-net expects set_features() will be called when the feature set
used by the guest changes to update the number of virtqueues but it is
not called during reset, which will clear all features, leaving the
queues added for VIRTIO_NET_F_MQ or VIRTIO_NET_F_RSS. Not only these
extra queues are visible to the guest, they will cause segmentation
fault during migration.

Call set_features() during reset to remove those queues for virtio-net
as we call set_status(). It will also prevent similar bugs for
virtio-net and other devices in the future.

Fixes: f9d6dbf0bf ("virtio-net: remove virtio queues if the guest doesn't support multiqueue")
Buglink: https://issues.redhat.com/browse/RHEL-73842
Cc: qemu-stable@nongnu.org
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Message-Id: <20250421-reset-v2-1-e4c1ead88ea1@daynix.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 0caed25cd1)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-16 01:00:59 +03:00
Fabiano Rosas 0883bdd92e s390x: Fix leak in machine_set_loadparm
ASAN spotted a leaking string in machine_set_loadparm():

Direct leak of 9 byte(s) in 1 object(s) allocated from:
    #0 0x560ffb5bb379 in malloc ../projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3
    #1 0x7f1aca926518 in g_malloc ../glib/gmem.c:106
    #2 0x7f1aca94113e in g_strdup ../glib/gstrfuncs.c:364
    #3 0x560ffc8afbf9 in qobject_input_type_str ../qapi/qobject-input-visitor.c:542:12
    #4 0x560ffc8a80ff in visit_type_str ../qapi/qapi-visit-core.c:349:10
    #5 0x560ffbe6053a in machine_set_loadparm ../hw/s390x/s390-virtio-ccw.c:802:10
    #6 0x560ffc0c5e52 in object_property_set ../qom/object.c:1450:5
    #7 0x560ffc0d4175 in object_property_set_qobject ../qom/qom-qobject.c:28:10
    #8 0x560ffc0c6004 in object_property_set_str ../qom/object.c:1458:15
    #9 0x560ffbe2ae60 in update_machine_ipl_properties ../hw/s390x/ipl.c:569:9
    #10 0x560ffbe2aa65 in s390_ipl_update_diag308 ../hw/s390x/ipl.c:594:5
    #11 0x560ffbdee132 in handle_diag_308 ../target/s390x/diag.c:147:9
    #12 0x560ffbebb956 in helper_diag ../target/s390x/tcg/misc_helper.c:137:9
    #13 0x7f1a3c51c730  (/memfd:tcg-jit (deleted)+0x39730)

Cc: qemu-stable@nongnu.org
Signed-off-by: Fabiano Rosas <farosas@suse.de>
Message-ID: <20250509174938.25935-1-farosas@suse.de>
Fixes: 1fd396e322 ("s390x: Register TYPE_S390_CCW_MACHINE properties as class properties")
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Thomas Huth <thuth@redhat.com>
(cherry picked from commit bdf12f2a56)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-16 00:54:49 +03:00
Christian Schoenebeck 3d2e7e1428 9pfs: fix FD leak and reduce latency of v9fs_reclaim_fd()
This patch fixes two different bugs in v9fs_reclaim_fd():

1. Reduce latency:

This function calls v9fs_co_close() and v9fs_co_closedir() in a loop. Each
one of the calls adds two thread hops (between main thread and a fs driver
background thread). Each thread hop adds latency, which sums up in
function's loop to a significant duration.

Reduce overall latency by open coding what v9fs_co_close() and
v9fs_co_closedir() do, executing those and the loop itself altogether in
only one background thread block, hence reducing the total amount of
thread hops to only two.

2. Fix file descriptor leak:

The existing code called v9fs_co_close() and v9fs_co_closedir() to close
file descriptors. Both functions check right at the beginning if the 9p
request was cancelled:

    if (v9fs_request_cancelled(pdu)) {
        return -EINTR;
    }

So if client sent a 'Tflush' message, v9fs_co_close() / v9fs_co_closedir()
returned without having closed the file descriptor and v9fs_reclaim_fd()
subsequently freed the FID without its file descriptor being closed, hence
leaking those file descriptors.

This 2nd bug is fixed by this patch as well by open coding v9fs_co_close()
and v9fs_co_closedir() inside of v9fs_reclaim_fd() and not performing the
v9fs_request_cancelled(pdu) check there.

Fixes: 7a46274529 ('hw/9pfs: Add file descriptor reclaim support')
Fixes: bccacf6c79 ('hw/9pfs: Implement TFLUSH operation')
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Message-Id: <5747469d3f039c53147e850b456943a1d4b5485c.1741339452.git.qemu_oss@crudebyte.com>
(cherry picked from commit 89f7b4da76)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-12 12:27:07 +03:00
Christian Schoenebeck 649ef0c6f1 9pfs: fix concurrent v9fs_reclaim_fd() calls
Even though this function is serialized to be always called from main
thread, v9fs_reclaim_fd() is dispatching the coroutine to a worker thread
in between via its v9fs_co_*() calls, hence leading to the situation where
v9fs_reclaim_fd() is effectively executed multiple times simultaniously,
which renders its LRU algorithm useless and causes high latency.

Fix this by adding a simple boolean variable to ensure this function is
only called once at a time. No synchronization needed for this boolean
variable as this function is only entered and returned on main thread.

Fixes: 7a46274529 ('hw/9pfs: Add file descriptor reclaim support')
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Message-Id: <5c622067efd66dd4ee5eca740dcf263f41db20b2.1741339452.git.qemu_oss@crudebyte.com>
(cherry picked from commit 61da38db70)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-12 12:27:07 +03:00
Bernhard Beschow 93e5ecd780 hw/i2c/imx: Always set interrupt status bit if interrupt condition occurs
According to the i.MX 8M Plus reference manual, the status flag
I2C_I2SR[IIF] continues to be set when an interrupt condition
occurs even when I2C interrupts are disabled (I2C_I2CR[IIEN] is
clear). However, the device model only sets the flag when I2C
interrupts are enabled which causes U-Boot to loop forever. Fix
the device model by always setting the flag and let I2C_I2CR[IIEN]
guard I2C interrupts only.

Also remove the comment in the code since it merely stated the
obvious and would be outdated now.

Cc: qemu-stable@nongnu.org
Fixes: 20d0f9cf6a ("i.MX: Add I2C controller emulator")
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Acked-by: Corey Minyard <cminyard@mvista.com>
Message-ID: <20250507124040.425773-1-shentey@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
(cherry picked from commit 54e54e594b)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-11 09:16:33 +03:00
Daniel P. Berrangé dc5208769a gitlab: use --refetch in check-patch/check-dco jobs
When gitlab initializes the repo checkout for a CI job, it will have
done a shallow clone with only partial history. Periodically the objects
that are omitted cause trouble with the check-patch/check-dco jobs. This
is exhibited as reporting strange errors being unable to fetch certain
objects that are known to exist.

Passing the --refetch flag to 'git fetch' causes it to not assume the
local checkout has all common objects and thus re-fetch everything that
is needed. This appears to solve the check-patch/check-dco job failures.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20250225110525.2209854-1-berrange@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
(cherry picked from commit d5d028eee3)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-08 18:27:32 +03:00
Paolo Bonzini 5dd4660f5f target/i386: do not block singlestep for STI
STI will trigger a singlestep exception even if it has inhibit-IRQ
behavior.  Do not suppress single-step for all IRQ-inhibiting
instructions, instead special case MOV SS and POP SS.

Cc: qemu-stable@nongnu.org
Fixes: f0f0136abb ("target/i386: no single-step exception after MOV or POP SS", 2024-05-25)
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 1e94ddc685)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-08 12:39:02 +03:00
Paolo Bonzini 4ba45dffde target/i386: do not trigger IRQ shadow for LSS
Because LSS need not trigger an IRQ shadow, gen_movl_seg can't just use
the destination register to decide whether to inhibit IRQs.  Add an
argument.

Cc: qemu-stable@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit e54ef98c8a)
(back-ported to 10.0)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-08 12:38:14 +03:00
Bernhard Beschow 9e13cd7232 hw/gpio/imx_gpio: Fix interpretation of GDIR polarity
According to the i.MX 8M Plus reference manual, a GPIO pin is
configured as an output when the corresponding bit in the GDIR
register is set.  The function imx_gpio_set_int_line() is intended to
be a no-op if the pin is configured as an output, returning early in
such cases.  However, it inverts the condition.  Fix this by
returning early when the bit is set.

cc: qemu-stable@nongnu.org
Fixes: f442728097 ("i.MX: Add GPIO device")
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Message-id: 20250501183445.2389-4-shentey@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit eba837a31b)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-08 12:18:57 +03:00
Peter Maydell 7407d2319d target/arm: Don't assert() for ISB/SB inside IT block
If the guest code has an ISB or SB insn inside an IT block, we
generate incorrect code which trips a TCG assertion:

qemu-system-arm: ../tcg/tcg-op.c:3343: void tcg_gen_goto_tb(unsigned int): Assertion `(tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0' failed.

This is because we call gen_goto_tb(dc, 1, ...) twice:

 brcond_i32 ZF,$0x0,ne,$L1
 add_i32 pc,pc,$0x4
 goto_tb $0x1
 exit_tb $0x73d948001b81
 set_label $L1
 add_i32 pc,pc,$0x4
 goto_tb $0x1
 exit_tb $0x73d948001b81

Both calls are in arm_tr_tb_stop(), one for the
DISAS_NEXT/DISAS_TOO_MANY handling, and one for the dc->condjump
condition-failed codepath.  The DISAS_NEXT handling doesn't have this
problem because arm_post_translate_insn() does the handling of "emit
the label for the condition-failed conditional execution" and so
arm_tr_tb_stop() doesn't have dc->condjump set.  But for
DISAS_TOO_MANY we don't do that.

Fix the bug by making arm_post_translate_insn() handle the
DISAS_TOO_MANY case.  This only affects the SB and ISB insns when
used in Thumb mode inside an IT block: only these insns specifically
set is_jmp to TOO_MANY, and their A32 encodings are unconditional.

For the major TOO_MANY case (breaking the TB because it would cross a
page boundary) we do that check and set is_jmp to TOO_MANY only after
the call to arm_post_translate_insn(); so arm_post_translate_insn()
sees is_jmp == DISAS_NEXT, and  we emit the correct code for that
situation.

With this fix we generate the somewhat more sensible set of TCG ops:
 brcond_i32 ZF,$0x0,ne,$L1
 set_label $L1
 add_i32 pc,pc,$0x4
 goto_tb $0x1
 exit_tb $0x7c5434001b81

(NB: the TCG optimizer doesn't optimize out the jump-to-next, but
we can't really avoid emitting it because we don't know at the
point we're emitting the handling for the condexec check whether
this insn is going to happen to be a nop for us or not.)

Cc: qemu-stable@nongnu.org
Fixes: https://gitlab.com/qemu-project/qemu/-/issues/2942
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20250501125544.727038-1-peter.maydell@linaro.org
(cherry picked from commit 8ed7c0b648)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-08 10:22:26 +03:00
Richard Henderson 83c926daf8 accel/tcg: Don't use TARGET_LONG_BITS in decode_sleb128
When we changed decode_sleb128 from target_long to
int64_t, we failed to adjust the shift limit.

Cc: qemu-stable@nongnu.org
Fixes: c9ad8d27ca ("tcg: Widen gen_insn_data to uint64_t")
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
(cherry picked from commit 9401f91b9b)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-05-07 16:42:10 +03:00
Akihiko Odaki 8696da0495 meson: Remove CONFIG_STATX and CONFIG_STATX_MNT_ID
CONFIG_STATX and CONFIG_STATX_MNT_ID are not used since commit
e0dc2631ec ("virtiofsd: Remove source").

Cc: qemu-stable@nongnu.org
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20250424-buildsys-v1-2-97655e3b25d7@daynix.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
(cherry picked from commit 6804b89fb5)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-29 10:07:03 +03:00
Akihiko Odaki dc13fed5f0 meson: Use has_header_symbol() to check getcpu()
The use of gnu_source_prefix in the detection of getcpu() was
ineffective because the header file that declares getcpu() when
_GNU_SOURCE is defined was not included. Pass sched.h to
has_header_symbol() so that the existence of the declaration will be
properly checked.

Cc: qemu-stable@nongnu.org
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20250424-buildsys-v1-1-97655e3b25d7@daynix.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
(cherry picked from commit 563cd698df)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-29 10:04:24 +03:00
Hauke Mehrtens 639cee5ed7 target/mips: Fix MIPS16e translation
Fix a wrong conversion to gen_op_addr_addi(). The framesize should be
added like it was done before.

This bug broke booting OpenWrt MIPS32 BE malta Linux system images
generated by OpenWrt.

Cc: qemu-stable@nongnu.org
Fixes: d0b24b7f50 ("target/mips: Use gen_op_addr_addi() when possible")
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20250412194003.181411-1-hauke@hauke-m.de>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
(cherry picked from commit d4a785ba30)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-29 10:03:15 +03:00
Peter Maydell c7e0189982 hw/core/cpu: gdb_arch_name string should not be freed
The documentation for the CPUClass::gdb_arch_name method claims that
the returned string should be freed with g_free().  This is not
correct: in commit a650683871 we changed this method to
instead return a simple constant string, but forgot to update
the documentation.

Make the documentation match the new semantics.

Fixes: a650683871 ("hw/core/cpu: Return static value with gdb_arch_name()")
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20250317142819.900029-2-peter.maydell@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
(cherry picked from commit 56a9f0d4c4)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-29 10:02:32 +03:00
Philippe Mathieu-Daudé e6e49667ae hw/core: Get default_cpu_type calling machine_class_default_cpu_type()
Since commit 62b4a227a3 the default cpu type can come from the
valid_cpu_types[] array. Call the machine_class_default_cpu_type()
instead of accessing MachineClass::default_cpu_type field.

Cc: qemu-stable@nongnu.org
Fixes: 62b4a227a3 ("hw/core: Add machine_class_default_cpu_type()")
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Message-Id: <20250422084114.39499-1-philmd@linaro.org>
(cherry picked from commit d5f241834b)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-29 10:01:21 +03:00
Richard Henderson 9f8bb7edac target/avr: Improve decode of LDS, STS
The comment about not being able to define a field with
zero bits is out of date since 94597b6146
("decodetree: Allow !function with no input bits").

This fixes the missing load of imm in the disassembler.

Cc: qemu-stable@nongnu.org
Fixes: 9d8caa67a2 ("target/avr: Add support for disassembling via option '-d in_asm'")
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
(cherry picked from commit 6b661b7ed7)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-24 11:16:03 +03:00
Paolo Bonzini 1cc062970e target/i386/hvf: fix lflags_to_rflags
Clear the flags before adding in the ones computed from lflags.

Cc: Wei Liu <liuwe@linux.microsoft.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 94a159f3dc)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-24 11:16:03 +03:00
Antoine Damhet af01cf195b Revert "virtio-net: Copy received header to buffer"
This reverts commit 7987d2be5a.

The goal was to remove the need to patch the (const) input buffer
with a recomputed UDP checksum by copying headers to a RW region and
inject the checksum there. The patch computed the checksum only from the
header fields (missing the rest of the payload) producing an invalid one
and making guests fail to acquire a DHCP lease.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2727
Cc: qemu-stable@nongnu.org
Signed-off-by: Antoine Damhet <adamhet@scaleway.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20250408145345.142947-1-adamhet@scaleway.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit e28fbd1c52)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-16 09:41:22 +03:00
Arthur Sengileyev 7f637d2922 Fix objdump output parser in "nsis.py"
In msys2 distribution objdump from gcc is using single tab character
prefix, but objdump from clang is using 4 white space characters instead.
The script will not identify any dll dependencies for a QEMU build
generated with clang. This in turn will fail the build, because there
will be no files inside dlldir and no setup file will be created.
Instead of checking for whitespace in prefix use lstrip to accommodate
for differences in outputs.

Signed-off-by: Arthur Sengileyev <arthur.sengileyev@gmail.com>
Reviewed-by: Stefan Weil <sw@weilnetz.de>
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit b0b5af62ef)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-15 12:23:44 +03:00
Pierrick Bouvier 138d48eca8 plugins/loader: fix deadlock when resetting/uninstalling a plugin
Reported and fixed by Dmitry Kurakin.

Fixes: https://gitlab.com/qemu-project/qemu/-/issues/2901
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Message-Id: <20250404032027.430575-2-pierrick.bouvier@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
(cherry picked from commit c07cd110a1)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-15 12:21:10 +03:00
Daan De Meyer d1960fafec smbios: Fix buffer overrun when using path= option
We have to make sure the array of bytes read from the path= file
is null-terminated, otherwise we run into a buffer overrun later on.

Fixes: bb99f4772f ("hw/smbios: support loading OEM strings values from a file")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2879

Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Tested-by: Valentin David <valentin.david@canonical.com>
Message-ID: <20250323213622.2581013-1-daan.j.demeyer@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
(cherry picked from commit a7a05f5f6a)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-10 15:43:46 +03:00
Kevin Wolf 6a3304c84a scsi-disk: Apply error policy for host_status errors again
Originally, all failed SG_IO requests called scsi_handle_rw_error() to
apply the configured error policy. However, commit f3126d65, which was
supposed to be a mere refactoring for scsi-disk.c, broke this and
accidentally completed the SCSI request without considering the error
policy any more if the error was signalled in the host_status field.

Apart from the commit message not describing the change as intended,
errors indicated in host_status are also obviously backend errors and
not something the guest must deal with independently of the error
policy.

This behaviour means that some recoverable errors (such as a path error
in multipath configurations) were reported to the guest anyway, which
might not expect it and might consider its disk broken.

Make sure that we apply the error policy again for host_status errors,
too. This addresses an existing FIXME comment and allows us to remove
some comments warning that callbacks weren't always called. With this
fix, they are called in all cases again.

The return value passed to the request callback doesn't have more free
values that could be used to indicate host_status errors as well as SAM
status codes and negative errno. Store the value in the host_status
field of the SCSIRequest instead and use -ENODEV as the return value (if
a path hasn't been reachable for a while, blk_aio_ioctl() will return
-ENODEV instead of just setting host_status, so just reuse it here -
it's not necessarily entirely accurate, but it's as good as any errno).

Cc: qemu-stable@nongnu.org
Fixes: f3126d65b3 ('scsi: move host_status handling into SCSI drivers')
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-ID: <20250407155949.44736-1-kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 61b6d9b749)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-09 11:56:24 +03:00
Nicholas Piggin 697209ff41 target/ppc: Fix SPRC/SPRD SPRs for P9/10
Commit 60d30cff84 ("target/ppc: Move SPR indirect registers into
PnvCore") was mismerged and moved the SPRs to power8-only, instead
of power9/10-only.

Fixes: 60d30cff84 ("target/ppc: Move SPR indirect registers into PnvCore")
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Cc: qemu-stable@nongnu.org
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
(cherry picked from commit b3d47c8303)
(Mjt: adjust context for v9.2.0-2634-gffb6440cc5 "ppc/pnv: Add new PowerPC Special Purpose Registers (RWMR)")
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-09 11:52:41 +03:00
Nicholas Piggin 849a6aea33 target/ppc: Big-core scratch register fix
The per-core SCRATCH0-7 registers are shared between big cores, which
was missed in the big-core implementation. It is difficult to model
well with the big-core == 2xPnvCore scheme we moved to, this fix
uses the even PnvCore to store the scrach data.

Also remove a stray log message that came in with the same patch that
introduced patch.

Fixes: c26504afd5 ("ppc/pnv: Add a big-core mode that joins two regular cores")
Cc: qemu-stable@nongnu.org
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
(cherry picked from commit 9808ce6d5c)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-09 11:48:56 +03:00
Philippe Mathieu-Daudé 5313973fd4 tcg: Allocate TEMP_VAL_MEM frame in temp_load()
Be sure to allocate the temp frame if it wasn't.

In the resolved issues, incomplete dead code elimination left a load
at the top of an unreachable loop.  We simply need to allocate the
stack slot to avoid crashing.

Fixes: c896fe29d6 ("TCG code generator")
Reported-by: Michael Tokarev <mjt@tls.msk.ru>
Reported-by: Helge Konetzka <hk@zapateado.de>
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2891
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2899
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-ID: <20250401144332.41615-1-philmd@linaro.org>
(cherry picked from commit e139bc4b17)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-05 16:48:28 +03:00
Suravee Suthikulpanit 83d36ab099 hw/i386/amd_iommu: Assign pci-id 0x1419 for the AMD IOMMU device
Currently, the QEMU-emulated AMD IOMMU device use PCI vendor id 0x1022
(AMD) with device id zero (undefined). Eventhough this does not cause any
functional issue for AMD IOMMU driver since it normally uses information
in the ACPI IVRS table to probe and initialize the device per
recommendation in the AMD IOMMU specification, the device id zero causes
the Windows Device Manager utility to show the device as an unknown device.

Since Windows only recognizes AMD IOMMU device with device id 0x1419 as
listed in the machine.inf file, modify the QEMU AMD IOMMU model to use
the id 0x1419 to avoid the issue. This advertise the IOMMU as the AMD
IOMMU device for Family 15h (Models 10h-1fh).

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Message-Id: <20250325021140.5676-1-suravee.suthikulpanit@amd.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Yan Vugenfirer <yvugenfi@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 719255486d)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-05 16:48:28 +03:00
Akihiko Odaki ff765e490e virtio-net: Fix num_buffers for version 1
The specification says the device MUST set num_buffers to 1 if
VIRTIO_NET_F_MRG_RXBUF has not been negotiated.

Fixes: df91055db5 ("virtio-net: enable virtio 1.0")
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Message-Id: <20250108-buffers-v1-1-a0c85ff31aeb@daynix.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Tested-by: Lei Yang <leiyang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit c17ad4b11b)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-05 16:48:28 +03:00
Marco Cavenati 6e827147d6 migration: fix SEEK_CUR offset calculation in qio_channel_block_seek
The SEEK_CUR case in qio_channel_block_seek was incorrectly using the
'whence' parameter instead of the 'offset' parameter when calculating the
new position.

Fixes: 65cf200a51 ("migration: introduce a QIOChannel impl for BlockDriverState VMState")
Signed-off-by: Marco Cavenati <Marco.Cavenati@eurecom.fr>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
Message-ID: <20250326162230.3323199-1-Marco.Cavenati@eurecom.fr>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
(cherry picked from commit c0b32426ce)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-05 16:48:28 +03:00
Richard Henderson 08c3572736 target/mips: Simplify and fix update_pagemask
When update_pagemask was split from helper_mtc0_pagemask,
we failed to actually write to the new parameter but continue
to write to env->CP0_PageMask.  Thus the use within
page_table_walk_refill modifies cpu state and not the local
variable as expected.

Simplify by renaming to compute_pagemask and returning the
value directly.  No need for either env or pointer return.

Fixes: 074cfcb4da ("target/mips: Implement hardware page table walker for MIPS32")
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20250328175526.368121-4-richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Cc: qemu-stable@nongnu.org
(cherry picked from commit 256ba7715b)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-05 16:48:28 +03:00
Richard Henderson 4580c38134 target/mips: Require even maskbits in update_pagemask
The number of bits set in PageMask must be even.

Fixes: d40b55bc1b ("target/mips: Fix PageMask with variable page size")
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20250328175526.368121-3-richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Cc: qemu-stable@nongnu.org
(cherry picked from commit d89b9899ba)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-05 16:48:28 +03:00
Richard Henderson 8a669b8aae target/mips: Revert TARGET_PAGE_BITS_VARY
Revert ee3863b9d4 and a08d60bc6c.  The logic behind changing
the system page size because of what the Loongson kernel "prefers"
is flawed.

In the Loongson-2E manual, section 5.5, it is clear that the cpu
supports a 4k page size (along with many others).  Similarly for
the Loongson-3 series CPUs, the 4k page size is mentioned in the
section 7.7 (PageMask Register).  Therefore we must continue to
support a 4k page size.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20250328175526.368121-2-richard.henderson@linaro.org>
[PMD: Mention Loongson-3 series CPUs]
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
(cherry picked from commit fca2817fdc)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-05 16:48:28 +03:00
Richard Henderson fa7638d8c1 target/avr: Fix buffer read in avr_print_insn
Do not unconditionally attempt to read 4 bytes, as there
may only be 2 bytes remaining in the translator cache.

Cc: qemu-stable@nongnu.org
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20250325224403.4011975-2-richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
(cherry picked from commit 070a500cc0)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-05 16:47:01 +03:00
Philippe Mathieu-Daudé 358f7c6892 hw/pci-host/designware: Fix ATU_UPPER_TARGET register access
Fix copy/paste error writing to the ATU_UPPER_TARGET
register, we want to update the upper 32 bits.

Cc: qemu-stable@nongnu.org
Reported-by: Joey <jeundery@gmail.com>
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2861
Fixes: d64e5eabc4 ("pci: Add support for Designware IP block")
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Gustavo Romero <gustavo.romero@linaro.org>
Message-Id: <20250331152041.74533-2-philmd@linaro.org>
(cherry picked from commit 04e99f9eb7)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-05 16:45:45 +03:00
Heinrich Schuchardt d87ee29327 hw/rtc/goldfish: keep time offset when resetting
Currently resetting the leads to resynchronizing the Goldfish RTC
with the system clock of the host. In real hardware an RTC reset
would not change the wall time. Other RTCs like pl031 do not show
this behavior.

Move the synchronization of the RTC with the system clock to the
instance realization.

Cc: qemu-stable@nongnu.org
Reported-by: Frederik Du Toit Lotter <fred.lotter@canonical.com>
Fixes: 9a5b40b842 ("hw: rtc: Add Goldfish RTC device")
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20250321221248.17764-1-heinrich.schuchardt@canonical.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
(cherry picked from commit 2542d5cf47)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-04-02 10:17:41 +03:00
hemanshu.khilari.foss ec877d2ab0 docs/specs/riscv-iommu: Fixed broken link to external risv iommu document
The links to riscv iommu specification document are incorrect. This patch
updates all the said link to point to correct location.

Cc: qemu-stable@nongnu.org
Cc: qemu-riscv@nongnu.org
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2808
Signed-off-by: hemanshu.khilari.foss <hemanshu.khilari.foss@gmail.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-ID: <20250323063404.13206-1-hemanshu.khilari.foss@gmail.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
(cherry picked from commit e768f0246c)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2025-03-28 23:47:41 +03:00
58 changed files with 611 additions and 401 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)
print(f"adding upstream git repo @ {repourl}")
subprocess.check_call(["git", "remote", "add", "check-dco", repourl])
subprocess.check_call(["git", "fetch", "check-dco", "master"])
subprocess.check_call(["git", "fetch", "--refetch", "check-dco", "master"])
ancestor = subprocess.check_output(["git", "merge-base",
"check-dco/master", "HEAD"],
+1 -1
View File
@@ -24,7 +24,7 @@ print(f"adding upstream git repo @ {repourl}")
# base for the user's branch. We thus need to figure out a common
# ancestor between the user's branch and current git master.
subprocess.check_call(["git", "remote", "add", "check-patch", repourl])
subprocess.check_call(["git", "fetch", "check-patch", "master"])
subprocess.check_call(["git", "fetch", "--refetch", "check-patch", "master"])
ancestor = subprocess.check_output(["git", "merge-base",
"check-patch/master", "HEAD"],
+1 -1
View File
@@ -1 +1 @@
9.2.3
9.2.4
+1 -1
View File
@@ -105,7 +105,7 @@ static int64_t decode_sleb128(const uint8_t **pp)
val |= (int64_t)(byte & 0x7f) << shift;
shift += 7;
} while (byte & 0x80);
if (shift < TARGET_LONG_BITS && (byte & 0x40)) {
if (shift < 64 && (byte & 0x40)) {
val |= -(int64_t)1 << shift;
}
+2 -2
View File
@@ -69,11 +69,11 @@ safe_syscall_end:
/* code path setting errno */
0: neg a0, a0
j safe_syscall_set_errno_tail
tail safe_syscall_set_errno_tail
/* code path when we didn't execute the syscall */
2: li a0, QEMU_ERESTARTSYS
j safe_syscall_set_errno_tail
tail safe_syscall_set_errno_tail
.cfi_endproc
.size safe_syscall_base, .-safe_syscall_base
+3 -3
View File
@@ -4,7 +4,7 @@ RISC-V IOMMU support for RISC-V machines
========================================
QEMU implements a RISC-V IOMMU emulation based on the RISC-V IOMMU spec
version 1.0 `iommu1.0`_.
version 1.0 `iommu1.0.0`_.
The emulation includes a PCI reference device, riscv-iommu-pci, that QEMU
RISC-V boards can use. The 'virt' RISC-V machine is compatible with this
@@ -14,7 +14,7 @@ riscv-iommu-pci reference device
--------------------------------
This device implements the RISC-V IOMMU emulation as recommended by the section
"Integrating an IOMMU as a PCIe device" of `iommu1.0`_: a PCI device with base
"Integrating an IOMMU as a PCIe device" of `iommu1.0.0`_: a PCI device with base
class 08h, sub-class 06h and programming interface 00h.
As a reference device it doesn't implement anything outside of the specification,
@@ -83,7 +83,7 @@ Several options are available to control the capabilities of the device, namely:
- "s-stage": enable s-stage support
- "g-stage": enable g-stage support
.. _iommu1.0: https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf
.. _iommu1.0.0: https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0.0/riscv-iommu.pdf
.. _linux-v8: https://lore.kernel.org/linux-riscv/cover.1718388908.git.tjeznach@rivosinc.com/
+30 -9
View File
@@ -434,16 +434,24 @@ void coroutine_fn v9fs_reclaim_fd(V9fsPDU *pdu)
V9fsFidState *f;
GHashTableIter iter;
gpointer fid;
int err;
int nclosed = 0;
/* prevent multiple coroutines running this function simultaniously */
if (s->reclaiming) {
return;
}
s->reclaiming = true;
g_hash_table_iter_init(&iter, s->fids);
QSLIST_HEAD(, V9fsFidState) reclaim_list =
QSLIST_HEAD_INITIALIZER(reclaim_list);
/* Pick FIDs to be closed, collect them on reclaim_list. */
while (g_hash_table_iter_next(&iter, &fid, (gpointer *) &f)) {
/*
* Unlink fids cannot be reclaimed. Check
* for them and skip them. Also skip fids
* Unlinked fids cannot be reclaimed, skip those, and also skip fids
* currently being operated on.
*/
if (f->ref || f->flags & FID_NON_RECLAIMABLE) {
@@ -493,23 +501,34 @@ void coroutine_fn v9fs_reclaim_fd(V9fsPDU *pdu)
}
}
/*
* Now close the fid in reclaim list. Free them if they
* are already clunked.
* Close the picked FIDs altogether on a background I/O driver thread. Do
* this all at once to keep latency (i.e. amount of thread hops between main
* thread <-> fs driver background thread) as low as possible.
*/
v9fs_co_run_in_worker({
QSLIST_FOREACH(f, &reclaim_list, reclaim_next) {
err = (f->fid_type == P9_FID_DIR) ?
s->ops->closedir(&s->ctx, &f->fs_reclaim) :
s->ops->close(&s->ctx, &f->fs_reclaim);
if (!err) {
/* total_open_fd must only be mutated on main thread */
nclosed++;
}
}
});
total_open_fd -= nclosed;
/* Free the closed FIDs. */
while (!QSLIST_EMPTY(&reclaim_list)) {
f = QSLIST_FIRST(&reclaim_list);
QSLIST_REMOVE(&reclaim_list, f, V9fsFidState, reclaim_next);
if (f->fid_type == P9_FID_FILE) {
v9fs_co_close(pdu, &f->fs_reclaim);
} else if (f->fid_type == P9_FID_DIR) {
v9fs_co_closedir(pdu, &f->fs_reclaim);
}
/*
* Now drop the fid reference, free it
* if clunked.
*/
put_fid(pdu, f);
}
s->reclaiming = false;
}
/*
@@ -4291,6 +4310,8 @@ int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t,
s->ctx.fst = &fse->fst;
fsdev_throttle_init(s->ctx.fst);
s->reclaiming = false;
rc = 0;
out:
if (rc) {
+1
View File
@@ -362,6 +362,7 @@ struct V9fsState {
uint64_t qp_ndevices; /* Amount of entries in qpd_table. */
uint16_t qp_affix_next;
uint64_t qp_fullpath_next;
bool reclaiming;
};
/* 9p2000.L open flags */
+3 -2
View File
@@ -72,6 +72,7 @@ MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props,
for (el = machines; el; el = el->next) {
MachineClass *mc = el->data;
const char *default_cpu_type = machine_class_default_cpu_type(mc);
MachineInfo *info;
info = g_malloc0(sizeof(*info));
@@ -90,8 +91,8 @@ MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props,
info->numa_mem_supported = mc->numa_mem_supported;
info->deprecated = !!mc->deprecation_reason;
info->acpi = !!object_class_property_find(OBJECT_CLASS(mc), "acpi");
if (mc->default_cpu_type) {
info->default_cpu_type = g_strdup(mc->default_cpu_type);
if (default_cpu_type) {
info->default_cpu_type = g_strdup(default_cpu_type);
}
if (mc->default_ram_id) {
info->default_ram_id = g_strdup(mc->default_ram_id);
+1 -1
View File
@@ -79,7 +79,7 @@ static void imx_gpio_update_int(IMXGPIOState *s)
static void imx_gpio_set_int_line(IMXGPIOState *s, int line, IMXGPIOLevel level)
{
/* if this signal isn't configured as an input signal, nothing to do */
if (!extract32(s->gdir, line, 1)) {
if (extract32(s->gdir, line, 1)) {
return;
}
+5 -6
View File
@@ -90,13 +90,12 @@ static void imx_i2c_reset(DeviceState *dev)
static inline void imx_i2c_raise_interrupt(IMXI2CState *s)
{
/*
* raise an interrupt if the device is enabled and it is configured
* to generate some interrupts.
*/
if (imx_i2c_is_enabled(s) && imx_i2c_interrupt_is_enabled(s)) {
if (imx_i2c_is_enabled(s)) {
s->i2sr |= I2SR_IIF;
qemu_irq_raise(s->irq);
if (imx_i2c_interrupt_is_enabled(s)) {
qemu_irq_raise(s->irq);
}
}
}
+1
View File
@@ -1716,6 +1716,7 @@ static void amdvi_pci_class_init(ObjectClass *klass, void *data)
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->vendor_id = PCI_VENDOR_ID_AMD;
k->device_id = 0x1419;
k->class_id = 0x0806;
k->realize = amdvi_pci_realize;
-1
View File
@@ -333,7 +333,6 @@ static void mips_fuloong2e_machine_init(MachineClass *mc)
mc->default_cpu_type = MIPS_CPU_TYPE_NAME("Loongson-2E");
mc->default_ram_size = 256 * MiB;
mc->default_ram_id = "fuloong2e.ram";
mc->minimum_page_bits = 14;
machine_add_audiodev_property(mc);
}
-1
View File
@@ -670,7 +670,6 @@ static void loongson3v_machine_class_init(ObjectClass *oc, void *data)
mc->max_cpus = LOONGSON_MAX_VCPUS;
mc->default_ram_id = "loongson3.highram";
mc->default_ram_size = 1600 * MiB;
mc->minimum_page_bits = 14;
mc->default_nic = "virtio-net-pci";
}
+41 -46
View File
@@ -1702,44 +1702,41 @@ static void virtio_net_hdr_swap(VirtIODevice *vdev, struct virtio_net_hdr *hdr)
* cache.
*/
static void work_around_broken_dhclient(struct virtio_net_hdr *hdr,
size_t *hdr_len, const uint8_t *buf,
size_t buf_size, size_t *buf_offset)
uint8_t *buf, size_t size)
{
size_t csum_size = ETH_HLEN + sizeof(struct ip_header) +
sizeof(struct udp_header);
buf += *buf_offset;
buf_size -= *buf_offset;
if ((hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && /* missing csum */
(buf_size >= csum_size && buf_size < 1500) && /* normal sized MTU */
(size >= csum_size && size < 1500) && /* normal sized MTU */
(buf[12] == 0x08 && buf[13] == 0x00) && /* ethertype == IPv4 */
(buf[23] == 17) && /* ip.protocol == UDP */
(buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */
memcpy((uint8_t *)hdr + *hdr_len, buf, csum_size);
net_checksum_calculate((uint8_t *)hdr + *hdr_len, csum_size, CSUM_UDP);
net_checksum_calculate(buf, size, CSUM_UDP);
hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
*hdr_len += csum_size;
*buf_offset += csum_size;
}
}
static size_t receive_header(VirtIONet *n, struct virtio_net_hdr *hdr,
const void *buf, size_t buf_size,
size_t *buf_offset)
static void receive_header(VirtIONet *n, const struct iovec *iov, int iov_cnt,
const void *buf, size_t size)
{
size_t hdr_len = n->guest_hdr_len;
if (n->has_vnet_hdr) {
/* FIXME this cast is evil */
void *wbuf = (void *)buf;
work_around_broken_dhclient(wbuf, wbuf + n->host_hdr_len,
size - n->host_hdr_len);
memcpy(hdr, buf, sizeof(struct virtio_net_hdr));
*buf_offset = n->host_hdr_len;
work_around_broken_dhclient(hdr, &hdr_len, buf, buf_size, buf_offset);
if (n->needs_vnet_hdr_swap) {
virtio_net_hdr_swap(VIRTIO_DEVICE(n), hdr);
if (n->needs_vnet_hdr_swap) {
virtio_net_hdr_swap(VIRTIO_DEVICE(n), wbuf);
}
iov_from_buf(iov, iov_cnt, 0, buf, sizeof(struct virtio_net_hdr));
} else {
struct virtio_net_hdr hdr = {
.flags = 0,
.gso_type = VIRTIO_NET_HDR_GSO_NONE
};
iov_from_buf(iov, iov_cnt, 0, &hdr, sizeof hdr);
}
return hdr_len;
}
static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
@@ -1907,13 +1904,6 @@ static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
return (index == new_index) ? -1 : new_index;
}
typedef struct Header {
struct virtio_net_hdr_v1_hash virtio_net;
struct eth_header eth;
struct ip_header ip;
struct udp_header udp;
} Header;
static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
size_t size)
{
@@ -1923,15 +1913,15 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
VirtQueueElement *elems[VIRTQUEUE_MAX_SIZE];
size_t lens[VIRTQUEUE_MAX_SIZE];
struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE];
Header hdr;
struct virtio_net_hdr_v1_hash extra_hdr;
unsigned mhdr_cnt = 0;
size_t offset, i, guest_offset, j;
ssize_t err;
memset(&hdr.virtio_net, 0, sizeof(hdr.virtio_net));
memset(&extra_hdr, 0, sizeof(extra_hdr));
if (n->rss_data.enabled && n->rss_data.enabled_software_rss) {
int index = virtio_net_process_rss(nc, buf, size, &hdr.virtio_net);
int index = virtio_net_process_rss(nc, buf, size, &extra_hdr);
if (index >= 0) {
nc = qemu_get_subqueue(n->nic, index % n->curr_queue_pairs);
}
@@ -1996,18 +1986,23 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
if (n->mergeable_rx_bufs) {
mhdr_cnt = iov_copy(mhdr_sg, ARRAY_SIZE(mhdr_sg),
sg, elem->in_num,
offsetof(typeof(hdr),
virtio_net.hdr.num_buffers),
sizeof(hdr.virtio_net.hdr.num_buffers));
offsetof(typeof(extra_hdr), hdr.num_buffers),
sizeof(extra_hdr.hdr.num_buffers));
} else {
extra_hdr.hdr.num_buffers = cpu_to_le16(1);
}
guest_offset = n->has_vnet_hdr ?
receive_header(n, (struct virtio_net_hdr *)&hdr,
buf, size, &offset) :
n->guest_hdr_len;
iov_from_buf(sg, elem->in_num, 0, &hdr, guest_offset);
total += guest_offset;
receive_header(n, sg, elem->in_num, buf, size);
if (n->rss_data.populate_hash) {
offset = offsetof(typeof(extra_hdr), hash_value);
iov_from_buf(sg, elem->in_num, offset,
(char *)&extra_hdr + offset,
sizeof(extra_hdr.hash_value) +
sizeof(extra_hdr.hash_report));
}
offset = n->host_hdr_len;
total += n->guest_hdr_len;
guest_offset = n->guest_hdr_len;
} else {
guest_offset = 0;
}
@@ -2033,11 +2028,11 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
}
if (mhdr_cnt) {
virtio_stw_p(vdev, &hdr.virtio_net.hdr.num_buffers, i);
virtio_stw_p(vdev, &extra_hdr.hdr.num_buffers, i);
iov_from_buf(mhdr_sg, mhdr_cnt,
0,
&hdr.virtio_net.hdr.num_buffers,
sizeof hdr.virtio_net.hdr.num_buffers);
&extra_hdr.hdr.num_buffers,
sizeof extra_hdr.hdr.num_buffers);
}
for (j = 0; j < i; j++) {
+1 -1
View File
@@ -362,7 +362,7 @@ static void designware_pcie_root_config_write(PCIDevice *d, uint32_t address,
case DESIGNWARE_PCIE_ATU_UPPER_TARGET:
viewport->target &= 0x00000000FFFFFFFFULL;
viewport->target |= val;
viewport->target |= (uint64_t)val << 32;
break;
case DESIGNWARE_PCIE_ATU_LIMIT:
+48 -34
View File
@@ -320,38 +320,6 @@ static void gt64120_isd_mapping(GT64120State *s)
memory_region_transaction_commit();
}
static void gt64120_update_pci_cfgdata_mapping(GT64120State *s)
{
/* Indexed on MByteSwap bit, see Table 158: PCI_0 Command, Offset: 0xc00 */
static const MemoryRegionOps *pci_host_data_ops[] = {
&pci_host_data_be_ops, &pci_host_data_le_ops
};
PCIHostState *phb = PCI_HOST_BRIDGE(s);
memory_region_transaction_begin();
/*
* The setting of the MByteSwap bit and MWordSwap bit in the PCI Internal
* Command Register determines how data transactions from the CPU to/from
* PCI are handled along with the setting of the Endianness bit in the CPU
* Configuration Register. See:
* - Table 16: 32-bit PCI Transaction Endianness
* - Table 158: PCI_0 Command, Offset: 0xc00
*/
if (memory_region_is_mapped(&phb->data_mem)) {
memory_region_del_subregion(&s->ISD_mem, &phb->data_mem);
object_unparent(OBJECT(&phb->data_mem));
}
memory_region_init_io(&phb->data_mem, OBJECT(phb),
pci_host_data_ops[s->regs[GT_PCI0_CMD] & 1],
s, "pci-conf-data", 4);
memory_region_add_subregion_overlap(&s->ISD_mem, GT_PCI0_CFGDATA << 2,
&phb->data_mem, 1);
memory_region_transaction_commit();
}
static void gt64120_pci_mapping(GT64120State *s)
{
memory_region_transaction_begin();
@@ -645,7 +613,6 @@ static void gt64120_writel(void *opaque, hwaddr addr,
case GT_PCI0_CMD:
case GT_PCI1_CMD:
s->regs[saddr] = val & 0x0401fc0f;
gt64120_update_pci_cfgdata_mapping(s);
break;
case GT_PCI0_TOR:
case GT_PCI0_BS_SCS10:
@@ -1024,6 +991,48 @@ static const MemoryRegionOps isd_mem_ops = {
},
};
static bool bswap(const GT64120State *s)
{
PCIHostState *phb = PCI_HOST_BRIDGE(s);
/*check for bus == 0 && device == 0, Bits 11:15 = Device , Bits 16:23 = Bus*/
bool is_phb_dev0 = extract32(phb->config_reg, 11, 13) == 0;
bool le_mode = FIELD_EX32(s->regs[GT_PCI0_CMD], GT_PCI0_CMD, MByteSwap);
/* Only swap for non-bridge devices in big-endian mode */
return !le_mode && !is_phb_dev0;
}
static uint64_t gt64120_pci_data_read(void *opaque, hwaddr addr, unsigned size)
{
GT64120State *s = opaque;
uint32_t val = pci_host_data_le_ops.read(opaque, addr, size);
if (bswap(s)) {
val = bswap32(val);
}
return val;
}
static void gt64120_pci_data_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
GT64120State *s = opaque;
if (bswap(s)) {
val = bswap32(val);
}
pci_host_data_le_ops.write(opaque, addr, val, size);
}
static const MemoryRegionOps gt64120_pci_data_ops = {
.read = gt64120_pci_data_read,
.write = gt64120_pci_data_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4,
},
};
static void gt64120_reset(DeviceState *dev)
{
GT64120State *s = GT64120_PCI_HOST_BRIDGE(dev);
@@ -1178,7 +1187,6 @@ static void gt64120_reset(DeviceState *dev)
gt64120_isd_mapping(s);
gt64120_pci_mapping(s);
gt64120_update_pci_cfgdata_mapping(s);
}
static void gt64120_realize(DeviceState *dev, Error **errp)
@@ -1202,6 +1210,12 @@ static void gt64120_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion_overlap(&s->ISD_mem, GT_PCI0_CFGADDR << 2,
&phb->conf_mem, 1);
memory_region_init_io(&phb->data_mem, OBJECT(phb),
&gt64120_pci_data_ops,
s, "pci-conf-data", 4);
memory_region_add_subregion_overlap(&s->ISD_mem, GT_PCI0_CFGDATA << 2,
&phb->data_mem, 1);
/*
* The whole address space decoded by the GT-64120A doesn't generate
-6
View File
@@ -217,12 +217,6 @@ const MemoryRegionOps pci_host_data_le_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};
const MemoryRegionOps pci_host_data_be_ops = {
.read = pci_host_data_read,
.write = pci_host_data_write,
.endianness = DEVICE_BIG_ENDIAN,
};
static bool pci_host_needed(void *opaque)
{
PCIHostState *s = opaque;
+6 -7
View File
@@ -239,15 +239,8 @@ static const VMStateDescription goldfish_rtc_vmstate = {
static void goldfish_rtc_reset(DeviceState *dev)
{
GoldfishRTCState *s = GOLDFISH_RTC(dev);
struct tm tm;
timer_del(s->timer);
qemu_get_timedate(&tm, 0);
s->tick_offset = mktimegm(&tm);
s->tick_offset *= NANOSECONDS_PER_SECOND;
s->tick_offset -= qemu_clock_get_ns(rtc_clock);
s->tick_offset_vmstate = 0;
s->alarm_next = 0;
s->alarm_running = 0;
s->irq_pending = 0;
@@ -258,6 +251,7 @@ static void goldfish_rtc_realize(DeviceState *d, Error **errp)
{
SysBusDevice *dev = SYS_BUS_DEVICE(d);
GoldfishRTCState *s = GOLDFISH_RTC(d);
struct tm tm;
memory_region_init_io(&s->iomem, OBJECT(s),
&goldfish_rtc_ops[s->big_endian], s,
@@ -267,6 +261,11 @@ static void goldfish_rtc_realize(DeviceState *d, Error **errp)
sysbus_init_irq(dev, &s->irq);
s->timer = timer_new_ns(rtc_clock, goldfish_rtc_interrupt, s);
qemu_get_timedate(&tm, 0);
s->tick_offset = mktimegm(&tm);
s->tick_offset *= NANOSECONDS_PER_SECOND;
s->tick_offset -= qemu_clock_get_ns(rtc_clock);
}
static Property goldfish_rtc_properties[] = {
+1
View File
@@ -739,6 +739,7 @@ static void machine_set_loadparm(Object *obj, Visitor *v,
}
s390_ipl_fmt_loadparm(ms->loadparm, val, errp);
g_free(val);
}
static void ccw_machine_class_init(ObjectClass *oc, void *data)
+25 -14
View File
@@ -68,10 +68,9 @@ struct SCSIDiskClass {
SCSIDeviceClass parent_class;
/*
* Callbacks receive ret == 0 for success. Errors are represented either as
* negative errno values, or as positive SAM status codes.
*
* Beware: For errors returned in host_status, the function may directly
* complete the request and never call the callback.
* negative errno values, or as positive SAM status codes. For host_status
* errors, the function passes ret == -ENODEV and sets the host_status field
* of the SCSIRequest.
*/
DMAIOFunc *dma_readv;
DMAIOFunc *dma_writev;
@@ -226,11 +225,26 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed)
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s));
SCSISense sense = SENSE_CODE(NO_SENSE);
int16_t host_status;
int error;
bool req_has_sense = false;
BlockErrorAction action;
int status;
/*
* host_status should only be set for SG_IO requests that came back with a
* host_status error in scsi_block_sgio_complete(). This error path passes
* -ENODEV as the return value.
*
* Reset host_status in the request because we may still want to complete
* the request successfully with the 'stop' or 'ignore' error policy.
*/
host_status = r->req.host_status;
if (host_status != -1) {
assert(ret == -ENODEV);
r->req.host_status = -1;
}
if (ret < 0) {
status = scsi_sense_from_errno(-ret, &sense);
error = -ret;
@@ -290,6 +304,10 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int ret, bool acct_failed)
if (acct_failed) {
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
}
if (host_status != -1) {
scsi_req_complete_failed(&r->req, host_status);
return true;
}
if (req_has_sense) {
sdc->update_sense(&r->req);
} else if (status == CHECK_CONDITION) {
@@ -411,7 +429,6 @@ done:
scsi_req_unref(&r->req);
}
/* May not be called in all error cases, don't rely on cleanup here */
static void scsi_dma_complete(void *opaque, int ret)
{
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
@@ -452,7 +469,6 @@ done:
scsi_req_unref(&r->req);
}
/* May not be called in all error cases, don't rely on cleanup here */
static void scsi_read_complete(void *opaque, int ret)
{
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
@@ -592,7 +608,6 @@ done:
scsi_req_unref(&r->req);
}
/* May not be called in all error cases, don't rely on cleanup here */
static void scsi_write_complete(void * opaque, int ret)
{
SCSIDiskReq *r = (SCSIDiskReq *)opaque;
@@ -2854,14 +2869,10 @@ static void scsi_block_sgio_complete(void *opaque, int ret)
sg_io_hdr_t *io_hdr = &req->io_header;
if (ret == 0) {
/* FIXME This skips calling req->cb() and any cleanup in it */
if (io_hdr->host_status != SCSI_HOST_OK) {
scsi_req_complete_failed(&r->req, io_hdr->host_status);
scsi_req_unref(&r->req);
return;
}
if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
r->req.host_status = io_hdr->host_status;
ret = -ENODEV;
} else if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
ret = BUSY;
} else {
ret = io_hdr->status;
+3
View File
@@ -1285,6 +1285,9 @@ static int save_opt_one(void *opaque,
g_byte_array_append(data, (guint8 *)buf, ret);
}
buf[0] = '\0';
g_byte_array_append(data, (guint8 *)buf, 1);
qemu_close(fd);
*opt->dest = g_renew(char *, *opt->dest, (*opt->ndest) + 1);
+3 -1
View File
@@ -2316,6 +2316,8 @@ void virtio_queue_enable(VirtIODevice *vdev, uint32_t queue_index)
}
}
static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val);
void virtio_reset(void *opaque)
{
VirtIODevice *vdev = opaque;
@@ -2346,7 +2348,7 @@ void virtio_reset(void *opaque)
vdev->start_on_kick = false;
vdev->started = false;
vdev->broken = false;
vdev->guest_features = 0;
virtio_set_features_nocheck(vdev, 0);
vdev->queue_sel = 0;
vdev->status = 0;
vdev->disabled = false;
+2 -1
View File
@@ -134,7 +134,8 @@ struct SysemuCPUOps;
* @gdb_stop_before_watchpoint: Indicates whether GDB expects the CPU to stop
* before the insn which triggers a watchpoint rather than after it.
* @gdb_arch_name: Optional callback that returns the architecture name known
* to GDB. The caller must free the returned string with g_free.
* to GDB. The returned value is expected to be a simple constant string:
* the caller will not g_free() it.
* @disas_set_info: Setup architecture specific components of disassembly info
* @adjust_watchpoint_address: Perform a target-specific adjustment to an
* address before attempting to match it against watchpoints.
-4
View File
@@ -109,10 +109,6 @@ static const uint32_t reg800_keep_bits[DINO800_REGS] = {
struct DinoState {
PCIHostState parent_obj;
/*
* PCI_CONFIG_ADDR is parent_obj.config_reg, via pci_host_conf_be_ops,
* so that we can map PCI_CONFIG_DATA to pci_host_data_be_ops.
*/
uint32_t config_reg_dino; /* keep original copy, including 2 lowest bits */
uint32_t iar0;
-1
View File
@@ -68,6 +68,5 @@ uint32_t pci_data_read(PCIBus *s, uint32_t addr, unsigned len);
extern const MemoryRegionOps pci_host_conf_le_ops;
extern const MemoryRegionOps pci_host_conf_be_ops;
extern const MemoryRegionOps pci_host_data_le_ops;
extern const MemoryRegionOps pci_host_data_be_ops;
#endif /* PCI_HOST_H */
+10 -2
View File
@@ -112,7 +112,7 @@ static abi_ulong hppa_lws(CPUHPPAState *env)
void cpu_loop(CPUHPPAState *env)
{
CPUState *cs = env_cpu(env);
abi_ulong ret;
abi_ulong ret, si_code = 0;
int trapnr;
while (1) {
@@ -169,7 +169,15 @@ void cpu_loop(CPUHPPAState *env)
force_sig_fault(TARGET_SIGFPE, TARGET_FPE_CONDTRAP, env->iaoq_f);
break;
case EXCP_ASSIST:
force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f);
#define set_si_code(mask, val) \
if (env->fr[0] & mask) { si_code = val; }
set_si_code(R_FPSR_FLG_I_MASK, TARGET_FPE_FLTRES);
set_si_code(R_FPSR_FLG_U_MASK, TARGET_FPE_FLTUND);
set_si_code(R_FPSR_FLG_O_MASK, TARGET_FPE_FLTOVF);
set_si_code(R_FPSR_FLG_Z_MASK, TARGET_FPE_FLTDIV);
set_si_code(R_FPSR_FLG_V_MASK, TARGET_FPE_FLTINV);
#undef set_si_code
force_sig_fault(TARGET_SIGFPE, si_code, env->iaoq_f);
break;
case EXCP_BREAK:
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f);
+2 -11
View File
@@ -2159,14 +2159,6 @@ gnu_source_prefix = '''
#endif
'''
# Check whether the glibc provides STATX_BASIC_STATS
has_statx = cc.has_header_symbol('sys/stat.h', 'STATX_BASIC_STATS', prefix: gnu_source_prefix)
# Check whether statx() provides mount ID information
has_statx_mnt_id = cc.has_header_symbol('sys/stat.h', 'STATX_MNT_ID', prefix: gnu_source_prefix)
have_vhost_user_blk_server = get_option('vhost_user_blk_server') \
.require(host_os == 'linux',
error_message: 'vhost_user_blk_server requires linux') \
@@ -2528,8 +2520,6 @@ config_host_data.set('CONFIG_CRYPTO_SM3', crypto_sm3.found())
config_host_data.set('CONFIG_HOGWEED', hogweed.found())
config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
config_host_data.set('CONFIG_STATX', has_statx)
config_host_data.set('CONFIG_STATX_MNT_ID', has_statx_mnt_id)
config_host_data.set('CONFIG_ZSTD', zstd.found())
config_host_data.set('CONFIG_QPL', qpl.found())
config_host_data.set('CONFIG_UADK', uadk.found())
@@ -2603,7 +2593,6 @@ config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
config_host_data.set('CONFIG_GETCPU', cc.has_function('getcpu', prefix: gnu_source_prefix))
config_host_data.set('CONFIG_SCHED_GETCPU', cc.has_function('sched_getcpu', prefix: '#include <sched.h>'))
# Note that we need to specify prefix: here to avoid incorrectly
# thinking that Windows has posix_memalign()
@@ -2680,6 +2669,8 @@ config_host_data.set('CONFIG_FALLOCATE_ZERO_RANGE',
config_host_data.set('CONFIG_FIEMAP',
cc.has_header('linux/fiemap.h') and
cc.has_header_symbol('linux/fs.h', 'FS_IOC_FIEMAP'))
config_host_data.set('CONFIG_GETCPU',
cc.has_header_symbol('sched.h', 'getcpu', prefix: gnu_source_prefix))
config_host_data.set('CONFIG_GETRANDOM',
cc.has_function('getrandom') and
cc.has_header_symbol('sys/random.h', 'GRND_NONBLOCK'))
+1 -1
View File
@@ -123,7 +123,7 @@ qio_channel_block_seek(QIOChannel *ioc,
bioc->offset = offset;
break;
case SEEK_CUR:
bioc->offset += whence;
bioc->offset += offset;
break;
case SEEK_END:
error_setg(errp, "Size of VMstate region is unknown");
+2 -2
View File
@@ -543,7 +543,7 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
return false;
}
if (migrate_incoming_started()) {
if (!migrate_postcopy_preempt() && migrate_incoming_started()) {
error_setg(errp,
"Postcopy preempt must be set before incoming starts");
return false;
@@ -551,7 +551,7 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
}
if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
if (migrate_incoming_started()) {
if (!migrate_multifd() && migrate_incoming_started()) {
error_setg(errp, "Multifd must be set before incoming starts");
return false;
}
+1 -1
View File
@@ -379,7 +379,7 @@ static void plugin_reset_destroy(struct qemu_plugin_reset_data *data)
{
qemu_rec_mutex_lock(&plugin.lock);
plugin_reset_destroy__locked(data);
qemu_rec_mutex_lock(&plugin.lock);
qemu_rec_mutex_unlock(&plugin.lock);
}
static void plugin_flush_destroy(CPUState *cpu, run_on_cpu_data arg)
+2 -2
View File
@@ -380,7 +380,7 @@
##
# @query-sgx:
#
# Returns information about SGX
# Returns information about configured SGX capabilities of guest
#
# Returns: @SGXInfo
#
@@ -399,7 +399,7 @@
##
# @query-sgx-capabilities:
#
# Returns information from host SGX capabilities
# Returns information about SGX capabilities of host
#
# Returns: @SGXInfo
#
+1 -1
View File
@@ -23,7 +23,7 @@ def find_deps(exe_or_dll, search_path, analyzed_deps):
output = subprocess.check_output(["objdump", "-p", exe_or_dll], text=True)
output = output.split("\n")
for line in output:
if not line.startswith("\tDLL Name: "):
if not line.lstrip().startswith("DLL Name: "):
continue
dep = line.split("DLL Name: ")[1].strip()
+2 -1
View File
@@ -7770,7 +7770,8 @@ static bool arm_check_ss_active(DisasContext *dc)
static void arm_post_translate_insn(DisasContext *dc)
{
if (dc->condjmp && dc->base.is_jmp == DISAS_NEXT) {
if (dc->condjmp &&
(dc->base.is_jmp == DISAS_NEXT || dc->base.is_jmp == DISAS_TOO_MANY)) {
if (dc->pc_save != dc->condlabel.pc_save) {
gen_update_pc(dc, dc->condlabel.pc_save - dc->pc_save);
}
+14 -7
View File
@@ -68,28 +68,35 @@ static bool decode_insn(DisasContext *ctx, uint16_t insn);
int avr_print_insn(bfd_vma addr, disassemble_info *info)
{
DisasContext ctx;
DisasContext ctx = { info };
DisasContext *pctx = &ctx;
bfd_byte buffer[4];
uint16_t insn;
int status;
ctx.info = info;
status = info->read_memory_func(addr, buffer, 4, info);
status = info->read_memory_func(addr, buffer, 2, info);
if (status != 0) {
info->memory_error_func(status, addr, info);
return -1;
}
insn = bfd_getl16(buffer);
ctx.next_word = bfd_getl16(buffer + 2);
ctx.next_word_used = false;
status = info->read_memory_func(addr + 2, buffer + 2, 2, info);
if (status == 0) {
ctx.next_word = bfd_getl16(buffer + 2);
}
if (!decode_insn(&ctx, insn)) {
output(".db", "0x%02x, 0x%02x", buffer[0], buffer[1]);
}
return ctx.next_word_used ? 4 : 2;
if (!ctx.next_word_used) {
return 2;
} else if (status == 0) {
return 4;
}
info->memory_error_func(status, addr + 2, info);
return -1;
}
+2 -5
View File
@@ -118,11 +118,8 @@ BRBC 1111 01 ....... ... @op_bit_imm
@io_rd_imm .... . .. ..... .... &rd_imm rd=%rd imm=%io_imm
@ldst_d .. . . .. . rd:5 . ... &rd_imm imm=%ldst_d_imm
# The 16-bit immediate is completely in the next word.
# Fields cannot be defined with no bits, so we cannot play
# the same trick and append to a zero-bit value.
# Defer reading the immediate until trans_{LDS,STS}.
@ldst_s .... ... rd:5 .... imm=0
%ldst_imm !function=next_word
@ldst_s .... ... rd:5 .... imm=%ldst_imm
MOV 0010 11 . ..... .... @op_rd_rr
MOVW 0000 0001 .... .... &rd_rr rd=%rd_d rr=%rr_d
-2
View File
@@ -1577,7 +1577,6 @@ static bool trans_LDS(DisasContext *ctx, arg_LDS *a)
TCGv Rd = cpu_r[a->rd];
TCGv addr = tcg_temp_new_i32();
TCGv H = cpu_rampD;
a->imm = next_word(ctx);
tcg_gen_mov_tl(addr, H); /* addr = H:M:L */
tcg_gen_shli_tl(addr, addr, 16);
@@ -1782,7 +1781,6 @@ static bool trans_STS(DisasContext *ctx, arg_STS *a)
TCGv Rd = cpu_r[a->rd];
TCGv addr = tcg_temp_new_i32();
TCGv H = cpu_rampD;
a->imm = next_word(ctx);
tcg_gen_mov_tl(addr, H); /* addr = H:M:L */
tcg_gen_shli_tl(addr, addr, 16);
+17 -3
View File
@@ -71,7 +71,8 @@ static void update_fr0_op(CPUHPPAState *env, uintptr_t ra)
{
uint32_t soft_exp = get_float_exception_flags(&env->fp_status);
uint32_t hard_exp = 0;
uint32_t shadow = env->fr0_shadow;
uint32_t shadow = env->fr0_shadow & 0x3ffffff;
uint32_t fr1 = 0;
if (likely(soft_exp == 0)) {
env->fr[0] = (uint64_t)shadow << 32;
@@ -84,9 +85,22 @@ static void update_fr0_op(CPUHPPAState *env, uintptr_t ra)
hard_exp |= CONVERT_BIT(soft_exp, float_flag_overflow, R_FPSR_ENA_O_MASK);
hard_exp |= CONVERT_BIT(soft_exp, float_flag_divbyzero, R_FPSR_ENA_Z_MASK);
hard_exp |= CONVERT_BIT(soft_exp, float_flag_invalid, R_FPSR_ENA_V_MASK);
shadow |= hard_exp << (R_FPSR_FLAGS_SHIFT - R_FPSR_ENABLES_SHIFT);
if (hard_exp & shadow) {
shadow = FIELD_DP32(shadow, FPSR, T, 1);
/* fill exception register #1, which is lower 32-bits of fr[0] */
#if !defined(CONFIG_USER_ONLY)
if (hard_exp & (R_FPSR_ENA_O_MASK | R_FPSR_ENA_U_MASK)) {
/* over- and underflow both set overflow flag only */
fr1 = FIELD_DP32(fr1, FPSR, C, 1);
fr1 = FIELD_DP32(fr1, FPSR, FLG_O, 1);
} else
#endif
{
fr1 |= hard_exp << (R_FPSR_FLAGS_SHIFT - R_FPSR_ENABLES_SHIFT);
}
}
env->fr0_shadow = shadow;
env->fr[0] = (uint64_t)shadow << 32;
env->fr[0] = (uint64_t)shadow << 32 | fr1;
if (hard_exp & shadow) {
hppa_dynamic_excp(env, EXCP_ASSIST, ra);
+4
View File
@@ -175,6 +175,10 @@ void hppa_cpu_do_interrupt(CPUState *cs)
}
}
env->cr[CR_IIR] = ldl_phys(cs->as, paddr);
if (i == EXCP_ASSIST) {
/* stuff insn code into bits of FP exception register #1 */
env->fr[0] |= (env->cr[CR_IIR] & 0x03ffffff);
}
}
break;
+1
View File
@@ -293,6 +293,7 @@ void set_SF(CPUX86State *env, bool val)
void lflags_to_rflags(CPUX86State *env)
{
env->eflags &= ~(CC_C|CC_P|CC_A|CC_Z|CC_S|CC_O);
env->eflags |= get_CF(env) ? CC_C : 0;
env->eflags |= get_PF(env) ? CC_P : 0;
env->eflags |= get_AF(env) ? CC_A : 0;
+2 -2
View File
@@ -355,7 +355,7 @@ static void gen_writeback(DisasContext *s, X86DecodedInsn *decode, int opn, TCGv
break;
case X86_OP_SEG:
/* Note that gen_movl_seg takes care of interrupt shadow and TF. */
gen_movl_seg(s, op->n, s->T0);
gen_movl_seg(s, op->n, v, op->n == R_SS);
break;
case X86_OP_INT:
if (op->has_ea) {
@@ -2360,7 +2360,7 @@ static void gen_lxx_seg(DisasContext *s, X86DecodedInsn *decode, int seg)
gen_op_ld_v(s, MO_16, s->T1, s->A0);
/* load the segment here to handle exceptions properly */
gen_movl_seg(s, seg, s->T1);
gen_movl_seg(s, seg, s->T1, false);
}
static void gen_LDS(DisasContext *s, X86DecodedInsn *decode)
+25 -14
View File
@@ -1876,25 +1876,36 @@ static void gen_op_movl_seg_real(DisasContext *s, X86Seg seg_reg, TCGv seg)
/* move SRC to seg_reg and compute if the CPU state may change. Never
call this function with seg_reg == R_CS */
static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src)
static void gen_movl_seg(DisasContext *s, X86Seg seg_reg, TCGv src, bool inhibit_irq)
{
if (PE(s) && !VM86(s)) {
tcg_gen_trunc_tl_i32(s->tmp2_i32, src);
gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), s->tmp2_i32);
/* abort translation because the addseg value may change or
because ss32 may change. For R_SS, translation must always
stop as a special handling must be done to disable hardware
interrupts for the next instruction */
if (seg_reg == R_SS) {
s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
} else if (CODE32(s) && seg_reg < R_FS) {
TCGv_i32 sel = tcg_temp_new_i32();
tcg_gen_trunc_tl_i32(sel, src);
gen_helper_load_seg(tcg_env, tcg_constant_i32(seg_reg), sel);
/* For move to DS/ES/SS, the addseg or ss32 flags may change. */
if (CODE32(s) && seg_reg < R_FS) {
s->base.is_jmp = DISAS_EOB_NEXT;
}
} else {
gen_op_movl_seg_real(s, seg_reg, src);
if (seg_reg == R_SS) {
s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
}
}
/*
* For MOV or POP to SS (but not LSS) translation must always
* stop as a special handling must be done to disable hardware
* interrupts for the next instruction.
*
* This is the last instruction, so it's okay to overwrite
* HF_TF_MASK; the next TB will start with the flag set.
*
* DISAS_EOB_INHIBIT_IRQ is a superset of DISAS_EOB_NEXT which
* might have been set above.
*/
if (inhibit_irq) {
s->base.is_jmp = DISAS_EOB_INHIBIT_IRQ;
s->flags &= ~HF_TF_MASK;
}
}
@@ -2182,7 +2193,7 @@ gen_eob(DisasContext *s, int mode)
if (mode == DISAS_EOB_RECHECK_TF) {
gen_helper_rechecking_single_step(tcg_env);
tcg_gen_exit_tb(NULL, 0);
} else if ((s->flags & HF_TF_MASK) && mode != DISAS_EOB_INHIBIT_IRQ) {
} else if (s->flags & HF_TF_MASK) {
gen_helper_single_step(tcg_env);
} else if (mode == DISAS_JUMP &&
/* give irqs a chance to happen */
-5
View File
@@ -23,12 +23,7 @@
# define TARGET_VIRT_ADDR_SPACE_BITS 32
#endif
#endif
#ifdef CONFIG_USER_ONLY
#define TARGET_PAGE_BITS 12
#else
#define TARGET_PAGE_BITS_VARY
#define TARGET_PAGE_BITS_MIN 12
#endif
#define TCG_GUEST_DEFAULT_MO (0)
+2 -2
View File
@@ -306,7 +306,7 @@ static void gen_mips16_restore(DisasContext *ctx,
int astatic;
TCGv t0 = tcg_temp_new();
gen_op_addr_addi(ctx, t0, cpu_gpr[29], -framesize);
gen_op_addr_addi(ctx, t0, cpu_gpr[29], framesize);
if (do_ra) {
decr_and_load(ctx, 31, t0);
@@ -386,7 +386,7 @@ static void gen_mips16_restore(DisasContext *ctx,
}
}
gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], -framesize);
gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], framesize);
}
#if defined(TARGET_MIPS64)
+10 -22
View File
@@ -864,36 +864,24 @@ void helper_mtc0_memorymapid(CPUMIPSState *env, target_ulong arg1)
}
}
void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
uint32_t compute_pagemask(uint32_t val)
{
uint32_t mask;
int maskbits;
/* Don't care MASKX as we don't support 1KB page */
mask = extract32((uint32_t)arg1, CP0PM_MASK, 16);
maskbits = cto32(mask);
uint32_t mask = extract32(val, CP0PM_MASK, 16);
int maskbits = cto32(mask);
/* Ensure no more set bit after first zero */
if ((mask >> maskbits) != 0) {
goto invalid;
/* Ensure no more set bit after first zero, and maskbits even. */
if ((mask >> maskbits) == 0 && maskbits % 2 == 0) {
return mask << CP0PM_MASK;
} else {
/* When invalid, set to default target page size. */
return 0;
}
/* We don't support VTLB entry smaller than target page */
if ((maskbits + TARGET_PAGE_BITS_MIN) < TARGET_PAGE_BITS) {
goto invalid;
}
env->CP0_PageMask = mask << CP0PM_MASK;
return;
invalid:
/* When invalid, set to default target page size. */
mask = (~TARGET_PAGE_MASK >> TARGET_PAGE_BITS_MIN);
env->CP0_PageMask = mask << CP0PM_MASK;
}
void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
{
update_pagemask(env, arg1, &env->CP0_PageMask);
env->CP0_PageMask = compute_pagemask(arg1);
}
void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
+2 -2
View File
@@ -874,8 +874,8 @@ refill:
break;
}
}
pw_pagemask = m >> TARGET_PAGE_BITS_MIN;
update_pagemask(env, pw_pagemask << CP0PM_MASK, &pw_pagemask);
pw_pagemask = m >> TARGET_PAGE_BITS;
pw_pagemask = compute_pagemask(pw_pagemask << CP0PM_MASK);
pw_entryhi = (address & ~0x1fff) | (env->CP0_EntryHi & 0xFF);
{
target_ulong tmp_entryhi = env->CP0_EntryHi;
+1 -1
View File
@@ -45,7 +45,7 @@ bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
void mmu_init(CPUMIPSState *env, const mips_def_t *def);
void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask);
uint32_t compute_pagemask(uint32_t val);
void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra);
uint32_t cpu_mips_get_random(CPUMIPSState *env);
+13 -12
View File
@@ -5765,6 +5765,18 @@ static void register_power9_book4_sprs(CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
KVM_REG_PPC_WORT, 0);
/* SPRC/SPRD exist in earlier CPUs but only tested on POWER9/10 */
spr_register_hv(env, SPR_POWER_SPRC, "SPRC",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_sprc,
0x00000000);
spr_register_hv(env, SPR_POWER_SPRD, "SPRD",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_sprd, &spr_write_sprd,
0x00000000);
#endif
}
@@ -5786,17 +5798,6 @@ static void register_power8_book4_sprs(CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
KVM_REG_PPC_WORT, 0);
/* SPRC/SPRD exist in earlier CPUs but only tested on POWER9/10 */
spr_register_hv(env, SPR_POWER_SPRC, "SPRC",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_sprc,
0x00000000);
spr_register_hv(env, SPR_POWER_SPRD, "SPRD",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_sprd, &spr_write_sprd,
0x00000000);
#endif
}
@@ -7033,7 +7034,7 @@ ObjectClass *ppc_cpu_class_by_name(const char *name)
if (strcmp(name, "max") == 0) {
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
if (mc) {
return object_class_by_name(mc->default_cpu_type);
return object_class_by_name(machine_class_default_cpu_type(mc));
}
}
#endif
+8 -1
View File
@@ -321,6 +321,10 @@ target_ulong helper_load_sprd(CPUPPCState *env)
PnvCore *pc = pnv_cpu_state(cpu)->pnv_core;
target_ulong sprc = env->spr[SPR_POWER_SPRC];
if (pc->big_core) {
pc = pnv_chip_find_core(pc->chip, CPU_CORE(pc)->core_id & ~0x1);
}
switch (sprc & 0x3e0) {
case 0: /* SCRATCH0-3 */
case 1: /* SCRATCH4-7 */
@@ -357,6 +361,10 @@ void helper_store_sprd(CPUPPCState *env, target_ulong val)
PnvCore *pc = pnv_cpu_state(cpu)->pnv_core;
int nr;
if (pc->big_core) {
pc = pnv_chip_find_core(pc->chip, CPU_CORE(pc)->core_id & ~0x1);
}
switch (sprc & 0x3e0) {
case 0: /* SCRATCH0-3 */
case 1: /* SCRATCH4-7 */
@@ -367,7 +375,6 @@ void helper_store_sprd(CPUPPCState *env, target_ulong val)
* information. Could also dump these upon checkstop.
*/
nr = (sprc >> 3) & 0x7;
qemu_log("SPRD write 0x" TARGET_FMT_lx " to SCRATCH%d\n", val, nr);
pc->scratch[nr] = val;
break;
default:
+1
View File
@@ -80,6 +80,7 @@ const char *riscv_get_misa_ext_name(uint32_t bit);
const char *riscv_get_misa_ext_description(uint32_t bit);
#define CPU_CFG_OFFSET(_prop) offsetof(struct RISCVCPUConfig, _prop)
#define ENV_CSR_OFFSET(_csr) offsetof(CPURISCVState, _csr)
typedef struct riscv_cpu_profile {
struct riscv_cpu_profile *parent;
+4 -2
View File
@@ -1240,9 +1240,11 @@ restart:
#else
target_ulong old_pte;
if (riscv_cpu_sxl(env) == MXL_RV32) {
old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, pte, updated_pte);
old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, cpu_to_le32(pte), cpu_to_le32(updated_pte));
old_pte = le32_to_cpu(old_pte);
} else {
old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
old_pte = qatomic_cmpxchg(pte_pa, cpu_to_le64(pte), cpu_to_le64(updated_pte));
old_pte = le64_to_cpu(old_pte);
}
if (old_pte != pte) {
goto restart;
+9 -9
View File
@@ -700,14 +700,14 @@ vfredmax_vs 000111 . ..... ..... 001 ..... 1010111 @r_vm
# Vector widening ordered and unordered float reduction sum
vfwredusum_vs 110001 . ..... ..... 001 ..... 1010111 @r_vm
vfwredosum_vs 110011 . ..... ..... 001 ..... 1010111 @r_vm
vmand_mm 011001 - ..... ..... 010 ..... 1010111 @r
vmnand_mm 011101 - ..... ..... 010 ..... 1010111 @r
vmandn_mm 011000 - ..... ..... 010 ..... 1010111 @r
vmxor_mm 011011 - ..... ..... 010 ..... 1010111 @r
vmor_mm 011010 - ..... ..... 010 ..... 1010111 @r
vmnor_mm 011110 - ..... ..... 010 ..... 1010111 @r
vmorn_mm 011100 - ..... ..... 010 ..... 1010111 @r
vmxnor_mm 011111 - ..... ..... 010 ..... 1010111 @r
vmand_mm 011001 1 ..... ..... 010 ..... 1010111 @r
vmnand_mm 011101 1 ..... ..... 010 ..... 1010111 @r
vmandn_mm 011000 1 ..... ..... 010 ..... 1010111 @r
vmxor_mm 011011 1 ..... ..... 010 ..... 1010111 @r
vmor_mm 011010 1 ..... ..... 010 ..... 1010111 @r
vmnor_mm 011110 1 ..... ..... 010 ..... 1010111 @r
vmorn_mm 011100 1 ..... ..... 010 ..... 1010111 @r
vmxnor_mm 011111 1 ..... ..... 010 ..... 1010111 @r
vcpop_m 010000 . ..... 10000 010 ..... 1010111 @r2_vm
vfirst_m 010000 . ..... 10001 010 ..... 1010111 @r2_vm
vmsbf_m 010100 . ..... 00001 010 ..... 1010111 @r2_vm
@@ -729,7 +729,7 @@ vrgather_vv 001100 . ..... ..... 000 ..... 1010111 @r_vm
vrgatherei16_vv 001110 . ..... ..... 000 ..... 1010111 @r_vm
vrgather_vx 001100 . ..... ..... 100 ..... 1010111 @r_vm
vrgather_vi 001100 . ..... ..... 011 ..... 1010111 @r_vm
vcompress_vm 010111 - ..... ..... 010 ..... 1010111 @r
vcompress_vm 010111 1 ..... ..... 010 ..... 1010111 @r
vmv1r_v 100111 1 ..... 00000 011 ..... 1010111 @r2rd
vmv2r_v 100111 1 ..... 00001 011 ..... 1010111 @r2rd
vmv4r_v 100111 1 ..... 00011 011 ..... 1010111 @r2rd
+7 -2
View File
@@ -119,8 +119,11 @@ static bool trans_vfwmaccbf16_vv(DisasContext *ctx, arg_vfwmaccbf16_vv *a)
REQUIRE_FPU;
REQUIRE_ZVFBFWMA(ctx);
uint8_t sew = ctx->sew;
if (require_rvv(ctx) && vext_check_isa_ill(ctx) && (ctx->sew == MO_16) &&
vext_check_dss(ctx, a->rd, a->rs1, a->rs2, a->vm)) {
vext_check_dss(ctx, a->rd, a->rs1, a->rs2, a->vm) &&
vext_check_input_eew(ctx, a->rd, sew + 1, a->rs1, sew, a->vm) &&
vext_check_input_eew(ctx, a->rd, sew + 1, a->rs2, sew, a->vm)) {
uint32_t data = 0;
gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN);
@@ -146,8 +149,10 @@ static bool trans_vfwmaccbf16_vf(DisasContext *ctx, arg_vfwmaccbf16_vf *a)
REQUIRE_FPU;
REQUIRE_ZVFBFWMA(ctx);
uint8_t sew = ctx->sew;
if (require_rvv(ctx) && (ctx->sew == MO_16) && vext_check_isa_ill(ctx) &&
vext_check_ds(ctx, a->rd, a->rs2, a->vm)) {
vext_check_ds(ctx, a->rd, a->rs2, a->vm) &&
vext_check_input_eew(ctx, a->rd, sew + 1, a->rs2, sew, a->vm)) {
uint32_t data = 0;
gen_set_rm(ctx, RISCV_FRM_DYN);
+137 -29
View File
@@ -100,10 +100,33 @@ static bool require_scale_rvfmin(DisasContext *s)
}
}
/* Destination vector register group cannot overlap source mask register. */
static bool require_vm(int vm, int vd)
/*
* Source and destination vector register groups cannot overlap source mask
* register:
*
* A vector register cannot be used to provide source operands with more than
* one EEW for a single instruction. A mask register source is considered to
* have EEW=1 for this constraint. An encoding that would result in the same
* vector register being read with two or more different EEWs, including when
* the vector register appears at different positions within two or more vector
* register groups, is reserved.
* (Section 5.2)
*
* A destination vector register group can overlap a source vector
* register group only if one of the following holds:
* 1. The destination EEW equals the source EEW.
* 2. The destination EEW is smaller than the source EEW and the overlap
* is in the lowest-numbered part of the source register group.
* 3. The destination EEW is greater than the source EEW, the source EMUL
* is at least 1, and the overlap is in the highest-numbered part of
* the destination register group.
* For the purpose of determining register group overlap constraints, mask
* elements have EEW=1.
* (Section 5.2)
*/
static bool require_vm(int vm, int v)
{
return (vm != 0 || vd != 0);
return (vm != 0 || v != 0);
}
static bool require_nf(int vd, int nf, int lmul)
@@ -356,11 +379,41 @@ static bool vext_check_ld_index(DisasContext *s, int vd, int vs2,
return ret;
}
/*
* Check whether a vector register is used to provide source operands with
* more than one EEW for the vector instruction.
* Returns true if the instruction has valid encoding
* Returns false if encoding violates the mismatched input EEWs constraint
*/
static bool vext_check_input_eew(DisasContext *s, int vs1, uint8_t eew_vs1,
int vs2, uint8_t eew_vs2, int vm)
{
bool is_valid = true;
int8_t emul_vs1 = eew_vs1 - s->sew + s->lmul;
int8_t emul_vs2 = eew_vs2 - s->sew + s->lmul;
/* When vm is 0, vs1 & vs2(EEW!=1) group can't overlap v0 (EEW=1) */
if ((vs1 != -1 && !require_vm(vm, vs1)) ||
(vs2 != -1 && !require_vm(vm, vs2))) {
is_valid = false;
}
/* When eew_vs1 != eew_vs2, check whether vs1 and vs2 are overlapped */
if ((vs1 != -1 && vs2 != -1) && (eew_vs1 != eew_vs2) &&
is_overlapped(vs1, 1 << MAX(emul_vs1, 0),
vs2, 1 << MAX(emul_vs2, 0))) {
is_valid = false;
}
return is_valid;
}
static bool vext_check_ss(DisasContext *s, int vd, int vs, int vm)
{
return require_vm(vm, vd) &&
require_align(vd, s->lmul) &&
require_align(vs, s->lmul);
require_align(vs, s->lmul) &&
vext_check_input_eew(s, vs, s->sew, -1, s->sew, vm);
}
/*
@@ -379,6 +432,7 @@ static bool vext_check_ss(DisasContext *s, int vd, int vs, int vm)
static bool vext_check_sss(DisasContext *s, int vd, int vs1, int vs2, int vm)
{
return vext_check_ss(s, vd, vs2, vm) &&
vext_check_input_eew(s, vs1, s->sew, vs2, s->sew, vm) &&
require_align(vs1, s->lmul);
}
@@ -474,6 +528,7 @@ static bool vext_narrow_check_common(DisasContext *s, int vd, int vs2,
static bool vext_check_ds(DisasContext *s, int vd, int vs, int vm)
{
return vext_wide_check_common(s, vd, vm) &&
vext_check_input_eew(s, vs, s->sew, -1, 0, vm) &&
require_align(vs, s->lmul) &&
require_noover(vd, s->lmul + 1, vs, s->lmul);
}
@@ -481,6 +536,7 @@ static bool vext_check_ds(DisasContext *s, int vd, int vs, int vm)
static bool vext_check_dd(DisasContext *s, int vd, int vs, int vm)
{
return vext_wide_check_common(s, vd, vm) &&
vext_check_input_eew(s, vs, s->sew + 1, -1, 0, vm) &&
require_align(vs, s->lmul + 1);
}
@@ -499,6 +555,7 @@ static bool vext_check_dd(DisasContext *s, int vd, int vs, int vm)
static bool vext_check_dss(DisasContext *s, int vd, int vs1, int vs2, int vm)
{
return vext_check_ds(s, vd, vs2, vm) &&
vext_check_input_eew(s, vs1, s->sew, vs2, s->sew, vm) &&
require_align(vs1, s->lmul) &&
require_noover(vd, s->lmul + 1, vs1, s->lmul);
}
@@ -521,12 +578,14 @@ static bool vext_check_dss(DisasContext *s, int vd, int vs1, int vs2, int vm)
static bool vext_check_dds(DisasContext *s, int vd, int vs1, int vs2, int vm)
{
return vext_check_ds(s, vd, vs1, vm) &&
vext_check_input_eew(s, vs1, s->sew, vs2, s->sew + 1, vm) &&
require_align(vs2, s->lmul + 1);
}
static bool vext_check_sd(DisasContext *s, int vd, int vs, int vm)
{
bool ret = vext_narrow_check_common(s, vd, vs, vm);
bool ret = vext_narrow_check_common(s, vd, vs, vm) &&
vext_check_input_eew(s, vs, s->sew + 1, -1, 0, vm);
if (vd != vs) {
ret &= require_noover(vd, s->lmul, vs, s->lmul + 1);
}
@@ -549,6 +608,7 @@ static bool vext_check_sd(DisasContext *s, int vd, int vs, int vm)
static bool vext_check_sds(DisasContext *s, int vd, int vs1, int vs2, int vm)
{
return vext_check_sd(s, vd, vs2, vm) &&
vext_check_input_eew(s, vs1, s->sew, vs2, s->sew + 1, vm) &&
require_align(vs1, s->lmul);
}
@@ -584,7 +644,9 @@ static bool vext_check_slide(DisasContext *s, int vd, int vs2,
{
bool ret = require_align(vs2, s->lmul) &&
require_align(vd, s->lmul) &&
require_vm(vm, vd);
require_vm(vm, vd) &&
vext_check_input_eew(s, -1, 0, vs2, s->sew, vm);
if (is_over) {
ret &= (vd != vs2);
}
@@ -981,7 +1043,8 @@ static bool ld_index_check(DisasContext *s, arg_rnfvm* a, uint8_t eew)
{
return require_rvv(s) &&
vext_check_isa_ill(s) &&
vext_check_ld_index(s, a->rd, a->rs2, a->nf, a->vm, eew);
vext_check_ld_index(s, a->rd, a->rs2, a->nf, a->vm, eew) &&
vext_check_input_eew(s, -1, 0, a->rs2, eew, a->vm);
}
GEN_VEXT_TRANS(vlxei8_v, MO_8, rnfvm, ld_index_op, ld_index_check)
@@ -1033,7 +1096,8 @@ static bool st_index_check(DisasContext *s, arg_rnfvm* a, uint8_t eew)
{
return require_rvv(s) &&
vext_check_isa_ill(s) &&
vext_check_st_index(s, a->rd, a->rs2, a->nf, eew);
vext_check_st_index(s, a->rd, a->rs2, a->nf, eew) &&
vext_check_input_eew(s, a->rd, s->sew, a->rs2, eew, a->vm);
}
GEN_VEXT_TRANS(vsxei8_v, MO_8, rnfvm, st_index_op, st_index_check)
@@ -1475,6 +1539,16 @@ static bool opivv_widen_check(DisasContext *s, arg_rmrr *a)
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
}
/* OPIVV with overwrite and WIDEN */
static bool opivv_overwrite_widen_check(DisasContext *s, arg_rmrr *a)
{
return require_rvv(s) &&
vext_check_isa_ill(s) &&
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm) &&
vext_check_input_eew(s, a->rd, s->sew + 1, a->rs1, s->sew, a->vm) &&
vext_check_input_eew(s, a->rd, s->sew + 1, a->rs2, s->sew, a->vm);
}
static bool do_opivv_widen(DisasContext *s, arg_rmrr *a,
gen_helper_gvec_4_ptr *fn,
bool (*checkfn)(DisasContext *, arg_rmrr *))
@@ -1522,6 +1596,14 @@ static bool opivx_widen_check(DisasContext *s, arg_rmrr *a)
vext_check_ds(s, a->rd, a->rs2, a->vm);
}
static bool opivx_overwrite_widen_check(DisasContext *s, arg_rmrr *a)
{
return require_rvv(s) &&
vext_check_isa_ill(s) &&
vext_check_ds(s, a->rd, a->rs2, a->vm) &&
vext_check_input_eew(s, a->rd, s->sew + 1, a->rs2, s->sew, a->vm);
}
#define GEN_OPIVX_WIDEN_TRANS(NAME, CHECK) \
static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
{ \
@@ -1993,13 +2075,13 @@ GEN_OPIVX_TRANS(vmadd_vx, opivx_check)
GEN_OPIVX_TRANS(vnmsub_vx, opivx_check)
/* Vector Widening Integer Multiply-Add Instructions */
GEN_OPIVV_WIDEN_TRANS(vwmaccu_vv, opivv_widen_check)
GEN_OPIVV_WIDEN_TRANS(vwmacc_vv, opivv_widen_check)
GEN_OPIVV_WIDEN_TRANS(vwmaccsu_vv, opivv_widen_check)
GEN_OPIVX_WIDEN_TRANS(vwmaccu_vx, opivx_widen_check)
GEN_OPIVX_WIDEN_TRANS(vwmacc_vx, opivx_widen_check)
GEN_OPIVX_WIDEN_TRANS(vwmaccsu_vx, opivx_widen_check)
GEN_OPIVX_WIDEN_TRANS(vwmaccus_vx, opivx_widen_check)
GEN_OPIVV_WIDEN_TRANS(vwmaccu_vv, opivv_overwrite_widen_check)
GEN_OPIVV_WIDEN_TRANS(vwmacc_vv, opivv_overwrite_widen_check)
GEN_OPIVV_WIDEN_TRANS(vwmaccsu_vv, opivv_overwrite_widen_check)
GEN_OPIVX_WIDEN_TRANS(vwmaccu_vx, opivx_overwrite_widen_check)
GEN_OPIVX_WIDEN_TRANS(vwmacc_vx, opivx_overwrite_widen_check)
GEN_OPIVX_WIDEN_TRANS(vwmaccsu_vx, opivx_overwrite_widen_check)
GEN_OPIVX_WIDEN_TRANS(vwmaccus_vx, opivx_overwrite_widen_check)
/* Vector Integer Merge and Move Instructions */
static bool trans_vmv_v_v(DisasContext *s, arg_vmv_v_v *a)
@@ -2340,6 +2422,17 @@ static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
}
static bool opfvv_overwrite_widen_check(DisasContext *s, arg_rmrr *a)
{
return require_rvv(s) &&
require_rvf(s) &&
require_scale_rvf(s) &&
vext_check_isa_ill(s) &&
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm) &&
vext_check_input_eew(s, a->rd, s->sew + 1, a->rs1, s->sew, a->vm) &&
vext_check_input_eew(s, a->rd, s->sew + 1, a->rs2, s->sew, a->vm);
}
/* OPFVV with WIDEN */
#define GEN_OPFVV_WIDEN_TRANS(NAME, CHECK) \
static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
@@ -2379,11 +2472,21 @@ static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
vext_check_ds(s, a->rd, a->rs2, a->vm);
}
static bool opfvf_overwrite_widen_check(DisasContext *s, arg_rmrr *a)
{
return require_rvv(s) &&
require_rvf(s) &&
require_scale_rvf(s) &&
vext_check_isa_ill(s) &&
vext_check_ds(s, a->rd, a->rs2, a->vm) &&
vext_check_input_eew(s, a->rd, s->sew + 1, a->rs2, s->sew, a->vm);
}
/* OPFVF with WIDEN */
#define GEN_OPFVF_WIDEN_TRANS(NAME) \
#define GEN_OPFVF_WIDEN_TRANS(NAME, CHECK) \
static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
{ \
if (opfvf_widen_check(s, a)) { \
if (CHECK(s, a)) { \
uint32_t data = 0; \
static gen_helper_opfvf *const fns[2] = { \
gen_helper_##NAME##_h, gen_helper_##NAME##_w, \
@@ -2399,8 +2502,8 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \
return false; \
}
GEN_OPFVF_WIDEN_TRANS(vfwadd_vf)
GEN_OPFVF_WIDEN_TRANS(vfwsub_vf)
GEN_OPFVF_WIDEN_TRANS(vfwadd_vf, opfvf_widen_check)
GEN_OPFVF_WIDEN_TRANS(vfwsub_vf, opfvf_widen_check)
static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
{
@@ -2482,7 +2585,7 @@ GEN_OPFVF_TRANS(vfrdiv_vf, opfvf_check)
/* Vector Widening Floating-Point Multiply */
GEN_OPFVV_WIDEN_TRANS(vfwmul_vv, opfvv_widen_check)
GEN_OPFVF_WIDEN_TRANS(vfwmul_vf)
GEN_OPFVF_WIDEN_TRANS(vfwmul_vf, opfvf_widen_check)
/* Vector Single-Width Floating-Point Fused Multiply-Add Instructions */
GEN_OPFVV_TRANS(vfmacc_vv, opfvv_check)
@@ -2503,14 +2606,14 @@ GEN_OPFVF_TRANS(vfmsub_vf, opfvf_check)
GEN_OPFVF_TRANS(vfnmsub_vf, opfvf_check)
/* Vector Widening Floating-Point Fused Multiply-Add Instructions */
GEN_OPFVV_WIDEN_TRANS(vfwmacc_vv, opfvv_widen_check)
GEN_OPFVV_WIDEN_TRANS(vfwnmacc_vv, opfvv_widen_check)
GEN_OPFVV_WIDEN_TRANS(vfwmsac_vv, opfvv_widen_check)
GEN_OPFVV_WIDEN_TRANS(vfwnmsac_vv, opfvv_widen_check)
GEN_OPFVF_WIDEN_TRANS(vfwmacc_vf)
GEN_OPFVF_WIDEN_TRANS(vfwnmacc_vf)
GEN_OPFVF_WIDEN_TRANS(vfwmsac_vf)
GEN_OPFVF_WIDEN_TRANS(vfwnmsac_vf)
GEN_OPFVV_WIDEN_TRANS(vfwmacc_vv, opfvv_overwrite_widen_check)
GEN_OPFVV_WIDEN_TRANS(vfwnmacc_vv, opfvv_overwrite_widen_check)
GEN_OPFVV_WIDEN_TRANS(vfwmsac_vv, opfvv_overwrite_widen_check)
GEN_OPFVV_WIDEN_TRANS(vfwnmsac_vv, opfvv_overwrite_widen_check)
GEN_OPFVF_WIDEN_TRANS(vfwmacc_vf, opfvf_overwrite_widen_check)
GEN_OPFVF_WIDEN_TRANS(vfwnmacc_vf, opfvf_overwrite_widen_check)
GEN_OPFVF_WIDEN_TRANS(vfwmsac_vf, opfvf_overwrite_widen_check)
GEN_OPFVF_WIDEN_TRANS(vfwnmsac_vf, opfvf_overwrite_widen_check)
/* Vector Floating-Point Square-Root Instruction */
@@ -3426,6 +3529,7 @@ static bool vrgather_vv_check(DisasContext *s, arg_rmrr *a)
{
return require_rvv(s) &&
vext_check_isa_ill(s) &&
vext_check_input_eew(s, a->rs1, s->sew, a->rs2, s->sew, a->vm) &&
require_align(a->rd, s->lmul) &&
require_align(a->rs1, s->lmul) &&
require_align(a->rs2, s->lmul) &&
@@ -3438,6 +3542,7 @@ static bool vrgatherei16_vv_check(DisasContext *s, arg_rmrr *a)
int8_t emul = MO_16 - s->sew + s->lmul;
return require_rvv(s) &&
vext_check_isa_ill(s) &&
vext_check_input_eew(s, a->rs1, MO_16, a->rs2, s->sew, a->vm) &&
(emul >= -3 && emul <= 3) &&
require_align(a->rd, s->lmul) &&
require_align(a->rs1, emul) &&
@@ -3457,6 +3562,7 @@ static bool vrgather_vx_check(DisasContext *s, arg_rmrr *a)
{
return require_rvv(s) &&
vext_check_isa_ill(s) &&
vext_check_input_eew(s, -1, MO_64, a->rs2, s->sew, a->vm) &&
require_align(a->rd, s->lmul) &&
require_align(a->rs2, s->lmul) &&
(a->rd != a->rs2) &&
@@ -3600,7 +3706,9 @@ static bool int_ext_check(DisasContext *s, arg_rmr *a, uint8_t div)
require_align(a->rd, s->lmul) &&
require_align(a->rs2, s->lmul - div) &&
require_vm(a->vm, a->rd) &&
require_noover(a->rd, s->lmul, a->rs2, s->lmul - div);
require_noover(a->rd, s->lmul, a->rs2, s->lmul - div) &&
vext_check_input_eew(s, -1, 0, a->rs2, s->sew, a->vm);
return ret;
}
+132 -104
View File
@@ -58,33 +58,17 @@ void riscv_kvm_aplic_request(void *opaque, int irq, int level)
static bool cap_has_mp_state;
static uint64_t kvm_riscv_reg_id_ulong(CPURISCVState *env, uint64_t type,
uint64_t idx)
{
uint64_t id = KVM_REG_RISCV | type | idx;
#define KVM_RISCV_REG_ID_U32(type, idx) (KVM_REG_RISCV | KVM_REG_SIZE_U32 | \
type | idx)
switch (riscv_cpu_mxl(env)) {
case MXL_RV32:
id |= KVM_REG_SIZE_U32;
break;
case MXL_RV64:
id |= KVM_REG_SIZE_U64;
break;
default:
g_assert_not_reached();
}
return id;
}
#define KVM_RISCV_REG_ID_U64(type, idx) (KVM_REG_RISCV | KVM_REG_SIZE_U64 | \
type | idx)
static uint64_t kvm_riscv_reg_id_u32(uint64_t type, uint64_t idx)
{
return KVM_REG_RISCV | KVM_REG_SIZE_U32 | type | idx;
}
static uint64_t kvm_riscv_reg_id_u64(uint64_t type, uint64_t idx)
{
return KVM_REG_RISCV | KVM_REG_SIZE_U64 | type | idx;
}
#if defined(TARGET_RISCV64)
#define KVM_RISCV_REG_ID_ULONG(type, idx) KVM_RISCV_REG_ID_U64(type, idx)
#else
#define KVM_RISCV_REG_ID_ULONG(type, idx) KVM_RISCV_REG_ID_U32(type, idx)
#endif
static uint64_t kvm_encode_reg_size_id(uint64_t id, size_t size_b)
{
@@ -107,45 +91,29 @@ static uint64_t kvm_riscv_vector_reg_id(RISCVCPU *cpu,
return kvm_encode_reg_size_id(id, size_b);
}
#define RISCV_CORE_REG(env, name) \
kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CORE, \
#define RISCV_CORE_REG(name) \
KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CORE, \
KVM_REG_RISCV_CORE_REG(name))
#define RISCV_CSR_REG(env, name) \
kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CSR, \
#define RISCV_CSR_REG(name) \
KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CSR, \
KVM_REG_RISCV_CSR_REG(name))
#define RISCV_CONFIG_REG(env, name) \
kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CONFIG, \
#define RISCV_CONFIG_REG(name) \
KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CONFIG, \
KVM_REG_RISCV_CONFIG_REG(name))
#define RISCV_TIMER_REG(name) kvm_riscv_reg_id_u64(KVM_REG_RISCV_TIMER, \
#define RISCV_TIMER_REG(name) KVM_RISCV_REG_ID_U64(KVM_REG_RISCV_TIMER, \
KVM_REG_RISCV_TIMER_REG(name))
#define RISCV_FP_F_REG(idx) kvm_riscv_reg_id_u32(KVM_REG_RISCV_FP_F, idx)
#define RISCV_FP_F_REG(idx) KVM_RISCV_REG_ID_U32(KVM_REG_RISCV_FP_F, idx)
#define RISCV_FP_D_REG(idx) kvm_riscv_reg_id_u64(KVM_REG_RISCV_FP_D, idx)
#define RISCV_FP_D_REG(idx) KVM_RISCV_REG_ID_U64(KVM_REG_RISCV_FP_D, idx)
#define RISCV_VECTOR_CSR_REG(env, name) \
kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_VECTOR, \
#define RISCV_VECTOR_CSR_REG(name) \
KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_VECTOR, \
KVM_REG_RISCV_VECTOR_CSR_REG(name))
#define KVM_RISCV_GET_CSR(cs, env, csr, reg) \
do { \
int _ret = kvm_get_one_reg(cs, RISCV_CSR_REG(env, csr), &reg); \
if (_ret) { \
return _ret; \
} \
} while (0)
#define KVM_RISCV_SET_CSR(cs, env, csr, reg) \
do { \
int _ret = kvm_set_one_reg(cs, RISCV_CSR_REG(env, csr), &reg); \
if (_ret) { \
return _ret; \
} \
} while (0)
#define KVM_RISCV_GET_TIMER(cs, name, reg) \
do { \
int ret = kvm_get_one_reg(cs, RISCV_TIMER_REG(name), &reg); \
@@ -248,7 +216,7 @@ static void kvm_riscv_update_cpu_misa_ext(RISCVCPU *cpu, CPUState *cs)
/* If we're here we're going to disable the MISA bit */
reg = 0;
id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_ISA_EXT,
id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_ISA_EXT,
misa_cfg->kvm_reg_id);
ret = kvm_set_one_reg(cs, id, &reg);
if (ret != 0) {
@@ -267,6 +235,53 @@ static void kvm_riscv_update_cpu_misa_ext(RISCVCPU *cpu, CPUState *cs)
}
}
#define KVM_CSR_CFG(_name, _env_prop, reg_id) \
{.name = _name, .offset = ENV_CSR_OFFSET(_env_prop), \
.kvm_reg_id = reg_id}
static KVMCPUConfig kvm_csr_cfgs[] = {
KVM_CSR_CFG("sstatus", mstatus, RISCV_CSR_REG(sstatus)),
KVM_CSR_CFG("sie", mie, RISCV_CSR_REG(sie)),
KVM_CSR_CFG("stvec", stvec, RISCV_CSR_REG(stvec)),
KVM_CSR_CFG("sscratch", sscratch, RISCV_CSR_REG(sscratch)),
KVM_CSR_CFG("sepc", sepc, RISCV_CSR_REG(sepc)),
KVM_CSR_CFG("scause", scause, RISCV_CSR_REG(scause)),
KVM_CSR_CFG("stval", stval, RISCV_CSR_REG(stval)),
KVM_CSR_CFG("sip", mip, RISCV_CSR_REG(sip)),
KVM_CSR_CFG("satp", satp, RISCV_CSR_REG(satp)),
};
static void *kvmconfig_get_env_addr(RISCVCPU *cpu, KVMCPUConfig *csr_cfg)
{
return (void *)&cpu->env + csr_cfg->offset;
}
static uint32_t kvm_cpu_csr_get_u32(RISCVCPU *cpu, KVMCPUConfig *csr_cfg)
{
uint32_t *val32 = kvmconfig_get_env_addr(cpu, csr_cfg);
return *val32;
}
static uint64_t kvm_cpu_csr_get_u64(RISCVCPU *cpu, KVMCPUConfig *csr_cfg)
{
uint64_t *val64 = kvmconfig_get_env_addr(cpu, csr_cfg);
return *val64;
}
static void kvm_cpu_csr_set_u32(RISCVCPU *cpu, KVMCPUConfig *csr_cfg,
uint32_t val)
{
uint32_t *val32 = kvmconfig_get_env_addr(cpu, csr_cfg);
*val32 = val;
}
static void kvm_cpu_csr_set_u64(RISCVCPU *cpu, KVMCPUConfig *csr_cfg,
uint64_t val)
{
uint64_t *val64 = kvmconfig_get_env_addr(cpu, csr_cfg);
*val64 = val;
}
#define KVM_EXT_CFG(_name, _prop, _reg_id) \
{.name = _name, .offset = CPU_CFG_OFFSET(_prop), \
.kvm_reg_id = _reg_id}
@@ -426,7 +441,6 @@ static KVMCPUConfig kvm_sbi_dbcn = {
static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
{
CPURISCVState *env = &cpu->env;
uint64_t id, reg;
int i, ret;
@@ -437,7 +451,7 @@ static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
continue;
}
id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_ISA_EXT,
id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_ISA_EXT,
multi_ext_cfg->kvm_reg_id);
reg = kvm_cpu_cfg_get(cpu, multi_ext_cfg);
ret = kvm_set_one_reg(cs, id, &reg);
@@ -562,14 +576,14 @@ static int kvm_riscv_get_regs_core(CPUState *cs)
target_ulong reg;
CPURISCVState *env = &RISCV_CPU(cs)->env;
ret = kvm_get_one_reg(cs, RISCV_CORE_REG(env, regs.pc), &reg);
ret = kvm_get_one_reg(cs, RISCV_CORE_REG(regs.pc), &reg);
if (ret) {
return ret;
}
env->pc = reg;
for (i = 1; i < 32; i++) {
uint64_t id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CORE, i);
uint64_t id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CORE, i);
ret = kvm_get_one_reg(cs, id, &reg);
if (ret) {
return ret;
@@ -588,13 +602,13 @@ static int kvm_riscv_put_regs_core(CPUState *cs)
CPURISCVState *env = &RISCV_CPU(cs)->env;
reg = env->pc;
ret = kvm_set_one_reg(cs, RISCV_CORE_REG(env, regs.pc), &reg);
ret = kvm_set_one_reg(cs, RISCV_CORE_REG(regs.pc), &reg);
if (ret) {
return ret;
}
for (i = 1; i < 32; i++) {
uint64_t id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CORE, i);
uint64_t id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CORE, i);
reg = env->gpr[i];
ret = kvm_set_one_reg(cs, id, &reg);
if (ret) {
@@ -607,34 +621,52 @@ static int kvm_riscv_put_regs_core(CPUState *cs)
static int kvm_riscv_get_regs_csr(CPUState *cs)
{
CPURISCVState *env = &RISCV_CPU(cs)->env;
RISCVCPU *cpu = RISCV_CPU(cs);
uint64_t reg;
int i, ret;
KVM_RISCV_GET_CSR(cs, env, sstatus, env->mstatus);
KVM_RISCV_GET_CSR(cs, env, sie, env->mie);
KVM_RISCV_GET_CSR(cs, env, stvec, env->stvec);
KVM_RISCV_GET_CSR(cs, env, sscratch, env->sscratch);
KVM_RISCV_GET_CSR(cs, env, sepc, env->sepc);
KVM_RISCV_GET_CSR(cs, env, scause, env->scause);
KVM_RISCV_GET_CSR(cs, env, stval, env->stval);
KVM_RISCV_GET_CSR(cs, env, sip, env->mip);
KVM_RISCV_GET_CSR(cs, env, satp, env->satp);
for (i = 0; i < ARRAY_SIZE(kvm_csr_cfgs); i++) {
KVMCPUConfig *csr_cfg = &kvm_csr_cfgs[i];
ret = kvm_get_one_reg(cs, csr_cfg->kvm_reg_id, &reg);
if (ret) {
return ret;
}
if (KVM_REG_SIZE(csr_cfg->kvm_reg_id) == sizeof(uint32_t)) {
kvm_cpu_csr_set_u32(cpu, csr_cfg, reg);
} else if (KVM_REG_SIZE(csr_cfg->kvm_reg_id) == sizeof(uint64_t)) {
kvm_cpu_csr_set_u64(cpu, csr_cfg, reg);
} else {
g_assert_not_reached();
}
}
return 0;
}
static int kvm_riscv_put_regs_csr(CPUState *cs)
{
CPURISCVState *env = &RISCV_CPU(cs)->env;
RISCVCPU *cpu = RISCV_CPU(cs);
uint64_t reg;
int i, ret;
KVM_RISCV_SET_CSR(cs, env, sstatus, env->mstatus);
KVM_RISCV_SET_CSR(cs, env, sie, env->mie);
KVM_RISCV_SET_CSR(cs, env, stvec, env->stvec);
KVM_RISCV_SET_CSR(cs, env, sscratch, env->sscratch);
KVM_RISCV_SET_CSR(cs, env, sepc, env->sepc);
KVM_RISCV_SET_CSR(cs, env, scause, env->scause);
KVM_RISCV_SET_CSR(cs, env, stval, env->stval);
KVM_RISCV_SET_CSR(cs, env, sip, env->mip);
KVM_RISCV_SET_CSR(cs, env, satp, env->satp);
for (i = 0; i < ARRAY_SIZE(kvm_csr_cfgs); i++) {
KVMCPUConfig *csr_cfg = &kvm_csr_cfgs[i];
if (KVM_REG_SIZE(csr_cfg->kvm_reg_id) == sizeof(uint32_t)) {
reg = kvm_cpu_csr_get_u32(cpu, csr_cfg);
} else if (KVM_REG_SIZE(csr_cfg->kvm_reg_id) == sizeof(uint64_t)) {
reg = kvm_cpu_csr_get_u64(cpu, csr_cfg);
} else {
g_assert_not_reached();
}
ret = kvm_set_one_reg(cs, csr_cfg->kvm_reg_id, &reg);
if (ret) {
return ret;
}
}
return 0;
}
@@ -779,26 +811,26 @@ static int kvm_riscv_get_regs_vector(CPUState *cs)
return 0;
}
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vstart), &reg);
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(vstart), &reg);
if (ret) {
return ret;
}
env->vstart = reg;
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vl), &reg);
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(vl), &reg);
if (ret) {
return ret;
}
env->vl = reg;
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vtype), &reg);
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(vtype), &reg);
if (ret) {
return ret;
}
env->vtype = reg;
if (kvm_v_vlenb.supported) {
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vlenb), &reg);
ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(vlenb), &reg);
if (ret) {
return ret;
}
@@ -836,26 +868,26 @@ static int kvm_riscv_put_regs_vector(CPUState *cs)
}
reg = env->vstart;
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vstart), &reg);
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(vstart), &reg);
if (ret) {
return ret;
}
reg = env->vl;
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vl), &reg);
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(vl), &reg);
if (ret) {
return ret;
}
reg = env->vtype;
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vtype), &reg);
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(vtype), &reg);
if (ret) {
return ret;
}
if (kvm_v_vlenb.supported) {
reg = cpu->cfg.vlenb;
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vlenb), &reg);
ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(vlenb), &reg);
for (int i = 0; i < 32; i++) {
/*
@@ -934,25 +966,24 @@ static void kvm_riscv_destroy_scratch_vcpu(KVMScratchCPU *scratch)
static void kvm_riscv_init_machine_ids(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
{
CPURISCVState *env = &cpu->env;
struct kvm_one_reg reg;
int ret;
reg.id = RISCV_CONFIG_REG(env, mvendorid);
reg.id = RISCV_CONFIG_REG(mvendorid);
reg.addr = (uint64_t)&cpu->cfg.mvendorid;
ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, &reg);
if (ret != 0) {
error_report("Unable to retrieve mvendorid from host, error %d", ret);
}
reg.id = RISCV_CONFIG_REG(env, marchid);
reg.id = RISCV_CONFIG_REG(marchid);
reg.addr = (uint64_t)&cpu->cfg.marchid;
ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, &reg);
if (ret != 0) {
error_report("Unable to retrieve marchid from host, error %d", ret);
}
reg.id = RISCV_CONFIG_REG(env, mimpid);
reg.id = RISCV_CONFIG_REG(mimpid);
reg.addr = (uint64_t)&cpu->cfg.mimpid;
ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, &reg);
if (ret != 0) {
@@ -967,7 +998,7 @@ static void kvm_riscv_init_misa_ext_mask(RISCVCPU *cpu,
struct kvm_one_reg reg;
int ret;
reg.id = RISCV_CONFIG_REG(env, isa);
reg.id = RISCV_CONFIG_REG(isa);
reg.addr = (uint64_t)&env->misa_ext_mask;
ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, &reg);
@@ -984,11 +1015,10 @@ static void kvm_riscv_init_misa_ext_mask(RISCVCPU *cpu,
static void kvm_riscv_read_cbomz_blksize(RISCVCPU *cpu, KVMScratchCPU *kvmcpu,
KVMCPUConfig *cbomz_cfg)
{
CPURISCVState *env = &cpu->env;
struct kvm_one_reg reg;
int ret;
reg.id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CONFIG,
reg.id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CONFIG,
cbomz_cfg->kvm_reg_id);
reg.addr = (uint64_t)kvmconfig_get_cfg_addr(cpu, cbomz_cfg);
ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, &reg);
@@ -1002,7 +1032,6 @@ static void kvm_riscv_read_cbomz_blksize(RISCVCPU *cpu, KVMScratchCPU *kvmcpu,
static void kvm_riscv_read_multiext_legacy(RISCVCPU *cpu,
KVMScratchCPU *kvmcpu)
{
CPURISCVState *env = &cpu->env;
uint64_t val;
int i, ret;
@@ -1010,7 +1039,7 @@ static void kvm_riscv_read_multiext_legacy(RISCVCPU *cpu,
KVMCPUConfig *multi_ext_cfg = &kvm_multi_ext_cfgs[i];
struct kvm_one_reg reg;
reg.id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_ISA_EXT,
reg.id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_ISA_EXT,
multi_ext_cfg->kvm_reg_id);
reg.addr = (uint64_t)&val;
ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, &reg);
@@ -1099,10 +1128,10 @@ static void kvm_riscv_read_vlenb(RISCVCPU *cpu, KVMScratchCPU *kvmcpu,
static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
{
g_autofree struct kvm_reg_list *reglist = NULL;
KVMCPUConfig *multi_ext_cfg;
struct kvm_one_reg reg;
struct kvm_reg_list rl_struct;
struct kvm_reg_list *reglist;
uint64_t val, reg_id, *reg_search;
int i, ret;
@@ -1143,7 +1172,7 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
for (i = 0; i < ARRAY_SIZE(kvm_multi_ext_cfgs); i++) {
multi_ext_cfg = &kvm_multi_ext_cfgs[i];
reg_id = kvm_riscv_reg_id_ulong(&cpu->env, KVM_REG_RISCV_ISA_EXT,
reg_id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_ISA_EXT,
multi_ext_cfg->kvm_reg_id);
reg_search = bsearch(&reg_id, reglist->reg, reglist->n,
sizeof(uint64_t), uint64_cmp);
@@ -1322,12 +1351,11 @@ void kvm_arch_init_irq_routing(KVMState *s)
static int kvm_vcpu_set_machine_ids(RISCVCPU *cpu, CPUState *cs)
{
CPURISCVState *env = &cpu->env;
target_ulong reg;
uint64_t id;
int ret;
id = RISCV_CONFIG_REG(env, mvendorid);
id = RISCV_CONFIG_REG(mvendorid);
/*
* cfg.mvendorid is an uint32 but a target_ulong will
* be written. Assign it to a target_ulong var to avoid
@@ -1339,13 +1367,13 @@ static int kvm_vcpu_set_machine_ids(RISCVCPU *cpu, CPUState *cs)
return ret;
}
id = RISCV_CONFIG_REG(env, marchid);
id = RISCV_CONFIG_REG(marchid);
ret = kvm_set_one_reg(cs, id, &cpu->cfg.marchid);
if (ret != 0) {
return ret;
}
id = RISCV_CONFIG_REG(env, mimpid);
id = RISCV_CONFIG_REG(mimpid);
ret = kvm_set_one_reg(cs, id, &cpu->cfg.mimpid);
return ret;
@@ -1901,7 +1929,7 @@ void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
if (cpu->cfg.ext_zicbom &&
riscv_cpu_option_set(kvm_cbom_blocksize.name)) {
reg.id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CONFIG,
reg.id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CONFIG,
kvm_cbom_blocksize.kvm_reg_id);
reg.addr = (uint64_t)&val;
ret = ioctl(kvmcpu.cpufd, KVM_GET_ONE_REG, &reg);
@@ -1920,7 +1948,7 @@ void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
if (cpu->cfg.ext_zicboz &&
riscv_cpu_option_set(kvm_cboz_blocksize.name)) {
reg.id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CONFIG,
reg.id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CONFIG,
kvm_cboz_blocksize.kvm_reg_id);
reg.addr = (uint64_t)&val;
ret = ioctl(kvmcpu.cpufd, KVM_GET_ONE_REG, &reg);
+12 -10
View File
@@ -31,6 +31,15 @@ static bool pmp_write_cfg(CPURISCVState *env, uint32_t addr_index,
uint8_t val);
static uint8_t pmp_read_cfg(CPURISCVState *env, uint32_t addr_index);
/*
* Convert the PMP permissions to match the truth table in the Smepmp spec.
*/
static inline uint8_t pmp_get_smepmp_operation(uint8_t cfg)
{
return ((cfg & PMP_LOCK) >> 4) | ((cfg & PMP_READ) << 2) |
(cfg & PMP_WRITE) | ((cfg & PMP_EXEC) >> 2);
}
/*
* Accessor method to extract address matching type 'a field' from cfg reg
*/
@@ -352,16 +361,6 @@ bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
const uint8_t a_field =
pmp_get_a_field(env->pmp_state.pmp[i].cfg_reg);
/*
* Convert the PMP permissions to match the truth table in the
* Smepmp spec.
*/
const uint8_t smepmp_operation =
((env->pmp_state.pmp[i].cfg_reg & PMP_LOCK) >> 4) |
((env->pmp_state.pmp[i].cfg_reg & PMP_READ) << 2) |
(env->pmp_state.pmp[i].cfg_reg & PMP_WRITE) |
((env->pmp_state.pmp[i].cfg_reg & PMP_EXEC) >> 2);
if (((s + e) == 2) && (PMP_AMATCH_OFF != a_field)) {
/*
* If the PMP entry is not off and the address is in range,
@@ -380,6 +379,9 @@ bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
/*
* If mseccfg.MML Bit set, do the enhanced pmp priv check
*/
const uint8_t smepmp_operation =
pmp_get_smepmp_operation(env->pmp_state.pmp[i].cfg_reg);
if (mode == PRV_M) {
switch (smepmp_operation) {
case 0:
+4 -2
View File
@@ -5089,9 +5089,11 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \
} \
\
for (i = i_max; i < vl; ++i) { \
if (vm || vext_elem_mask(v0, i)) { \
*((ETYPE *)vd + H(i)) = 0; \
if (!vm && !vext_elem_mask(v0, i)) { \
vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \
continue; \
} \
*((ETYPE *)vd + H(i)) = 0; \
} \
\
env->vstart = 0; \
+3
View File
@@ -4461,6 +4461,9 @@ static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs,
ts->mem_coherent = 0;
break;
case TEMP_VAL_MEM:
if (!ts->mem_allocated) {
temp_allocate_frame(s, ts);
}
reg = tcg_reg_alloc(s, desired_regs, allocated_regs,
preferred_regs, ts->indirect_base);
tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);