mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-11 03:24:58 -06:00
target-arm queue:
* target/arm: refactoring for compile-twice changes * MAINTAINERS: Add an entry for the Bananapi machine * arm/omap: remove hard coded tabs * rust: pl011: Cut down amount of text quoted from PL011 TRM * target/arm: refactor Arm CPU class hierarchy -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmglwIUZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3sclD/9AgQ5uDlN6gIRupx2PUHAt liFvncSS/1hPHbf4h9A1WgN34EDaF8TuHi8eexSMMlHQpI5yFumd7UIYUDxpRqj4 13gYhBqbnV68S4tWB2g/kCcSNYSLmRQT/b+iwCBtwEJJrDFXlMYFWS50DDS/wxzl sIbcEnixT9PfPh22e01Ib9jCILPzHEVzegMtn5dFl86nLCqQufycNExOvEOXTC9w smCTNHGSIM4TFzKOQ7pNgaAFiqpYenwvPgYElqgGZdwpEB/vmFokXUauQzf2uwVH Nx/361YWi8hQQkG/qEqzcu+J5PwydZssXCO2gEsQVUZMCK/g+naNAiFThMWv/zAu gJ+MWghlSXqAEStLf/+D8w03+I+jChINNxip/F4pgAzbi8mPp/Te+u/G+ra6vD8W AvWzvZwxbTLOlTOYzKsOGF7nq86A20hJBTfpm/Hlbd0ou80YQLO23Dxr4Wmbua5n gbvUad88V5J9KeZUAg4wCyuMGii6X4rezJVL55hE+PIrPRi3q4TXBjk7KG29SkA1 UCbXm8EGiBMCAE04u6dWkcd8003RbgAfrAK0b9VGUEcEXO1O//ivlWJw/TQWf8pn V1UOiXocmXOI5vyy01gjz2iDv8ty/4jSGPzCQ80ijl58Gmm8fmDRxuWPLtDS0lBS QcFEV2oIUjMEEpsCYV07KQ== =MECx -----END PGP SIGNATURE----- Merge tag 'pull-target-arm-20250515' of https://git.linaro.org/people/pmaydell/qemu-arm into staging target-arm queue: * target/arm: refactoring for compile-twice changes * MAINTAINERS: Add an entry for the Bananapi machine * arm/omap: remove hard coded tabs * rust: pl011: Cut down amount of text quoted from PL011 TRM * target/arm: refactor Arm CPU class hierarchy # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmglwIUZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3sclD/9AgQ5uDlN6gIRupx2PUHAt # liFvncSS/1hPHbf4h9A1WgN34EDaF8TuHi8eexSMMlHQpI5yFumd7UIYUDxpRqj4 # 13gYhBqbnV68S4tWB2g/kCcSNYSLmRQT/b+iwCBtwEJJrDFXlMYFWS50DDS/wxzl # sIbcEnixT9PfPh22e01Ib9jCILPzHEVzegMtn5dFl86nLCqQufycNExOvEOXTC9w # smCTNHGSIM4TFzKOQ7pNgaAFiqpYenwvPgYElqgGZdwpEB/vmFokXUauQzf2uwVH # Nx/361YWi8hQQkG/qEqzcu+J5PwydZssXCO2gEsQVUZMCK/g+naNAiFThMWv/zAu # gJ+MWghlSXqAEStLf/+D8w03+I+jChINNxip/F4pgAzbi8mPp/Te+u/G+ra6vD8W # AvWzvZwxbTLOlTOYzKsOGF7nq86A20hJBTfpm/Hlbd0ou80YQLO23Dxr4Wmbua5n # gbvUad88V5J9KeZUAg4wCyuMGii6X4rezJVL55hE+PIrPRi3q4TXBjk7KG29SkA1 # UCbXm8EGiBMCAE04u6dWkcd8003RbgAfrAK0b9VGUEcEXO1O//ivlWJw/TQWf8pn # V1UOiXocmXOI5vyy01gjz2iDv8ty/4jSGPzCQ80ijl58Gmm8fmDRxuWPLtDS0lBS # QcFEV2oIUjMEEpsCYV07KQ== # =MECx # -----END PGP SIGNATURE----- # gpg: Signature made Thu 15 May 2025 06:23:01 EDT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [full] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [full] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [full] # gpg: aka "Peter Maydell <peter@archaic.org.uk>" [unknown] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * tag 'pull-target-arm-20250515' of https://git.linaro.org/people/pmaydell/qemu-arm: (58 commits) target/arm/tcg/vfp_helper: compile file twice (system, user) target/arm/tcg/arith_helper: compile file once target/arm/tcg/tlb-insns: compile file once (system) target/arm/helper: restrict define_tlb_insn_regs to system target target/arm/tcg/tlb_helper: compile file twice (system, user) target/arm/tcg/neon_helper: compile file twice (system, user) target/arm/tcg/iwmmxt_helper: compile file twice (system, user) target/arm/tcg/hflags: compile file twice (system, user) target/arm/tcg/crypto_helper: compile file once target/arm/tcg/vec_internal: use forward declaration for CPUARMState target/arm/machine: compile file once (system) target/arm/kvm-stub: add missing stubs target/arm/machine: move cpu_post_load kvm bits to kvm_arm_cpu_post_load function target/arm/machine: remove TARGET_AARCH64 from migration state target/arm/machine: reduce migration include to avoid target specific definitions target/arm/kvm-stub: compile file once (system) target/arm/meson: accelerator files are not needed in user mode target/arm/ptw: compile file once (system) target/arm/ptw: replace TARGET_AARCH64 by CONFIG_ATOMIC64 from arm_casq_ptw target/arm/ptw: replace target_ulong with int64_t ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
5cb8b0988b
53 changed files with 3033 additions and 3100 deletions
10
MAINTAINERS
10
MAINTAINERS
|
@ -732,6 +732,16 @@ F: include/hw/timer/armv7m_systick.h
|
||||||
F: include/hw/misc/armv7m_ras.h
|
F: include/hw/misc/armv7m_ras.h
|
||||||
F: tests/qtest/test-arm-mptimer.c
|
F: tests/qtest/test-arm-mptimer.c
|
||||||
|
|
||||||
|
Bananapi M2U
|
||||||
|
M: Peter Maydell <peter.maydell@linaro.org>
|
||||||
|
L: qemu-arm@nongnu.org
|
||||||
|
S: Odd Fixes
|
||||||
|
F: docs/system/arm/bananapi_m2u.rst
|
||||||
|
F: hw/*/allwinner-r40*.c
|
||||||
|
F: hw/arm/bananapi_m2u.c
|
||||||
|
F: include/hw/*/allwinner-r40*.h
|
||||||
|
F: tests/functional/test_arm_bpim2u.py
|
||||||
|
|
||||||
B-L475E-IOT01A IoT Node
|
B-L475E-IOT01A IoT Node
|
||||||
M: Samuel Tardieu <sam@rfc1149.net>
|
M: Samuel Tardieu <sam@rfc1149.net>
|
||||||
L: qemu-arm@nongnu.org
|
L: qemu-arm@nongnu.org
|
||||||
|
|
|
@ -234,6 +234,8 @@ bool cpu_exec_realizefn(CPUState *cpu, Error **errp)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gdb_init_cpu(cpu);
|
||||||
|
|
||||||
/* Wait until cpu initialization complete before exposing cpu. */
|
/* Wait until cpu initialization complete before exposing cpu. */
|
||||||
cpu_list_add(cpu);
|
cpu_list_add(cpu);
|
||||||
|
|
||||||
|
@ -304,7 +306,6 @@ static void cpu_common_initfn(Object *obj)
|
||||||
/* cache the cpu class for the hotpath */
|
/* cache the cpu class for the hotpath */
|
||||||
cpu->cc = CPU_GET_CLASS(cpu);
|
cpu->cc = CPU_GET_CLASS(cpu);
|
||||||
|
|
||||||
gdb_init_cpu(cpu);
|
|
||||||
cpu->cpu_index = UNASSIGNED_CPU_INDEX;
|
cpu->cpu_index = UNASSIGNED_CPU_INDEX;
|
||||||
cpu->cluster_index = UNASSIGNED_CLUSTER_INDEX;
|
cpu->cluster_index = UNASSIGNED_CLUSTER_INDEX;
|
||||||
cpu->as = NULL;
|
cpu->as = NULL;
|
||||||
|
|
|
@ -58,6 +58,17 @@
|
||||||
# define dh_ctype_tl target_ulong
|
# define dh_ctype_tl target_ulong
|
||||||
#endif /* COMPILING_PER_TARGET */
|
#endif /* COMPILING_PER_TARGET */
|
||||||
|
|
||||||
|
#if __SIZEOF_POINTER__ == 4
|
||||||
|
# define dh_alias_vaddr i32
|
||||||
|
# define dh_typecode_vaddr dh_typecode_i32
|
||||||
|
#elif __SIZEOF_POINTER__ == 8
|
||||||
|
# define dh_alias_vaddr i64
|
||||||
|
# define dh_typecode_vaddr dh_typecode_i64
|
||||||
|
#else
|
||||||
|
# error "sizeof pointer is different from {4,8}"
|
||||||
|
#endif /* __SIZEOF_POINTER__ */
|
||||||
|
# define dh_ctype_vaddr uintptr_t
|
||||||
|
|
||||||
/* We can't use glue() here because it falls foul of C preprocessor
|
/* We can't use glue() here because it falls foul of C preprocessor
|
||||||
recursive expansion rules. */
|
recursive expansion rules. */
|
||||||
#define dh_retvar_decl0_void void
|
#define dh_retvar_decl0_void void
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "qemu/queue.h"
|
#include "qemu/queue.h"
|
||||||
#include "exec/vaddr.h"
|
#include "exec/vaddr.h"
|
||||||
#include "qom/object.h"
|
#include "qom/object.h"
|
||||||
|
#include "exec/vaddr.h"
|
||||||
|
|
||||||
#ifdef COMPILING_PER_TARGET
|
#ifdef COMPILING_PER_TARGET
|
||||||
# ifdef CONFIG_HVF
|
# ifdef CONFIG_HVF
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
TCGv_i32 tcg_constant_i32(int32_t val);
|
TCGv_i32 tcg_constant_i32(int32_t val);
|
||||||
TCGv_i64 tcg_constant_i64(int64_t val);
|
TCGv_i64 tcg_constant_i64(int64_t val);
|
||||||
|
TCGv_vaddr tcg_constant_vaddr(uintptr_t val);
|
||||||
TCGv_vec tcg_constant_vec(TCGType type, unsigned vece, int64_t val);
|
TCGv_vec tcg_constant_vec(TCGType type, unsigned vece, int64_t val);
|
||||||
TCGv_vec tcg_constant_vec_matching(TCGv_vec match, unsigned vece, int64_t val);
|
TCGv_vec tcg_constant_vec_matching(TCGv_vec match, unsigned vece, int64_t val);
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,7 @@ typedef tcg_target_ulong TCGArg;
|
||||||
* TCGv_i64 : 64 bit integer type
|
* TCGv_i64 : 64 bit integer type
|
||||||
* TCGv_i128 : 128 bit integer type
|
* TCGv_i128 : 128 bit integer type
|
||||||
* TCGv_ptr : a host pointer type
|
* TCGv_ptr : a host pointer type
|
||||||
|
* TCGv_vaddr: an integer type wide enough to hold a target pointer type
|
||||||
* TCGv_vec : a host vector type; the exact size is not exposed
|
* TCGv_vec : a host vector type; the exact size is not exposed
|
||||||
to the CPU front-end code.
|
to the CPU front-end code.
|
||||||
* TCGv : an integer type the same size as target_ulong
|
* TCGv : an integer type the same size as target_ulong
|
||||||
|
@ -217,6 +218,14 @@ typedef struct TCGv_ptr_d *TCGv_ptr;
|
||||||
typedef struct TCGv_vec_d *TCGv_vec;
|
typedef struct TCGv_vec_d *TCGv_vec;
|
||||||
typedef TCGv_ptr TCGv_env;
|
typedef TCGv_ptr TCGv_env;
|
||||||
|
|
||||||
|
#if __SIZEOF_POINTER__ == 4
|
||||||
|
typedef TCGv_i32 TCGv_vaddr;
|
||||||
|
#elif __SIZEOF_POINTER__ == 8
|
||||||
|
typedef TCGv_i64 TCGv_vaddr;
|
||||||
|
#else
|
||||||
|
# error "sizeof pointer is different from {4,8}"
|
||||||
|
#endif /* __SIZEOF_POINTER__ */
|
||||||
|
|
||||||
/* call flags */
|
/* call flags */
|
||||||
/* Helper does not read globals (either directly or through an exception). It
|
/* Helper does not read globals (either directly or through an exception). It
|
||||||
implies TCG_CALL_NO_WRITE_GLOBALS. */
|
implies TCG_CALL_NO_WRITE_GLOBALS. */
|
||||||
|
@ -577,6 +586,11 @@ static inline TCGv_ptr temp_tcgv_ptr(TCGTemp *t)
|
||||||
return (TCGv_ptr)temp_tcgv_i32(t);
|
return (TCGv_ptr)temp_tcgv_i32(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline TCGv_vaddr temp_tcgv_vaddr(TCGTemp *t)
|
||||||
|
{
|
||||||
|
return (TCGv_vaddr)temp_tcgv_i32(t);
|
||||||
|
}
|
||||||
|
|
||||||
static inline TCGv_vec temp_tcgv_vec(TCGTemp *t)
|
static inline TCGv_vec temp_tcgv_vec(TCGTemp *t)
|
||||||
{
|
{
|
||||||
return (TCGv_vec)temp_tcgv_i32(t);
|
return (TCGv_vec)temp_tcgv_i32(t);
|
||||||
|
|
64
meson.build
64
meson.build
|
@ -3709,6 +3709,8 @@ target_arch = {}
|
||||||
target_system_arch = {}
|
target_system_arch = {}
|
||||||
target_user_arch = {}
|
target_user_arch = {}
|
||||||
hw_common_arch = {}
|
hw_common_arch = {}
|
||||||
|
target_common_arch = {}
|
||||||
|
target_common_system_arch = {}
|
||||||
|
|
||||||
# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
|
# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
|
||||||
# that is filled in by qapi/.
|
# that is filled in by qapi/.
|
||||||
|
@ -4107,30 +4109,60 @@ common_all = static_library('common',
|
||||||
|
|
||||||
# construct common libraries per base architecture
|
# construct common libraries per base architecture
|
||||||
hw_common_arch_libs = {}
|
hw_common_arch_libs = {}
|
||||||
|
target_common_arch_libs = {}
|
||||||
|
target_common_system_arch_libs = {}
|
||||||
foreach target : target_dirs
|
foreach target : target_dirs
|
||||||
config_target = config_target_mak[target]
|
config_target = config_target_mak[target]
|
||||||
target_base_arch = config_target['TARGET_BASE_ARCH']
|
target_base_arch = config_target['TARGET_BASE_ARCH']
|
||||||
|
target_inc = [include_directories('target' / target_base_arch)]
|
||||||
|
inc = [common_user_inc + target_inc]
|
||||||
|
|
||||||
# check if already generated
|
# prevent common code to access cpu compile time definition,
|
||||||
if target_base_arch in hw_common_arch_libs
|
# but still allow access to cpu.h
|
||||||
continue
|
target_c_args = ['-DCPU_DEFS_H']
|
||||||
endif
|
target_system_c_args = target_c_args + ['-DCOMPILING_SYSTEM_VS_USER', '-DCONFIG_SOFTMMU']
|
||||||
|
|
||||||
if target_base_arch in hw_common_arch
|
if target_base_arch in hw_common_arch
|
||||||
target_inc = [include_directories('target' / target_base_arch)]
|
if target_base_arch not in hw_common_arch_libs
|
||||||
src = hw_common_arch[target_base_arch]
|
src = hw_common_arch[target_base_arch]
|
||||||
lib = static_library(
|
lib = static_library(
|
||||||
'hw_' + target_base_arch,
|
'hw_' + target_base_arch,
|
||||||
build_by_default: false,
|
build_by_default: false,
|
||||||
sources: src.all_sources() + genh,
|
sources: src.all_sources() + genh,
|
||||||
include_directories: common_user_inc + target_inc,
|
include_directories: inc,
|
||||||
implicit_include_directories: false,
|
c_args: target_system_c_args,
|
||||||
# prevent common code to access cpu compile time
|
|
||||||
# definition, but still allow access to cpu.h
|
|
||||||
c_args: ['-DCPU_DEFS_H', '-DCOMPILING_SYSTEM_VS_USER', '-DCONFIG_SOFTMMU'],
|
|
||||||
dependencies: src.all_dependencies())
|
dependencies: src.all_dependencies())
|
||||||
hw_common_arch_libs += {target_base_arch: lib}
|
hw_common_arch_libs += {target_base_arch: lib}
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if target_base_arch in target_common_arch
|
||||||
|
if target_base_arch not in target_common_arch_libs
|
||||||
|
src = target_common_arch[target_base_arch]
|
||||||
|
lib = static_library(
|
||||||
|
'target_' + target_base_arch,
|
||||||
|
build_by_default: false,
|
||||||
|
sources: src.all_sources() + genh,
|
||||||
|
include_directories: inc,
|
||||||
|
c_args: target_c_args,
|
||||||
|
dependencies: src.all_dependencies())
|
||||||
|
target_common_arch_libs += {target_base_arch: lib}
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if target_base_arch in target_common_system_arch
|
||||||
|
if target_base_arch not in target_common_system_arch_libs
|
||||||
|
src = target_common_system_arch[target_base_arch]
|
||||||
|
lib = static_library(
|
||||||
|
'target_system_' + target_base_arch,
|
||||||
|
build_by_default: false,
|
||||||
|
sources: src.all_sources() + genh,
|
||||||
|
include_directories: inc,
|
||||||
|
c_args: target_system_c_args,
|
||||||
|
dependencies: src.all_dependencies())
|
||||||
|
target_common_system_arch_libs += {target_base_arch: lib}
|
||||||
|
endif
|
||||||
|
endif
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
if have_rust
|
if have_rust
|
||||||
|
@ -4300,12 +4332,24 @@ foreach target : target_dirs
|
||||||
target_common = common_ss.apply(config_target, strict: false)
|
target_common = common_ss.apply(config_target, strict: false)
|
||||||
objects = [common_all.extract_objects(target_common.sources())]
|
objects = [common_all.extract_objects(target_common.sources())]
|
||||||
arch_deps += target_common.dependencies()
|
arch_deps += target_common.dependencies()
|
||||||
|
if target_base_arch in target_common_arch_libs
|
||||||
|
src = target_common_arch[target_base_arch].apply(config_target, strict: false)
|
||||||
|
lib = target_common_arch_libs[target_base_arch]
|
||||||
|
objects += lib.extract_objects(src.sources())
|
||||||
|
arch_deps += src.dependencies()
|
||||||
|
endif
|
||||||
if target_type == 'system' and target_base_arch in hw_common_arch_libs
|
if target_type == 'system' and target_base_arch in hw_common_arch_libs
|
||||||
src = hw_common_arch[target_base_arch].apply(config_target, strict: false)
|
src = hw_common_arch[target_base_arch].apply(config_target, strict: false)
|
||||||
lib = hw_common_arch_libs[target_base_arch]
|
lib = hw_common_arch_libs[target_base_arch]
|
||||||
objects += lib.extract_objects(src.sources())
|
objects += lib.extract_objects(src.sources())
|
||||||
arch_deps += src.dependencies()
|
arch_deps += src.dependencies()
|
||||||
endif
|
endif
|
||||||
|
if target_type == 'system' and target_base_arch in target_common_system_arch_libs
|
||||||
|
src = target_common_system_arch[target_base_arch].apply(config_target, strict: false)
|
||||||
|
lib = target_common_system_arch_libs[target_base_arch]
|
||||||
|
objects += lib.extract_objects(src.sources())
|
||||||
|
arch_deps += src.dependencies()
|
||||||
|
endif
|
||||||
|
|
||||||
target_specific = specific_ss.apply(config_target, strict: false)
|
target_specific = specific_ss.apply(config_target, strict: false)
|
||||||
arch_srcs += target_specific.sources()
|
arch_srcs += target_specific.sources()
|
||||||
|
|
|
@ -5,13 +5,13 @@
|
||||||
//! Device registers exposed as typed structs which are backed by arbitrary
|
//! Device registers exposed as typed structs which are backed by arbitrary
|
||||||
//! integer bitmaps. [`Data`], [`Control`], [`LineControl`], etc.
|
//! integer bitmaps. [`Data`], [`Control`], [`LineControl`], etc.
|
||||||
|
|
||||||
|
// For more detail see the PL011 Technical Reference Manual DDI0183:
|
||||||
|
// https://developer.arm.com/documentation/ddi0183/latest/
|
||||||
|
|
||||||
use bilge::prelude::*;
|
use bilge::prelude::*;
|
||||||
use qemu_api::impl_vmstate_bitsized;
|
use qemu_api::impl_vmstate_bitsized;
|
||||||
|
|
||||||
/// Offset of each register from the base memory address of the device.
|
/// Offset of each register from the base memory address of the device.
|
||||||
///
|
|
||||||
/// # Source
|
|
||||||
/// ARM DDI 0183G, Table 3-1 p.3-3
|
|
||||||
#[doc(alias = "offset")]
|
#[doc(alias = "offset")]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[repr(u64)]
|
#[repr(u64)]
|
||||||
|
@ -87,48 +87,11 @@ pub struct Errors {
|
||||||
_reserved_unpredictable: u4,
|
_reserved_unpredictable: u4,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: FIFO Mode has different semantics
|
|
||||||
/// Data Register, `UARTDR`
|
/// Data Register, `UARTDR`
|
||||||
///
|
///
|
||||||
/// The `UARTDR` register is the data register.
|
/// The `UARTDR` register is the data register; write for TX and
|
||||||
///
|
/// read for RX. It is a 12-bit register, where bits 7..0 are the
|
||||||
/// For words to be transmitted:
|
/// character and bits 11..8 are error bits.
|
||||||
///
|
|
||||||
/// - if the FIFOs are enabled, data written to this location is pushed onto the
|
|
||||||
/// transmit
|
|
||||||
/// FIFO
|
|
||||||
/// - if the FIFOs are not enabled, data is stored in the transmitter holding
|
|
||||||
/// register (the
|
|
||||||
/// bottom word of the transmit FIFO).
|
|
||||||
///
|
|
||||||
/// The write operation initiates transmission from the UART. The data is
|
|
||||||
/// prefixed with a start bit, appended with the appropriate parity bit
|
|
||||||
/// (if parity is enabled), and a stop bit. The resultant word is then
|
|
||||||
/// transmitted.
|
|
||||||
///
|
|
||||||
/// For received words:
|
|
||||||
///
|
|
||||||
/// - if the FIFOs are enabled, the data byte and the 4-bit status (break,
|
|
||||||
/// frame, parity,
|
|
||||||
/// and overrun) is pushed onto the 12-bit wide receive FIFO
|
|
||||||
/// - if the FIFOs are not enabled, the data byte and status are stored in the
|
|
||||||
/// receiving
|
|
||||||
/// holding register (the bottom word of the receive FIFO).
|
|
||||||
///
|
|
||||||
/// The received data byte is read by performing reads from the `UARTDR`
|
|
||||||
/// register along with the corresponding status information. The status
|
|
||||||
/// information can also be read by a read of the `UARTRSR/UARTECR`
|
|
||||||
/// register.
|
|
||||||
///
|
|
||||||
/// # Note
|
|
||||||
///
|
|
||||||
/// You must disable the UART before any of the control registers are
|
|
||||||
/// reprogrammed. When the UART is disabled in the middle of
|
|
||||||
/// transmission or reception, it completes the current character before
|
|
||||||
/// stopping.
|
|
||||||
///
|
|
||||||
/// # Source
|
|
||||||
/// ARM DDI 0183G 3.3.1 Data Register, UARTDR
|
|
||||||
#[bitsize(32)]
|
#[bitsize(32)]
|
||||||
#[derive(Clone, Copy, Default, DebugBits, FromBits)]
|
#[derive(Clone, Copy, Default, DebugBits, FromBits)]
|
||||||
#[doc(alias = "UARTDR")]
|
#[doc(alias = "UARTDR")]
|
||||||
|
@ -144,30 +107,17 @@ impl Data {
|
||||||
pub const BREAK: Self = Self { value: 1 << 10 };
|
pub const BREAK: Self = Self { value: 1 << 10 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: FIFO Mode has different semantics
|
|
||||||
/// Receive Status Register / Error Clear Register, `UARTRSR/UARTECR`
|
/// Receive Status Register / Error Clear Register, `UARTRSR/UARTECR`
|
||||||
///
|
///
|
||||||
/// The UARTRSR/UARTECR register is the receive status register/error clear
|
/// This register provides a different way to read the four receive
|
||||||
/// register. Receive status can also be read from the `UARTRSR`
|
/// status error bits that can be found in bits 11..8 of the UARTDR
|
||||||
/// register. If the status is read from this register, then the status
|
/// on a read. It gets updated when the guest reads UARTDR, and the
|
||||||
/// information for break, framing and parity corresponds to the
|
/// status bits correspond to that character that was just read.
|
||||||
/// data character read from the [Data register](Data), `UARTDR` prior to
|
|
||||||
/// reading the UARTRSR register. The status information for overrun is
|
|
||||||
/// set immediately when an overrun condition occurs.
|
|
||||||
///
|
///
|
||||||
///
|
/// The TRM confusingly describes this offset as UARTRSR for reads
|
||||||
/// # Note
|
/// and UARTECR for writes, but really it's a single error status
|
||||||
/// The received data character must be read first from the [Data
|
/// register where writing anything to the register clears the error
|
||||||
/// Register](Data), `UARTDR` before reading the error status associated
|
/// bits.
|
||||||
/// with that data character from the `UARTRSR` register. This read
|
|
||||||
/// sequence cannot be reversed, because the `UARTRSR` register is
|
|
||||||
/// updated only when a read occurs from the `UARTDR` register. However,
|
|
||||||
/// the status information can also be obtained by reading the `UARTDR`
|
|
||||||
/// register
|
|
||||||
///
|
|
||||||
/// # Source
|
|
||||||
/// ARM DDI 0183G 3.3.2 Receive Status Register/Error Clear Register,
|
|
||||||
/// UARTRSR/UARTECR
|
|
||||||
#[bitsize(32)]
|
#[bitsize(32)]
|
||||||
#[derive(Clone, Copy, DebugBits, FromBits)]
|
#[derive(Clone, Copy, DebugBits, FromBits)]
|
||||||
pub struct ReceiveStatusErrorClear {
|
pub struct ReceiveStatusErrorClear {
|
||||||
|
@ -196,54 +146,29 @@ impl Default for ReceiveStatusErrorClear {
|
||||||
#[bitsize(32)]
|
#[bitsize(32)]
|
||||||
#[derive(Clone, Copy, DebugBits, FromBits)]
|
#[derive(Clone, Copy, DebugBits, FromBits)]
|
||||||
/// Flag Register, `UARTFR`
|
/// Flag Register, `UARTFR`
|
||||||
|
///
|
||||||
|
/// This has the usual inbound RS232 modem-control signals, plus flags
|
||||||
|
/// for RX and TX FIFO fill levels and a BUSY flag.
|
||||||
#[doc(alias = "UARTFR")]
|
#[doc(alias = "UARTFR")]
|
||||||
pub struct Flags {
|
pub struct Flags {
|
||||||
/// CTS Clear to send. This bit is the complement of the UART clear to
|
/// CTS: Clear to send
|
||||||
/// send, `nUARTCTS`, modem status input. That is, the bit is 1
|
|
||||||
/// when `nUARTCTS` is LOW.
|
|
||||||
pub clear_to_send: bool,
|
pub clear_to_send: bool,
|
||||||
/// DSR Data set ready. This bit is the complement of the UART data set
|
/// DSR: Data set ready
|
||||||
/// ready, `nUARTDSR`, modem status input. That is, the bit is 1 when
|
|
||||||
/// `nUARTDSR` is LOW.
|
|
||||||
pub data_set_ready: bool,
|
pub data_set_ready: bool,
|
||||||
/// DCD Data carrier detect. This bit is the complement of the UART data
|
/// DCD: Data carrier detect
|
||||||
/// carrier detect, `nUARTDCD`, modem status input. That is, the bit is
|
|
||||||
/// 1 when `nUARTDCD` is LOW.
|
|
||||||
pub data_carrier_detect: bool,
|
pub data_carrier_detect: bool,
|
||||||
/// BUSY UART busy. If this bit is set to 1, the UART is busy
|
/// BUSY: UART busy. In real hardware, set while the UART is
|
||||||
/// transmitting data. This bit remains set until the complete
|
/// busy transmitting data. QEMU's implementation never sets BUSY.
|
||||||
/// byte, including all the stop bits, has been sent from the
|
|
||||||
/// shift register. This bit is set as soon as the transmit FIFO
|
|
||||||
/// becomes non-empty, regardless of whether the UART is enabled
|
|
||||||
/// or not.
|
|
||||||
pub busy: bool,
|
pub busy: bool,
|
||||||
/// RXFE Receive FIFO empty. The meaning of this bit depends on the
|
/// RXFE: Receive FIFO empty
|
||||||
/// state of the FEN bit in the UARTLCR_H register. If the FIFO
|
|
||||||
/// is disabled, this bit is set when the receive holding
|
|
||||||
/// register is empty. If the FIFO is enabled, the RXFE bit is
|
|
||||||
/// set when the receive FIFO is empty.
|
|
||||||
pub receive_fifo_empty: bool,
|
pub receive_fifo_empty: bool,
|
||||||
/// TXFF Transmit FIFO full. The meaning of this bit depends on the
|
/// TXFF: Transmit FIFO full
|
||||||
/// state of the FEN bit in the UARTLCR_H register. If the FIFO
|
|
||||||
/// is disabled, this bit is set when the transmit holding
|
|
||||||
/// register is full. If the FIFO is enabled, the TXFF bit is
|
|
||||||
/// set when the transmit FIFO is full.
|
|
||||||
pub transmit_fifo_full: bool,
|
pub transmit_fifo_full: bool,
|
||||||
/// RXFF Receive FIFO full. The meaning of this bit depends on the state
|
/// RXFF: Receive FIFO full
|
||||||
/// of the FEN bit in the UARTLCR_H register. If the FIFO is
|
|
||||||
/// disabled, this bit is set when the receive holding register
|
|
||||||
/// is full. If the FIFO is enabled, the RXFF bit is set when
|
|
||||||
/// the receive FIFO is full.
|
|
||||||
pub receive_fifo_full: bool,
|
pub receive_fifo_full: bool,
|
||||||
/// Transmit FIFO empty. The meaning of this bit depends on the state of
|
/// TXFE: Transmit FIFO empty
|
||||||
/// the FEN bit in the [Line Control register](LineControl),
|
|
||||||
/// `UARTLCR_H`. If the FIFO is disabled, this bit is set when the
|
|
||||||
/// transmit holding register is empty. If the FIFO is enabled,
|
|
||||||
/// the TXFE bit is set when the transmit FIFO is empty. This
|
|
||||||
/// bit does not indicate if there is data in the transmit shift
|
|
||||||
/// register.
|
|
||||||
pub transmit_fifo_empty: bool,
|
pub transmit_fifo_empty: bool,
|
||||||
/// `RI`, is `true` when `nUARTRI` is `LOW`.
|
/// RI: Ring indicator
|
||||||
pub ring_indicator: bool,
|
pub ring_indicator: bool,
|
||||||
_reserved_zero_no_modify: u23,
|
_reserved_zero_no_modify: u23,
|
||||||
}
|
}
|
||||||
|
@ -270,54 +195,23 @@ impl Default for Flags {
|
||||||
/// Line Control Register, `UARTLCR_H`
|
/// Line Control Register, `UARTLCR_H`
|
||||||
#[doc(alias = "UARTLCR_H")]
|
#[doc(alias = "UARTLCR_H")]
|
||||||
pub struct LineControl {
|
pub struct LineControl {
|
||||||
/// BRK Send break.
|
/// BRK: Send break
|
||||||
///
|
|
||||||
/// If this bit is set to `1`, a low-level is continually output on the
|
|
||||||
/// `UARTTXD` output, after completing transmission of the
|
|
||||||
/// current character. For the proper execution of the break command,
|
|
||||||
/// the software must set this bit for at least two complete
|
|
||||||
/// frames. For normal use, this bit must be cleared to `0`.
|
|
||||||
pub send_break: bool,
|
pub send_break: bool,
|
||||||
/// 1 PEN Parity enable:
|
/// PEN: Parity enable
|
||||||
///
|
|
||||||
/// - 0 = parity is disabled and no parity bit added to the data frame
|
|
||||||
/// - 1 = parity checking and generation is enabled.
|
|
||||||
///
|
|
||||||
/// See Table 3-11 on page 3-14 for the parity truth table.
|
|
||||||
pub parity_enabled: bool,
|
pub parity_enabled: bool,
|
||||||
/// EPS Even parity select. Controls the type of parity the UART uses
|
/// EPS: Even parity select
|
||||||
/// during transmission and reception:
|
|
||||||
/// - 0 = odd parity. The UART generates or checks for an odd number of 1s
|
|
||||||
/// in the data and parity bits.
|
|
||||||
/// - 1 = even parity. The UART generates or checks for an even number of 1s
|
|
||||||
/// in the data and parity bits.
|
|
||||||
/// This bit has no effect when the `PEN` bit disables parity checking
|
|
||||||
/// and generation. See Table 3-11 on page 3-14 for the parity
|
|
||||||
/// truth table.
|
|
||||||
pub parity: Parity,
|
pub parity: Parity,
|
||||||
/// 3 STP2 Two stop bits select. If this bit is set to 1, two stop bits
|
/// STP2: Two stop bits select
|
||||||
/// are transmitted at the end of the frame. The receive
|
|
||||||
/// logic does not check for two stop bits being received.
|
|
||||||
pub two_stops_bits: bool,
|
pub two_stops_bits: bool,
|
||||||
/// FEN Enable FIFOs:
|
/// FEN: Enable FIFOs
|
||||||
/// 0 = FIFOs are disabled (character mode) that is, the FIFOs become
|
|
||||||
/// 1-byte-deep holding registers 1 = transmit and receive FIFO
|
|
||||||
/// buffers are enabled (FIFO mode).
|
|
||||||
pub fifos_enabled: Mode,
|
pub fifos_enabled: Mode,
|
||||||
/// WLEN Word length. These bits indicate the number of data bits
|
/// WLEN: Word length in bits
|
||||||
/// transmitted or received in a frame as follows: b11 = 8 bits
|
/// b11 = 8 bits
|
||||||
/// b10 = 7 bits
|
/// b10 = 7 bits
|
||||||
/// b01 = 6 bits
|
/// b01 = 6 bits
|
||||||
/// b00 = 5 bits.
|
/// b00 = 5 bits.
|
||||||
pub word_length: WordLength,
|
pub word_length: WordLength,
|
||||||
/// 7 SPS Stick parity select.
|
/// SPS Stick parity select
|
||||||
/// 0 = stick parity is disabled
|
|
||||||
/// 1 = either:
|
|
||||||
/// • if the EPS bit is 0 then the parity bit is transmitted and checked
|
|
||||||
/// as a 1 • if the EPS bit is 1 then the parity bit is
|
|
||||||
/// transmitted and checked as a 0. This bit has no effect when
|
|
||||||
/// the PEN bit disables parity checking and generation. See Table 3-11
|
|
||||||
/// on page 3-14 for the parity truth table.
|
|
||||||
pub sticky_parity: bool,
|
pub sticky_parity: bool,
|
||||||
/// 31:8 - Reserved, do not modify, read as zero.
|
/// 31:8 - Reserved, do not modify, read as zero.
|
||||||
_reserved_zero_no_modify: u24,
|
_reserved_zero_no_modify: u24,
|
||||||
|
@ -342,11 +236,7 @@ impl Default for LineControl {
|
||||||
/// `EPS` "Even parity select", field of [Line Control
|
/// `EPS` "Even parity select", field of [Line Control
|
||||||
/// register](LineControl).
|
/// register](LineControl).
|
||||||
pub enum Parity {
|
pub enum Parity {
|
||||||
/// - 0 = odd parity. The UART generates or checks for an odd number of 1s
|
|
||||||
/// in the data and parity bits.
|
|
||||||
Odd = 0,
|
Odd = 0,
|
||||||
/// - 1 = even parity. The UART generates or checks for an even number of 1s
|
|
||||||
/// in the data and parity bits.
|
|
||||||
Even = 1,
|
Even = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,88 +271,39 @@ pub enum WordLength {
|
||||||
|
|
||||||
/// Control Register, `UARTCR`
|
/// Control Register, `UARTCR`
|
||||||
///
|
///
|
||||||
/// The `UARTCR` register is the control register. All the bits are cleared
|
/// The `UARTCR` register is the control register. It contains various
|
||||||
/// to `0` on reset except for bits `9` and `8` that are set to `1`.
|
/// enable bits, and the bits to write to set the usual outbound RS232
|
||||||
///
|
/// modem control signals. All bits reset to 0 except TXE and RXE.
|
||||||
/// # Source
|
|
||||||
/// ARM DDI 0183G, 3.3.8 Control Register, `UARTCR`, Table 3-12
|
|
||||||
#[bitsize(32)]
|
#[bitsize(32)]
|
||||||
#[doc(alias = "UARTCR")]
|
#[doc(alias = "UARTCR")]
|
||||||
#[derive(Clone, Copy, DebugBits, FromBits)]
|
#[derive(Clone, Copy, DebugBits, FromBits)]
|
||||||
pub struct Control {
|
pub struct Control {
|
||||||
/// `UARTEN` UART enable: 0 = UART is disabled. If the UART is disabled
|
/// `UARTEN` UART enable: 0 = UART is disabled.
|
||||||
/// in the middle of transmission or reception, it completes the current
|
|
||||||
/// character before stopping. 1 = the UART is enabled. Data
|
|
||||||
/// transmission and reception occurs for either UART signals or SIR
|
|
||||||
/// signals depending on the setting of the SIREN bit.
|
|
||||||
pub enable_uart: bool,
|
pub enable_uart: bool,
|
||||||
/// `SIREN` `SIR` enable: 0 = IrDA SIR ENDEC is disabled. `nSIROUT`
|
/// `SIREN` `SIR` enable: disable or enable IrDA SIR ENDEC.
|
||||||
/// remains LOW (no light pulse generated), and signal transitions on
|
/// QEMU does not model this.
|
||||||
/// SIRIN have no effect. 1 = IrDA SIR ENDEC is enabled. Data is
|
|
||||||
/// transmitted and received on nSIROUT and SIRIN. UARTTXD remains HIGH,
|
|
||||||
/// in the marking state. Signal transitions on UARTRXD or modem status
|
|
||||||
/// inputs have no effect. This bit has no effect if the UARTEN bit
|
|
||||||
/// disables the UART.
|
|
||||||
pub enable_sir: bool,
|
pub enable_sir: bool,
|
||||||
/// `SIRLP` SIR low-power IrDA mode. This bit selects the IrDA encoding
|
/// `SIRLP` SIR low-power IrDA mode. QEMU does not model this.
|
||||||
/// mode. If this bit is cleared to 0, low-level bits are transmitted as
|
|
||||||
/// an active high pulse with a width of 3/ 16th of the bit period. If
|
|
||||||
/// this bit is set to 1, low-level bits are transmitted with a pulse
|
|
||||||
/// width that is 3 times the period of the IrLPBaud16 input signal,
|
|
||||||
/// regardless of the selected bit rate. Setting this bit uses less
|
|
||||||
/// power, but might reduce transmission distances.
|
|
||||||
pub sir_lowpower_irda_mode: u1,
|
pub sir_lowpower_irda_mode: u1,
|
||||||
/// Reserved, do not modify, read as zero.
|
/// Reserved, do not modify, read as zero.
|
||||||
_reserved_zero_no_modify: u4,
|
_reserved_zero_no_modify: u4,
|
||||||
/// `LBE` Loopback enable. If this bit is set to 1 and the SIREN bit is
|
/// `LBE` Loopback enable: feed UART output back to the input
|
||||||
/// set to 1 and the SIRTEST bit in the Test Control register, UARTTCR
|
|
||||||
/// on page 4-5 is set to 1, then the nSIROUT path is inverted, and fed
|
|
||||||
/// through to the SIRIN path. The SIRTEST bit in the test register must
|
|
||||||
/// be set to 1 to override the normal half-duplex SIR operation. This
|
|
||||||
/// must be the requirement for accessing the test registers during
|
|
||||||
/// normal operation, and SIRTEST must be cleared to 0 when loopback
|
|
||||||
/// testing is finished. This feature reduces the amount of external
|
|
||||||
/// coupling required during system test. If this bit is set to 1, and
|
|
||||||
/// the SIRTEST bit is set to 0, the UARTTXD path is fed through to the
|
|
||||||
/// UARTRXD path. In either SIR mode or UART mode, when this bit is set,
|
|
||||||
/// the modem outputs are also fed through to the modem inputs. This bit
|
|
||||||
/// is cleared to 0 on reset, to disable loopback.
|
|
||||||
pub enable_loopback: bool,
|
pub enable_loopback: bool,
|
||||||
/// `TXE` Transmit enable. If this bit is set to 1, the transmit section
|
/// `TXE` Transmit enable
|
||||||
/// of the UART is enabled. Data transmission occurs for either UART
|
|
||||||
/// signals, or SIR signals depending on the setting of the SIREN bit.
|
|
||||||
/// When the UART is disabled in the middle of transmission, it
|
|
||||||
/// completes the current character before stopping.
|
|
||||||
pub enable_transmit: bool,
|
pub enable_transmit: bool,
|
||||||
/// `RXE` Receive enable. If this bit is set to 1, the receive section
|
/// `RXE` Receive enable
|
||||||
/// of the UART is enabled. Data reception occurs for either UART
|
|
||||||
/// signals or SIR signals depending on the setting of the SIREN bit.
|
|
||||||
/// When the UART is disabled in the middle of reception, it completes
|
|
||||||
/// the current character before stopping.
|
|
||||||
pub enable_receive: bool,
|
pub enable_receive: bool,
|
||||||
/// `DTR` Data transmit ready. This bit is the complement of the UART
|
/// `DTR` Data transmit ready
|
||||||
/// data transmit ready, `nUARTDTR`, modem status output. That is, when
|
|
||||||
/// the bit is programmed to a 1 then `nUARTDTR` is LOW.
|
|
||||||
pub data_transmit_ready: bool,
|
pub data_transmit_ready: bool,
|
||||||
/// `RTS` Request to send. This bit is the complement of the UART
|
/// `RTS` Request to send
|
||||||
/// request to send, `nUARTRTS`, modem status output. That is, when the
|
|
||||||
/// bit is programmed to a 1 then `nUARTRTS` is LOW.
|
|
||||||
pub request_to_send: bool,
|
pub request_to_send: bool,
|
||||||
/// `Out1` This bit is the complement of the UART Out1 (`nUARTOut1`)
|
/// `Out1` UART Out1 signal; can be used as DCD
|
||||||
/// modem status output. That is, when the bit is programmed to a 1 the
|
|
||||||
/// output is 0. For DTE this can be used as Data Carrier Detect (DCD).
|
|
||||||
pub out_1: bool,
|
pub out_1: bool,
|
||||||
/// `Out2` This bit is the complement of the UART Out2 (`nUARTOut2`)
|
/// `Out2` UART Out2 signal; can be used as RI
|
||||||
/// modem status output. That is, when the bit is programmed to a 1, the
|
|
||||||
/// output is 0. For DTE this can be used as Ring Indicator (RI).
|
|
||||||
pub out_2: bool,
|
pub out_2: bool,
|
||||||
/// `RTSEn` RTS hardware flow control enable. If this bit is set to 1,
|
/// `RTSEn` RTS hardware flow control enable
|
||||||
/// RTS hardware flow control is enabled. Data is only requested when
|
|
||||||
/// there is space in the receive FIFO for it to be received.
|
|
||||||
pub rts_hardware_flow_control_enable: bool,
|
pub rts_hardware_flow_control_enable: bool,
|
||||||
/// `CTSEn` CTS hardware flow control enable. If this bit is set to 1,
|
/// `CTSEn` CTS hardware flow control enable
|
||||||
/// CTS hardware flow control is enabled. Data is only transmitted when
|
|
||||||
/// the `nUARTCTS` signal is asserted.
|
|
||||||
pub cts_hardware_flow_control_enable: bool,
|
pub cts_hardware_flow_control_enable: bool,
|
||||||
/// 31:16 - Reserved, do not modify, read as zero.
|
/// 31:16 - Reserved, do not modify, read as zero.
|
||||||
_reserved_zero_no_modify2: u16,
|
_reserved_zero_no_modify2: u16,
|
||||||
|
|
|
@ -143,7 +143,6 @@ static int aarch64_write_elf64_prfpreg(WriteCoreDumpFunction f,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
static off_t sve_zreg_offset(uint32_t vq, int n)
|
static off_t sve_zreg_offset(uint32_t vq, int n)
|
||||||
{
|
{
|
||||||
off_t off = sizeof(struct aarch64_user_sve_header);
|
off_t off = sizeof(struct aarch64_user_sve_header);
|
||||||
|
@ -231,7 +230,6 @@ static int aarch64_write_elf64_sve(WriteCoreDumpFunction f,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
int cpuid, DumpState *s)
|
int cpuid, DumpState *s)
|
||||||
|
@ -273,11 +271,9 @@ int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
if (cpu_isar_feature(aa64_sve, cpu)) {
|
if (cpu_isar_feature(aa64_sve, cpu)) {
|
||||||
ret = aarch64_write_elf64_sve(f, env, cpuid, s);
|
ret = aarch64_write_elf64_sve(f, env, cpuid, s);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -451,11 +447,9 @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
|
||||||
if (class == ELFCLASS64) {
|
if (class == ELFCLASS64) {
|
||||||
note_size = AARCH64_PRSTATUS_NOTE_SIZE;
|
note_size = AARCH64_PRSTATUS_NOTE_SIZE;
|
||||||
note_size += AARCH64_PRFPREG_NOTE_SIZE;
|
note_size += AARCH64_PRFPREG_NOTE_SIZE;
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
if (cpu_isar_feature(aa64_sve, cpu)) {
|
if (cpu_isar_feature(aa64_sve, cpu)) {
|
||||||
note_size += AARCH64_SVE_NOTE_SIZE(&cpu->env);
|
note_size += AARCH64_SVE_NOTE_SIZE(&cpu->env);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
note_size = ARM_PRSTATUS_NOTE_SIZE;
|
note_size = ARM_PRSTATUS_NOTE_SIZE;
|
||||||
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
|
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
|
||||||
|
|
|
@ -28,11 +28,6 @@ OBJECT_DECLARE_CPU_TYPE(ARMCPU, ARMCPUClass, ARM_CPU)
|
||||||
|
|
||||||
#define TYPE_ARM_MAX_CPU "max-" TYPE_ARM_CPU
|
#define TYPE_ARM_MAX_CPU "max-" TYPE_ARM_CPU
|
||||||
|
|
||||||
#define TYPE_AARCH64_CPU "aarch64-cpu"
|
|
||||||
typedef struct AArch64CPUClass AArch64CPUClass;
|
|
||||||
DECLARE_CLASS_CHECKERS(AArch64CPUClass, AARCH64_CPU,
|
|
||||||
TYPE_AARCH64_CPU)
|
|
||||||
|
|
||||||
#define ARM_CPU_TYPE_SUFFIX "-" TYPE_ARM_CPU
|
#define ARM_CPU_TYPE_SUFFIX "-" TYPE_ARM_CPU
|
||||||
#define ARM_CPU_TYPE_NAME(name) (name ARM_CPU_TYPE_SUFFIX)
|
#define ARM_CPU_TYPE_NAME(name) (name ARM_CPU_TYPE_SUFFIX)
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "qemu/timer.h"
|
#include "qemu/timer.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
#include "exec/page-vary.h"
|
#include "exec/page-vary.h"
|
||||||
|
#include "exec/tswap.h"
|
||||||
#include "target/arm/idau.h"
|
#include "target/arm/idau.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
@ -1098,37 +1099,6 @@ static void arm_cpu_set_irq(void *opaque, int irq, int level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_KVM
|
|
||||||
ARMCPU *cpu = opaque;
|
|
||||||
CPUARMState *env = &cpu->env;
|
|
||||||
CPUState *cs = CPU(cpu);
|
|
||||||
uint32_t linestate_bit;
|
|
||||||
int irq_id;
|
|
||||||
|
|
||||||
switch (irq) {
|
|
||||||
case ARM_CPU_IRQ:
|
|
||||||
irq_id = KVM_ARM_IRQ_CPU_IRQ;
|
|
||||||
linestate_bit = CPU_INTERRUPT_HARD;
|
|
||||||
break;
|
|
||||||
case ARM_CPU_FIQ:
|
|
||||||
irq_id = KVM_ARM_IRQ_CPU_FIQ;
|
|
||||||
linestate_bit = CPU_INTERRUPT_FIQ;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (level) {
|
|
||||||
env->irq_line_state |= linestate_bit;
|
|
||||||
} else {
|
|
||||||
env->irq_line_state &= ~linestate_bit;
|
|
||||||
}
|
|
||||||
kvm_arm_set_irq(cs->cpu_index, KVM_ARM_IRQ_TYPE_CPU, irq_id, !!level);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool arm_cpu_virtio_is_big_endian(CPUState *cs)
|
static bool arm_cpu_virtio_is_big_endian(CPUState *cs)
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = ARM_CPU(cs);
|
ARMCPU *cpu = ARM_CPU(cs);
|
||||||
|
@ -1202,7 +1172,7 @@ static void arm_disas_set_info(CPUState *cpu, disassemble_info *info)
|
||||||
|
|
||||||
info->endian = BFD_ENDIAN_LITTLE;
|
info->endian = BFD_ENDIAN_LITTLE;
|
||||||
if (bswap_code(sctlr_b)) {
|
if (bswap_code(sctlr_b)) {
|
||||||
info->endian = TARGET_BIG_ENDIAN ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
|
info->endian = target_big_endian() ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
|
||||||
}
|
}
|
||||||
info->flags &= ~INSN_ARM_BE32;
|
info->flags &= ~INSN_ARM_BE32;
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
@ -1212,8 +1182,6 @@ static void arm_disas_set_info(CPUState *cpu, disassemble_info *info)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
|
|
||||||
static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = ARM_CPU(cs);
|
ARMCPU *cpu = ARM_CPU(cs);
|
||||||
|
@ -1371,15 +1339,6 @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
static inline void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
|
||||||
{
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
static void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = ARM_CPU(cs);
|
ARMCPU *cpu = ARM_CPU(cs);
|
||||||
|
@ -1609,6 +1568,35 @@ static void arm_set_pmu(Object *obj, bool value, Error **errp)
|
||||||
cpu->has_pmu = value;
|
cpu->has_pmu = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool aarch64_cpu_get_aarch64(Object *obj, Error **errp)
|
||||||
|
{
|
||||||
|
ARMCPU *cpu = ARM_CPU(obj);
|
||||||
|
|
||||||
|
return arm_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aarch64_cpu_set_aarch64(Object *obj, bool value, Error **errp)
|
||||||
|
{
|
||||||
|
ARMCPU *cpu = ARM_CPU(obj);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this time, this property is only allowed if KVM is enabled. This
|
||||||
|
* restriction allows us to avoid fixing up functionality that assumes a
|
||||||
|
* uniform execution state like do_interrupt.
|
||||||
|
*/
|
||||||
|
if (value == false) {
|
||||||
|
if (!kvm_enabled() || !kvm_arm_aarch32_supported()) {
|
||||||
|
error_setg(errp, "'aarch64' feature cannot be disabled "
|
||||||
|
"unless KVM is enabled and 32-bit EL1 "
|
||||||
|
"is supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unset_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||||
|
} else {
|
||||||
|
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
|
unsigned int gt_cntfrq_period_ns(ARMCPU *cpu)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -1736,6 +1724,13 @@ void arm_cpu_post_init(Object *obj)
|
||||||
*/
|
*/
|
||||||
arm_cpu_propagate_feature_implications(cpu);
|
arm_cpu_propagate_feature_implications(cpu);
|
||||||
|
|
||||||
|
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
|
||||||
|
object_property_add_bool(obj, "aarch64", aarch64_cpu_get_aarch64,
|
||||||
|
aarch64_cpu_set_aarch64);
|
||||||
|
object_property_set_description(obj, "aarch64",
|
||||||
|
"Set on/off to enable/disable aarch64 "
|
||||||
|
"execution state ");
|
||||||
|
}
|
||||||
if (arm_feature(&cpu->env, ARM_FEATURE_CBAR) ||
|
if (arm_feature(&cpu->env, ARM_FEATURE_CBAR) ||
|
||||||
arm_feature(&cpu->env, ARM_FEATURE_CBAR_RO)) {
|
arm_feature(&cpu->env, ARM_FEATURE_CBAR_RO)) {
|
||||||
qdev_property_add_static(DEVICE(obj), &arm_cpu_reset_cbar_property);
|
qdev_property_add_static(DEVICE(obj), &arm_cpu_reset_cbar_property);
|
||||||
|
@ -1918,7 +1913,6 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp)
|
||||||
{
|
{
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
|
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
|
||||||
arm_cpu_sve_finalize(cpu, &local_err);
|
arm_cpu_sve_finalize(cpu, &local_err);
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
|
@ -1954,7 +1948,6 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (kvm_enabled()) {
|
if (kvm_enabled()) {
|
||||||
kvm_arm_steal_time_finalize(cpu, &local_err);
|
kvm_arm_steal_time_finalize(cpu, &local_err);
|
||||||
|
|
|
@ -1138,10 +1138,6 @@ struct ARMCPUClass {
|
||||||
ResettablePhases parent_phases;
|
ResettablePhases parent_phases;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AArch64CPUClass {
|
|
||||||
ARMCPUClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Callback functions for the generic timer's timers. */
|
/* Callback functions for the generic timer's timers. */
|
||||||
void arm_gt_ptimer_cb(void *opaque);
|
void arm_gt_ptimer_cb(void *opaque);
|
||||||
void arm_gt_vtimer_cb(void *opaque);
|
void arm_gt_vtimer_cb(void *opaque);
|
||||||
|
|
26
target/arm/cpu32-stubs.c
Normal file
26
target/arm/cpu32-stubs.c
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "target/arm/cpu.h"
|
||||||
|
#include "target/arm/internals.h"
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
|
@ -781,92 +781,12 @@ static const ARMCPUInfo aarch64_cpus[] = {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool aarch64_cpu_get_aarch64(Object *obj, Error **errp)
|
|
||||||
{
|
|
||||||
ARMCPU *cpu = ARM_CPU(obj);
|
|
||||||
|
|
||||||
return arm_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void aarch64_cpu_set_aarch64(Object *obj, bool value, Error **errp)
|
|
||||||
{
|
|
||||||
ARMCPU *cpu = ARM_CPU(obj);
|
|
||||||
|
|
||||||
/* At this time, this property is only allowed if KVM is enabled. This
|
|
||||||
* restriction allows us to avoid fixing up functionality that assumes a
|
|
||||||
* uniform execution state like do_interrupt.
|
|
||||||
*/
|
|
||||||
if (value == false) {
|
|
||||||
if (!kvm_enabled() || !kvm_arm_aarch32_supported()) {
|
|
||||||
error_setg(errp, "'aarch64' feature cannot be disabled "
|
|
||||||
"unless KVM is enabled and 32-bit EL1 "
|
|
||||||
"is supported");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
unset_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
|
||||||
} else {
|
|
||||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void aarch64_cpu_finalizefn(Object *obj)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void aarch64_cpu_class_init(ObjectClass *oc, const void *data)
|
|
||||||
{
|
|
||||||
object_class_property_add_bool(oc, "aarch64", aarch64_cpu_get_aarch64,
|
|
||||||
aarch64_cpu_set_aarch64);
|
|
||||||
object_class_property_set_description(oc, "aarch64",
|
|
||||||
"Set on/off to enable/disable aarch64 "
|
|
||||||
"execution state ");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void aarch64_cpu_instance_init(Object *obj)
|
|
||||||
{
|
|
||||||
ARMCPUClass *acc = ARM_CPU_GET_CLASS(obj);
|
|
||||||
|
|
||||||
acc->info->initfn(obj);
|
|
||||||
arm_cpu_post_init(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cpu_register_class_init(ObjectClass *oc, const void *data)
|
|
||||||
{
|
|
||||||
ARMCPUClass *acc = ARM_CPU_CLASS(oc);
|
|
||||||
|
|
||||||
acc->info = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void aarch64_cpu_register(const ARMCPUInfo *info)
|
|
||||||
{
|
|
||||||
TypeInfo type_info = {
|
|
||||||
.parent = TYPE_AARCH64_CPU,
|
|
||||||
.instance_init = aarch64_cpu_instance_init,
|
|
||||||
.class_init = info->class_init ?: cpu_register_class_init,
|
|
||||||
.class_data = info,
|
|
||||||
};
|
|
||||||
|
|
||||||
type_info.name = g_strdup_printf("%s-" TYPE_ARM_CPU, info->name);
|
|
||||||
type_register_static(&type_info);
|
|
||||||
g_free((void *)type_info.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const TypeInfo aarch64_cpu_type_info = {
|
|
||||||
.name = TYPE_AARCH64_CPU,
|
|
||||||
.parent = TYPE_ARM_CPU,
|
|
||||||
.instance_finalize = aarch64_cpu_finalizefn,
|
|
||||||
.abstract = true,
|
|
||||||
.class_init = aarch64_cpu_class_init,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void aarch64_cpu_register_types(void)
|
static void aarch64_cpu_register_types(void)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
type_register_static(&aarch64_cpu_type_info);
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(aarch64_cpus); ++i) {
|
for (i = 0; i < ARRAY_SIZE(aarch64_cpus); ++i) {
|
||||||
aarch64_cpu_register(&aarch64_cpus[i]);
|
arm_cpu_register(&aarch64_cpus[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,12 @@
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
#include "cpu-features.h"
|
#include "cpu-features.h"
|
||||||
#include "cpregs.h"
|
#include "cpregs.h"
|
||||||
#include "exec/helper-proto.h"
|
|
||||||
#include "exec/watchpoint.h"
|
#include "exec/watchpoint.h"
|
||||||
#include "system/tcg.h"
|
#include "system/tcg.h"
|
||||||
|
|
||||||
|
#define HELPER_H "tcg/helper.h"
|
||||||
|
#include "exec/helper-proto.h.inc"
|
||||||
|
|
||||||
#ifdef CONFIG_TCG
|
#ifdef CONFIG_TCG
|
||||||
/* Return the Exception Level targeted by debug exceptions. */
|
/* Return the Exception Level targeted by debug exceptions. */
|
||||||
static int arm_debug_target_el(CPUARMState *env)
|
static int arm_debug_target_el(CPUARMState *env)
|
||||||
|
@ -378,7 +380,7 @@ bool arm_debug_check_breakpoint(CPUState *cs)
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = ARM_CPU(cs);
|
ARMCPU *cpu = ARM_CPU(cs);
|
||||||
CPUARMState *env = &cpu->env;
|
CPUARMState *env = &cpu->env;
|
||||||
target_ulong pc;
|
vaddr pc;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
#include "cpu-features.h"
|
#include "cpu-features.h"
|
||||||
#include "exec/helper-proto.h"
|
|
||||||
#include "exec/page-protection.h"
|
#include "exec/page-protection.h"
|
||||||
#include "exec/mmap-lock.h"
|
#include "exec/mmap-lock.h"
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
|
@ -30,11 +29,15 @@
|
||||||
#include "qemu/guest-random.h"
|
#include "qemu/guest-random.h"
|
||||||
#ifdef CONFIG_TCG
|
#ifdef CONFIG_TCG
|
||||||
#include "accel/tcg/probe.h"
|
#include "accel/tcg/probe.h"
|
||||||
|
#include "accel/tcg/getpc.h"
|
||||||
#include "semihosting/common-semi.h"
|
#include "semihosting/common-semi.h"
|
||||||
#endif
|
#endif
|
||||||
#include "cpregs.h"
|
#include "cpregs.h"
|
||||||
#include "target/arm/gtimer.h"
|
#include "target/arm/gtimer.h"
|
||||||
|
|
||||||
|
#define HELPER_H "tcg/helper.h"
|
||||||
|
#include "exec/helper-proto.h.inc"
|
||||||
|
|
||||||
#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
|
#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
|
||||||
|
|
||||||
static void switch_mode(CPUARMState *env, int mode);
|
static void switch_mode(CPUARMState *env, int mode);
|
||||||
|
@ -6563,9 +6566,7 @@ static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
*/
|
*/
|
||||||
new_len = sve_vqm1_for_el(env, cur_el);
|
new_len = sve_vqm1_for_el(env, cur_el);
|
||||||
if (new_len < old_len) {
|
if (new_len < old_len) {
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
aarch64_sve_narrow_vq(env, new_len + 1);
|
aarch64_sve_narrow_vq(env, new_len + 1);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6588,7 +6589,6 @@ static const ARMCPRegInfo zcr_reginfo[] = {
|
||||||
.writefn = zcr_write, .raw_writefn = raw_write },
|
.writefn = zcr_write, .raw_writefn = raw_write },
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
static CPAccessResult access_tpidr2(CPUARMState *env, const ARMCPRegInfo *ri,
|
static CPAccessResult access_tpidr2(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
bool isread)
|
bool isread)
|
||||||
{
|
{
|
||||||
|
@ -6822,7 +6822,6 @@ static const ARMCPRegInfo nmi_reginfo[] = {
|
||||||
.writefn = aa64_allint_write, .readfn = aa64_allint_read,
|
.writefn = aa64_allint_write, .readfn = aa64_allint_read,
|
||||||
.resetfn = arm_cp_reset_ignore },
|
.resetfn = arm_cp_reset_ignore },
|
||||||
};
|
};
|
||||||
#endif /* TARGET_AARCH64 */
|
|
||||||
|
|
||||||
static void define_pmu_regs(ARMCPU *cpu)
|
static void define_pmu_regs(ARMCPU *cpu)
|
||||||
{
|
{
|
||||||
|
@ -7014,7 +7013,6 @@ static const ARMCPRegInfo lor_reginfo[] = {
|
||||||
.type = ARM_CP_CONST, .resetvalue = 0 },
|
.type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
static CPAccessResult access_pauth(CPUARMState *env, const ARMCPRegInfo *ri,
|
static CPAccessResult access_pauth(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
bool isread)
|
bool isread)
|
||||||
{
|
{
|
||||||
|
@ -7507,8 +7505,6 @@ static const ARMCPRegInfo nv2_reginfo[] = {
|
||||||
.fieldoffset = offsetof(CPUARMState, cp15.vncr_el2) },
|
.fieldoffset = offsetof(CPUARMState, cp15.vncr_el2) },
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* TARGET_AARCH64 */
|
|
||||||
|
|
||||||
static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo *ri,
|
static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
bool isread)
|
bool isread)
|
||||||
{
|
{
|
||||||
|
@ -7768,7 +7764,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||||
define_arm_cp_regs(cpu, not_v8_cp_reginfo);
|
define_arm_cp_regs(cpu, not_v8_cp_reginfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
define_tlb_insn_regs(cpu);
|
define_tlb_insn_regs(cpu);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (arm_feature(env, ARM_FEATURE_V6)) {
|
if (arm_feature(env, ARM_FEATURE_V6)) {
|
||||||
/* The ID registers all have impdef reset values */
|
/* The ID registers all have impdef reset values */
|
||||||
|
@ -8949,7 +8947,6 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||||
define_one_arm_cp_reg(cpu, &hcrx_el2_reginfo);
|
define_one_arm_cp_reg(cpu, &hcrx_el2_reginfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
if (cpu_isar_feature(aa64_sme, cpu)) {
|
if (cpu_isar_feature(aa64_sme, cpu)) {
|
||||||
define_arm_cp_regs(cpu, sme_reginfo);
|
define_arm_cp_regs(cpu, sme_reginfo);
|
||||||
}
|
}
|
||||||
|
@ -9010,7 +9007,6 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||||
if (cpu_isar_feature(aa64_nmi, cpu)) {
|
if (cpu_isar_feature(aa64_nmi, cpu)) {
|
||||||
define_arm_cp_regs(cpu, nmi_reginfo);
|
define_arm_cp_regs(cpu, nmi_reginfo);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (cpu_isar_feature(any_predinv, cpu)) {
|
if (cpu_isar_feature(any_predinv, cpu)) {
|
||||||
define_arm_cp_regs(cpu, predinv_reginfo);
|
define_arm_cp_regs(cpu, predinv_reginfo);
|
||||||
|
@ -10619,7 +10615,7 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
|
||||||
ARMCPU *cpu = ARM_CPU(cs);
|
ARMCPU *cpu = ARM_CPU(cs);
|
||||||
CPUARMState *env = &cpu->env;
|
CPUARMState *env = &cpu->env;
|
||||||
unsigned int new_el = env->exception.target_el;
|
unsigned int new_el = env->exception.target_el;
|
||||||
target_ulong addr = env->cp15.vbar_el[new_el];
|
vaddr addr = env->cp15.vbar_el[new_el];
|
||||||
unsigned int new_mode = aarch64_pstate_mode(new_el, true);
|
unsigned int new_mode = aarch64_pstate_mode(new_el, true);
|
||||||
unsigned int old_mode;
|
unsigned int old_mode;
|
||||||
unsigned int cur_el = arm_current_el(env);
|
unsigned int cur_el = arm_current_el(env);
|
||||||
|
@ -10630,9 +10626,7 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
|
||||||
* Note that new_el can never be 0. If cur_el is 0, then
|
* Note that new_el can never be 0. If cur_el is 0, then
|
||||||
* el0_a64 is is_a64(), else el0_a64 is ignored.
|
* el0_a64 is is_a64(), else el0_a64 is ignored.
|
||||||
*/
|
*/
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
aarch64_sve_change_el(env, cur_el, new_el, is_a64(env));
|
aarch64_sve_change_el(env, cur_el, new_el, is_a64(env));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur_el < new_el) {
|
if (cur_el < new_el) {
|
||||||
|
@ -11423,7 +11417,6 @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env)
|
||||||
return arm_mmu_idx_el(env, arm_current_el(env));
|
return arm_mmu_idx_el(env, arm_current_el(env));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
/*
|
/*
|
||||||
* The manual says that when SVE is enabled and VQ is widened the
|
* The manual says that when SVE is enabled and VQ is widened the
|
||||||
* implementation is allowed to zero the previously inaccessible
|
* implementation is allowed to zero the previously inaccessible
|
||||||
|
@ -11535,12 +11528,9 @@ void aarch64_sve_change_el(CPUARMState *env, int old_el,
|
||||||
|
|
||||||
/* When changing vector length, clear inaccessible state. */
|
/* When changing vector length, clear inaccessible state. */
|
||||||
if (new_len < old_len) {
|
if (new_len < old_len) {
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
aarch64_sve_narrow_vq(env, new_len + 1);
|
aarch64_sve_narrow_vq(env, new_len + 1);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
ARMSecuritySpace arm_security_space(CPUARMState *env)
|
ARMSecuritySpace arm_security_space(CPUARMState *env)
|
||||||
|
|
1152
target/arm/helper.h
1152
target/arm/helper.h
File diff suppressed because it is too large
Load diff
|
@ -54,7 +54,7 @@ GArray *hw_breakpoints, *hw_watchpoints;
|
||||||
* here so future PC comparisons will work properly.
|
* here so future PC comparisons will work properly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int insert_hw_breakpoint(target_ulong addr)
|
int insert_hw_breakpoint(vaddr addr)
|
||||||
{
|
{
|
||||||
HWBreakpoint brk = {
|
HWBreakpoint brk = {
|
||||||
.bcr = 0x1, /* BCR E=1, enable */
|
.bcr = 0x1, /* BCR E=1, enable */
|
||||||
|
@ -80,7 +80,7 @@ int insert_hw_breakpoint(target_ulong addr)
|
||||||
* Delete a breakpoint and shuffle any above down
|
* Delete a breakpoint and shuffle any above down
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int delete_hw_breakpoint(target_ulong pc)
|
int delete_hw_breakpoint(vaddr pc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < hw_breakpoints->len; i++) {
|
for (i = 0; i < hw_breakpoints->len; i++) {
|
||||||
|
@ -226,7 +226,7 @@ int delete_hw_watchpoint(vaddr addr, vaddr len, int type)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool find_hw_breakpoint(CPUState *cpu, target_ulong pc)
|
bool find_hw_breakpoint(CPUState *cpu, vaddr pc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
|
@ -354,7 +354,6 @@ static inline int r14_bank_number(int mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
void arm_cpu_register(const ARMCPUInfo *info);
|
void arm_cpu_register(const ARMCPUInfo *info);
|
||||||
void aarch64_cpu_register(const ARMCPUInfo *info);
|
|
||||||
|
|
||||||
void register_cp_regs_for_features(ARMCPU *cpu);
|
void register_cp_regs_for_features(ARMCPU *cpu);
|
||||||
void init_cpreg_list(ARMCPU *cpu);
|
void init_cpreg_list(ARMCPU *cpu);
|
||||||
|
@ -1833,7 +1832,7 @@ void aarch64_add_sme_properties(Object *obj);
|
||||||
/* Return true if the gdbstub is presenting an AArch64 CPU */
|
/* Return true if the gdbstub is presenting an AArch64 CPU */
|
||||||
static inline bool arm_gdbstub_is_aarch64(ARMCPU *cpu)
|
static inline bool arm_gdbstub_is_aarch64(ARMCPU *cpu)
|
||||||
{
|
{
|
||||||
return object_dynamic_cast(OBJECT(cpu), TYPE_AARCH64_CPU);
|
return arm_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the CONTROL register as the MRS instruction would. */
|
/* Read the CONTROL register as the MRS instruction would. */
|
||||||
|
@ -1949,9 +1948,9 @@ extern GArray *hw_breakpoints, *hw_watchpoints;
|
||||||
#define get_hw_bp(i) (&g_array_index(hw_breakpoints, HWBreakpoint, i))
|
#define get_hw_bp(i) (&g_array_index(hw_breakpoints, HWBreakpoint, i))
|
||||||
#define get_hw_wp(i) (&g_array_index(hw_watchpoints, HWWatchpoint, i))
|
#define get_hw_wp(i) (&g_array_index(hw_watchpoints, HWWatchpoint, i))
|
||||||
|
|
||||||
bool find_hw_breakpoint(CPUState *cpu, target_ulong pc);
|
bool find_hw_breakpoint(CPUState *cpu, vaddr pc);
|
||||||
int insert_hw_breakpoint(target_ulong pc);
|
int insert_hw_breakpoint(vaddr pc);
|
||||||
int delete_hw_breakpoint(target_ulong pc);
|
int delete_hw_breakpoint(vaddr pc);
|
||||||
|
|
||||||
bool check_watchpoint_in_range(int i, vaddr addr);
|
bool check_watchpoint_in_range(int i, vaddr addr);
|
||||||
CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, vaddr addr);
|
CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, vaddr addr);
|
||||||
|
|
|
@ -22,3 +22,100 @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level)
|
||||||
{
|
{
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It's safe to call these functions without KVM support.
|
||||||
|
* They should either do nothing or return "not supported".
|
||||||
|
*/
|
||||||
|
bool kvm_arm_aarch32_supported(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool kvm_arm_pmu_supported(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool kvm_arm_sve_supported(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool kvm_arm_mte_supported(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These functions should never actually be called without KVM support.
|
||||||
|
*/
|
||||||
|
void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
void kvm_arm_add_vcpu_properties(ARMCPU *cpu)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
int kvm_arm_vgic_probe(void)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
void kvm_arm_pmu_set_irq(ARMCPU *cpu, int irq)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
void kvm_arm_pmu_init(ARMCPU *cpu)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
void kvm_arm_pvtime_init(ARMCPU *cpu, uint64_t ipa)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
void kvm_arm_steal_time_finalize(ARMCPU *cpu, Error **errp)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t kvm_arm_sve_get_vls(ARMCPU *cpu)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
void kvm_arm_enable_mte(Object *cpuobj, Error **errp)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
void kvm_arm_reset_vcpu(ARMCPU *cpu)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
void arm_cpu_kvm_set_irq(void *arm_cpu, int irq, int level)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
void kvm_arm_cpu_pre_save(ARMCPU *cpu)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool kvm_arm_cpu_post_load(ARMCPU *cpu)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
|
@ -938,13 +938,24 @@ void kvm_arm_cpu_pre_save(ARMCPU *cpu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void kvm_arm_cpu_post_load(ARMCPU *cpu)
|
bool kvm_arm_cpu_post_load(ARMCPU *cpu)
|
||||||
{
|
{
|
||||||
|
if (!write_list_to_kvmstate(cpu, KVM_PUT_FULL_STATE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Note that it's OK for the TCG side not to know about
|
||||||
|
* every register in the list; KVM is authoritative if
|
||||||
|
* we're using it.
|
||||||
|
*/
|
||||||
|
write_list_to_cpustate(cpu);
|
||||||
|
|
||||||
/* KVM virtual time adjustment */
|
/* KVM virtual time adjustment */
|
||||||
if (cpu->kvm_adjvtime) {
|
if (cpu->kvm_adjvtime) {
|
||||||
cpu->kvm_vtime = *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT);
|
cpu->kvm_vtime = *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT);
|
||||||
cpu->kvm_vtime_dirty = true;
|
cpu->kvm_vtime_dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kvm_arm_reset_vcpu(ARMCPU *cpu)
|
void kvm_arm_reset_vcpu(ARMCPU *cpu)
|
||||||
|
@ -1843,8 +1854,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
CPUARMState *env = &cpu->env;
|
CPUARMState *env = &cpu->env;
|
||||||
uint64_t psciver;
|
uint64_t psciver;
|
||||||
|
|
||||||
if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE ||
|
if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE) {
|
||||||
!object_dynamic_cast(OBJECT(cpu), TYPE_AARCH64_CPU)) {
|
|
||||||
error_report("KVM is not supported for this guest CPU type");
|
error_report("KVM is not supported for this guest CPU type");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -2429,3 +2439,32 @@ void kvm_arm_enable_mte(Object *cpuobj, Error **errp)
|
||||||
cpu->kvm_mte = true;
|
cpu->kvm_mte = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void arm_cpu_kvm_set_irq(void *arm_cpu, int irq, int level)
|
||||||
|
{
|
||||||
|
ARMCPU *cpu = arm_cpu;
|
||||||
|
CPUARMState *env = &cpu->env;
|
||||||
|
CPUState *cs = CPU(cpu);
|
||||||
|
uint32_t linestate_bit;
|
||||||
|
int irq_id;
|
||||||
|
|
||||||
|
switch (irq) {
|
||||||
|
case ARM_CPU_IRQ:
|
||||||
|
irq_id = KVM_ARM_IRQ_CPU_IRQ;
|
||||||
|
linestate_bit = CPU_INTERRUPT_HARD;
|
||||||
|
break;
|
||||||
|
case ARM_CPU_FIQ:
|
||||||
|
irq_id = KVM_ARM_IRQ_CPU_FIQ;
|
||||||
|
linestate_bit = CPU_INTERRUPT_FIQ;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level) {
|
||||||
|
env->irq_line_state |= linestate_bit;
|
||||||
|
} else {
|
||||||
|
env->irq_line_state &= ~linestate_bit;
|
||||||
|
}
|
||||||
|
kvm_arm_set_irq(cs->cpu_index, KVM_ARM_IRQ_TYPE_CPU, irq_id, !!level);
|
||||||
|
}
|
||||||
|
|
|
@ -83,8 +83,10 @@ void kvm_arm_cpu_pre_save(ARMCPU *cpu);
|
||||||
* @cpu: ARMCPU
|
* @cpu: ARMCPU
|
||||||
*
|
*
|
||||||
* Called from cpu_post_load() to update KVM CPU state from the cpreg list.
|
* Called from cpu_post_load() to update KVM CPU state from the cpreg list.
|
||||||
|
*
|
||||||
|
* Returns: true on success, or false if write_list_to_kvmstate failed.
|
||||||
*/
|
*/
|
||||||
void kvm_arm_cpu_post_load(ARMCPU *cpu);
|
bool kvm_arm_cpu_post_load(ARMCPU *cpu);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kvm_arm_reset_vcpu:
|
* kvm_arm_reset_vcpu:
|
||||||
|
@ -94,7 +96,7 @@ void kvm_arm_cpu_post_load(ARMCPU *cpu);
|
||||||
*/
|
*/
|
||||||
void kvm_arm_reset_vcpu(ARMCPU *cpu);
|
void kvm_arm_reset_vcpu(ARMCPU *cpu);
|
||||||
|
|
||||||
#ifdef CONFIG_KVM
|
struct kvm_vcpu_init;
|
||||||
/**
|
/**
|
||||||
* kvm_arm_create_scratch_host_vcpu:
|
* kvm_arm_create_scratch_host_vcpu:
|
||||||
* @fdarray: filled in with kvmfd, vmfd, cpufd file descriptors in that order
|
* @fdarray: filled in with kvmfd, vmfd, cpufd file descriptors in that order
|
||||||
|
@ -216,85 +218,6 @@ int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level);
|
||||||
|
|
||||||
void kvm_arm_enable_mte(Object *cpuobj, Error **errp);
|
void kvm_arm_enable_mte(Object *cpuobj, Error **errp);
|
||||||
|
|
||||||
#else
|
void arm_cpu_kvm_set_irq(void *arm_cpu, int irq, int level);
|
||||||
|
|
||||||
/*
|
|
||||||
* It's safe to call these functions without KVM support.
|
|
||||||
* They should either do nothing or return "not supported".
|
|
||||||
*/
|
|
||||||
static inline bool kvm_arm_aarch32_supported(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool kvm_arm_pmu_supported(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool kvm_arm_sve_supported(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool kvm_arm_mte_supported(void)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* These functions should never actually be called without KVM support.
|
|
||||||
*/
|
|
||||||
static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
|
|
||||||
{
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void kvm_arm_add_vcpu_properties(ARMCPU *cpu)
|
|
||||||
{
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa)
|
|
||||||
{
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int kvm_arm_vgic_probe(void)
|
|
||||||
{
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void kvm_arm_pmu_set_irq(ARMCPU *cpu, int irq)
|
|
||||||
{
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void kvm_arm_pmu_init(ARMCPU *cpu)
|
|
||||||
{
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void kvm_arm_pvtime_init(ARMCPU *cpu, uint64_t ipa)
|
|
||||||
{
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void kvm_arm_steal_time_finalize(ARMCPU *cpu, Error **errp)
|
|
||||||
{
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t kvm_arm_sve_get_vls(ARMCPU *cpu)
|
|
||||||
{
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void kvm_arm_enable_mte(Object *cpuobj, Error **errp)
|
|
||||||
{
|
|
||||||
g_assert_not_reached();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
#include "kvm_arm.h"
|
#include "kvm_arm.h"
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
#include "cpu-features.h"
|
#include "cpu-features.h"
|
||||||
#include "migration/cpu.h"
|
#include "migration/qemu-file-types.h"
|
||||||
|
#include "migration/vmstate.h"
|
||||||
#include "target/arm/gtimer.h"
|
#include "target/arm/gtimer.h"
|
||||||
|
|
||||||
static bool vfp_needed(void *opaque)
|
static bool vfp_needed(void *opaque)
|
||||||
|
@ -240,7 +241,6 @@ static const VMStateDescription vmstate_iwmmxt = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
/* The expression ARM_MAX_VQ - 2 is 0 for pure AArch32 build,
|
/* The expression ARM_MAX_VQ - 2 is 0 for pure AArch32 build,
|
||||||
* and ARMPredicateReg is actively empty. This triggers errors
|
* and ARMPredicateReg is actively empty. This triggers errors
|
||||||
* in the expansion of the VMSTATE macros.
|
* in the expansion of the VMSTATE macros.
|
||||||
|
@ -320,7 +320,6 @@ static const VMStateDescription vmstate_za = {
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif /* AARCH64 */
|
|
||||||
|
|
||||||
static bool serror_needed(void *opaque)
|
static bool serror_needed(void *opaque)
|
||||||
{
|
{
|
||||||
|
@ -977,15 +976,9 @@ static int cpu_post_load(void *opaque, int version_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kvm_enabled()) {
|
if (kvm_enabled()) {
|
||||||
if (!write_list_to_kvmstate(cpu, KVM_PUT_FULL_STATE)) {
|
if (!kvm_arm_cpu_post_load(cpu)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Note that it's OK for the TCG side not to know about
|
|
||||||
* every register in the list; KVM is authoritative if
|
|
||||||
* we're using it.
|
|
||||||
*/
|
|
||||||
write_list_to_cpustate(cpu);
|
|
||||||
kvm_arm_cpu_post_load(cpu);
|
|
||||||
} else {
|
} else {
|
||||||
if (!write_list_to_cpustate(cpu)) {
|
if (!write_list_to_cpustate(cpu)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1101,10 +1094,8 @@ const VMStateDescription vmstate_arm_cpu = {
|
||||||
&vmstate_pmsav7,
|
&vmstate_pmsav7,
|
||||||
&vmstate_pmsav8,
|
&vmstate_pmsav8,
|
||||||
&vmstate_m_security,
|
&vmstate_m_security,
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
&vmstate_sve,
|
&vmstate_sve,
|
||||||
&vmstate_za,
|
&vmstate_za,
|
||||||
#endif
|
|
||||||
&vmstate_serror,
|
&vmstate_serror,
|
||||||
&vmstate_irq_line_state,
|
&vmstate_irq_line_state,
|
||||||
&vmstate_wfxt_timer,
|
&vmstate_wfxt_timer,
|
||||||
|
|
|
@ -1,32 +1,47 @@
|
||||||
arm_ss = ss.source_set()
|
arm_ss = ss.source_set()
|
||||||
|
arm_common_ss = ss.source_set()
|
||||||
arm_ss.add(files(
|
arm_ss.add(files(
|
||||||
'cpu.c',
|
|
||||||
'debug_helper.c',
|
|
||||||
'gdbstub.c',
|
'gdbstub.c',
|
||||||
'helper.c',
|
|
||||||
'vfp_fpscr.c',
|
|
||||||
))
|
))
|
||||||
arm_ss.add(zlib)
|
arm_ss.add(zlib)
|
||||||
|
|
||||||
arm_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c'), if_false: files('kvm-stub.c'))
|
|
||||||
arm_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c'))
|
|
||||||
|
|
||||||
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
|
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
|
||||||
'cpu64.c',
|
'cpu64.c',
|
||||||
'gdbstub64.c',
|
'gdbstub64.c'))
|
||||||
))
|
|
||||||
|
|
||||||
arm_system_ss = ss.source_set()
|
arm_system_ss = ss.source_set()
|
||||||
|
arm_common_system_ss = ss.source_set()
|
||||||
arm_system_ss.add(files(
|
arm_system_ss.add(files(
|
||||||
'arch_dump.c',
|
|
||||||
'arm-powerctl.c',
|
|
||||||
'arm-qmp-cmds.c',
|
'arm-qmp-cmds.c',
|
||||||
'cortex-regs.c',
|
|
||||||
'machine.c',
|
|
||||||
'ptw.c',
|
|
||||||
))
|
))
|
||||||
|
arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c'))
|
||||||
|
arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c'))
|
||||||
|
|
||||||
arm_user_ss = ss.source_set()
|
arm_user_ss = ss.source_set()
|
||||||
|
arm_user_ss.add(files('cpu.c'))
|
||||||
|
arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files(
|
||||||
|
'cpu32-stubs.c',
|
||||||
|
))
|
||||||
|
arm_user_ss.add(files(
|
||||||
|
'debug_helper.c',
|
||||||
|
'helper.c',
|
||||||
|
'vfp_fpscr.c',
|
||||||
|
))
|
||||||
|
|
||||||
|
arm_common_system_ss.add(files('cpu.c'), capstone)
|
||||||
|
arm_common_system_ss.add(when: 'TARGET_AARCH64', if_false: files(
|
||||||
|
'cpu32-stubs.c'))
|
||||||
|
arm_common_system_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
|
||||||
|
arm_common_system_ss.add(files(
|
||||||
|
'arch_dump.c',
|
||||||
|
'arm-powerctl.c',
|
||||||
|
'cortex-regs.c',
|
||||||
|
'debug_helper.c',
|
||||||
|
'helper.c',
|
||||||
|
'machine.c',
|
||||||
|
'ptw.c',
|
||||||
|
'vfp_fpscr.c',
|
||||||
|
))
|
||||||
|
|
||||||
subdir('hvf')
|
subdir('hvf')
|
||||||
|
|
||||||
|
@ -39,3 +54,5 @@ endif
|
||||||
target_arch += {'arm': arm_ss}
|
target_arch += {'arm': arm_ss}
|
||||||
target_system_arch += {'arm': arm_system_ss}
|
target_system_arch += {'arm': arm_system_ss}
|
||||||
target_user_arch += {'arm': arm_user_ss}
|
target_user_arch += {'arm': arm_user_ss}
|
||||||
|
target_common_arch += {'arm': arm_common_ss}
|
||||||
|
target_common_system_arch += {'arm': arm_common_system_ss}
|
||||||
|
|
|
@ -737,7 +737,7 @@ static uint64_t arm_casq_ptw(CPUARMState *env, uint64_t old_val,
|
||||||
uint64_t new_val, S1Translate *ptw,
|
uint64_t new_val, S1Translate *ptw,
|
||||||
ARMMMUFaultInfo *fi)
|
ARMMMUFaultInfo *fi)
|
||||||
{
|
{
|
||||||
#if defined(TARGET_AARCH64) && defined(CONFIG_TCG)
|
#if defined(CONFIG_ATOMIC64) && defined(CONFIG_TCG)
|
||||||
uint64_t cur_val;
|
uint64_t cur_val;
|
||||||
void *host = ptw->out_host;
|
void *host = ptw->out_host;
|
||||||
|
|
||||||
|
@ -1660,7 +1660,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
|
||||||
uint64_t ttbr;
|
uint64_t ttbr;
|
||||||
hwaddr descaddr, indexmask, indexmask_grainsize;
|
hwaddr descaddr, indexmask, indexmask_grainsize;
|
||||||
uint32_t tableattrs;
|
uint32_t tableattrs;
|
||||||
target_ulong page_size;
|
uint64_t page_size;
|
||||||
uint64_t attrs;
|
uint64_t attrs;
|
||||||
int32_t stride;
|
int32_t stride;
|
||||||
int addrsize, inputsize, outputsize;
|
int addrsize, inputsize, outputsize;
|
||||||
|
@ -1733,7 +1733,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
|
||||||
* validation to do here.
|
* validation to do here.
|
||||||
*/
|
*/
|
||||||
if (inputsize < addrsize) {
|
if (inputsize < addrsize) {
|
||||||
target_ulong top_bits = sextract64(address, inputsize,
|
uint64_t top_bits = sextract64(address, inputsize,
|
||||||
addrsize - inputsize);
|
addrsize - inputsize);
|
||||||
if (-top_bits != param.select) {
|
if (-top_bits != param.select) {
|
||||||
/* The gap between the two regions is a Translation fault */
|
/* The gap between the two regions is a Translation fault */
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
*/
|
*/
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "cpu.h"
|
|
||||||
#include "exec/helper-proto.h"
|
|
||||||
#include "qemu/crc32c.h"
|
#include "qemu/crc32c.h"
|
||||||
#include <zlib.h> /* for crc32 */
|
#include <zlib.h> /* for crc32 */
|
||||||
|
|
||||||
|
#define HELPER_H "tcg/helper.h"
|
||||||
|
#include "exec/helper-proto.h.inc"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that signed overflow is undefined in C. The following routines are
|
* Note that signed overflow is undefined in C. The following routines are
|
||||||
* careful to use unsigned types where modulo arithmetic is required.
|
* careful to use unsigned types where modulo arithmetic is required.
|
||||||
|
|
|
@ -1316,7 +1316,7 @@ static void aarch64_cpu_register_types(void)
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(aarch64_cpus); ++i) {
|
for (i = 0; i < ARRAY_SIZE(aarch64_cpus); ++i) {
|
||||||
aarch64_cpu_register(&aarch64_cpus[i]);
|
arm_cpu_register(&aarch64_cpus[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/bitops.h"
|
||||||
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "exec/helper-proto.h"
|
|
||||||
#include "tcg/tcg-gvec-desc.h"
|
#include "tcg/tcg-gvec-desc.h"
|
||||||
#include "crypto/aes-round.h"
|
#include "crypto/aes-round.h"
|
||||||
#include "crypto/sm4.h"
|
#include "crypto/sm4.h"
|
||||||
#include "vec_internal.h"
|
#include "vec_internal.h"
|
||||||
|
|
||||||
|
#define HELPER_H "tcg/helper.h"
|
||||||
|
#include "exec/helper-proto.h.inc"
|
||||||
|
|
||||||
union CRYPTO_STATE {
|
union CRYPTO_STATE {
|
||||||
uint8_t bytes[16];
|
uint8_t bytes[16];
|
||||||
uint32_t words[4];
|
uint32_t words[4];
|
||||||
|
|
1153
target/arm/tcg/helper.h
Normal file
1153
target/arm/tcg/helper.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -9,11 +9,13 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
#include "cpu-features.h"
|
#include "cpu-features.h"
|
||||||
#include "exec/helper-proto.h"
|
|
||||||
#include "exec/translation-block.h"
|
#include "exec/translation-block.h"
|
||||||
#include "accel/tcg/cpu-ops.h"
|
#include "accel/tcg/cpu-ops.h"
|
||||||
#include "cpregs.h"
|
#include "cpregs.h"
|
||||||
|
|
||||||
|
#define HELPER_H "tcg/helper.h"
|
||||||
|
#include "exec/helper-proto.h.inc"
|
||||||
|
|
||||||
static inline bool fgt_svc(CPUARMState *env, int el)
|
static inline bool fgt_svc(CPUARMState *env, int el)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -22,7 +22,9 @@
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "exec/helper-proto.h"
|
|
||||||
|
#define HELPER_H "tcg/helper.h"
|
||||||
|
#include "exec/helper-proto.h.inc"
|
||||||
|
|
||||||
/* iwMMXt macros extracted from GNU gdb. */
|
/* iwMMXt macros extracted from GNU gdb. */
|
||||||
|
|
||||||
|
|
|
@ -30,18 +30,10 @@ arm_ss.add(files(
|
||||||
'translate-mve.c',
|
'translate-mve.c',
|
||||||
'translate-neon.c',
|
'translate-neon.c',
|
||||||
'translate-vfp.c',
|
'translate-vfp.c',
|
||||||
'crypto_helper.c',
|
|
||||||
'hflags.c',
|
|
||||||
'iwmmxt_helper.c',
|
|
||||||
'm_helper.c',
|
'm_helper.c',
|
||||||
'mve_helper.c',
|
'mve_helper.c',
|
||||||
'neon_helper.c',
|
|
||||||
'op_helper.c',
|
'op_helper.c',
|
||||||
'tlb_helper.c',
|
|
||||||
'vec_helper.c',
|
'vec_helper.c',
|
||||||
'tlb-insns.c',
|
|
||||||
'arith_helper.c',
|
|
||||||
'vfp_helper.c',
|
|
||||||
))
|
))
|
||||||
|
|
||||||
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
|
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
|
||||||
|
@ -63,3 +55,24 @@ arm_system_ss.add(files(
|
||||||
|
|
||||||
arm_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c'))
|
arm_system_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('cpu-v7m.c'))
|
||||||
arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files('cpu-v7m.c'))
|
arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files('cpu-v7m.c'))
|
||||||
|
|
||||||
|
arm_common_ss.add(files(
|
||||||
|
'arith_helper.c',
|
||||||
|
'crypto_helper.c',
|
||||||
|
))
|
||||||
|
|
||||||
|
arm_common_system_ss.add(files(
|
||||||
|
'hflags.c',
|
||||||
|
'iwmmxt_helper.c',
|
||||||
|
'neon_helper.c',
|
||||||
|
'tlb_helper.c',
|
||||||
|
'tlb-insns.c',
|
||||||
|
'vfp_helper.c',
|
||||||
|
))
|
||||||
|
arm_user_ss.add(files(
|
||||||
|
'hflags.c',
|
||||||
|
'iwmmxt_helper.c',
|
||||||
|
'neon_helper.c',
|
||||||
|
'tlb_helper.c',
|
||||||
|
'vfp_helper.c',
|
||||||
|
))
|
||||||
|
|
|
@ -9,11 +9,13 @@
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "exec/helper-proto.h"
|
|
||||||
#include "tcg/tcg-gvec-desc.h"
|
#include "tcg/tcg-gvec-desc.h"
|
||||||
#include "fpu/softfloat.h"
|
#include "fpu/softfloat.h"
|
||||||
#include "vec_internal.h"
|
#include "vec_internal.h"
|
||||||
|
|
||||||
|
#define HELPER_H "tcg/helper.h"
|
||||||
|
#include "exec/helper-proto.h.inc"
|
||||||
|
|
||||||
#define SIGNBIT (uint32_t)0x80000000
|
#define SIGNBIT (uint32_t)0x80000000
|
||||||
#define SIGNBIT64 ((uint64_t)1 << 63)
|
#define SIGNBIT64 ((uint64_t)1 << 63)
|
||||||
|
|
||||||
|
|
|
@ -1222,7 +1222,7 @@ uint32_t HELPER(ror_cc)(CPUARMState *env, uint32_t x, uint32_t i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HELPER(probe_access)(CPUARMState *env, target_ulong ptr,
|
void HELPER(probe_access)(CPUARMState *env, vaddr ptr,
|
||||||
uint32_t access_type, uint32_t mmu_idx,
|
uint32_t access_type, uint32_t mmu_idx,
|
||||||
uint32_t size)
|
uint32_t size)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,7 +35,6 @@ static CPAccessResult access_ttlbis(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
return CP_ACCESS_OK;
|
return CP_ACCESS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
/* Check for traps from EL1 due to HCR_EL2.TTLB or TTLBOS. */
|
/* Check for traps from EL1 due to HCR_EL2.TTLB or TTLBOS. */
|
||||||
static CPAccessResult access_ttlbos(CPUARMState *env, const ARMCPRegInfo *ri,
|
static CPAccessResult access_ttlbos(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
bool isread)
|
bool isread)
|
||||||
|
@ -46,7 +45,6 @@ static CPAccessResult access_ttlbos(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
}
|
}
|
||||||
return CP_ACCESS_OK;
|
return CP_ACCESS_OK;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* IS variants of TLB operations must affect all cores */
|
/* IS variants of TLB operations must affect all cores */
|
||||||
static void tlbiall_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
static void tlbiall_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
|
@ -802,7 +800,6 @@ static const ARMCPRegInfo tlbi_el3_cp_reginfo[] = {
|
||||||
.writefn = tlbi_aa64_vae3_write },
|
.writefn = tlbi_aa64_vae3_write },
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t base;
|
uint64_t base;
|
||||||
uint64_t length;
|
uint64_t length;
|
||||||
|
@ -1270,8 +1267,6 @@ static const ARMCPRegInfo tlbi_rme_reginfo[] = {
|
||||||
.writefn = tlbi_aa64_paallos_write },
|
.writefn = tlbi_aa64_paallos_write },
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void define_tlb_insn_regs(ARMCPU *cpu)
|
void define_tlb_insn_regs(ARMCPU *cpu)
|
||||||
{
|
{
|
||||||
CPUARMState *env = &cpu->env;
|
CPUARMState *env = &cpu->env;
|
||||||
|
@ -1299,7 +1294,6 @@ void define_tlb_insn_regs(ARMCPU *cpu)
|
||||||
if (arm_feature(env, ARM_FEATURE_EL3)) {
|
if (arm_feature(env, ARM_FEATURE_EL3)) {
|
||||||
define_arm_cp_regs(cpu, tlbi_el3_cp_reginfo);
|
define_arm_cp_regs(cpu, tlbi_el3_cp_reginfo);
|
||||||
}
|
}
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
if (cpu_isar_feature(aa64_tlbirange, cpu)) {
|
if (cpu_isar_feature(aa64_tlbirange, cpu)) {
|
||||||
define_arm_cp_regs(cpu, tlbirange_reginfo);
|
define_arm_cp_regs(cpu, tlbirange_reginfo);
|
||||||
}
|
}
|
||||||
|
@ -1309,5 +1303,4 @@ void define_tlb_insn_regs(ARMCPU *cpu)
|
||||||
if (cpu_isar_feature(aa64_rme, cpu)) {
|
if (cpu_isar_feature(aa64_rme, cpu)) {
|
||||||
define_arm_cp_regs(cpu, tlbi_rme_reginfo);
|
define_arm_cp_regs(cpu, tlbi_rme_reginfo);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,9 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
#include "cpu-features.h"
|
#include "cpu-features.h"
|
||||||
#include "exec/helper-proto.h"
|
|
||||||
|
|
||||||
|
#define HELPER_H "tcg/helper.h"
|
||||||
|
#include "exec/helper-proto.h.inc"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true if the stage 1 translation regime is using LPAE format page
|
* Returns true if the stage 1 translation regime is using LPAE format page
|
||||||
|
@ -276,7 +277,7 @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
|
||||||
arm_deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi);
|
arm_deliver_fault(cpu, vaddr, access_type, mmu_idx, &fi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_exception_pc_alignment(CPUARMState *env, target_ulong pc)
|
void helper_exception_pc_alignment(CPUARMState *env, vaddr pc)
|
||||||
{
|
{
|
||||||
ARMMMUFaultInfo fi = { .type = ARMFault_Alignment };
|
ARMMMUFaultInfo fi = { .type = ARMFault_Alignment };
|
||||||
int target_el = exception_target_el(env);
|
int target_el = exception_target_el(env);
|
||||||
|
|
|
@ -10242,7 +10242,7 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
* start of the TB.
|
* start of the TB.
|
||||||
*/
|
*/
|
||||||
assert(s->base.num_insns == 1);
|
assert(s->base.num_insns == 1);
|
||||||
gen_helper_exception_pc_alignment(tcg_env, tcg_constant_tl(pc));
|
gen_helper_exception_pc_alignment(tcg_env, tcg_constant_vaddr(pc));
|
||||||
s->base.is_jmp = DISAS_NORETURN;
|
s->base.is_jmp = DISAS_NORETURN;
|
||||||
s->base.pc_next = QEMU_ALIGN_UP(pc, 4);
|
s->base.pc_next = QEMU_ALIGN_UP(pc, 4);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -7791,7 +7791,7 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
* be possible after an indirect branch, at the start of the TB.
|
* be possible after an indirect branch, at the start of the TB.
|
||||||
*/
|
*/
|
||||||
assert(dc->base.num_insns == 1);
|
assert(dc->base.num_insns == 1);
|
||||||
gen_helper_exception_pc_alignment(tcg_env, tcg_constant_tl(pc));
|
gen_helper_exception_pc_alignment(tcg_env, tcg_constant_vaddr(pc));
|
||||||
dc->base.is_jmp = DISAS_NORETURN;
|
dc->base.is_jmp = DISAS_NORETURN;
|
||||||
dc->base.pc_next = QEMU_ALIGN_UP(pc, 4);
|
dc->base.pc_next = QEMU_ALIGN_UP(pc, 4);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
|
|
||||||
#include "fpu/softfloat.h"
|
#include "fpu/softfloat.h"
|
||||||
|
|
||||||
|
typedef struct CPUArchState CPUARMState;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that vector data is stored in host-endian 64-bit chunks,
|
* Note that vector data is stored in host-endian 64-bit chunks,
|
||||||
* so addressing units smaller than that needs a host-endian fixup.
|
* so addressing units smaller than that needs a host-endian fixup.
|
||||||
|
|
|
@ -19,12 +19,14 @@
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "exec/helper-proto.h"
|
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
#include "cpu-features.h"
|
#include "cpu-features.h"
|
||||||
#include "fpu/softfloat.h"
|
#include "fpu/softfloat.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
|
|
||||||
|
#define HELPER_H "tcg/helper.h"
|
||||||
|
#include "exec/helper-proto.h.inc"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the float_status behaviour to match the Arm defaults:
|
* Set the float_status behaviour to match the Arm defaults:
|
||||||
* * tininess-before-rounding
|
* * tininess-before-rounding
|
||||||
|
|
|
@ -263,6 +263,11 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gdb_register_coprocessor(cs, mb_cpu_gdb_read_stack_protect,
|
||||||
|
mb_cpu_gdb_write_stack_protect,
|
||||||
|
gdb_find_static_feature("microblaze-stack-protect.xml"),
|
||||||
|
0);
|
||||||
|
|
||||||
qemu_init_vcpu(cs);
|
qemu_init_vcpu(cs);
|
||||||
|
|
||||||
version = cpu->cfg.version ? cpu->cfg.version : DEFAULT_CPU_VERSION;
|
version = cpu->cfg.version ? cpu->cfg.version : DEFAULT_CPU_VERSION;
|
||||||
|
@ -335,20 +340,13 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
|
|
||||||
static void mb_cpu_initfn(Object *obj)
|
static void mb_cpu_initfn(Object *obj)
|
||||||
{
|
{
|
||||||
MicroBlazeCPU *cpu = MICROBLAZE_CPU(obj);
|
|
||||||
|
|
||||||
gdb_register_coprocessor(CPU(cpu), mb_cpu_gdb_read_stack_protect,
|
|
||||||
mb_cpu_gdb_write_stack_protect,
|
|
||||||
gdb_find_static_feature("microblaze-stack-protect.xml"),
|
|
||||||
0);
|
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
/* Inbound IRQ and FIR lines */
|
/* Inbound IRQ and FIR lines */
|
||||||
qdev_init_gpio_in(DEVICE(cpu), microblaze_cpu_set_irq, 2);
|
qdev_init_gpio_in(DEVICE(obj), microblaze_cpu_set_irq, 2);
|
||||||
qdev_init_gpio_in_named(DEVICE(cpu), mb_cpu_ns_axi_dp, "ns_axi_dp", 1);
|
qdev_init_gpio_in_named(DEVICE(obj), mb_cpu_ns_axi_dp, "ns_axi_dp", 1);
|
||||||
qdev_init_gpio_in_named(DEVICE(cpu), mb_cpu_ns_axi_ip, "ns_axi_ip", 1);
|
qdev_init_gpio_in_named(DEVICE(obj), mb_cpu_ns_axi_ip, "ns_axi_ip", 1);
|
||||||
qdev_init_gpio_in_named(DEVICE(cpu), mb_cpu_ns_axi_dc, "ns_axi_dc", 1);
|
qdev_init_gpio_in_named(DEVICE(obj), mb_cpu_ns_axi_dc, "ns_axi_dc", 1);
|
||||||
qdev_init_gpio_in_named(DEVICE(cpu), mb_cpu_ns_axi_ic, "ns_axi_ic", 1);
|
qdev_init_gpio_in_named(DEVICE(obj), mb_cpu_ns_axi_ic, "ns_axi_ic", 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Restricted 'endianness' property is equivalent of 'little-endian' */
|
/* Restricted 'endianness' property is equivalent of 'little-endian' */
|
||||||
|
|
|
@ -2367,6 +2367,11 @@ TCGv_i64 tcg_constant_i64(int64_t val)
|
||||||
return temp_tcgv_i64(tcg_constant_internal(TCG_TYPE_I64, val));
|
return temp_tcgv_i64(tcg_constant_internal(TCG_TYPE_I64, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TCGv_vaddr tcg_constant_vaddr(uintptr_t val)
|
||||||
|
{
|
||||||
|
return temp_tcgv_vaddr(tcg_constant_internal(TCG_TYPE_PTR, val));
|
||||||
|
}
|
||||||
|
|
||||||
TCGv_ptr tcg_constant_ptr_int(intptr_t val)
|
TCGv_ptr tcg_constant_ptr_int(intptr_t val)
|
||||||
{
|
{
|
||||||
return temp_tcgv_ptr(tcg_constant_internal(TCG_TYPE_PTR, val));
|
return temp_tcgv_ptr(tcg_constant_internal(TCG_TYPE_PTR, val));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue