mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-target-arm-20250830' of https://gitlab.com/pm215/qemu into staging
target-arm queue: * Implement FEAT_SCTLR2 * Implement FEAT_TCR2 * Implement FEAT_CSSC * Implement FEAT_LSE128 * Clean up of register field definitions * Trap PMCR when MDCR_EL2.TPMCR is set * tests/functional: update aarch64 RME test images * hw/intc/arm_gicv3_kvm: preserve pending interrupts during cpr * hw/arm: add static NVDIMMs in device tree * hw/arm/stm32f205_soc: Don't leak TYPE_OR_IRQ objects * scripts/kernel-doc: Avoid new Perl precedence warning * scripts/kernel-doc: Update to kernel's new Python implementation # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmizIcAZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3tmCD/9Pe4Evw/I2e3Nqr4X87+KC # JtX3s9U8Gly1ttnWd5a+fRubBqIvpxRsJYf0PJQi7otPGDq4E3TZ5UCRnInArpRh # hJqyNxi2ELgDU0Z917UYMnxBwpv7+V/635V1/svSOWDf9RPHnf6GwrmlCvu4Llgf # mVtDlQd+Ta5hoICM0VzrMZfTYevxGqi/cr/oVzCObKmh1YMpPTtSNlfYPMFcY7py # JLu5e7YNN2krh19nCXieS3iqXMsFoLp31kXcCmKE1BgIKeVPNxTRMfOWa4uNDtUN # 17iLfHLatNfSWUA1gvUHxv2maCdm4xJZdGowP/uYvzaemquFSjfM/8qaBxxFqZ1v # 7jdZEzdnn1CX4Kmu3cPvhcuACyYRprlrKZYvCrTH4yCKbJsm0Uo7M66ia3EIF5EQ # kehnGGwu3rv3qrliTXiXoAr7fC0OOiN0afAkS6a5lAi13s6M+Se2VElnRvIoXR2W # 0Xw21/05p/WuXLoMNFjEpAaQgWYEc0kQhFAQczcZH+pyGlaU2QxCTTnaeuHUWcke # y7OtpVBk4Fukaqd4gn0SQtYQLxeFq6vPOL4b1VKR5FuGDSucBUjuVl0dG4gkdbII # yvCBaTb+IEY4fJ1E8IMTI3Lcydv9yblLyGXLr42e22x/l51SCZs1WvIx2i6u6VST # lYnoOObEknvf25YAu3rDTw== # =VItP # -----END PGP SIGNATURE----- # gpg: Signature made Sun 31 Aug 2025 02:07:28 AM AEST # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [unknown] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [unknown] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [unknown] # gpg: aka "Peter Maydell <peter@archaic.org.uk>" [unknown] # gpg: WARNING: The key's User ID is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * tag 'pull-target-arm-20250830' of https://gitlab.com/pm215/qemu: (32 commits) hw/arm/stm32f205_soc: Don't leak TYPE_OR_IRQ objects target/arm: Enable FEAT_LSE128 for -cpu max target/arm: Implement FEAT_LSE128 target/arm: Rename isar_feature_aa64_atomics tcg: Add tcg_gen_atomic_{xchg,fetch_and,fetch_or}_i128 accel/tcg: Add cpu_atomic_*_mmu for 16-byte xchg, fetch_and, fetch_or qemu/atomic: Add atomic16 primitives for xchg, fetch_and, fetch_or qemu/atomic: Finish renaming atomic128-cas.h headers target/arm: Correct condition of aa64_atomics feature function MAINTAINERS: Put kernel-doc under the "docs build machinery" section scripts/kernel-doc: Delete the old Perl kernel-doc script scripts/kerneldoc: Switch to the Python kernel-doc script scripts/kernel-doc: tweak for QEMU coding standards scripts/kernel-doc: strip QEMU_ from function definitions scripts: Import Python kerneldoc from Linux kernel tests/qtest/libqtest.h: Remove stray space from doc comment docs/sphinx/kerneldoc.py: Handle new LINENO syntax scripts/kernel-doc: Avoid new Perl precedence warning hw/arm: add static NVDIMMs in device tree target/arm: Enable FEAT_CSSC for -cpu max ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
+1
-1
@@ -55,7 +55,7 @@ indent_size = 4
|
||||
emacs_mode = perl
|
||||
|
||||
# but user kernel "style" for imported scripts
|
||||
[scripts/{kernel-doc,get_maintainer.pl,checkpatch.pl}]
|
||||
[scripts/{get_maintainer.pl,checkpatch.pl}]
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
emacs_mode = perl
|
||||
|
||||
@@ -4441,6 +4441,7 @@ F: po/*.po
|
||||
Sphinx documentation configuration and build machinery
|
||||
M: John Snow <jsnow@redhat.com>
|
||||
M: Peter Maydell <peter.maydell@linaro.org>
|
||||
M: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
||||
S: Maintained
|
||||
F: docs/conf.py
|
||||
F: docs/*/conf.py
|
||||
@@ -4449,6 +4450,8 @@ F: docs/sphinx/
|
||||
F: docs/_templates/
|
||||
F: docs/devel/docs.rst
|
||||
F: docs/devel/qapi-domain.rst
|
||||
F: scripts/kernel-doc
|
||||
F: scripts/lib/kdoc/
|
||||
|
||||
Rust build system integration
|
||||
M: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
|
||||
|
||||
@@ -122,5 +122,14 @@ GEN_ATOMIC_HELPERS(umax_fetch)
|
||||
|
||||
GEN_ATOMIC_HELPERS(xchg)
|
||||
|
||||
#if HAVE_CMPXCHG128
|
||||
ATOMIC_HELPER(xchgo_be, Int128)
|
||||
ATOMIC_HELPER(xchgo_le, Int128)
|
||||
ATOMIC_HELPER(fetch_ando_be, Int128)
|
||||
ATOMIC_HELPER(fetch_ando_le, Int128)
|
||||
ATOMIC_HELPER(fetch_oro_be, Int128)
|
||||
ATOMIC_HELPER(fetch_oro_le, Int128)
|
||||
#endif
|
||||
|
||||
#undef ATOMIC_HELPER
|
||||
#undef GEN_ATOMIC_HELPERS
|
||||
|
||||
@@ -100,7 +100,6 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, vaddr addr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if DATA_SIZE < 16
|
||||
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, vaddr addr, ABI_TYPE val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
@@ -108,7 +107,11 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, vaddr addr, ABI_TYPE val,
|
||||
DATA_SIZE, retaddr);
|
||||
DATA_TYPE ret;
|
||||
|
||||
#if DATA_SIZE == 16
|
||||
ret = atomic16_xchg(haddr, val);
|
||||
#else
|
||||
ret = qatomic_xchg__nocheck(haddr, val);
|
||||
#endif
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr,
|
||||
VALUE_LOW(ret),
|
||||
@@ -119,6 +122,39 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, vaddr addr, ABI_TYPE val,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if DATA_SIZE == 16
|
||||
ABI_TYPE ATOMIC_NAME(fetch_and)(CPUArchState *env, vaddr addr, ABI_TYPE val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env_cpu(env), addr, oi,
|
||||
DATA_SIZE, retaddr);
|
||||
DATA_TYPE ret = atomic16_fetch_and(haddr, val);
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr,
|
||||
VALUE_LOW(ret),
|
||||
VALUE_HIGH(ret),
|
||||
VALUE_LOW(val),
|
||||
VALUE_HIGH(val),
|
||||
oi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ABI_TYPE ATOMIC_NAME(fetch_or)(CPUArchState *env, vaddr addr, ABI_TYPE val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env_cpu(env), addr, oi,
|
||||
DATA_SIZE, retaddr);
|
||||
DATA_TYPE ret = atomic16_fetch_or(haddr, val);
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr,
|
||||
VALUE_LOW(ret),
|
||||
VALUE_HIGH(ret),
|
||||
VALUE_LOW(val),
|
||||
VALUE_HIGH(val),
|
||||
oi);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
#define GEN_ATOMIC_HELPER(X) \
|
||||
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, vaddr addr, \
|
||||
ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \
|
||||
@@ -188,7 +224,7 @@ GEN_ATOMIC_HELPER_FN(smax_fetch, MAX, SDATA_TYPE, new)
|
||||
GEN_ATOMIC_HELPER_FN(umax_fetch, MAX, DATA_TYPE, new)
|
||||
|
||||
#undef GEN_ATOMIC_HELPER_FN
|
||||
#endif /* DATA SIZE < 16 */
|
||||
#endif /* DATA SIZE == 16 */
|
||||
|
||||
#undef END
|
||||
|
||||
@@ -225,7 +261,6 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, vaddr addr,
|
||||
return BSWAP(ret);
|
||||
}
|
||||
|
||||
#if DATA_SIZE < 16
|
||||
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, vaddr addr, ABI_TYPE val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
@@ -233,7 +268,11 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, vaddr addr, ABI_TYPE val,
|
||||
DATA_SIZE, retaddr);
|
||||
ABI_TYPE ret;
|
||||
|
||||
#if DATA_SIZE == 16
|
||||
ret = atomic16_xchg(haddr, BSWAP(val));
|
||||
#else
|
||||
ret = qatomic_xchg__nocheck(haddr, BSWAP(val));
|
||||
#endif
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr,
|
||||
VALUE_LOW(ret),
|
||||
@@ -244,6 +283,39 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, vaddr addr, ABI_TYPE val,
|
||||
return BSWAP(ret);
|
||||
}
|
||||
|
||||
#if DATA_SIZE == 16
|
||||
ABI_TYPE ATOMIC_NAME(fetch_and)(CPUArchState *env, vaddr addr, ABI_TYPE val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env_cpu(env), addr, oi,
|
||||
DATA_SIZE, retaddr);
|
||||
DATA_TYPE ret = atomic16_fetch_and(haddr, BSWAP(val));
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr,
|
||||
VALUE_LOW(ret),
|
||||
VALUE_HIGH(ret),
|
||||
VALUE_LOW(val),
|
||||
VALUE_HIGH(val),
|
||||
oi);
|
||||
return BSWAP(ret);
|
||||
}
|
||||
|
||||
ABI_TYPE ATOMIC_NAME(fetch_or)(CPUArchState *env, vaddr addr, ABI_TYPE val,
|
||||
MemOpIdx oi, uintptr_t retaddr)
|
||||
{
|
||||
DATA_TYPE *haddr = atomic_mmu_lookup(env_cpu(env), addr, oi,
|
||||
DATA_SIZE, retaddr);
|
||||
DATA_TYPE ret = atomic16_fetch_or(haddr, BSWAP(val));
|
||||
ATOMIC_MMU_CLEANUP;
|
||||
atomic_trace_rmw_post(env, addr,
|
||||
VALUE_LOW(ret),
|
||||
VALUE_HIGH(ret),
|
||||
VALUE_LOW(val),
|
||||
VALUE_HIGH(val),
|
||||
oi);
|
||||
return BSWAP(ret);
|
||||
}
|
||||
#else
|
||||
#define GEN_ATOMIC_HELPER(X) \
|
||||
ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, vaddr addr, \
|
||||
ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \
|
||||
@@ -317,7 +389,7 @@ GEN_ATOMIC_HELPER_FN(add_fetch, ADD, DATA_TYPE, new)
|
||||
#undef ADD
|
||||
|
||||
#undef GEN_ATOMIC_HELPER_FN
|
||||
#endif /* DATA_SIZE < 16 */
|
||||
#endif /* DATA_SIZE == 16 */
|
||||
|
||||
#undef END
|
||||
#endif /* DATA_SIZE > 1 */
|
||||
|
||||
@@ -63,6 +63,18 @@ DEF_HELPER_FLAGS_5(atomic_cmpxchgo_be, TCG_CALL_NO_WG,
|
||||
i128, env, i64, i128, i128, i32)
|
||||
DEF_HELPER_FLAGS_5(atomic_cmpxchgo_le, TCG_CALL_NO_WG,
|
||||
i128, env, i64, i128, i128, i32)
|
||||
DEF_HELPER_FLAGS_4(atomic_xchgo_be, TCG_CALL_NO_WG,
|
||||
i128, env, i64, i128, i32)
|
||||
DEF_HELPER_FLAGS_4(atomic_xchgo_le, TCG_CALL_NO_WG,
|
||||
i128, env, i64, i128, i32)
|
||||
DEF_HELPER_FLAGS_4(atomic_fetch_ando_be, TCG_CALL_NO_WG,
|
||||
i128, env, i64, i128, i32)
|
||||
DEF_HELPER_FLAGS_4(atomic_fetch_ando_le, TCG_CALL_NO_WG,
|
||||
i128, env, i64, i128, i32)
|
||||
DEF_HELPER_FLAGS_4(atomic_fetch_oro_be, TCG_CALL_NO_WG,
|
||||
i128, env, i64, i128, i32)
|
||||
DEF_HELPER_FLAGS_4(atomic_fetch_oro_le, TCG_CALL_NO_WG,
|
||||
i128, env, i64, i128, i32)
|
||||
#endif
|
||||
|
||||
DEF_HELPER_FLAGS_5(nonatomic_cmpxchgo, TCG_CALL_NO_WG,
|
||||
|
||||
@@ -114,7 +114,7 @@ static uint32_t get_elf_hwcap(void)
|
||||
GET_FEATURE_ID(aa64_sm3, ARM_HWCAP_A64_SM3);
|
||||
GET_FEATURE_ID(aa64_sm4, ARM_HWCAP_A64_SM4);
|
||||
GET_FEATURE_ID(aa64_fp16, ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
|
||||
GET_FEATURE_ID(aa64_atomics, ARM_HWCAP_A64_ATOMICS);
|
||||
GET_FEATURE_ID(aa64_lse, ARM_HWCAP_A64_ATOMICS);
|
||||
GET_FEATURE_ID(aa64_rdm, ARM_HWCAP_A64_ASIMDRDM);
|
||||
GET_FEATURE_ID(aa64_dp, ARM_HWCAP_A64_ASIMDDP);
|
||||
GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA);
|
||||
|
||||
+3
-1
@@ -341,7 +341,9 @@ man_make_section_directory = False
|
||||
# We use paths starting from qemu_docdir here so that you can run
|
||||
# sphinx-build from anywhere and the kerneldoc extension can still
|
||||
# find everything.
|
||||
kerneldoc_bin = ['perl', os.path.join(qemu_docdir, '../scripts/kernel-doc')]
|
||||
# Since kernel-doc is now a Python script, we should run it with whatever
|
||||
# Python this sphinx is using (rather than letting it find one via env)
|
||||
kerneldoc_bin = [sys.executable, os.path.join(qemu_docdir, '../scripts/kernel-doc.py')]
|
||||
kerneldoc_srctree = os.path.join(qemu_docdir, '..')
|
||||
hxtool_srctree = os.path.join(qemu_docdir, '..')
|
||||
qapidoc_srctree = os.path.join(qemu_docdir, '..')
|
||||
|
||||
@@ -63,11 +63,6 @@ class KernelDocDirective(Directive):
|
||||
env = self.state.document.settings.env
|
||||
cmd = env.config.kerneldoc_bin + ['-rst', '-enable-lineno']
|
||||
|
||||
# Pass the version string to kernel-doc, as it needs to use a different
|
||||
# dialect, depending what the C domain supports for each specific
|
||||
# Sphinx versions
|
||||
cmd += ['-sphinx-version', sphinx.__version__]
|
||||
|
||||
# Pass through the warnings-as-errors flag
|
||||
if env.config.kerneldoc_werror:
|
||||
cmd += ['-Werror']
|
||||
@@ -127,7 +122,7 @@ class KernelDocDirective(Directive):
|
||||
result = ViewList()
|
||||
|
||||
lineoffset = 0;
|
||||
line_regex = re.compile("^#define LINENO ([0-9]+)$")
|
||||
line_regex = re.compile(r"^(?:\.\.|#define) LINENO ([0-9]+)$")
|
||||
for line in lines:
|
||||
match = line_regex.search(line)
|
||||
if match:
|
||||
|
||||
@@ -30,6 +30,7 @@ the following architecture extensions:
|
||||
- FEAT_CMOW (Control for cache maintenance permission)
|
||||
- FEAT_CRC32 (CRC32 instructions)
|
||||
- FEAT_Crypto (Cryptographic Extension)
|
||||
- FEAT_CSSC (Common Short Sequence Compression instructions)
|
||||
- FEAT_CSV2 (Cache speculation variant 2)
|
||||
- FEAT_CSV2_1p1 (Cache speculation variant 2, version 1.1)
|
||||
- FEAT_CSV2_1p2 (Cache speculation variant 2, version 1.2)
|
||||
@@ -88,6 +89,7 @@ the following architecture extensions:
|
||||
- FEAT_LRCPC2 (Load-acquire RCpc instructions v2)
|
||||
- FEAT_LSE (Large System Extensions)
|
||||
- FEAT_LSE2 (Large System Extensions v2)
|
||||
- FEAT_LSE128 (128-bit Atomics)
|
||||
- FEAT_LVA (Large Virtual Address space)
|
||||
- FEAT_MixedEnd (Mixed-endian support)
|
||||
- FEAT_MixedEndEL0 (Mixed-endian support at EL0)
|
||||
@@ -121,6 +123,7 @@ the following architecture extensions:
|
||||
- FEAT_RPRES (Increased precision of FRECPE and FRSQRTE)
|
||||
- FEAT_S2FWB (Stage 2 forced Write-Back)
|
||||
- FEAT_SB (Speculation Barrier)
|
||||
- FEAT_SCTLR2 (Extension to SCTLR_ELx)
|
||||
- FEAT_SEL2 (Secure EL2)
|
||||
- FEAT_SHA1 (SHA1 instructions)
|
||||
- FEAT_SHA256 (SHA256 instructions)
|
||||
@@ -148,6 +151,7 @@ the following architecture extensions:
|
||||
- FEAT_SPECRES (Speculation restriction instructions)
|
||||
- FEAT_SSBS (Speculative Store Bypass Safe)
|
||||
- FEAT_SSBS2 (MRS and MSR instructions for SSBS version 2)
|
||||
- FEAT_TCR2 (Support for TCR2_ELx)
|
||||
- FEAT_TGran16K (Support for 16KB memory translation granule size at stage 1)
|
||||
- FEAT_TGran4K (Support for 4KB memory translation granule size at stage 1)
|
||||
- FEAT_TGran64K (Support for 64KB memory translation granule size at stage 1)
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Compare-and-swap for 128-bit atomic operations, AArch64 version.
|
||||
*
|
||||
* Copyright (C) 2018, 2023 Linaro, Ltd.
|
||||
*
|
||||
* See docs/devel/atomics.rst for discussion about the guarantees each
|
||||
* atomic primitive is meant to provide.
|
||||
*/
|
||||
|
||||
#ifndef AARCH64_ATOMIC128_CAS_H
|
||||
#define AARCH64_ATOMIC128_CAS_H
|
||||
|
||||
/* Through gcc 10, aarch64 has no support for 128-bit atomics. */
|
||||
#if defined(CONFIG_ATOMIC128) || defined(CONFIG_CMPXCHG128)
|
||||
#include "host/include/generic/host/atomic128-cas.h.inc"
|
||||
#else
|
||||
static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
|
||||
{
|
||||
uint64_t cmpl = int128_getlo(cmp), cmph = int128_gethi(cmp);
|
||||
uint64_t newl = int128_getlo(new), newh = int128_gethi(new);
|
||||
uint64_t oldl, oldh;
|
||||
uint32_t tmp;
|
||||
|
||||
asm("0: ldaxp %[oldl], %[oldh], %[mem]\n\t"
|
||||
"cmp %[oldl], %[cmpl]\n\t"
|
||||
"ccmp %[oldh], %[cmph], #0, eq\n\t"
|
||||
"b.ne 1f\n\t"
|
||||
"stlxp %w[tmp], %[newl], %[newh], %[mem]\n\t"
|
||||
"cbnz %w[tmp], 0b\n"
|
||||
"1:"
|
||||
: [mem] "+m"(*ptr), [tmp] "=&r"(tmp),
|
||||
[oldl] "=&r"(oldl), [oldh] "=&r"(oldh)
|
||||
: [cmpl] "r"(cmpl), [cmph] "r"(cmph),
|
||||
[newl] "r"(newl), [newh] "r"(newh)
|
||||
: "memory", "cc");
|
||||
|
||||
return int128_make128(oldl, oldh);
|
||||
}
|
||||
|
||||
# define CONFIG_CMPXCHG128 1
|
||||
# define HAVE_CMPXCHG128 1
|
||||
#endif
|
||||
|
||||
#endif /* AARCH64_ATOMIC128_CAS_H */
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Compare-and-swap for 128-bit atomic operations, AArch64 version.
|
||||
*
|
||||
* Copyright (C) 2018, 2023 Linaro, Ltd.
|
||||
*
|
||||
* See docs/devel/atomics.rst for discussion about the guarantees each
|
||||
* atomic primitive is meant to provide.
|
||||
*/
|
||||
|
||||
#ifndef AARCH64_ATOMIC128_CAS_H
|
||||
#define AARCH64_ATOMIC128_CAS_H
|
||||
|
||||
/* Through gcc 10, aarch64 has no support for 128-bit atomics. */
|
||||
#if defined(CONFIG_ATOMIC128) || defined(CONFIG_CMPXCHG128)
|
||||
#include "host/include/generic/host/atomic128-cas.h.inc"
|
||||
#else
|
||||
static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
|
||||
{
|
||||
uint64_t cmpl = int128_getlo(cmp), cmph = int128_gethi(cmp);
|
||||
uint64_t newl = int128_getlo(new), newh = int128_gethi(new);
|
||||
uint64_t oldl, oldh;
|
||||
uint32_t tmp;
|
||||
|
||||
asm("0: ldaxp %[oldl], %[oldh], %[mem]\n\t"
|
||||
"cmp %[oldl], %[cmpl]\n\t"
|
||||
"ccmp %[oldh], %[cmph], #0, eq\n\t"
|
||||
"b.ne 1f\n\t"
|
||||
"stlxp %w[tmp], %[newl], %[newh], %[mem]\n\t"
|
||||
"cbnz %w[tmp], 0b\n"
|
||||
"1:"
|
||||
: [mem] "+m"(*ptr), [tmp] "=&r"(tmp),
|
||||
[oldl] "=&r"(oldl), [oldh] "=&r"(oldh)
|
||||
: [cmpl] "r"(cmpl), [cmph] "r"(cmph),
|
||||
[newl] "r"(newl), [newh] "r"(newh)
|
||||
: "memory", "cc");
|
||||
|
||||
return int128_make128(oldl, oldh);
|
||||
}
|
||||
|
||||
static inline Int128 atomic16_xchg(Int128 *ptr, Int128 new)
|
||||
{
|
||||
uint64_t newl = int128_getlo(new), newh = int128_gethi(new);
|
||||
uint64_t oldl, oldh;
|
||||
uint32_t tmp;
|
||||
|
||||
asm("0: ldaxp %[oldl], %[oldh], %[mem]\n\t"
|
||||
"stlxp %w[tmp], %[newl], %[newh], %[mem]\n\t"
|
||||
"cbnz %w[tmp], 0b"
|
||||
: [mem] "+m"(*ptr), [tmp] "=&r"(tmp),
|
||||
[oldl] "=&r"(oldl), [oldh] "=&r"(oldh)
|
||||
: [newl] "r"(newl), [newh] "r"(newh)
|
||||
: "memory");
|
||||
|
||||
return int128_make128(oldl, oldh);
|
||||
}
|
||||
|
||||
static inline Int128 atomic16_fetch_and(Int128 *ptr, Int128 new)
|
||||
{
|
||||
uint64_t newl = int128_getlo(new), newh = int128_gethi(new);
|
||||
uint64_t oldl, oldh, tmpl, tmph;
|
||||
uint32_t tmp;
|
||||
|
||||
asm("0: ldaxp %[oldl], %[oldh], %[mem]\n\t"
|
||||
"and %[tmpl], %[oldl], %[newl]\n\t"
|
||||
"and %[tmph], %[oldh], %[newh]\n\t"
|
||||
"stlxp %w[tmp], %[tmpl], %[tmph], %[mem]\n\t"
|
||||
"cbnz %w[tmp], 0b"
|
||||
: [mem] "+m"(*ptr), [tmp] "=&r"(tmp),
|
||||
[oldl] "=&r"(oldl), [oldh] "=&r"(oldh)
|
||||
: [newl] "r"(newl), [newh] "r"(newh),
|
||||
[tmpl] "r"(tmpl), [tmph] "r"(tmph)
|
||||
: "memory");
|
||||
|
||||
return int128_make128(oldl, oldh);
|
||||
}
|
||||
|
||||
static inline Int128 atomic16_fetch_or(Int128 *ptr, Int128 new)
|
||||
{
|
||||
uint64_t newl = int128_getlo(new), newh = int128_gethi(new);
|
||||
uint64_t oldl, oldh, tmpl, tmph;
|
||||
uint32_t tmp;
|
||||
|
||||
asm("0: ldaxp %[oldl], %[oldh], %[mem]\n\t"
|
||||
"orr %[tmpl], %[oldl], %[newl]\n\t"
|
||||
"orr %[tmph], %[oldh], %[newh]\n\t"
|
||||
"stlxp %w[tmp], %[tmpl], %[tmph], %[mem]\n\t"
|
||||
"cbnz %w[tmp], 0b"
|
||||
: [mem] "+m"(*ptr), [tmp] "=&r"(tmp),
|
||||
[oldl] "=&r"(oldl), [oldh] "=&r"(oldh)
|
||||
: [newl] "r"(newl), [newh] "r"(newh),
|
||||
[tmpl] "r"(tmpl), [tmph] "r"(tmph)
|
||||
: "memory");
|
||||
|
||||
return int128_make128(oldl, oldh);
|
||||
}
|
||||
|
||||
# define CONFIG_CMPXCHG128 1
|
||||
# define HAVE_CMPXCHG128 1
|
||||
#endif
|
||||
|
||||
#endif /* AARCH64_ATOMIC128_CAS_H */
|
||||
@@ -23,6 +23,51 @@ atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
|
||||
r.i = qatomic_cmpxchg__nocheck(ptr_align, c.i, n.i);
|
||||
return r.s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we're looping anyway, use weak compare and swap.
|
||||
* If the host supports weak, this will eliminate a second loop hidden
|
||||
* within the atomic operation itself; otherwise the weak parameter is
|
||||
* ignored.
|
||||
*/
|
||||
static inline Int128 ATTRIBUTE_ATOMIC128_OPT
|
||||
atomic16_xchg(Int128 *ptr, Int128 new)
|
||||
{
|
||||
__int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
|
||||
Int128 old = *ptr_align;
|
||||
|
||||
while (!__atomic_compare_exchange_n(ptr_align, &old, new, true,
|
||||
__ATOMIC_SEQ_CST, 0)) {
|
||||
continue;
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
static inline Int128 ATTRIBUTE_ATOMIC128_OPT
|
||||
atomic16_fetch_and(Int128 *ptr, Int128 val)
|
||||
{
|
||||
__int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
|
||||
Int128 old = *ptr_align;
|
||||
|
||||
while (!__atomic_compare_exchange_n(ptr_align, &old, old & val, true,
|
||||
__ATOMIC_SEQ_CST, 0)) {
|
||||
continue;
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
static inline Int128 ATTRIBUTE_ATOMIC128_OPT
|
||||
atomic16_fetch_or(Int128 *ptr, Int128 val)
|
||||
{
|
||||
__int128_t *ptr_align = __builtin_assume_aligned(ptr, 16);
|
||||
Int128 old = *ptr_align;
|
||||
|
||||
while (!__atomic_compare_exchange_n(ptr_align, &old, old | val, true,
|
||||
__ATOMIC_SEQ_CST, 0)) {
|
||||
continue;
|
||||
}
|
||||
return old;
|
||||
}
|
||||
# define HAVE_CMPXCHG128 1
|
||||
#elif defined(CONFIG_CMPXCHG128)
|
||||
static inline Int128 ATTRIBUTE_ATOMIC128_OPT
|
||||
@@ -36,6 +81,57 @@ atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
|
||||
r.i = __sync_val_compare_and_swap_16(ptr_align, c.i, n.i);
|
||||
return r.s;
|
||||
}
|
||||
|
||||
static inline Int128 ATTRIBUTE_ATOMIC128_OPT
|
||||
atomic16_xchg(Int128 *ptr, Int128 new)
|
||||
{
|
||||
Int128Aligned *ptr_align = __builtin_assume_aligned(ptr, 16);
|
||||
Int128Alias o, n;
|
||||
|
||||
n.s = new;
|
||||
o.s = *ptr_align;
|
||||
while (1) {
|
||||
__int128 c = __sync_val_compare_and_swap_16(ptr_align, o.i, n.i);
|
||||
if (c == o.i) {
|
||||
return o.s;
|
||||
}
|
||||
o.i = c;
|
||||
}
|
||||
}
|
||||
|
||||
static inline Int128 ATTRIBUTE_ATOMIC128_OPT
|
||||
atomic16_fetch_and(Int128 *ptr, Int128 val)
|
||||
{
|
||||
Int128Aligned *ptr_align = __builtin_assume_aligned(ptr, 16);
|
||||
Int128Alias o, v;
|
||||
|
||||
v.s = val;
|
||||
o.s = *ptr_align;
|
||||
while (1) {
|
||||
__int128 c = __sync_val_compare_and_swap_16(ptr_align, o.i, o.i & v.i);
|
||||
if (c == o.i) {
|
||||
return o.s;
|
||||
}
|
||||
o.i = c;
|
||||
}
|
||||
}
|
||||
|
||||
static inline Int128 ATTRIBUTE_ATOMIC128_OPT
|
||||
atomic16_fetch_or(Int128 *ptr, Int128 val)
|
||||
{
|
||||
Int128Aligned *ptr_align = __builtin_assume_aligned(ptr, 16);
|
||||
Int128Alias o, v;
|
||||
|
||||
v.s = val;
|
||||
o.s = *ptr_align;
|
||||
while (1) {
|
||||
__int128 c = __sync_val_compare_and_swap_16(ptr_align, o.i, o.i | v.i);
|
||||
if (c == o.i) {
|
||||
return o.s;
|
||||
}
|
||||
o.i = c;
|
||||
}
|
||||
}
|
||||
# define HAVE_CMPXCHG128 1
|
||||
#else
|
||||
/* Fallback definition that must be optimized away, or error. */
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "hw/boards.h"
|
||||
#include "system/reset.h"
|
||||
#include "hw/loader.h"
|
||||
#include "hw/mem/memory-device.h"
|
||||
#include "elf.h"
|
||||
#include "system/device_tree.h"
|
||||
#include "qemu/config-file.h"
|
||||
@@ -515,6 +516,29 @@ static void fdt_add_psci_node(void *fdt, ARMCPU *armcpu)
|
||||
qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn);
|
||||
}
|
||||
|
||||
static int fdt_add_pmem_node(void *fdt, uint32_t acells, uint32_t scells,
|
||||
int64_t mem_base, int64_t size, int64_t node)
|
||||
{
|
||||
int ret;
|
||||
|
||||
g_autofree char *nodename = g_strdup_printf("/pmem@%" PRIx64, mem_base);
|
||||
|
||||
qemu_fdt_add_subnode(fdt, nodename);
|
||||
qemu_fdt_setprop_string(fdt, nodename, "compatible", "pmem-region");
|
||||
ret = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg", acells,
|
||||
mem_base, scells, size);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (node >= 0) {
|
||||
return qemu_fdt_setprop_cell(fdt, nodename, "numa-node-id",
|
||||
node);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
|
||||
hwaddr addr_limit, AddressSpace *as, MachineState *ms,
|
||||
ARMCPU *cpu)
|
||||
@@ -525,6 +549,7 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
|
||||
unsigned int i;
|
||||
hwaddr mem_base, mem_len;
|
||||
char **node_path;
|
||||
g_autofree MemoryDeviceInfoList *md_list = NULL;
|
||||
Error *err = NULL;
|
||||
|
||||
if (binfo->dtb_filename) {
|
||||
@@ -628,6 +653,23 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
|
||||
}
|
||||
}
|
||||
|
||||
md_list = qmp_memory_device_list();
|
||||
for (MemoryDeviceInfoList *m = md_list; m != NULL; m = m->next) {
|
||||
MemoryDeviceInfo *mi = m->value;
|
||||
|
||||
if (mi->type == MEMORY_DEVICE_INFO_KIND_NVDIMM) {
|
||||
PCDIMMDeviceInfo *di = mi->u.nvdimm.data;
|
||||
|
||||
rc = fdt_add_pmem_node(fdt, acells, scells,
|
||||
di->addr, di->size, di->node);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "couldn't add NVDIMM /pmem@%"PRIx64" node\n",
|
||||
di->addr);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = fdt_path_offset(fdt, "/chosen");
|
||||
if (rc < 0) {
|
||||
qemu_fdt_add_subnode(fdt, "/chosen");
|
||||
|
||||
@@ -66,7 +66,7 @@ static void stm32f205_soc_initfn(Object *obj)
|
||||
TYPE_STM32F2XX_TIMER);
|
||||
}
|
||||
|
||||
s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
|
||||
object_initialize_child(obj, "adc-irq-orgate", &s->adc_irqs, TYPE_OR_IRQ);
|
||||
|
||||
for (i = 0; i < STM_NUM_ADCS; i++) {
|
||||
object_initialize_child(obj, "adc[*]", &s->adc[i], TYPE_STM32F2XX_ADC);
|
||||
@@ -171,12 +171,12 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
}
|
||||
|
||||
/* ADC 1 to 3 */
|
||||
object_property_set_int(OBJECT(s->adc_irqs), "num-lines", STM_NUM_ADCS,
|
||||
object_property_set_int(OBJECT(&s->adc_irqs), "num-lines", STM_NUM_ADCS,
|
||||
&error_abort);
|
||||
if (!qdev_realize(DEVICE(s->adc_irqs), NULL, errp)) {
|
||||
if (!qdev_realize(DEVICE(&s->adc_irqs), NULL, errp)) {
|
||||
return;
|
||||
}
|
||||
qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
|
||||
qdev_connect_gpio_out(DEVICE(&s->adc_irqs), 0,
|
||||
qdev_get_gpio_in(armv7m, ADC_IRQ));
|
||||
|
||||
for (i = 0; i < STM_NUM_ADCS; i++) {
|
||||
@@ -187,7 +187,7 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
|
||||
busdev = SYS_BUS_DEVICE(dev);
|
||||
sysbus_mmio_map(busdev, 0, adc_addr[i]);
|
||||
sysbus_connect_irq(busdev, 0,
|
||||
qdev_get_gpio_in(DEVICE(s->adc_irqs), i));
|
||||
qdev_get_gpio_in(DEVICE(&s->adc_irqs), i));
|
||||
}
|
||||
|
||||
/* SPI 1 and 2 */
|
||||
|
||||
+5
-3
@@ -2917,7 +2917,7 @@ static void virt_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||
const MachineState *ms = MACHINE(hotplug_dev);
|
||||
const bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
|
||||
|
||||
if (!vms->acpi_dev) {
|
||||
if (!vms->acpi_dev && !(is_nvdimm && !dev->hotplugged)) {
|
||||
error_setg(errp,
|
||||
"memory hotplug is not enabled: missing acpi-ged device");
|
||||
return;
|
||||
@@ -2949,8 +2949,10 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev,
|
||||
nvdimm_plug(ms->nvdimms_state);
|
||||
}
|
||||
|
||||
hotplug_handler_plug(HOTPLUG_HANDLER(vms->acpi_dev),
|
||||
dev, &error_abort);
|
||||
if (vms->acpi_dev) {
|
||||
hotplug_handler_plug(HOTPLUG_HANDLER(vms->acpi_dev),
|
||||
dev, &error_abort);
|
||||
}
|
||||
}
|
||||
|
||||
static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "gicv3_internal.h"
|
||||
#include "vgic_common.h"
|
||||
#include "migration/blocker.h"
|
||||
#include "migration/misc.h"
|
||||
#include "qom/object.h"
|
||||
#include "target/arm/cpregs.h"
|
||||
|
||||
@@ -776,6 +777,17 @@ static void vm_change_state_handler(void *opaque, bool running,
|
||||
}
|
||||
}
|
||||
|
||||
static int kvm_arm_gicv3_notifier(NotifierWithReturn *notifier,
|
||||
MigrationEvent *e, Error **errp)
|
||||
{
|
||||
if (e->type == MIG_EVENT_PRECOPY_DONE) {
|
||||
GICv3State *s = container_of(notifier, GICv3State, cpr_notifier);
|
||||
return kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
|
||||
KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES,
|
||||
NULL, true, errp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
@@ -917,6 +929,9 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
|
||||
if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
|
||||
KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES)) {
|
||||
qemu_add_vm_change_state_handler(vm_change_state_handler, s);
|
||||
migration_add_notifier_mode(&s->cpr_notifier,
|
||||
kvm_arm_gicv3_notifier,
|
||||
MIG_MODE_CPR_TRANSFER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,9 +100,6 @@ GEN_ATOMIC_HELPER_ALL(umax_fetch)
|
||||
|
||||
GEN_ATOMIC_HELPER_ALL(xchg)
|
||||
|
||||
#undef GEN_ATOMIC_HELPER_ALL
|
||||
#undef GEN_ATOMIC_HELPER
|
||||
|
||||
Int128 cpu_atomic_cmpxchgo_le_mmu(CPUArchState *env, vaddr addr,
|
||||
Int128 cmpv, Int128 newv,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
@@ -110,6 +107,16 @@ Int128 cpu_atomic_cmpxchgo_be_mmu(CPUArchState *env, vaddr addr,
|
||||
Int128 cmpv, Int128 newv,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
|
||||
GEN_ATOMIC_HELPER(xchg, Int128, o_le)
|
||||
GEN_ATOMIC_HELPER(xchg, Int128, o_be)
|
||||
GEN_ATOMIC_HELPER(fetch_and, Int128, o_le)
|
||||
GEN_ATOMIC_HELPER(fetch_and, Int128, o_be)
|
||||
GEN_ATOMIC_HELPER(fetch_or, Int128, o_le)
|
||||
GEN_ATOMIC_HELPER(fetch_or, Int128, o_be)
|
||||
|
||||
#undef GEN_ATOMIC_HELPER_ALL
|
||||
#undef GEN_ATOMIC_HELPER
|
||||
|
||||
uint8_t cpu_ldb_code_mmu(CPUArchState *env, vaddr addr,
|
||||
MemOpIdx oi, uintptr_t ra);
|
||||
uint16_t cpu_ldw_code_mmu(CPUArchState *env, vaddr addr,
|
||||
|
||||
@@ -59,7 +59,7 @@ struct STM32F205State {
|
||||
STM32F2XXADCState adc[STM_NUM_ADCS];
|
||||
STM32F2XXSPIState spi[STM_NUM_SPIS];
|
||||
|
||||
OrIRQState *adc_irqs;
|
||||
OrIRQState adc_irqs;
|
||||
|
||||
MemoryRegion sram;
|
||||
MemoryRegion flash;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/intc/arm_gic_common.h"
|
||||
#include "qom/object.h"
|
||||
#include "qemu/notify.h"
|
||||
|
||||
/*
|
||||
* Maximum number of possible interrupts, determined by the GIC architecture.
|
||||
@@ -271,6 +272,8 @@ struct GICv3State {
|
||||
GICv3CPUState *cpu;
|
||||
/* List of all ITSes connected to this GIC */
|
||||
GPtrArray *itslist;
|
||||
|
||||
NotifierWithReturn cpr_notifier;
|
||||
};
|
||||
|
||||
#define GICV3_BITMAP_ACCESSORS(BMP) \
|
||||
|
||||
@@ -344,6 +344,8 @@ void tcg_gen_atomic_xchg_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
|
||||
TCGArg, MemOp, TCGType);
|
||||
void tcg_gen_atomic_xchg_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
|
||||
TCGArg, MemOp, TCGType);
|
||||
void tcg_gen_atomic_xchg_i128_chk(TCGv_i128, TCGTemp *, TCGv_i128,
|
||||
TCGArg, MemOp, TCGType);
|
||||
|
||||
void tcg_gen_atomic_fetch_add_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
|
||||
TCGArg, MemOp, TCGType);
|
||||
@@ -411,6 +413,11 @@ void tcg_gen_atomic_umax_fetch_i32_chk(TCGv_i32, TCGTemp *, TCGv_i32,
|
||||
void tcg_gen_atomic_umax_fetch_i64_chk(TCGv_i64, TCGTemp *, TCGv_i64,
|
||||
TCGArg, MemOp, TCGType);
|
||||
|
||||
void tcg_gen_atomic_fetch_and_i128_chk(TCGv_i128, TCGTemp *, TCGv_i128,
|
||||
TCGArg, MemOp, TCGType);
|
||||
void tcg_gen_atomic_fetch_or_i128_chk(TCGv_i128, TCGTemp *, TCGv_i128,
|
||||
TCGArg, MemOp, TCGType);
|
||||
|
||||
/* Vector ops */
|
||||
|
||||
void tcg_gen_mov_vec(TCGv_vec, TCGv_vec);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user