Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210119-1' into staging

target-arm queue:
 * Implement IMPDEF pauth algorithm
 * Support ARMv8.4-SEL2
 * Fix bug where we were truncating predicate vector lengths in SVE insns
 * npcm7xx_adc-test: Fix memleak in adc_qom_set
 * target/arm/m_helper: Silence GCC 10 maybe-uninitialized error
 * docs: Build and install all the docs in a single manual

# gpg: Signature made Tue 19 Jan 2021 15:46:34 GMT
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20210119-1: (29 commits)
  docs: Build and install all the docs in a single manual
  target/arm/m_helper: Silence GCC 10 maybe-uninitialized error
  npcm7xx_adc-test: Fix memleak in adc_qom_set
  target/arm: Update REV, PUNPK for pred_desc
  target/arm: Update ZIP, UZP, TRN for pred_desc
  target/arm: Update PFIRST, PNEXT for pred_desc
  target/arm: Introduce PREDDESC field definitions
  target/arm: refactor vae1_tlbmask()
  target/arm: enable Secure EL2 in max CPU
  target/arm: Implement SCR_EL2.EEL2
  target/arm: revector to run-time pick target EL
  target/arm: set HPFAR_EL2.NS on secure stage 2 faults
  target/arm: secure stage 2 translation regime
  target/arm: generalize 2-stage page-walk condition
  target/arm: translate NS bit in page-walks
  target/arm: do S1_ptw_translate() before address space lookup
  target/arm: handle VMID change in secure state
  target/arm: add ARMv8.4-SEL2 system registers
  target/arm: add MMU stage 1 for Secure EL2
  target/arm: add 64-bit S-EL2 to EL exception table
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2021-01-19 15:47:23 +00:00
30 changed files with 770 additions and 438 deletions
+2 -2
View File
@@ -622,8 +622,8 @@ pages:
-t "Welcome to the QEMU sourcecode"
- mv HTML public/src
# Project documentation
- mv build/docs/index.html public/
- for i in devel interop specs system tools user ; do mv build/docs/$i public/ ; done
- make -C build install DESTDIR=$(pwd)/temp-install
- mv temp-install/usr/local/share/doc/qemu/* public/
artifacts:
paths:
- public
+45 -1
View File
@@ -224,7 +224,51 @@ latex_documents = [
# -- Options for manual page output ---------------------------------------
# Individual manual/conf.py can override this to create man pages
man_pages = []
man_pages = [
('interop/qemu-ga', 'qemu-ga',
'QEMU Guest Agent',
['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
('interop/qemu-ga-ref', 'qemu-ga-ref',
'QEMU Guest Agent Protocol Reference',
[], 7),
('interop/qemu-qmp-ref', 'qemu-qmp-ref',
'QEMU QMP Reference Manual',
[], 7),
('interop/qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
'QEMU Storage Daemon QMP Reference Manual',
[], 7),
('system/qemu-manpage', 'qemu',
'QEMU User Documentation',
['Fabrice Bellard'], 1),
('system/qemu-block-drivers', 'qemu-block-drivers',
'QEMU block drivers reference',
['Fabrice Bellard and the QEMU Project developers'], 7),
('system/qemu-cpu-models', 'qemu-cpu-models',
'QEMU CPU Models',
['The QEMU Project developers'], 7),
('tools/qemu-img', 'qemu-img',
'QEMU disk image utility',
['Fabrice Bellard'], 1),
('tools/qemu-nbd', 'qemu-nbd',
'QEMU Disk Network Block Device Server',
['Anthony Liguori <anthony@codemonkey.ws>'], 8),
('tools/qemu-pr-helper', 'qemu-pr-helper',
'QEMU persistent reservation helper',
[], 8),
('tools/qemu-storage-daemon', 'qemu-storage-daemon',
'QEMU storage daemon',
[], 1),
('tools/qemu-trace-stap', 'qemu-trace-stap',
'QEMU SystemTap trace tool',
[], 1),
('tools/virtfs-proxy-helper', 'virtfs-proxy-helper',
'QEMU 9p virtfs proxy filesystem helper',
['M. Mohan Kumar'], 1),
('tools/virtiofsd', 'virtiofsd',
'QEMU virtio-fs shared file system daemon',
['Stefan Hajnoczi <stefanha@redhat.com>',
'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
]
# -- Options for Texinfo output -------------------------------------------
-15
View File
@@ -1,15 +0,0 @@
# -*- coding: utf-8 -*-
#
# QEMU documentation build configuration file for the 'devel' manual.
#
# This includes the top level conf file and then makes any necessary tweaks.
import sys
import os
qemu_docdir = os.path.abspath("..")
parent_config = os.path.join(qemu_docdir, "conf.py")
exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
# This slightly misuses the 'description', but is the best way to get
# the manual title to appear in the sidebar.
html_theme_options['description'] = u'Developer''s Guide'
-17
View File
@@ -1,17 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>QEMU @VERSION@ Documentation</title>
</head>
<body>
<h1>QEMU @VERSION@ Documentation</h1>
<ul>
<li><a href="system/index.html">System Emulation User's Guide</a></li>
<li><a href="user/index.html">User Mode Emulation User's Guide</a></li>
<li><a href="tools/index.html">Tools Guide</a></li>
<li><a href="interop/index.html">System Emulation Management and Interoperability Guide</a></li>
<li><a href="specs/index.html">System Emulation Guest Hardware Specifications</a></li>
</ul>
</body>
</html>
-28
View File
@@ -1,28 +0,0 @@
# -*- coding: utf-8 -*-
#
# QEMU documentation build configuration file for the 'interop' manual.
#
# This includes the top level conf file and then makes any necessary tweaks.
import sys
import os
qemu_docdir = os.path.abspath("..")
parent_config = os.path.join(qemu_docdir, "conf.py")
exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
# This slightly misuses the 'description', but is the best way to get
# the manual title to appear in the sidebar.
html_theme_options['description'] = u'System Emulation Management and Interoperability Guide'
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('qemu-ga', 'qemu-ga', u'QEMU Guest Agent',
['Michael Roth <mdroth@linux.vnet.ibm.com>'], 8),
('qemu-ga-ref', 'qemu-ga-ref', 'QEMU Guest Agent Protocol Reference',
[], 7),
('qemu-qmp-ref', 'qemu-qmp-ref', 'QEMU QMP Reference Manual',
[], 7),
('qemu-storage-daemon-qmp-ref', 'qemu-storage-daemon-qmp-ref',
'QEMU Storage Daemon QMP Reference Manual', [], 7),
]
+25 -39
View File
@@ -46,19 +46,11 @@ if build_docs
meson.source_root() / 'docs/sphinx/qmp_lexer.py',
qapi_gen_depends ]
configure_file(output: 'index.html',
input: files('index.html.in'),
configuration: {'VERSION': meson.project_version()},
install_dir: qemu_docdir)
manuals = [ 'devel', 'interop', 'tools', 'specs', 'system', 'user' ]
man_pages = {
'interop' : {
'qemu-ga.8': (have_tools ? 'man8' : ''),
'qemu-ga-ref.7': 'man7',
'qemu-qmp-ref.7': 'man7',
'qemu-storage-daemon-qmp-ref.7': (have_tools ? 'man7' : ''),
},
'tools': {
'qemu-img.1': (have_tools ? 'man1' : ''),
'qemu-nbd.8': (have_tools ? 'man8' : ''),
'qemu-pr-helper.8': (have_tools ? 'man8' : ''),
@@ -66,53 +58,47 @@ if build_docs
'qemu-trace-stap.1': (config_host.has_key('CONFIG_TRACE_SYSTEMTAP') ? 'man1' : ''),
'virtfs-proxy-helper.1': (have_virtfs_proxy_helper ? 'man1' : ''),
'virtiofsd.1': (have_virtiofsd ? 'man1' : ''),
},
'system': {
'qemu.1': 'man1',
'qemu-block-drivers.7': 'man7',
'qemu-cpu-models.7': 'man7'
},
}
sphinxdocs = []
sphinxmans = []
foreach manual : manuals
private_dir = meson.current_build_dir() / (manual + '.p')
output_dir = meson.current_build_dir() / manual
input_dir = meson.current_source_dir() / manual
this_manual = custom_target(manual + ' manual',
private_dir = meson.current_build_dir() / 'manual.p'
output_dir = meson.current_build_dir() / 'manual'
input_dir = meson.current_source_dir()
this_manual = custom_target('QEMU manual',
build_by_default: build_docs,
output: [manual + '.stamp'],
input: [files('conf.py'), files(manual / 'conf.py')],
depfile: manual + '.d',
output: 'docs.stamp',
input: files('conf.py'),
depfile: 'docs.d',
depend_files: sphinx_extn_depends,
command: [SPHINX_ARGS, '-Ddepfile=@DEPFILE@',
'-Ddepfile_stamp=@OUTPUT0@',
'-b', 'html', '-d', private_dir,
input_dir, output_dir])
sphinxdocs += this_manual
if build_docs and manual != 'devel'
install_subdir(output_dir, install_dir: qemu_docdir)
endif
sphinxdocs += this_manual
install_subdir(output_dir, install_dir: qemu_docdir, strip_directory: true)
these_man_pages = []
install_dirs = []
foreach page, section : man_pages.get(manual, {})
these_man_pages += page
install_dirs += section == '' ? false : get_option('mandir') / section
endforeach
if these_man_pages.length() > 0
sphinxmans += custom_target(manual + ' man pages',
build_by_default: build_docs,
output: these_man_pages,
input: this_manual,
install: build_docs,
install_dir: install_dirs,
command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
input_dir, meson.current_build_dir()])
endif
these_man_pages = []
install_dirs = []
foreach page, section : man_pages
these_man_pages += page
install_dirs += section == '' ? false : get_option('mandir') / section
endforeach
sphinxmans += custom_target('QEMU man pages',
build_by_default: build_docs,
output: these_man_pages,
input: this_manual,
install: build_docs,
install_dir: install_dirs,
command: [SPHINX_ARGS, '-b', 'man', '-d', private_dir,
input_dir, meson.current_build_dir()])
alias_target('sphinxdocs', sphinxdocs)
alias_target('html', sphinxdocs)
alias_target('man', sphinxmans)
-16
View File
@@ -1,16 +0,0 @@
# -*- coding: utf-8 -*-
#
# QEMU documentation build configuration file for the 'specs' manual.
#
# This includes the top level conf file and then makes any necessary tweaks.
import sys
import os
qemu_docdir = os.path.abspath("..")
parent_config = os.path.join(qemu_docdir, "conf.py")
exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
# This slightly misuses the 'description', but is the best way to get
# the manual title to appear in the sidebar.
html_theme_options['description'] = \
u'System Emulation Guest Hardware Specifications'
+21
View File
@@ -211,6 +211,27 @@ the list of KVM VCPU features and their descriptions.
influence the guest scheduler behavior and/or be
exposed to the guest userspace.
TCG VCPU Features
=================
TCG VCPU features are CPU features that are specific to TCG.
Below is the list of TCG VCPU features and their descriptions.
pauth Enable or disable `FEAT_Pauth`, pointer
authentication. By default, the feature is
enabled with `-cpu max`.
pauth-impdef When `FEAT_Pauth` is enabled, either the
*impdef* (Implementation Defined) algorithm
is enabled or the *architected* QARMA algorithm
is enabled. By default the impdef algorithm
is disabled, and QARMA is enabled.
The architected QARMA algorithm has good
cryptographic properties, but can be quite slow
to emulate. The impdef algorithm used by QEMU
is non-cryptographic but significantly faster.
SVE CPU Properties
==================
-28
View File
@@ -1,28 +0,0 @@
# -*- coding: utf-8 -*-
#
# QEMU documentation build configuration file for the 'system' manual.
#
# This includes the top level conf file and then makes any necessary tweaks.
import sys
import os
qemu_docdir = os.path.abspath("..")
parent_config = os.path.join(qemu_docdir, "conf.py")
exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
# This slightly misuses the 'description', but is the best way to get
# the manual title to appear in the sidebar.
html_theme_options['description'] = u'System Emulation User''s Guide'
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('qemu-manpage', 'qemu', u'QEMU User Documentation',
['Fabrice Bellard'], 1),
('qemu-block-drivers', 'qemu-block-drivers',
u'QEMU block drivers reference',
['Fabrice Bellard and the QEMU Project developers'], 7),
('qemu-cpu-models', 'qemu-cpu-models',
u'QEMU CPU Models',
['The QEMU Project developers'], 7)
]
-37
View File
@@ -1,37 +0,0 @@
# -*- coding: utf-8 -*-
#
# QEMU documentation build configuration file for the 'tools' manual.
#
# This includes the top level conf file and then makes any necessary tweaks.
import sys
import os
qemu_docdir = os.path.abspath("..")
parent_config = os.path.join(qemu_docdir, "conf.py")
exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
# This slightly misuses the 'description', but is the best way to get
# the manual title to appear in the sidebar.
html_theme_options['description'] = \
u'Tools Guide'
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('qemu-img', 'qemu-img', u'QEMU disk image utility',
['Fabrice Bellard'], 1),
('qemu-storage-daemon', 'qemu-storage-daemon', u'QEMU storage daemon',
[], 1),
('qemu-nbd', 'qemu-nbd', u'QEMU Disk Network Block Device Server',
['Anthony Liguori <anthony@codemonkey.ws>'], 8),
('qemu-pr-helper', 'qemu-pr-helper', 'QEMU persistent reservation helper',
[], 8),
('qemu-trace-stap', 'qemu-trace-stap', u'QEMU SystemTap trace tool',
[], 1),
('virtfs-proxy-helper', 'virtfs-proxy-helper',
u'QEMU 9p virtfs proxy filesystem helper',
['M. Mohan Kumar'], 1),
('virtiofsd', 'virtiofsd', u'QEMU virtio-fs shared file system daemon',
['Stefan Hajnoczi <stefanha@redhat.com>',
'Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>'], 1),
]
-15
View File
@@ -1,15 +0,0 @@
# -*- coding: utf-8 -*-
#
# QEMU documentation build configuration file for the 'user' manual.
#
# This includes the top level conf file and then makes any necessary tweaks.
import sys
import os
qemu_docdir = os.path.abspath("..")
parent_config = os.path.join(qemu_docdir, "conf.py")
exec(compile(open(parent_config, "rb").read(), parent_config, 'exec'))
# This slightly misuses the 'description', but is the best way to get
# the manual title to appear in the sidebar.
html_theme_options['description'] = u'User Mode Emulation User''s Guide'
+98
View File
@@ -119,4 +119,102 @@ static inline uint32_t qemu_xxhash6(uint64_t ab, uint64_t cd, uint32_t e,
return qemu_xxhash7(ab, cd, e, f, 0);
}
/*
* Component parts of the XXH64 algorithm from
* https://github.com/Cyan4973/xxHash/blob/v0.8.0/xxhash.h
*
* The complete algorithm looks like
*
* i = 0;
* if (len >= 32) {
* v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
* v2 = seed + XXH_PRIME64_2;
* v3 = seed + 0;
* v4 = seed - XXH_PRIME64_1;
* do {
* v1 = XXH64_round(v1, get64bits(input + i));
* v2 = XXH64_round(v2, get64bits(input + i + 8));
* v3 = XXH64_round(v3, get64bits(input + i + 16));
* v4 = XXH64_round(v4, get64bits(input + i + 24));
* } while ((i += 32) <= len);
* h64 = XXH64_mergerounds(v1, v2, v3, v4);
* } else {
* h64 = seed + XXH_PRIME64_5;
* }
* h64 += len;
*
* for (; i + 8 <= len; i += 8) {
* h64 ^= XXH64_round(0, get64bits(input + i));
* h64 = rol64(h64, 27) * XXH_PRIME64_1 + XXH_PRIME64_4;
* }
* for (; i + 4 <= len; i += 4) {
* h64 ^= get32bits(input + i) * PRIME64_1;
* h64 = rol64(h64, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;
* }
* for (; i < len; i += 1) {
* h64 ^= get8bits(input + i) * XXH_PRIME64_5;
* h64 = rol64(h64, 11) * XXH_PRIME64_1;
* }
*
* return XXH64_avalanche(h64)
*
* Exposing the pieces instead allows for simplified usage when
* the length is a known constant and the inputs are in registers.
*/
#define XXH_PRIME64_1 0x9E3779B185EBCA87ULL
#define XXH_PRIME64_2 0xC2B2AE3D27D4EB4FULL
#define XXH_PRIME64_3 0x165667B19E3779F9ULL
#define XXH_PRIME64_4 0x85EBCA77C2B2AE63ULL
#define XXH_PRIME64_5 0x27D4EB2F165667C5ULL
static inline uint64_t XXH64_round(uint64_t acc, uint64_t input)
{
return rol64(acc + input * XXH_PRIME64_2, 31) * XXH_PRIME64_1;
}
static inline uint64_t XXH64_mergeround(uint64_t acc, uint64_t val)
{
return (acc ^ XXH64_round(0, val)) * XXH_PRIME64_1 + XXH_PRIME64_4;
}
static inline uint64_t XXH64_mergerounds(uint64_t v1, uint64_t v2,
uint64_t v3, uint64_t v4)
{
uint64_t h64;
h64 = rol64(v1, 1) + rol64(v2, 7) + rol64(v3, 12) + rol64(v4, 18);
h64 = XXH64_mergeround(h64, v1);
h64 = XXH64_mergeround(h64, v2);
h64 = XXH64_mergeround(h64, v3);
h64 = XXH64_mergeround(h64, v4);
return h64;
}
static inline uint64_t XXH64_avalanche(uint64_t h64)
{
h64 ^= h64 >> 33;
h64 *= XXH_PRIME64_2;
h64 ^= h64 >> 29;
h64 *= XXH_PRIME64_3;
h64 ^= h64 >> 32;
return h64;
}
static inline uint64_t qemu_xxhash64_4(uint64_t a, uint64_t b,
uint64_t c, uint64_t d)
{
uint64_t v1 = QEMU_XXHASH_SEED + XXH_PRIME64_1 + XXH_PRIME64_2;
uint64_t v2 = QEMU_XXHASH_SEED + XXH_PRIME64_2;
uint64_t v3 = QEMU_XXHASH_SEED + 0;
uint64_t v4 = QEMU_XXHASH_SEED - XXH_PRIME64_1;
v1 = XXH64_round(v1, a);
v2 = XXH64_round(v2, b);
v3 = XXH64_round(v3, c);
v4 = XXH64_round(v4, d);
return XXH64_avalanche(XXH64_mergerounds(v1, v2, v3, v4));
}
#endif /* QEMU_XXHASH_H */
+1 -1
View File
@@ -29,6 +29,6 @@
# define TARGET_PAGE_BITS_MIN 10
#endif
#define NB_MMU_MODES 11
#define NB_MMU_MODES 15
#endif
+18 -5
View File
@@ -451,14 +451,14 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
break;
case EXCP_VFIQ:
if (secure || !(hcr_el2 & HCR_FMO) || (hcr_el2 & HCR_TGE)) {
/* VFIQs are only taken when hypervized and non-secure. */
if (!(hcr_el2 & HCR_FMO) || (hcr_el2 & HCR_TGE)) {
/* VFIQs are only taken when hypervized. */
return false;
}
return !(env->daif & PSTATE_F);
case EXCP_VIRQ:
if (secure || !(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) {
/* VIRQs are only taken when hypervized and non-secure. */
if (!(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) {
/* VIRQs are only taken when hypervized. */
return false;
}
return !(env->daif & PSTATE_I);
@@ -480,7 +480,7 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
* masked from Secure state. The HCR and SCR settings
* don't affect the masking logic, only the interrupt routing.
*/
if (target_el == 3 || !secure) {
if (target_el == 3 || !secure || (env->cp15.scr_el3 & SCR_EEL2)) {
unmasked = true;
}
} else {
@@ -1320,6 +1320,19 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp)
error_propagate(errp, local_err);
return;
}
/*
* KVM does not support modifications to this feature.
* We have not registered the cpu properties when KVM
* is in use, so the user will not be able to set them.
*/
if (!kvm_enabled()) {
arm_cpu_pauth_finalize(cpu, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
return;
}
}
}
if (kvm_enabled()) {
+86 -21
View File
@@ -168,6 +168,11 @@ typedef struct {
uint32_t base_mask;
} TCR;
#define VTCR_NSW (1u << 29)
#define VTCR_NSA (1u << 30)
#define VSTCR_SW VTCR_NSW
#define VSTCR_SA VTCR_NSA
/* Define a maximum sized vector register.
* For 32-bit, this is a 128-bit NEON/AdvSIMD register.
* For 64-bit, this is a 2048-bit SVE register.
@@ -197,9 +202,11 @@ typedef struct {
#ifdef TARGET_AARCH64
# define ARM_MAX_VQ 16
void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);
#else
# define ARM_MAX_VQ 1
static inline void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { }
static inline void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) { }
#endif
typedef struct ARMVectorReg {
@@ -323,9 +330,11 @@ typedef struct CPUARMState {
uint64_t ttbr1_el[4];
};
uint64_t vttbr_el2; /* Virtualization Translation Table Base. */
uint64_t vsttbr_el2; /* Secure Virtualization Translation Table. */
/* MMU translation table base control. */
TCR tcr_el[4];
TCR vtcr_el2; /* Virtualization Translation Control. */
TCR vstcr_el2; /* Secure Virtualization Translation Control. */
uint32_t c2_data; /* MPU data cacheable bits. */
uint32_t c2_insn; /* MPU instruction cacheable bits. */
union { /* MMU domain access control register
@@ -947,6 +956,14 @@ struct ARMCPU {
uint64_t reset_cbar;
uint32_t reset_auxcr;
bool reset_hivecs;
/*
* Intermediate values used during property parsing.
* Once finalized, the values should be read from ID_AA64ISAR1.
*/
bool prop_pauth;
bool prop_pauth_impdef;
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
uint32_t dcz_blocksize;
uint64_t rvbar;
@@ -1467,6 +1484,8 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define HCR_TWEDEN (1ULL << 59)
#define HCR_TWEDEL MAKE_64BIT_MASK(60, 4)
#define HPFAR_NS (1ULL << 63)
#define SCR_NS (1U << 0)
#define SCR_IRQ (1U << 1)
#define SCR_FIQ (1U << 2)
@@ -2138,6 +2157,21 @@ static inline bool arm_is_secure(CPUARMState *env)
return arm_is_secure_below_el3(env);
}
/*
* Return true if the current security state has AArch64 EL2 or AArch32 Hyp.
* This corresponds to the pseudocode EL2Enabled()
*/
static inline bool arm_is_el2_enabled(CPUARMState *env)
{
if (arm_feature(env, ARM_FEATURE_EL2)) {
if (arm_is_secure_below_el3(env)) {
return (env->cp15.scr_el3 & SCR_EEL2) != 0;
}
return true;
}
return false;
}
#else
static inline bool arm_is_secure_below_el3(CPUARMState *env)
{
@@ -2148,6 +2182,11 @@ static inline bool arm_is_secure(CPUARMState *env)
{
return false;
}
static inline bool arm_is_el2_enabled(CPUARMState *env)
{
return false;
}
#endif
/**
@@ -2175,7 +2214,8 @@ static inline bool arm_el_is_aa64(CPUARMState *env, int el)
return aa64;
}
if (arm_feature(env, ARM_FEATURE_EL3)) {
if (arm_feature(env, ARM_FEATURE_EL3) &&
((env->cp15.scr_el3 & SCR_NS) || !(env->cp15.scr_el3 & SCR_EEL2))) {
aa64 = aa64 && (env->cp15.scr_el3 & SCR_RW);
}
@@ -2183,7 +2223,7 @@ static inline bool arm_el_is_aa64(CPUARMState *env, int el)
return aa64;
}
if (arm_feature(env, ARM_FEATURE_EL2) && !arm_is_secure_below_el3(env)) {
if (arm_is_el2_enabled(env)) {
aa64 = aa64 && (env->cp15.hcr_el2 & HCR_RW);
}
@@ -3022,6 +3062,9 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
#define ARM_MMU_IDX_NOTLB 0x20 /* does not have a TLB */
#define ARM_MMU_IDX_M 0x40 /* M profile */
/* Meanings of the bits for A profile mmu idx values */
#define ARM_MMU_IDX_A_NS 0x8
/* Meanings of the bits for M profile mmu idx values */
#define ARM_MMU_IDX_M_PRIV 0x1
#define ARM_MMU_IDX_M_NEGPRI 0x2
@@ -3035,20 +3078,22 @@ typedef enum ARMMMUIdx {
/*
* A-profile.
*/
ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
ARMMMUIdx_SE10_0 = 0 | ARM_MMU_IDX_A,
ARMMMUIdx_SE20_0 = 1 | ARM_MMU_IDX_A,
ARMMMUIdx_SE10_1 = 2 | ARM_MMU_IDX_A,
ARMMMUIdx_SE20_2 = 3 | ARM_MMU_IDX_A,
ARMMMUIdx_SE10_1_PAN = 4 | ARM_MMU_IDX_A,
ARMMMUIdx_SE20_2_PAN = 5 | ARM_MMU_IDX_A,
ARMMMUIdx_SE2 = 6 | ARM_MMU_IDX_A,
ARMMMUIdx_SE3 = 7 | ARM_MMU_IDX_A,
ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
ARMMMUIdx_E10_1_PAN = 3 | ARM_MMU_IDX_A,
ARMMMUIdx_E2 = 4 | ARM_MMU_IDX_A,
ARMMMUIdx_E20_2 = 5 | ARM_MMU_IDX_A,
ARMMMUIdx_E20_2_PAN = 6 | ARM_MMU_IDX_A,
ARMMMUIdx_SE10_0 = 7 | ARM_MMU_IDX_A,
ARMMMUIdx_SE10_1 = 8 | ARM_MMU_IDX_A,
ARMMMUIdx_SE10_1_PAN = 9 | ARM_MMU_IDX_A,
ARMMMUIdx_SE3 = 10 | ARM_MMU_IDX_A,
ARMMMUIdx_E10_0 = ARMMMUIdx_SE10_0 | ARM_MMU_IDX_A_NS,
ARMMMUIdx_E20_0 = ARMMMUIdx_SE20_0 | ARM_MMU_IDX_A_NS,
ARMMMUIdx_E10_1 = ARMMMUIdx_SE10_1 | ARM_MMU_IDX_A_NS,
ARMMMUIdx_E20_2 = ARMMMUIdx_SE20_2 | ARM_MMU_IDX_A_NS,
ARMMMUIdx_E10_1_PAN = ARMMMUIdx_SE10_1_PAN | ARM_MMU_IDX_A_NS,
ARMMMUIdx_E20_2_PAN = ARMMMUIdx_SE20_2_PAN | ARM_MMU_IDX_A_NS,
ARMMMUIdx_E2 = ARMMMUIdx_SE2 | ARM_MMU_IDX_A_NS,
/*
* These are not allocated TLBs and are used only for AT system
@@ -3057,6 +3102,9 @@ typedef enum ARMMMUIdx {
ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
ARMMMUIdx_Stage1_E1_PAN = 2 | ARM_MMU_IDX_NOTLB,
ARMMMUIdx_Stage1_SE0 = 3 | ARM_MMU_IDX_NOTLB,
ARMMMUIdx_Stage1_SE1 = 4 | ARM_MMU_IDX_NOTLB,
ARMMMUIdx_Stage1_SE1_PAN = 5 | ARM_MMU_IDX_NOTLB,
/*
* Not allocated a TLB: used only for second stage of an S12 page
* table walk, or for descriptor loads during first stage of an S1
@@ -3064,7 +3112,8 @@ typedef enum ARMMMUIdx {
* then various TLB flush insns which currently are no-ops or flush
* only stage 1 MMU indexes will need to change to flush stage 2.
*/
ARMMMUIdx_Stage2 = 3 | ARM_MMU_IDX_NOTLB,
ARMMMUIdx_Stage2 = 6 | ARM_MMU_IDX_NOTLB,
ARMMMUIdx_Stage2_S = 7 | ARM_MMU_IDX_NOTLB,
/*
* M-profile.
@@ -3095,8 +3144,12 @@ typedef enum ARMMMUIdxBit {
TO_CORE_BIT(E20_2),
TO_CORE_BIT(E20_2_PAN),
TO_CORE_BIT(SE10_0),
TO_CORE_BIT(SE20_0),
TO_CORE_BIT(SE10_1),
TO_CORE_BIT(SE20_2),
TO_CORE_BIT(SE10_1_PAN),
TO_CORE_BIT(SE20_2_PAN),
TO_CORE_BIT(SE2),
TO_CORE_BIT(SE3),
TO_CORE_BIT(MUser),
@@ -3127,7 +3180,7 @@ static inline int arm_debug_target_el(CPUARMState *env)
bool secure = arm_is_secure(env);
bool route_to_el2 = false;
if (arm_feature(env, ARM_FEATURE_EL2) && !secure) {
if (arm_is_el2_enabled(env)) {
route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||
env->cp15.mdcr_el2 & MDCR_TDE;
}
@@ -3918,10 +3971,8 @@ static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id)
{
/*
* Note that while QEMU will only implement the architected algorithm
* QARMA, and thus APA+GPA, the host cpu for kvm may use implementation
* defined algorithms, and thus API+GPI, and this predicate controls
* migration of the 128-bit keys.
* Return true if any form of pauth is enabled, as this
* predicate controls migration of the 128-bit keys.
*/
return (id->id_aa64isar1 &
(FIELD_DP64(0, ID_AA64ISAR1, APA, 0xf) |
@@ -3930,6 +3981,15 @@ static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id)
FIELD_DP64(0, ID_AA64ISAR1, GPI, 0xf))) != 0;
}
static inline bool isar_feature_aa64_pauth_arch(const ARMISARegisters *id)
{
/*
* Return true if pauth is enabled with the architected QARMA algorithm.
* QEMU will always set APA+GPA to the same value.
*/
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) != 0;
}
static inline bool isar_feature_aa64_sb(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0;
@@ -3977,6 +4037,11 @@ static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
}
static inline bool isar_feature_aa64_sel2(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SEL2) != 0;
}
static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
+47 -18
View File
@@ -28,6 +28,8 @@
#include "sysemu/kvm.h"
#include "kvm_arm.h"
#include "qapi/visitor.h"
#include "hw/qdev-properties.h"
#ifndef CONFIG_USER_ONLY
static uint64_t a57_a53_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
@@ -486,6 +488,12 @@ static void cpu_max_set_sve_max_vq(Object *obj, Visitor *v, const char *name,
cpu->sve_max_vq = max_vq;
}
/*
* Note that cpu_arm_get/set_sve_vq cannot use the simpler
* object_property_add_bool interface because they make use
* of the contents of "name" to determine which bit on which
* to operate.
*/
static void cpu_arm_get_sve_vq(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
@@ -527,26 +535,17 @@ static void cpu_arm_set_sve_vq(Object *obj, Visitor *v, const char *name,
set_bit(vq - 1, cpu->sve_vq_init);
}
static void cpu_arm_get_sve(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
static bool cpu_arm_get_sve(Object *obj, Error **errp)
{
ARMCPU *cpu = ARM_CPU(obj);
bool value = cpu_isar_feature(aa64_sve, cpu);
visit_type_bool(v, name, &value, errp);
return cpu_isar_feature(aa64_sve, cpu);
}
static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
static void cpu_arm_set_sve(Object *obj, bool value, Error **errp)
{
ARMCPU *cpu = ARM_CPU(obj);
bool value;
uint64_t t;
if (!visit_type_bool(v, name, &value, errp)) {
return;
}
if (value && kvm_enabled() && !kvm_arm_sve_supported()) {
error_setg(errp, "'sve' feature not supported by KVM on this host");
return;
@@ -561,8 +560,7 @@ void aarch64_add_sve_properties(Object *obj)
{
uint32_t vq;
object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
cpu_arm_set_sve, NULL, NULL);
object_property_add_bool(obj, "sve", cpu_arm_get_sve, cpu_arm_set_sve);
for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
char name[8];
@@ -572,6 +570,36 @@ void aarch64_add_sve_properties(Object *obj)
}
}
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp)
{
int arch_val = 0, impdef_val = 0;
uint64_t t;
/* TODO: Handle HaveEnhancedPAC, HaveEnhancedPAC2, HaveFPAC. */
if (cpu->prop_pauth) {
if (cpu->prop_pauth_impdef) {
impdef_val = 1;
} else {
arch_val = 1;
}
} else if (cpu->prop_pauth_impdef) {
error_setg(errp, "cannot enable pauth-impdef without pauth");
error_append_hint(errp, "Add pauth=on to the CPU property list.\n");
}
t = cpu->isar.id_aa64isar1;
t = FIELD_DP64(t, ID_AA64ISAR1, APA, arch_val);
t = FIELD_DP64(t, ID_AA64ISAR1, GPA, arch_val);
t = FIELD_DP64(t, ID_AA64ISAR1, API, impdef_val);
t = FIELD_DP64(t, ID_AA64ISAR1, GPI, impdef_val);
cpu->isar.id_aa64isar1 = t;
}
static Property arm_cpu_pauth_property =
DEFINE_PROP_BOOL("pauth", ARMCPU, prop_pauth, true);
static Property arm_cpu_pauth_impdef_property =
DEFINE_PROP_BOOL("pauth-impdef", ARMCPU, prop_pauth_impdef, false);
/* -cpu max: if KVM is enabled, like -cpu host (best possible with this host);
* otherwise, a CPU with as many features enabled as our emulation supports.
* The version of '-cpu max' for qemu-system-arm is defined in cpu.c;
@@ -627,10 +655,6 @@ static void aarch64_max_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64ISAR1, DPB, 2);
t = FIELD_DP64(t, ID_AA64ISAR1, JSCVT, 1);
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 1);
t = FIELD_DP64(t, ID_AA64ISAR1, APA, 1); /* PAuth, architected only */
t = FIELD_DP64(t, ID_AA64ISAR1, API, 0);
t = FIELD_DP64(t, ID_AA64ISAR1, GPA, 1);
t = FIELD_DP64(t, ID_AA64ISAR1, GPI, 0);
t = FIELD_DP64(t, ID_AA64ISAR1, SB, 1);
t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1);
@@ -641,6 +665,7 @@ static void aarch64_max_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
t = FIELD_DP64(t, ID_AA64PFR0, FP, 1);
t = FIELD_DP64(t, ID_AA64PFR0, ADVSIMD, 1);
t = FIELD_DP64(t, ID_AA64PFR0, SEL2, 1);
cpu->isar.id_aa64pfr0 = t;
t = cpu->isar.id_aa64pfr1;
@@ -721,6 +746,10 @@ static void aarch64_max_initfn(Object *obj)
cpu->ctr = 0x80038003; /* 32 byte I and D cacheline size, VIPT icache */
cpu->dcz_blocksize = 7; /* 512 bytes */
#endif
/* Default to PAUTH on, with the architected algorithm. */
qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_property);
qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_impdef_property);
}
aarch64_add_sve_properties(obj);
+1 -7
View File
@@ -972,8 +972,7 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
if (new_el == -1) {
goto illegal_return;
}
if (new_el > cur_el
|| (new_el == 2 && !arm_feature(env, ARM_FEATURE_EL2))) {
if (new_el > cur_el || (new_el == 2 && !arm_is_el2_enabled(env))) {
/* Disallow return to an EL which is unimplemented or higher
* than the current one.
*/
@@ -985,11 +984,6 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
goto illegal_return;
}
if (new_el == 2 && arm_is_secure_below_el3(env)) {
/* Return to the non-existent secure-EL2 */
goto illegal_return;
}
if (new_el == 1 && (arm_hcr_el2_eff(env) & HCR_TGE)) {
goto illegal_return;
}
+273 -141
View File
File diff suppressed because it is too large Load Diff
+45
View File
@@ -593,6 +593,7 @@ typedef enum ARMFaultType {
* @s2addr: Address that caused a fault at stage 2
* @stage2: True if we faulted at stage 2
* @s1ptw: True if we faulted at stage 2 while doing a stage 1 page-table walk
* @s1ns: True if we faulted on a non-secure IPA while in secure state
* @ea: True if we should set the EA (external abort type) bit in syndrome
*/
typedef struct ARMMMUFaultInfo ARMMMUFaultInfo;
@@ -603,6 +604,7 @@ struct ARMMMUFaultInfo {
int domain;
bool stage2;
bool s1ptw;
bool s1ns;
bool ea;
};
@@ -851,6 +853,9 @@ static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_Stage1_E1:
case ARMMMUIdx_Stage1_E1_PAN:
case ARMMMUIdx_Stage1_SE0:
case ARMMMUIdx_Stage1_SE1:
case ARMMMUIdx_Stage1_SE1_PAN:
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
case ARMMMUIdx_E10_1_PAN:
@@ -860,6 +865,9 @@ static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
case ARMMMUIdx_SE10_0:
case ARMMMUIdx_SE10_1:
case ARMMMUIdx_SE10_1_PAN:
case ARMMMUIdx_SE20_0:
case ARMMMUIdx_SE20_2:
case ARMMMUIdx_SE20_2_PAN:
return true;
default:
return false;
@@ -890,6 +898,14 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
case ARMMMUIdx_SE10_0:
case ARMMMUIdx_SE10_1:
case ARMMMUIdx_SE10_1_PAN:
case ARMMMUIdx_SE20_0:
case ARMMMUIdx_SE20_2:
case ARMMMUIdx_SE20_2_PAN:
case ARMMMUIdx_Stage1_SE0:
case ARMMMUIdx_Stage1_SE1:
case ARMMMUIdx_Stage1_SE1_PAN:
case ARMMMUIdx_SE2:
case ARMMMUIdx_Stage2_S:
case ARMMMUIdx_MSPrivNegPri:
case ARMMMUIdx_MSUserNegPri:
case ARMMMUIdx_MSPriv:
@@ -904,9 +920,11 @@ static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
{
switch (mmu_idx) {
case ARMMMUIdx_Stage1_E1_PAN:
case ARMMMUIdx_Stage1_SE1_PAN:
case ARMMMUIdx_E10_1_PAN:
case ARMMMUIdx_E20_2_PAN:
case ARMMMUIdx_SE10_1_PAN:
case ARMMMUIdx_SE20_2_PAN:
return true;
default:
return false;
@@ -917,21 +935,29 @@ static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
{
switch (mmu_idx) {
case ARMMMUIdx_SE20_0:
case ARMMMUIdx_SE20_2:
case ARMMMUIdx_SE20_2_PAN:
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
case ARMMMUIdx_E20_2_PAN:
case ARMMMUIdx_Stage2:
case ARMMMUIdx_Stage2_S:
case ARMMMUIdx_SE2:
case ARMMMUIdx_E2:
return 2;
case ARMMMUIdx_SE3:
return 3;
case ARMMMUIdx_SE10_0:
case ARMMMUIdx_Stage1_SE0:
return arm_el_is_aa64(env, 3) ? 1 : 3;
case ARMMMUIdx_SE10_1:
case ARMMMUIdx_SE10_1_PAN:
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_Stage1_E1:
case ARMMMUIdx_Stage1_E1_PAN:
case ARMMMUIdx_Stage1_SE1:
case ARMMMUIdx_Stage1_SE1_PAN:
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
case ARMMMUIdx_E10_1_PAN:
@@ -955,6 +981,13 @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
if (mmu_idx == ARMMMUIdx_Stage2) {
return &env->cp15.vtcr_el2;
}
if (mmu_idx == ARMMMUIdx_Stage2_S) {
/*
* Note: Secure stage 2 nominally shares fields from VTCR_EL2, but
* those are not currently used by QEMU, so just return VSTCR_EL2.
*/
return &env->cp15.vstcr_el2;
}
return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
}
@@ -1157,6 +1190,9 @@ static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx mmu_idx)
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_Stage1_E1:
case ARMMMUIdx_Stage1_E1_PAN:
case ARMMMUIdx_Stage1_SE0:
case ARMMMUIdx_Stage1_SE1:
case ARMMMUIdx_Stage1_SE1_PAN:
return true;
default:
return false;
@@ -1312,6 +1348,15 @@ void arm_log_exception(int idx);
#define LOG2_TAG_GRANULE 4
#define TAG_GRANULE (1 << LOG2_TAG_GRANULE)
/*
* SVE predicates are 1/8 the size of SVE vectors, and cannot use
* the same simd_desc() encoding due to restrictions on size.
* Use these instead.
*/
FIELD(PREDDESC, OPRSZ, 0, 6)
FIELD(PREDDESC, ESZ, 6, 2)
FIELD(PREDDESC, DATA, 8, 24)
/*
* The SVE simd_data field, for memory ops, contains either
* rd (5 bits) or a shift count (2 bits).
+1 -1
View File
@@ -1347,7 +1347,7 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
bool exc_secure = false;
bool return_to_secure;
bool ftype;
bool restore_s16_s31;
bool restore_s16_s31 = false;
/*
* If we're not in Handler mode then jumps to magic exception-exit

Some files were not shown because too many files have changed in this diff Show More