mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210525' into staging
target-arm queue: * Implement SVE2 emulation * Implement integer matrix multiply accumulate * Implement FEAT_TLBIOS * Implement FEAT_TLBRANGE * disas/libvixl: Protect C system header for C++ compiler * Use correct SP in M-profile exception return * AN524, AN547: Correct modelling of internal SRAMs * hw/intc/arm_gicv3_cpuif: Fix EOIR write access check logic * hw/arm/smmuv3: Another range invalidation fix # gpg: Signature made Tue 25 May 2021 16:02:25 BST # 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-20210525: (114 commits) target/arm: Enable SVE2 and related extensions linux-user/aarch64: Enable hwcap bits for sve2 and related extensions target/arm: Implement integer matrix multiply accumulate target/arm: Implement aarch32 VSUDOT, VUSDOT target/arm: Split decode of VSDOT and VUDOT target/arm: Split out do_neon_ddda target/arm: Fix decode for VDOT (indexed) target/arm: Remove unused fpst from VDOT_scalar target/arm: Split out do_neon_ddda_fpst target/arm: Implement aarch64 SUDOT, USDOT target/arm: Implement SVE2 fp multiply-add long target/arm: Move endian adjustment macros to vec_internal.h target/arm: Implement SVE2 bitwise shift immediate target/arm: Implement 128-bit ZIP, UZP, TRN target/arm: Implement SVE2 LD1RO target/arm: Tidy do_ldrq target/arm: Share table of sve load functions target/arm: Implement SVE2 FLOGB target/arm: Implement SVE2 FCVTXNT, FCVTX target/arm: Implement SVE2 FCVTLT ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+114
-117
@@ -707,8 +707,9 @@ void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
|
||||
tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS);
|
||||
}
|
||||
|
||||
static void tlb_flush_page_bits_locked(CPUArchState *env, int midx,
|
||||
target_ulong page, unsigned bits)
|
||||
static void tlb_flush_range_locked(CPUArchState *env, int midx,
|
||||
target_ulong addr, target_ulong len,
|
||||
unsigned bits)
|
||||
{
|
||||
CPUTLBDesc *d = &env_tlb(env)->d[midx];
|
||||
CPUTLBDescFast *f = &env_tlb(env)->f[midx];
|
||||
@@ -718,20 +719,26 @@ static void tlb_flush_page_bits_locked(CPUArchState *env, int midx,
|
||||
* If @bits is smaller than the tlb size, there may be multiple entries
|
||||
* within the TLB; otherwise all addresses that match under @mask hit
|
||||
* the same TLB entry.
|
||||
*
|
||||
* TODO: Perhaps allow bits to be a few bits less than the size.
|
||||
* For now, just flush the entire TLB.
|
||||
*
|
||||
* If @len is larger than the tlb size, then it will take longer to
|
||||
* test all of the entries in the TLB than it will to flush it all.
|
||||
*/
|
||||
if (mask < f->mask) {
|
||||
if (mask < f->mask || len > f->mask) {
|
||||
tlb_debug("forcing full flush midx %d ("
|
||||
TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
|
||||
midx, page, mask);
|
||||
TARGET_FMT_lx "/" TARGET_FMT_lx "+" TARGET_FMT_lx ")\n",
|
||||
midx, addr, mask, len);
|
||||
tlb_flush_one_mmuidx_locked(env, midx, get_clock_realtime());
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if we need to flush due to large pages. */
|
||||
if ((page & d->large_page_mask) == d->large_page_addr) {
|
||||
/*
|
||||
* Check if we need to flush due to large pages.
|
||||
* Because large_page_mask contains all 1's from the msb,
|
||||
* we only need to test the end of the range.
|
||||
*/
|
||||
if (((addr + len - 1) & d->large_page_mask) == d->large_page_addr) {
|
||||
tlb_debug("forcing full flush midx %d ("
|
||||
TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
|
||||
midx, d->large_page_addr, d->large_page_mask);
|
||||
@@ -739,85 +746,67 @@ static void tlb_flush_page_bits_locked(CPUArchState *env, int midx,
|
||||
return;
|
||||
}
|
||||
|
||||
if (tlb_flush_entry_mask_locked(tlb_entry(env, midx, page), page, mask)) {
|
||||
tlb_n_used_entries_dec(env, midx);
|
||||
for (target_ulong i = 0; i < len; i += TARGET_PAGE_SIZE) {
|
||||
target_ulong page = addr + i;
|
||||
CPUTLBEntry *entry = tlb_entry(env, midx, page);
|
||||
|
||||
if (tlb_flush_entry_mask_locked(entry, page, mask)) {
|
||||
tlb_n_used_entries_dec(env, midx);
|
||||
}
|
||||
tlb_flush_vtlb_page_mask_locked(env, midx, page, mask);
|
||||
}
|
||||
tlb_flush_vtlb_page_mask_locked(env, midx, page, mask);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
target_ulong addr;
|
||||
target_ulong len;
|
||||
uint16_t idxmap;
|
||||
uint16_t bits;
|
||||
} TLBFlushPageBitsByMMUIdxData;
|
||||
} TLBFlushRangeData;
|
||||
|
||||
static void
|
||||
tlb_flush_page_bits_by_mmuidx_async_0(CPUState *cpu,
|
||||
TLBFlushPageBitsByMMUIdxData d)
|
||||
static void tlb_flush_range_by_mmuidx_async_0(CPUState *cpu,
|
||||
TLBFlushRangeData d)
|
||||
{
|
||||
CPUArchState *env = cpu->env_ptr;
|
||||
int mmu_idx;
|
||||
|
||||
assert_cpu_is_self(cpu);
|
||||
|
||||
tlb_debug("page addr:" TARGET_FMT_lx "/%u mmu_map:0x%x\n",
|
||||
d.addr, d.bits, d.idxmap);
|
||||
tlb_debug("range:" TARGET_FMT_lx "/%u+" TARGET_FMT_lx " mmu_map:0x%x\n",
|
||||
d.addr, d.bits, d.len, d.idxmap);
|
||||
|
||||
qemu_spin_lock(&env_tlb(env)->c.lock);
|
||||
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
|
||||
if ((d.idxmap >> mmu_idx) & 1) {
|
||||
tlb_flush_page_bits_locked(env, mmu_idx, d.addr, d.bits);
|
||||
tlb_flush_range_locked(env, mmu_idx, d.addr, d.len, d.bits);
|
||||
}
|
||||
}
|
||||
qemu_spin_unlock(&env_tlb(env)->c.lock);
|
||||
|
||||
tb_flush_jmp_cache(cpu, d.addr);
|
||||
}
|
||||
|
||||
static bool encode_pbm_to_runon(run_on_cpu_data *out,
|
||||
TLBFlushPageBitsByMMUIdxData d)
|
||||
{
|
||||
/* We need 6 bits to hold to hold @bits up to 63. */
|
||||
if (d.idxmap <= MAKE_64BIT_MASK(0, TARGET_PAGE_BITS - 6)) {
|
||||
*out = RUN_ON_CPU_TARGET_PTR(d.addr | (d.idxmap << 6) | d.bits);
|
||||
return true;
|
||||
for (target_ulong i = 0; i < d.len; i += TARGET_PAGE_SIZE) {
|
||||
tb_flush_jmp_cache(cpu, d.addr + i);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static TLBFlushPageBitsByMMUIdxData
|
||||
decode_runon_to_pbm(run_on_cpu_data data)
|
||||
static void tlb_flush_range_by_mmuidx_async_1(CPUState *cpu,
|
||||
run_on_cpu_data data)
|
||||
{
|
||||
target_ulong addr_map_bits = (target_ulong) data.target_ptr;
|
||||
return (TLBFlushPageBitsByMMUIdxData){
|
||||
.addr = addr_map_bits & TARGET_PAGE_MASK,
|
||||
.idxmap = (addr_map_bits & ~TARGET_PAGE_MASK) >> 6,
|
||||
.bits = addr_map_bits & 0x3f
|
||||
};
|
||||
}
|
||||
|
||||
static void tlb_flush_page_bits_by_mmuidx_async_1(CPUState *cpu,
|
||||
run_on_cpu_data runon)
|
||||
{
|
||||
tlb_flush_page_bits_by_mmuidx_async_0(cpu, decode_runon_to_pbm(runon));
|
||||
}
|
||||
|
||||
static void tlb_flush_page_bits_by_mmuidx_async_2(CPUState *cpu,
|
||||
run_on_cpu_data data)
|
||||
{
|
||||
TLBFlushPageBitsByMMUIdxData *d = data.host_ptr;
|
||||
tlb_flush_page_bits_by_mmuidx_async_0(cpu, *d);
|
||||
TLBFlushRangeData *d = data.host_ptr;
|
||||
tlb_flush_range_by_mmuidx_async_0(cpu, *d);
|
||||
g_free(d);
|
||||
}
|
||||
|
||||
void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
|
||||
uint16_t idxmap, unsigned bits)
|
||||
void tlb_flush_range_by_mmuidx(CPUState *cpu, target_ulong addr,
|
||||
target_ulong len, uint16_t idxmap,
|
||||
unsigned bits)
|
||||
{
|
||||
TLBFlushPageBitsByMMUIdxData d;
|
||||
run_on_cpu_data runon;
|
||||
TLBFlushRangeData d;
|
||||
|
||||
/* If all bits are significant, this devolves to tlb_flush_page. */
|
||||
if (bits >= TARGET_LONG_BITS) {
|
||||
/*
|
||||
* If all bits are significant, and len is small,
|
||||
* this devolves to tlb_flush_page.
|
||||
*/
|
||||
if (bits >= TARGET_LONG_BITS && len <= TARGET_PAGE_SIZE) {
|
||||
tlb_flush_page_by_mmuidx(cpu, addr, idxmap);
|
||||
return;
|
||||
}
|
||||
@@ -829,34 +818,38 @@ void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
|
||||
|
||||
/* This should already be page aligned */
|
||||
d.addr = addr & TARGET_PAGE_MASK;
|
||||
d.len = len;
|
||||
d.idxmap = idxmap;
|
||||
d.bits = bits;
|
||||
|
||||
if (qemu_cpu_is_self(cpu)) {
|
||||
tlb_flush_page_bits_by_mmuidx_async_0(cpu, d);
|
||||
} else if (encode_pbm_to_runon(&runon, d)) {
|
||||
async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
|
||||
tlb_flush_range_by_mmuidx_async_0(cpu, d);
|
||||
} else {
|
||||
TLBFlushPageBitsByMMUIdxData *p
|
||||
= g_new(TLBFlushPageBitsByMMUIdxData, 1);
|
||||
|
||||
/* Otherwise allocate a structure, freed by the worker. */
|
||||
*p = d;
|
||||
async_run_on_cpu(cpu, tlb_flush_page_bits_by_mmuidx_async_2,
|
||||
TLBFlushRangeData *p = g_memdup(&d, sizeof(d));
|
||||
async_run_on_cpu(cpu, tlb_flush_range_by_mmuidx_async_1,
|
||||
RUN_ON_CPU_HOST_PTR(p));
|
||||
}
|
||||
}
|
||||
|
||||
void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *src_cpu,
|
||||
target_ulong addr,
|
||||
uint16_t idxmap,
|
||||
unsigned bits)
|
||||
void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, target_ulong addr,
|
||||
uint16_t idxmap, unsigned bits)
|
||||
{
|
||||
TLBFlushPageBitsByMMUIdxData d;
|
||||
run_on_cpu_data runon;
|
||||
tlb_flush_range_by_mmuidx(cpu, addr, TARGET_PAGE_SIZE, idxmap, bits);
|
||||
}
|
||||
|
||||
/* If all bits are significant, this devolves to tlb_flush_page. */
|
||||
if (bits >= TARGET_LONG_BITS) {
|
||||
void tlb_flush_range_by_mmuidx_all_cpus(CPUState *src_cpu,
|
||||
target_ulong addr, target_ulong len,
|
||||
uint16_t idxmap, unsigned bits)
|
||||
{
|
||||
TLBFlushRangeData d;
|
||||
CPUState *dst_cpu;
|
||||
|
||||
/*
|
||||
* If all bits are significant, and len is small,
|
||||
* this devolves to tlb_flush_page.
|
||||
*/
|
||||
if (bits >= TARGET_LONG_BITS && len <= TARGET_PAGE_SIZE) {
|
||||
tlb_flush_page_by_mmuidx_all_cpus(src_cpu, addr, idxmap);
|
||||
return;
|
||||
}
|
||||
@@ -868,40 +861,45 @@ void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *src_cpu,
|
||||
|
||||
/* This should already be page aligned */
|
||||
d.addr = addr & TARGET_PAGE_MASK;
|
||||
d.len = len;
|
||||
d.idxmap = idxmap;
|
||||
d.bits = bits;
|
||||
|
||||
if (encode_pbm_to_runon(&runon, d)) {
|
||||
flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
|
||||
} else {
|
||||
CPUState *dst_cpu;
|
||||
TLBFlushPageBitsByMMUIdxData *p;
|
||||
|
||||
/* Allocate a separate data block for each destination cpu. */
|
||||
CPU_FOREACH(dst_cpu) {
|
||||
if (dst_cpu != src_cpu) {
|
||||
p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
|
||||
*p = d;
|
||||
async_run_on_cpu(dst_cpu,
|
||||
tlb_flush_page_bits_by_mmuidx_async_2,
|
||||
RUN_ON_CPU_HOST_PTR(p));
|
||||
}
|
||||
/* Allocate a separate data block for each destination cpu. */
|
||||
CPU_FOREACH(dst_cpu) {
|
||||
if (dst_cpu != src_cpu) {
|
||||
TLBFlushRangeData *p = g_memdup(&d, sizeof(d));
|
||||
async_run_on_cpu(dst_cpu,
|
||||
tlb_flush_range_by_mmuidx_async_1,
|
||||
RUN_ON_CPU_HOST_PTR(p));
|
||||
}
|
||||
}
|
||||
|
||||
tlb_flush_page_bits_by_mmuidx_async_0(src_cpu, d);
|
||||
tlb_flush_range_by_mmuidx_async_0(src_cpu, d);
|
||||
}
|
||||
|
||||
void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
|
||||
target_ulong addr,
|
||||
uint16_t idxmap,
|
||||
unsigned bits)
|
||||
void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *src_cpu,
|
||||
target_ulong addr,
|
||||
uint16_t idxmap, unsigned bits)
|
||||
{
|
||||
TLBFlushPageBitsByMMUIdxData d;
|
||||
run_on_cpu_data runon;
|
||||
tlb_flush_range_by_mmuidx_all_cpus(src_cpu, addr, TARGET_PAGE_SIZE,
|
||||
idxmap, bits);
|
||||
}
|
||||
|
||||
/* If all bits are significant, this devolves to tlb_flush_page. */
|
||||
if (bits >= TARGET_LONG_BITS) {
|
||||
void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
|
||||
target_ulong addr,
|
||||
target_ulong len,
|
||||
uint16_t idxmap,
|
||||
unsigned bits)
|
||||
{
|
||||
TLBFlushRangeData d, *p;
|
||||
CPUState *dst_cpu;
|
||||
|
||||
/*
|
||||
* If all bits are significant, and len is small,
|
||||
* this devolves to tlb_flush_page.
|
||||
*/
|
||||
if (bits >= TARGET_LONG_BITS && len <= TARGET_PAGE_SIZE) {
|
||||
tlb_flush_page_by_mmuidx_all_cpus_synced(src_cpu, addr, idxmap);
|
||||
return;
|
||||
}
|
||||
@@ -913,32 +911,31 @@ void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
|
||||
|
||||
/* This should already be page aligned */
|
||||
d.addr = addr & TARGET_PAGE_MASK;
|
||||
d.len = len;
|
||||
d.idxmap = idxmap;
|
||||
d.bits = bits;
|
||||
|
||||
if (encode_pbm_to_runon(&runon, d)) {
|
||||
flush_all_helper(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1, runon);
|
||||
async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_1,
|
||||
runon);
|
||||
} else {
|
||||
CPUState *dst_cpu;
|
||||
TLBFlushPageBitsByMMUIdxData *p;
|
||||
|
||||
/* Allocate a separate data block for each destination cpu. */
|
||||
CPU_FOREACH(dst_cpu) {
|
||||
if (dst_cpu != src_cpu) {
|
||||
p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
|
||||
*p = d;
|
||||
async_run_on_cpu(dst_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
|
||||
RUN_ON_CPU_HOST_PTR(p));
|
||||
}
|
||||
/* Allocate a separate data block for each destination cpu. */
|
||||
CPU_FOREACH(dst_cpu) {
|
||||
if (dst_cpu != src_cpu) {
|
||||
p = g_memdup(&d, sizeof(d));
|
||||
async_run_on_cpu(dst_cpu, tlb_flush_range_by_mmuidx_async_1,
|
||||
RUN_ON_CPU_HOST_PTR(p));
|
||||
}
|
||||
|
||||
p = g_new(TLBFlushPageBitsByMMUIdxData, 1);
|
||||
*p = d;
|
||||
async_safe_run_on_cpu(src_cpu, tlb_flush_page_bits_by_mmuidx_async_2,
|
||||
RUN_ON_CPU_HOST_PTR(p));
|
||||
}
|
||||
|
||||
p = g_memdup(&d, sizeof(d));
|
||||
async_safe_run_on_cpu(src_cpu, tlb_flush_range_by_mmuidx_async_1,
|
||||
RUN_ON_CPU_HOST_PTR(p));
|
||||
}
|
||||
|
||||
void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
|
||||
target_ulong addr,
|
||||
uint16_t idxmap,
|
||||
unsigned bits)
|
||||
{
|
||||
tlb_flush_range_by_mmuidx_all_cpus_synced(src_cpu, addr, TARGET_PAGE_SIZE,
|
||||
idxmap, bits);
|
||||
}
|
||||
|
||||
/* update the TLBs so that writes to code in the virtual page 'addr'
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#ifndef VIXL_CODE_BUFFER_H
|
||||
#define VIXL_CODE_BUFFER_H
|
||||
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
#include "vixl/globals.h"
|
||||
|
||||
namespace vixl {
|
||||
|
||||
@@ -40,15 +40,17 @@
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
extern "C" {
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
}
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "vixl/platform.h"
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#ifndef VIXL_INVALSET_H_
|
||||
#define VIXL_INVALSET_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
#define PLATFORM_H
|
||||
|
||||
// Define platform specific functionalities.
|
||||
extern "C" {
|
||||
#include <signal.h>
|
||||
}
|
||||
|
||||
namespace vixl {
|
||||
inline void HostBreakpoint() { raise(SIGINT); }
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "vixl/utils.h"
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
|
||||
namespace vixl {
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
#ifndef VIXL_UTILS_H
|
||||
#define VIXL_UTILS_H
|
||||
|
||||
#include <string.h>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include "vixl/globals.h"
|
||||
#include "vixl/compiler-intrinsics.h"
|
||||
|
||||
|
||||
+29
-6
@@ -13,6 +13,7 @@
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qapi/error.h"
|
||||
#include "trace.h"
|
||||
#include "hw/sysbus.h"
|
||||
@@ -59,6 +60,7 @@ struct ARMSSEInfo {
|
||||
const char *cpu_type;
|
||||
uint32_t sse_version;
|
||||
int sram_banks;
|
||||
uint32_t sram_bank_base;
|
||||
int num_cpus;
|
||||
uint32_t sys_version;
|
||||
uint32_t iidr;
|
||||
@@ -69,6 +71,7 @@ struct ARMSSEInfo {
|
||||
bool has_cpuid;
|
||||
bool has_cpu_pwrctrl;
|
||||
bool has_sse_counter;
|
||||
bool has_tcms;
|
||||
Property *props;
|
||||
const ARMSSEDeviceInfo *devinfo;
|
||||
const bool *irq_is_common;
|
||||
@@ -102,7 +105,7 @@ static Property sse300_properties[] = {
|
||||
DEFINE_PROP_LINK("memory", ARMSSE, board_memory, TYPE_MEMORY_REGION,
|
||||
MemoryRegion *),
|
||||
DEFINE_PROP_UINT32("EXP_NUMIRQ", ARMSSE, exp_numirq, 64),
|
||||
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 15),
|
||||
DEFINE_PROP_UINT32("SRAM_ADDR_WIDTH", ARMSSE, sram_addr_width, 18),
|
||||
DEFINE_PROP_UINT32("init-svtor", ARMSSE, init_svtor, 0x10000000),
|
||||
DEFINE_PROP_BOOL("CPU0_FPU", ARMSSE, cpu_fpu[0], true),
|
||||
DEFINE_PROP_BOOL("CPU0_DSP", ARMSSE, cpu_dsp[0], true),
|
||||
@@ -504,6 +507,7 @@ static const ARMSSEInfo armsse_variants[] = {
|
||||
.sse_version = ARMSSE_IOTKIT,
|
||||
.cpu_type = ARM_CPU_TYPE_NAME("cortex-m33"),
|
||||
.sram_banks = 1,
|
||||
.sram_bank_base = 0x20000000,
|
||||
.num_cpus = 1,
|
||||
.sys_version = 0x41743,
|
||||
.iidr = 0,
|
||||
@@ -514,6 +518,7 @@ static const ARMSSEInfo armsse_variants[] = {
|
||||
.has_cpuid = false,
|
||||
.has_cpu_pwrctrl = false,
|
||||
.has_sse_counter = false,
|
||||
.has_tcms = false,
|
||||
.props = iotkit_properties,
|
||||
.devinfo = iotkit_devices,
|
||||
.irq_is_common = sse200_irq_is_common,
|
||||
@@ -523,6 +528,7 @@ static const ARMSSEInfo armsse_variants[] = {
|
||||
.sse_version = ARMSSE_SSE200,
|
||||
.cpu_type = ARM_CPU_TYPE_NAME("cortex-m33"),
|
||||
.sram_banks = 4,
|
||||
.sram_bank_base = 0x20000000,
|
||||
.num_cpus = 2,
|
||||
.sys_version = 0x22041743,
|
||||
.iidr = 0,
|
||||
@@ -533,6 +539,7 @@ static const ARMSSEInfo armsse_variants[] = {
|
||||
.has_cpuid = true,
|
||||
.has_cpu_pwrctrl = false,
|
||||
.has_sse_counter = false,
|
||||
.has_tcms = false,
|
||||
.props = sse200_properties,
|
||||
.devinfo = sse200_devices,
|
||||
.irq_is_common = sse200_irq_is_common,
|
||||
@@ -542,6 +549,7 @@ static const ARMSSEInfo armsse_variants[] = {
|
||||
.sse_version = ARMSSE_SSE300,
|
||||
.cpu_type = ARM_CPU_TYPE_NAME("cortex-m55"),
|
||||
.sram_banks = 2,
|
||||
.sram_bank_base = 0x21000000,
|
||||
.num_cpus = 1,
|
||||
.sys_version = 0x7e00043b,
|
||||
.iidr = 0x74a0043b,
|
||||
@@ -552,6 +560,7 @@ static const ARMSSEInfo armsse_variants[] = {
|
||||
.has_cpuid = true,
|
||||
.has_cpu_pwrctrl = true,
|
||||
.has_sse_counter = true,
|
||||
.has_tcms = true,
|
||||
.props = sse300_properties,
|
||||
.devinfo = sse300_devices,
|
||||
.irq_is_common = sse300_irq_is_common,
|
||||
@@ -909,7 +918,6 @@ static void armsse_realize(DeviceState *dev, Error **errp)
|
||||
const ARMSSEDeviceInfo *devinfo;
|
||||
int i;
|
||||
MemoryRegion *mr;
|
||||
Error *err = NULL;
|
||||
SysBusDevice *sbd_apb_ppc0;
|
||||
SysBusDevice *sbd_secctl;
|
||||
DeviceState *dev_apb_ppc0;
|
||||
@@ -918,6 +926,8 @@ static void armsse_realize(DeviceState *dev, Error **errp)
|
||||
DeviceState *dev_splitter;
|
||||
uint32_t addr_width_max;
|
||||
|
||||
ERRP_GUARD();
|
||||
|
||||
if (!s->board_memory) {
|
||||
error_setg(errp, "memory property was not set");
|
||||
return;
|
||||
@@ -1147,10 +1157,9 @@ static void armsse_realize(DeviceState *dev, Error **errp)
|
||||
uint32_t sram_bank_size = 1 << s->sram_addr_width;
|
||||
|
||||
memory_region_init_ram(&s->sram[i], NULL, ramname,
|
||||
sram_bank_size, &err);
|
||||
sram_bank_size, errp);
|
||||
g_free(ramname);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
if (*errp) {
|
||||
return;
|
||||
}
|
||||
object_property_set_link(OBJECT(&s->mpc[i]), "downstream",
|
||||
@@ -1161,7 +1170,7 @@ static void armsse_realize(DeviceState *dev, Error **errp)
|
||||
/* Map the upstream end of the MPC into the right place... */
|
||||
sbd_mpc = SYS_BUS_DEVICE(&s->mpc[i]);
|
||||
memory_region_add_subregion(&s->container,
|
||||
0x20000000 + i * sram_bank_size,
|
||||
info->sram_bank_base + i * sram_bank_size,
|
||||
sysbus_mmio_get_region(sbd_mpc, 1));
|
||||
/* ...and its register interface */
|
||||
memory_region_add_subregion(&s->container, 0x50083000 + i * 0x1000,
|
||||
@@ -1210,6 +1219,20 @@ static void armsse_realize(DeviceState *dev, Error **errp)
|
||||
sysbus_mmio_get_region(sbd, 1));
|
||||
}
|
||||
|
||||
if (info->has_tcms) {
|
||||
/* The SSE-300 has an ITCM at 0x0000_0000 and a DTCM at 0x2000_0000 */
|
||||
memory_region_init_ram(&s->itcm, NULL, "sse300-itcm", 512 * KiB, errp);
|
||||
if (*errp) {
|
||||
return;
|
||||
}
|
||||
memory_region_init_ram(&s->dtcm, NULL, "sse300-dtcm", 512 * KiB, errp);
|
||||
if (*errp) {
|
||||
return;
|
||||
}
|
||||
memory_region_add_subregion(&s->container, 0x00000000, &s->itcm);
|
||||
memory_region_add_subregion(&s->container, 0x20000000, &s->dtcm);
|
||||
}
|
||||
|
||||
/* Devices behind APB PPC0:
|
||||
* 0x40000000: timer0
|
||||
* 0x40001000: timer1
|
||||
|
||||
+20
-19
@@ -123,8 +123,10 @@ struct MPS2TZMachineClass {
|
||||
int numirq; /* Number of external interrupts */
|
||||
int uart_overflow_irq; /* number of the combined UART overflow IRQ */
|
||||
uint32_t init_svtor; /* init-svtor setting for SSE */
|
||||
uint32_t sram_addr_width; /* SRAM_ADDR_WIDTH setting for SSE */
|
||||
const RAMInfo *raminfo;
|
||||
const char *armsse_type;
|
||||
uint32_t boot_ram_size; /* size of ram at address 0; 0 == find in raminfo */
|
||||
};
|
||||
|
||||
struct MPS2TZMachineState {
|
||||
@@ -243,19 +245,13 @@ static const RAMInfo an524_raminfo[] = { {
|
||||
.size = 512 * KiB,
|
||||
.mpc = 0,
|
||||
.mrindex = 0,
|
||||
}, {
|
||||
.name = "sram",
|
||||
.base = 0x20000000,
|
||||
.size = 32 * 4 * KiB,
|
||||
.mpc = -1,
|
||||
.mrindex = 1,
|
||||
}, {
|
||||
/* We don't model QSPI flash yet; for now expose it as simple ROM */
|
||||
.name = "QSPI",
|
||||
.base = 0x28000000,
|
||||
.size = 8 * MiB,
|
||||
.mpc = 1,
|
||||
.mrindex = 2,
|
||||
.mrindex = 1,
|
||||
.flags = IS_ROM,
|
||||
}, {
|
||||
.name = "DDR",
|
||||
@@ -269,23 +265,11 @@ static const RAMInfo an524_raminfo[] = { {
|
||||
};
|
||||
|
||||
static const RAMInfo an547_raminfo[] = { {
|
||||
.name = "itcm",
|
||||
.base = 0x00000000,
|
||||
.size = 512 * KiB,
|
||||
.mpc = -1,
|
||||
.mrindex = 0,
|
||||
}, {
|
||||
.name = "sram",
|
||||
.base = 0x01000000,
|
||||
.size = 2 * MiB,
|
||||
.mpc = 0,
|
||||
.mrindex = 1,
|
||||
}, {
|
||||
.name = "dtcm",
|
||||
.base = 0x20000000,
|
||||
.size = 4 * 128 * KiB,
|
||||
.mpc = -1,
|
||||
.mrindex = 2,
|
||||
}, {
|
||||
.name = "sram 2",
|
||||
.base = 0x21000000,
|
||||
@@ -766,6 +750,14 @@ static uint32_t boot_ram_size(MPS2TZMachineState *mms)
|
||||
const RAMInfo *p;
|
||||
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
|
||||
|
||||
/*
|
||||
* Use a per-board specification (for when the boot RAM is in
|
||||
* the SSE and so doesn't have a RAMInfo list entry)
|
||||
*/
|
||||
if (mmc->boot_ram_size) {
|
||||
return mmc->boot_ram_size;
|
||||
}
|
||||
|
||||
for (p = mmc->raminfo; p->name; p++) {
|
||||
if (p->base == boot_mem_base(mms)) {
|
||||
return p->size;
|
||||
@@ -812,6 +804,7 @@ static void mps2tz_common_init(MachineState *machine)
|
||||
OBJECT(system_memory), &error_abort);
|
||||
qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", mmc->numirq);
|
||||
qdev_prop_set_uint32(iotkitdev, "init-svtor", mmc->init_svtor);
|
||||
qdev_prop_set_uint32(iotkitdev, "SRAM_ADDR_WIDTH", mmc->sram_addr_width);
|
||||
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
|
||||
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
|
||||
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
|
||||
@@ -1269,8 +1262,10 @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
|
||||
mmc->numirq = 92;
|
||||
mmc->uart_overflow_irq = 47;
|
||||
mmc->init_svtor = 0x10000000;
|
||||
mmc->sram_addr_width = 15;
|
||||
mmc->raminfo = an505_raminfo;
|
||||
mmc->armsse_type = TYPE_IOTKIT;
|
||||
mmc->boot_ram_size = 0;
|
||||
mps2tz_set_default_ram_info(mmc);
|
||||
}
|
||||
|
||||
@@ -1296,8 +1291,10 @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
|
||||
mmc->numirq = 92;
|
||||
mmc->uart_overflow_irq = 47;
|
||||
mmc->init_svtor = 0x10000000;
|
||||
mmc->sram_addr_width = 15;
|
||||
mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
|
||||
mmc->armsse_type = TYPE_SSE200;
|
||||
mmc->boot_ram_size = 0;
|
||||
mps2tz_set_default_ram_info(mmc);
|
||||
}
|
||||
|
||||
@@ -1323,8 +1320,10 @@ static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
|
||||
mmc->numirq = 95;
|
||||
mmc->uart_overflow_irq = 47;
|
||||
mmc->init_svtor = 0x10000000;
|
||||
mmc->sram_addr_width = 15;
|
||||
mmc->raminfo = an524_raminfo;
|
||||
mmc->armsse_type = TYPE_SSE200;
|
||||
mmc->boot_ram_size = 0;
|
||||
mps2tz_set_default_ram_info(mmc);
|
||||
|
||||
object_class_property_add_str(oc, "remap", mps2_get_remap, mps2_set_remap);
|
||||
@@ -1355,8 +1354,10 @@ static void mps3tz_an547_class_init(ObjectClass *oc, void *data)
|
||||
mmc->numirq = 96;
|
||||
mmc->uart_overflow_irq = 48;
|
||||
mmc->init_svtor = 0x00000000;
|
||||
mmc->sram_addr_width = 21;
|
||||
mmc->raminfo = an547_raminfo;
|
||||
mmc->armsse_type = TYPE_SSE300;
|
||||
mmc->boot_ram_size = 512 * KiB;
|
||||
mps2tz_set_default_ram_info(mmc);
|
||||
}
|
||||
|
||||
|
||||
+26
-24
@@ -857,43 +857,45 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova,
|
||||
|
||||
static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
|
||||
{
|
||||
uint8_t scale = 0, num = 0, ttl = 0;
|
||||
dma_addr_t addr = CMD_ADDR(cmd);
|
||||
dma_addr_t end, addr = CMD_ADDR(cmd);
|
||||
uint8_t type = CMD_TYPE(cmd);
|
||||
uint16_t vmid = CMD_VMID(cmd);
|
||||
uint8_t scale = CMD_SCALE(cmd);
|
||||
uint8_t num = CMD_NUM(cmd);
|
||||
uint8_t ttl = CMD_TTL(cmd);
|
||||
bool leaf = CMD_LEAF(cmd);
|
||||
uint8_t tg = CMD_TG(cmd);
|
||||
uint64_t first_page = 0, last_page;
|
||||
uint64_t num_pages = 1;
|
||||
uint64_t num_pages;
|
||||
uint8_t granule;
|
||||
int asid = -1;
|
||||
|
||||
if (tg) {
|
||||
scale = CMD_SCALE(cmd);
|
||||
num = CMD_NUM(cmd);
|
||||
ttl = CMD_TTL(cmd);
|
||||
num_pages = (num + 1) * BIT_ULL(scale);
|
||||
}
|
||||
|
||||
if (type == SMMU_CMD_TLBI_NH_VA) {
|
||||
asid = CMD_ASID(cmd);
|
||||
}
|
||||
|
||||
if (!tg) {
|
||||
trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, 1, ttl, leaf);
|
||||
smmuv3_inv_notifiers_iova(s, asid, addr, tg, 1);
|
||||
smmu_iotlb_inv_iova(s, asid, addr, tg, 1, ttl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* RIL in use */
|
||||
|
||||
num_pages = (num + 1) * BIT_ULL(scale);
|
||||
granule = tg * 2 + 10;
|
||||
|
||||
/* Split invalidations into ^2 range invalidations */
|
||||
last_page = num_pages - 1;
|
||||
while (num_pages) {
|
||||
uint8_t granule = tg * 2 + 10;
|
||||
uint64_t mask, count;
|
||||
end = addr + (num_pages << granule) - 1;
|
||||
|
||||
mask = dma_aligned_pow2_mask(first_page, last_page, 64 - granule);
|
||||
count = mask + 1;
|
||||
while (addr != end + 1) {
|
||||
uint64_t mask = dma_aligned_pow2_mask(addr, end, 64);
|
||||
|
||||
trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, count, ttl, leaf);
|
||||
smmuv3_inv_notifiers_iova(s, asid, addr, tg, count);
|
||||
smmu_iotlb_inv_iova(s, asid, addr, tg, count, ttl);
|
||||
|
||||
num_pages -= count;
|
||||
first_page += count;
|
||||
addr += count * BIT_ULL(granule);
|
||||
num_pages = (mask + 1) >> granule;
|
||||
trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf);
|
||||
smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages);
|
||||
smmu_iotlb_inv_iova(s, asid, addr, tg, num_pages, ttl);
|
||||
addr += mask + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+32
-16
@@ -1307,27 +1307,16 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
GICv3CPUState *cs = icc_cs_from_env(env);
|
||||
int irq = value & 0xffffff;
|
||||
int grp;
|
||||
bool is_eoir0 = ri->crm == 8;
|
||||
|
||||
if (icv_access(env, ri->crm == 8 ? HCR_FMO : HCR_IMO)) {
|
||||
if (icv_access(env, is_eoir0 ? HCR_FMO : HCR_IMO)) {
|
||||
icv_eoir_write(env, ri, value);
|
||||
return;
|
||||
}
|
||||
|
||||
trace_gicv3_icc_eoir_write(ri->crm == 8 ? 0 : 1,
|
||||
trace_gicv3_icc_eoir_write(is_eoir0 ? 0 : 1,
|
||||
gicv3_redist_affid(cs), value);
|
||||
|
||||
if (ri->crm == 8) {
|
||||
/* EOIR0 */
|
||||
grp = GICV3_G0;
|
||||
} else {
|
||||
/* EOIR1 */
|
||||
if (arm_is_secure(env)) {
|
||||
grp = GICV3_G1;
|
||||
} else {
|
||||
grp = GICV3_G1NS;
|
||||
}
|
||||
}
|
||||
|
||||
if (irq >= cs->gic->num_irq) {
|
||||
/* This handles two cases:
|
||||
* 1. If software writes the ID of a spurious interrupt [ie 1020-1023]
|
||||
@@ -1340,8 +1329,35 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
return;
|
||||
}
|
||||
|
||||
if (icc_highest_active_group(cs) != grp) {
|
||||
return;
|
||||
grp = icc_highest_active_group(cs);
|
||||
switch (grp) {
|
||||
case GICV3_G0:
|
||||
if (!is_eoir0) {
|
||||
return;
|
||||
}
|
||||
if (!(cs->gic->gicd_ctlr & GICD_CTLR_DS)
|
||||
&& arm_feature(env, ARM_FEATURE_EL3) && !arm_is_secure(env)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GICV3_G1:
|
||||
if (is_eoir0) {
|
||||
return;
|
||||
}
|
||||
if (!arm_is_secure(env)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GICV3_G1NS:
|
||||
if (is_eoir0) {
|
||||
return;
|
||||
}
|
||||
if (!arm_is_el3_or_mon(env) && arm_is_secure(env)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
icc_drop_prio(cs, grp);
|
||||
|
||||
@@ -262,6 +262,31 @@ void tlb_flush_page_bits_by_mmuidx_all_cpus(CPUState *cpu, target_ulong addr,
|
||||
void tlb_flush_page_bits_by_mmuidx_all_cpus_synced
|
||||
(CPUState *cpu, target_ulong addr, uint16_t idxmap, unsigned bits);
|
||||
|
||||
/**
|
||||
* tlb_flush_range_by_mmuidx
|
||||
* @cpu: CPU whose TLB should be flushed
|
||||
* @addr: virtual address of the start of the range to be flushed
|
||||
* @len: length of range to be flushed
|
||||
* @idxmap: bitmap of mmu indexes to flush
|
||||
* @bits: number of significant bits in address
|
||||
*
|
||||
* For each mmuidx in @idxmap, flush all pages within [@addr,@addr+@len),
|
||||
* comparing only the low @bits worth of each virtual page.
|
||||
*/
|
||||
void tlb_flush_range_by_mmuidx(CPUState *cpu, target_ulong addr,
|
||||
target_ulong len, uint16_t idxmap,
|
||||
unsigned bits);
|
||||
|
||||
/* Similarly, with broadcast and syncing. */
|
||||
void tlb_flush_range_by_mmuidx_all_cpus(CPUState *cpu, target_ulong addr,
|
||||
target_ulong len, uint16_t idxmap,
|
||||
unsigned bits);
|
||||
void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu,
|
||||
target_ulong addr,
|
||||
target_ulong len,
|
||||
uint16_t idxmap,
|
||||
unsigned bits);
|
||||
|
||||
/**
|
||||
* tlb_set_page_with_attrs:
|
||||
* @cpu: CPU to add this TLB entry for
|
||||
@@ -365,6 +390,25 @@ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, target_ulong addr,
|
||||
uint16_t idxmap, unsigned bits)
|
||||
{
|
||||
}
|
||||
static inline void tlb_flush_range_by_mmuidx(CPUState *cpu, target_ulong addr,
|
||||
target_ulong len, uint16_t idxmap,
|
||||
unsigned bits)
|
||||
{
|
||||
}
|
||||
static inline void tlb_flush_range_by_mmuidx_all_cpus(CPUState *cpu,
|
||||
target_ulong addr,
|
||||
target_ulong len,
|
||||
uint16_t idxmap,
|
||||
unsigned bits)
|
||||
{
|
||||
}
|
||||
static inline void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu,
|
||||
target_ulong addr,
|
||||
target_long len,
|
||||
uint16_t idxmap,
|
||||
unsigned bits)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* probe_access:
|
||||
|
||||
@@ -198,6 +198,8 @@ struct ARMSSE {
|
||||
MemoryRegion alias2;
|
||||
MemoryRegion alias3[SSE_MAX_CPUS];
|
||||
MemoryRegion sram[MAX_SRAM_BANKS];
|
||||
MemoryRegion itcm;
|
||||
MemoryRegion dtcm;
|
||||
|
||||
qemu_irq *exp_irqs[SSE_MAX_CPUS];
|
||||
qemu_irq ppc0_irq;
|
||||
|
||||
@@ -648,8 +648,18 @@ static uint32_t get_elf_hwcap2(void)
|
||||
uint32_t hwcaps = 0;
|
||||
|
||||
GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP);
|
||||
GET_FEATURE_ID(aa64_sve2, ARM_HWCAP2_A64_SVE2);
|
||||
GET_FEATURE_ID(aa64_sve2_aes, ARM_HWCAP2_A64_SVEAES);
|
||||
GET_FEATURE_ID(aa64_sve2_pmull128, ARM_HWCAP2_A64_SVEPMULL);
|
||||
GET_FEATURE_ID(aa64_sve2_bitperm, ARM_HWCAP2_A64_SVEBITPERM);
|
||||
GET_FEATURE_ID(aa64_sve2_sha3, ARM_HWCAP2_A64_SVESHA3);
|
||||
GET_FEATURE_ID(aa64_sve2_sm4, ARM_HWCAP2_A64_SVESM4);
|
||||
GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2);
|
||||
GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT);
|
||||
GET_FEATURE_ID(aa64_sve_i8mm, ARM_HWCAP2_A64_SVEI8MM);
|
||||
GET_FEATURE_ID(aa64_sve_f32mm, ARM_HWCAP2_A64_SVEF32MM);
|
||||
GET_FEATURE_ID(aa64_sve_f64mm, ARM_HWCAP2_A64_SVEF64MM);
|
||||
GET_FEATURE_ID(aa64_i8mm, ARM_HWCAP2_A64_I8MM);
|
||||
GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG);
|
||||
GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI);
|
||||
GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE);
|
||||
|
||||
@@ -1503,6 +1503,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
|
||||
t = cpu->isar.id_aa64isar1;
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, FCMA, 0);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 0);
|
||||
cpu->isar.id_aa64isar1 = t;
|
||||
|
||||
t = cpu->isar.id_aa64pfr0;
|
||||
@@ -1517,6 +1518,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
u = cpu->isar.id_isar6;
|
||||
u = FIELD_DP32(u, ID_ISAR6, DP, 0);
|
||||
u = FIELD_DP32(u, ID_ISAR6, FHM, 0);
|
||||
u = FIELD_DP32(u, ID_ISAR6, I8MM, 0);
|
||||
cpu->isar.id_isar6 = u;
|
||||
|
||||
if (!arm_feature(env, ARM_FEATURE_M)) {
|
||||
|
||||
@@ -947,6 +947,7 @@ struct ARMCPU {
|
||||
uint64_t id_aa64mmfr2;
|
||||
uint64_t id_aa64dfr0;
|
||||
uint64_t id_aa64dfr1;
|
||||
uint64_t id_aa64zfr0;
|
||||
} isar;
|
||||
uint64_t midr;
|
||||
uint32_t revidr;
|
||||
@@ -2034,6 +2035,16 @@ FIELD(ID_AA64DFR0, DOUBLELOCK, 36, 4)
|
||||
FIELD(ID_AA64DFR0, TRACEFILT, 40, 4)
|
||||
FIELD(ID_AA64DFR0, MTPMU, 48, 4)
|
||||
|
||||
FIELD(ID_AA64ZFR0, SVEVER, 0, 4)
|
||||
FIELD(ID_AA64ZFR0, AES, 4, 4)
|
||||
FIELD(ID_AA64ZFR0, BITPERM, 16, 4)
|
||||
FIELD(ID_AA64ZFR0, BFLOAT16, 20, 4)
|
||||
FIELD(ID_AA64ZFR0, SHA3, 32, 4)
|
||||
FIELD(ID_AA64ZFR0, SM4, 40, 4)
|
||||
FIELD(ID_AA64ZFR0, I8MM, 44, 4)
|
||||
FIELD(ID_AA64ZFR0, F32MM, 52, 4)
|
||||
FIELD(ID_AA64ZFR0, F64MM, 56, 4)
|
||||
|
||||
FIELD(ID_DFR0, COPDBG, 0, 4)
|
||||
FIELD(ID_DFR0, COPSDBG, 4, 4)
|
||||
FIELD(ID_DFR0, MMAPDBG, 8, 4)
|
||||
@@ -3772,6 +3783,11 @@ static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
|
||||
return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX32(id->id_isar6, ID_ISAR6, I8MM) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0;
|
||||
@@ -4071,6 +4087,16 @@ static inline bool isar_feature_aa64_pauth_arch(const ARMISARegisters *id)
|
||||
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) == 2;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_sb(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0;
|
||||
@@ -4195,6 +4221,11 @@ static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id)
|
||||
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0;
|
||||
@@ -4215,6 +4246,51 @@ static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
|
||||
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_sve2_aes(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_sve2_pmull128(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) >= 2;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_sve2_bitperm(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BITPERM) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_sve2_sha3(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SHA3) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_sve2_sm4(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SM4) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, I8MM) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_sve_f32mm(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F32MM) != 0;
|
||||
}
|
||||
|
||||
static inline bool isar_feature_aa64_sve_f64mm(const ARMISARegisters *id)
|
||||
{
|
||||
return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F64MM) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Feature tests for "does this exist in either 32-bit or 64-bit?"
|
||||
*/
|
||||
|
||||
@@ -651,6 +651,7 @@ static void aarch64_max_initfn(Object *obj)
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, DP, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, FHM, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, TS, 2); /* v8.5-CondM */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, TLB, 2); /* FEAT_TLBIRANGE */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR0, RNDR, 1);
|
||||
cpu->isar.id_aa64isar0 = t;
|
||||
|
||||
@@ -662,6 +663,7 @@ static void aarch64_max_initfn(Object *obj)
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, SPECRES, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, FRINTTS, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, LRCPC, 2); /* ARMv8.4-RCPC */
|
||||
t = FIELD_DP64(t, ID_AA64ISAR1, I8MM, 1);
|
||||
cpu->isar.id_aa64isar1 = t;
|
||||
|
||||
t = cpu->isar.id_aa64pfr0;
|
||||
@@ -702,6 +704,17 @@ static void aarch64_max_initfn(Object *obj)
|
||||
t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1); /* TTST */
|
||||
cpu->isar.id_aa64mmfr2 = t;
|
||||
|
||||
t = cpu->isar.id_aa64zfr0;
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, SVEVER, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, AES, 2); /* PMULL */
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, BITPERM, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, SHA3, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, SM4, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, I8MM, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, F32MM, 1);
|
||||
t = FIELD_DP64(t, ID_AA64ZFR0, F64MM, 1);
|
||||
cpu->isar.id_aa64zfr0 = t;
|
||||
|
||||
/* Replicate the same data to the 32-bit id registers. */
|
||||
u = cpu->isar.id_isar5;
|
||||
u = FIELD_DP32(u, ID_ISAR5, AES, 2); /* AES + PMULL */
|
||||
@@ -718,6 +731,7 @@ static void aarch64_max_initfn(Object *obj)
|
||||
u = FIELD_DP32(u, ID_ISAR6, FHM, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR6, SB, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1);
|
||||
u = FIELD_DP32(u, ID_ISAR6, I8MM, 1);
|
||||
cpu->isar.id_isar6 = u;
|
||||
|
||||
u = cpu->isar.id_pfr0;
|
||||
|
||||
@@ -968,6 +968,7 @@ static void arm_max_initfn(Object *obj)
|
||||
t = FIELD_DP32(t, ID_ISAR6, FHM, 1);
|
||||
t = FIELD_DP32(t, ID_ISAR6, SB, 1);
|
||||
t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1);
|
||||
t = FIELD_DP32(t, ID_ISAR6, I8MM, 1);
|
||||
cpu->isar.id_isar6 = t;
|
||||
|
||||
t = cpu->isar.mvfr1;
|
||||
|
||||
+721
-1
File diff suppressed because it is too large
Load Diff
+325
-2
@@ -4759,6 +4759,172 @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
ARMMMUIdxBit_SE3, bits);
|
||||
}
|
||||
|
||||
#ifdef TARGET_AARCH64
|
||||
static uint64_t tlbi_aa64_range_get_length(CPUARMState *env,
|
||||
uint64_t value)
|
||||
{
|
||||
unsigned int page_shift;
|
||||
unsigned int page_size_granule;
|
||||
uint64_t num;
|
||||
uint64_t scale;
|
||||
uint64_t exponent;
|
||||
uint64_t length;
|
||||
|
||||
num = extract64(value, 39, 4);
|
||||
scale = extract64(value, 44, 2);
|
||||
page_size_granule = extract64(value, 46, 2);
|
||||
|
||||
page_shift = page_size_granule * 2 + 12;
|
||||
|
||||
if (page_size_granule == 0) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "Invalid page size granule %d\n",
|
||||
page_size_granule);
|
||||
return 0;
|
||||
}
|
||||
|
||||
exponent = (5 * scale) + 1;
|
||||
length = (num + 1) << (exponent + page_shift);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static uint64_t tlbi_aa64_range_get_base(CPUARMState *env, uint64_t value,
|
||||
bool two_ranges)
|
||||
{
|
||||
/* TODO: ARMv8.7 FEAT_LPA2 */
|
||||
uint64_t pageaddr;
|
||||
|
||||
if (two_ranges) {
|
||||
pageaddr = sextract64(value, 0, 37) << TARGET_PAGE_BITS;
|
||||
} else {
|
||||
pageaddr = extract64(value, 0, 37) << TARGET_PAGE_BITS;
|
||||
}
|
||||
|
||||
return pageaddr;
|
||||
}
|
||||
|
||||
static void do_rvae_write(CPUARMState *env, uint64_t value,
|
||||
int idxmap, bool synced)
|
||||
{
|
||||
ARMMMUIdx one_idx = ARM_MMU_IDX_A | ctz32(idxmap);
|
||||
bool two_ranges = regime_has_2_ranges(one_idx);
|
||||
uint64_t baseaddr, length;
|
||||
int bits;
|
||||
|
||||
baseaddr = tlbi_aa64_range_get_base(env, value, two_ranges);
|
||||
length = tlbi_aa64_range_get_length(env, value);
|
||||
bits = tlbbits_for_regime(env, one_idx, baseaddr);
|
||||
|
||||
if (synced) {
|
||||
tlb_flush_range_by_mmuidx_all_cpus_synced(env_cpu(env),
|
||||
baseaddr,
|
||||
length,
|
||||
idxmap,
|
||||
bits);
|
||||
} else {
|
||||
tlb_flush_range_by_mmuidx(env_cpu(env), baseaddr,
|
||||
length, idxmap, bits);
|
||||
}
|
||||
}
|
||||
|
||||
static void tlbi_aa64_rvae1_write(CPUARMState *env,
|
||||
const ARMCPRegInfo *ri,
|
||||
uint64_t value)
|
||||
{
|
||||
/*
|
||||
* Invalidate by VA range, EL1&0.
|
||||
* Currently handles all of RVAE1, RVAAE1, RVAALE1 and RVALE1,
|
||||
* since we don't support flush-for-specific-ASID-only or
|
||||
* flush-last-level-only.
|
||||
*/
|
||||
|
||||
do_rvae_write(env, value, vae1_tlbmask(env),
|
||||
tlb_force_broadcast(env));
|
||||
}
|
||||
|
||||
static void tlbi_aa64_rvae1is_write(CPUARMState *env,
|
||||
const ARMCPRegInfo *ri,
|
||||
uint64_t value)
|
||||
{
|
||||
/*
|
||||
* Invalidate by VA range, Inner/Outer Shareable EL1&0.
|
||||
* Currently handles all of RVAE1IS, RVAE1OS, RVAAE1IS, RVAAE1OS,
|
||||
* RVAALE1IS, RVAALE1OS, RVALE1IS and RVALE1OS, since we don't support
|
||||
* flush-for-specific-ASID-only, flush-last-level-only or inner/outer
|
||||
* shareable specific flushes.
|
||||
*/
|
||||
|
||||
do_rvae_write(env, value, vae1_tlbmask(env), true);
|
||||
}
|
||||
|
||||
static int vae2_tlbmask(CPUARMState *env)
|
||||
{
|
||||
return (arm_is_secure_below_el3(env)
|
||||
? ARMMMUIdxBit_SE2 : ARMMMUIdxBit_E2);
|
||||
}
|
||||
|
||||
static void tlbi_aa64_rvae2_write(CPUARMState *env,
|
||||
const ARMCPRegInfo *ri,
|
||||
uint64_t value)
|
||||
{
|
||||
/*
|
||||
* Invalidate by VA range, EL2.
|
||||
* Currently handles all of RVAE2 and RVALE2,
|
||||
* since we don't support flush-for-specific-ASID-only or
|
||||
* flush-last-level-only.
|
||||
*/
|
||||
|
||||
do_rvae_write(env, value, vae2_tlbmask(env),
|
||||
tlb_force_broadcast(env));
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void tlbi_aa64_rvae2is_write(CPUARMState *env,
|
||||
const ARMCPRegInfo *ri,
|
||||
uint64_t value)
|
||||
{
|
||||
/*
|
||||
* Invalidate by VA range, Inner/Outer Shareable, EL2.
|
||||
* Currently handles all of RVAE2IS, RVAE2OS, RVALE2IS and RVALE2OS,
|
||||
* since we don't support flush-for-specific-ASID-only,
|
||||
* flush-last-level-only or inner/outer shareable specific flushes.
|
||||
*/
|
||||
|
||||
do_rvae_write(env, value, vae2_tlbmask(env), true);
|
||||
|
||||
}
|
||||
|
||||
static void tlbi_aa64_rvae3_write(CPUARMState *env,
|
||||
const ARMCPRegInfo *ri,
|
||||
uint64_t value)
|
||||
{
|
||||
/*
|
||||
* Invalidate by VA range, EL3.
|
||||
* Currently handles all of RVAE3 and RVALE3,
|
||||
* since we don't support flush-for-specific-ASID-only or
|
||||
* flush-last-level-only.
|
||||
*/
|
||||
|
||||
do_rvae_write(env, value, ARMMMUIdxBit_SE3,
|
||||
tlb_force_broadcast(env));
|
||||
}
|
||||
|
||||
static void tlbi_aa64_rvae3is_write(CPUARMState *env,
|
||||
const ARMCPRegInfo *ri,
|
||||
uint64_t value)
|
||||
{
|
||||
/*
|
||||
* Invalidate by VA range, EL3, Inner/Outer Shareable.
|
||||
* Currently handles all of RVAE3IS, RVAE3OS, RVALE3IS and RVALE3OS,
|
||||
* since we don't support flush-for-specific-ASID-only,
|
||||
* flush-last-level-only or inner/outer specific flushes.
|
||||
*/
|
||||
|
||||
do_rvae_write(env, value, ARMMMUIdxBit_SE3, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
bool isread)
|
||||
{
|
||||
@@ -6920,6 +7086,158 @@ static const ARMCPRegInfo pauth_reginfo[] = {
|
||||
REGINFO_SENTINEL
|
||||
};
|
||||
|
||||
static const ARMCPRegInfo tlbirange_reginfo[] = {
|
||||
{ .name = "TLBI_RVAE1IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 1,
|
||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae1is_write },
|
||||
{ .name = "TLBI_RVAAE1IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 3,
|
||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae1is_write },
|
||||
{ .name = "TLBI_RVALE1IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 5,
|
||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae1is_write },
|
||||
{ .name = "TLBI_RVAALE1IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 2, .opc2 = 7,
|
||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae1is_write },
|
||||
{ .name = "TLBI_RVAE1OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 1,
|
||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae1is_write },
|
||||
{ .name = "TLBI_RVAAE1OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 3,
|
||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae1is_write },
|
||||
{ .name = "TLBI_RVALE1OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 5,
|
||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae1is_write },
|
||||
{ .name = "TLBI_RVAALE1OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 5, .opc2 = 7,
|
||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae1is_write },
|
||||
{ .name = "TLBI_RVAE1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 1,
|
||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae1_write },
|
||||
{ .name = "TLBI_RVAAE1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 3,
|
||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae1_write },
|
||||
{ .name = "TLBI_RVALE1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 5,
|
||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae1_write },
|
||||
{ .name = "TLBI_RVAALE1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 6, .opc2 = 7,
|
||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae1_write },
|
||||
{ .name = "TLBI_RIPAS2E1IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 2,
|
||||
.access = PL2_W, .type = ARM_CP_NOP },
|
||||
{ .name = "TLBI_RIPAS2LE1IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 0, .opc2 = 6,
|
||||
.access = PL2_W, .type = ARM_CP_NOP },
|
||||
{ .name = "TLBI_RVAE2IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 2, .opc2 = 1,
|
||||
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae2is_write },
|
||||
{ .name = "TLBI_RVALE2IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 2, .opc2 = 5,
|
||||
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae2is_write },
|
||||
{ .name = "TLBI_RIPAS2E1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 2,
|
||||
.access = PL2_W, .type = ARM_CP_NOP },
|
||||
{ .name = "TLBI_RIPAS2LE1", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 6,
|
||||
.access = PL2_W, .type = ARM_CP_NOP },
|
||||
{ .name = "TLBI_RVAE2OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 5, .opc2 = 1,
|
||||
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae2is_write },
|
||||
{ .name = "TLBI_RVALE2OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 5, .opc2 = 5,
|
||||
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae2is_write },
|
||||
{ .name = "TLBI_RVAE2", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 6, .opc2 = 1,
|
||||
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae2_write },
|
||||
{ .name = "TLBI_RVALE2", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 6, .opc2 = 5,
|
||||
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae2_write },
|
||||
{ .name = "TLBI_RVAE3IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 2, .opc2 = 1,
|
||||
.access = PL3_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae3is_write },
|
||||
{ .name = "TLBI_RVALE3IS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 2, .opc2 = 5,
|
||||
.access = PL3_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae3is_write },
|
||||
{ .name = "TLBI_RVAE3OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 5, .opc2 = 1,
|
||||
.access = PL3_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae3is_write },
|
||||
{ .name = "TLBI_RVALE3OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 5, .opc2 = 5,
|
||||
.access = PL3_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae3is_write },
|
||||
{ .name = "TLBI_RVAE3", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 6, .opc2 = 1,
|
||||
.access = PL3_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae3_write },
|
||||
{ .name = "TLBI_RVALE3", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 6, .opc2 = 5,
|
||||
.access = PL3_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_rvae3_write },
|
||||
REGINFO_SENTINEL
|
||||
};
|
||||
|
||||
static const ARMCPRegInfo tlbios_reginfo[] = {
|
||||
{ .name = "TLBI_VMALLE1OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 0,
|
||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_vmalle1is_write },
|
||||
{ .name = "TLBI_ASIDE1OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 2,
|
||||
.access = PL1_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_vmalle1is_write },
|
||||
{ .name = "TLBI_ALLE2OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 0,
|
||||
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_alle2is_write },
|
||||
{ .name = "TLBI_ALLE1OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 4,
|
||||
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_alle1is_write },
|
||||
{ .name = "TLBI_VMALLS12E1OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 6,
|
||||
.access = PL2_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_alle1is_write },
|
||||
{ .name = "TLBI_IPAS2E1OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 0,
|
||||
.access = PL2_W, .type = ARM_CP_NOP },
|
||||
{ .name = "TLBI_RIPAS2E1OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 3,
|
||||
.access = PL2_W, .type = ARM_CP_NOP },
|
||||
{ .name = "TLBI_IPAS2LE1OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 4,
|
||||
.access = PL2_W, .type = ARM_CP_NOP },
|
||||
{ .name = "TLBI_RIPAS2LE1OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 4, .opc2 = 7,
|
||||
.access = PL2_W, .type = ARM_CP_NOP },
|
||||
{ .name = "TLBI_ALLE3OS", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 0,
|
||||
.access = PL3_W, .type = ARM_CP_NO_RAW,
|
||||
.writefn = tlbi_aa64_alle3is_write },
|
||||
REGINFO_SENTINEL
|
||||
};
|
||||
|
||||
static uint64_t rndr_readfn(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
{
|
||||
Error *err = NULL;
|
||||
@@ -7561,8 +7879,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 4,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
.accessfn = access_aa64_tid3,
|
||||
/* At present, only SVEver == 0 is defined anyway. */
|
||||
.resetvalue = 0 },
|
||||
.resetvalue = cpu->isar.id_aa64zfr0 },
|
||||
{ .name = "ID_AA64PFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
|
||||
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 5,
|
||||
.access = PL1_R, .type = ARM_CP_CONST,
|
||||
@@ -8289,6 +8606,12 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||
if (cpu_isar_feature(aa64_rndr, cpu)) {
|
||||
define_arm_cp_regs(cpu, rndr_reginfo);
|
||||
}
|
||||
if (cpu_isar_feature(aa64_tlbirange, cpu)) {
|
||||
define_arm_cp_regs(cpu, tlbirange_reginfo);
|
||||
}
|
||||
if (cpu_isar_feature(aa64_tlbios, cpu)) {
|
||||
define_arm_cp_regs(cpu, tlbios_reginfo);
|
||||
}
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* Data Cache clean instructions up to PoP */
|
||||
if (cpu_isar_feature(aa64_dcpop, cpu)) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user