target-arm queue:

* Support EL0 v7m msr/mrs for CONFIG_USER_ONLY
  * Relax r13 restriction for ldrex/strex for v8.0
  * Do not reject rt == rt2 for strexd
  * net/cadence_gem: Set PHY autonegotiation restart status
  * ssi: xilinx_spips: Skip spi bus update for a few register writes
  * pl031: Expose RTCICR as proper WC register
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAl3T7nsZHHBldGVyLm1h
 eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3uMOD/4xK9KDvUyCxwJkEziskodk
 3d9JHrG3YWhpCzUpO01DmqYS6Hy32HYctoSYGoF3eWVYBoA+axqUtiVmcskYOx2F
 BIhBtTW3Svq8I5xP9jYOTS/wTUcHUJ+mWkl1aMDPRD7VJ2TJDUqD8ncFHg0aJI1S
 USFMj8D9bZiyGb5E+JI26LwKmvJO4G+upDyysL7Tmf5n3eTp6W1wdjrriAjFZeq4
 +nMg9Qk3X5hpM3o86acGr3wnLyw3ECMAq932bpcjjRJyHaaYFuz8hF/gQaKohUAB
 KCD7zv/sEu0i4XlzS69J3milFWAl32qF9wCrbWLgb4WMDWVnB4EKKmo5tk92jIK+
 CmddGgJHeyaR2UB6Fczk8khCWB5NpdnECi/7bcVfTBf/ceelrDWUebNztZbKR4UH
 UYpk1GPYbsFTsZyFj0x+b3PcRVDYKgPKrgsHNU3pAZDNwqRXh+R1SBApcQWy7ZDR
 wMTX1Sw92MoigiQS0phqDeUe0saToS3lkNchuFOOW224FsEwk0OpkvXi0c54Wn87
 ao4ScCyxMJkE7lDH0GWpz9w3f8co/+B20X1HwpaCkkm2MvkV4stjuej8O80mtLqE
 kK5CirW9kOjkzhy47L7muAwZlciUlA9p+ZdVTwfTwWSb5aYUuIfHQV5Bz+Pq4uHu
 215+GvJhFCtdcstDu8l+Qg==
 =9Prn
 -----END PGP SIGNATURE-----

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

target-arm queue:
 * Support EL0 v7m msr/mrs for CONFIG_USER_ONLY
 * Relax r13 restriction for ldrex/strex for v8.0
 * Do not reject rt == rt2 for strexd
 * net/cadence_gem: Set PHY autonegotiation restart status
 * ssi: xilinx_spips: Skip spi bus update for a few register writes
 * pl031: Expose RTCICR as proper WC register

# gpg: Signature made Tue 19 Nov 2019 13:30:35 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-20191119:
  target/arm: Support EL0 v7m msr/mrs for CONFIG_USER_ONLY
  target/arm: Relax r13 restriction for ldrex/strex for v8.0
  target/arm: Do not reject rt == rt2 for strexd
  net/cadence_gem: Set PHY autonegotiation restart status
  ssi: xilinx_spips: Skip spi bus update for a few register writes
  target/arm: Merge arm_cpu_vq_map_next_smaller into sole caller
  pl031: Expose RTCICR as proper WC register

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
master
Peter Maydell 2019-11-19 13:32:07 +00:00
commit 9263dec8ef
8 changed files with 113 additions and 81 deletions

View File

@ -271,9 +271,10 @@
#define PHY_REG_EXT_PHYSPCFC_ST 27
#define PHY_REG_CABLE_DIAG 28
#define PHY_REG_CONTROL_RST 0x8000
#define PHY_REG_CONTROL_LOOP 0x4000
#define PHY_REG_CONTROL_ANEG 0x1000
#define PHY_REG_CONTROL_RST 0x8000
#define PHY_REG_CONTROL_LOOP 0x4000
#define PHY_REG_CONTROL_ANEG 0x1000
#define PHY_REG_CONTROL_ANRESTART 0x0200
#define PHY_REG_STATUS_LINK 0x0004
#define PHY_REG_STATUS_ANEGCMPL 0x0020
@ -1345,7 +1346,7 @@ static void gem_phy_write(CadenceGEMState *s, unsigned reg_num, uint16_t val)
}
if (val & PHY_REG_CONTROL_ANEG) {
/* Complete autonegotiation immediately */
val &= ~PHY_REG_CONTROL_ANEG;
val &= ~(PHY_REG_CONTROL_ANEG | PHY_REG_CONTROL_ANRESTART);
s->phy_regs[PHY_REG_STATUS] |= PHY_REG_STATUS_ANEGCMPL;
}
if (val & PHY_REG_CONTROL_LOOP) {

View File

@ -149,11 +149,7 @@ static void pl031_write(void * opaque, hwaddr offset,
pl031_update(s);
break;
case RTC_ICR:
/* The PL031 documentation (DDI0224B) states that the interrupt is
cleared when bit 0 of the written value is set. However the
arm926e documentation (DDI0287B) states that the interrupt is
cleared when any value is written. */
s->is = 0;
s->is &= ~value;
pl031_update(s);
break;
case RTC_CR:

View File

@ -109,6 +109,7 @@
#define R_GPIO (0x30 / 4)
#define R_LPBK_DLY_ADJ (0x38 / 4)
#define R_LPBK_DLY_ADJ_RESET (0x33)
#define R_IOU_TAPDLY_BYPASS (0x3C / 4)
#define R_TXD1 (0x80 / 4)
#define R_TXD2 (0x84 / 4)
#define R_TXD3 (0x88 / 4)
@ -139,6 +140,8 @@
#define R_LQSPI_STS (0xA4 / 4)
#define LQSPI_STS_WR_RECVD (1 << 1)
#define R_DUMMY_CYCLE_EN (0xC8 / 4)
#define R_ECO (0xF8 / 4)
#define R_MOD_ID (0xFC / 4)
#define R_GQSPI_SELECT (0x144 / 4)
@ -970,6 +973,7 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
{
int mask = ~0;
XilinxSPIPS *s = opaque;
bool try_flush = true;
DB_PRINT_L(0, "addr=" TARGET_FMT_plx " = %x\n", addr, (unsigned)value);
addr >>= 2;
@ -1019,13 +1023,23 @@ static void xilinx_spips_write(void *opaque, hwaddr addr,
tx_data_bytes(&s->tx_fifo, (uint32_t)value, 3,
s->regs[R_CONFIG] & R_CONFIG_ENDIAN);
goto no_reg_update;
/* Skip SPI bus update for below registers writes */
case R_GPIO:
case R_LPBK_DLY_ADJ:
case R_IOU_TAPDLY_BYPASS:
case R_DUMMY_CYCLE_EN:
case R_ECO:
try_flush = false;
break;
}
s->regs[addr] = (s->regs[addr] & ~mask) | (value & mask);
no_reg_update:
xilinx_spips_update_cs_lines(s);
xilinx_spips_check_flush(s);
xilinx_spips_update_cs_lines(s);
xilinx_spips_update_ixr(s);
if (try_flush) {
xilinx_spips_update_cs_lines(s);
xilinx_spips_check_flush(s);
xilinx_spips_update_cs_lines(s);
xilinx_spips_update_ixr(s);
}
}
static const MemoryRegionOps spips_ops = {

View File

@ -185,12 +185,9 @@ typedef struct {
#ifdef TARGET_AARCH64
# define ARM_MAX_VQ 16
void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq);
#else
# define ARM_MAX_VQ 1
static inline void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { }
static inline uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq)
{ return 0; }
#endif
typedef struct ARMVectorReg {
@ -1317,6 +1314,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
if (mask & XPSR_GE) {
env->GE = (val & XPSR_GE) >> 16;
}
#ifndef CONFIG_USER_ONLY
if (mask & XPSR_T) {
env->thumb = ((val & XPSR_T) != 0);
}
@ -1332,6 +1330,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
/* Note that this only happens on exception exit */
write_v7m_exception(env, val & XPSR_EXCP);
}
#endif
}
#define HCR_VM (1ULL << 0)

View File

@ -458,21 +458,6 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
cpu->sve_max_vq = max_vq;
}
uint32_t arm_cpu_vq_map_next_smaller(ARMCPU *cpu, uint32_t vq)
{
uint32_t bitnum;
/*
* We allow vq == ARM_MAX_VQ + 1 to be input because the caller may want
* to find the maximum vq enabled, which may be ARM_MAX_VQ, but this
* function always returns the next smaller than the input.
*/
assert(vq && vq <= ARM_MAX_VQ + 1);
bitnum = find_last_bit(cpu->sve_vq_map, vq - 1);
return bitnum == vq - 1 ? 0 : bitnum + 1;
}
static void cpu_max_get_sve_max_vq(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{

View File

@ -5363,9 +5363,14 @@ int sve_exception_el(CPUARMState *env, int el)
static uint32_t sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len)
{
uint32_t start_vq = (start_len & 0xf) + 1;
uint32_t end_len;
return arm_cpu_vq_map_next_smaller(cpu, start_vq + 1) - 1;
end_len = start_len &= 0xf;
if (!test_bit(start_len, cpu->sve_vq_map)) {
end_len = find_last_bit(cpu->sve_vq_map, start_len);
assert(end_len < start_len);
}
return end_len;
}
/*

View File

@ -33,22 +33,82 @@
#include "exec/cpu_ldst.h"
#endif
static void v7m_msr_xpsr(CPUARMState *env, uint32_t mask,
uint32_t reg, uint32_t val)
{
/* Only APSR is actually writable */
if (!(reg & 4)) {
uint32_t apsrmask = 0;
if (mask & 8) {
apsrmask |= XPSR_NZCV | XPSR_Q;
}
if ((mask & 4) && arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
apsrmask |= XPSR_GE;
}
xpsr_write(env, val, apsrmask);
}
}
static uint32_t v7m_mrs_xpsr(CPUARMState *env, uint32_t reg, unsigned el)
{
uint32_t mask = 0;
if ((reg & 1) && el) {
mask |= XPSR_EXCP; /* IPSR (unpriv. reads as zero) */
}
if (!(reg & 4)) {
mask |= XPSR_NZCV | XPSR_Q; /* APSR */
if (arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
mask |= XPSR_GE;
}
}
/* EPSR reads as zero */
return xpsr_read(env) & mask;
}
static uint32_t v7m_mrs_control(CPUARMState *env, uint32_t secure)
{
uint32_t value = env->v7m.control[secure];
if (!secure) {
/* SFPA is RAZ/WI from NS; FPCA is stored in the M_REG_S bank */
value |= env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK;
}
return value;
}
#ifdef CONFIG_USER_ONLY
/* These should probably raise undefined insn exceptions. */
void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
{
ARMCPU *cpu = env_archcpu(env);
uint32_t mask = extract32(maskreg, 8, 4);
uint32_t reg = extract32(maskreg, 0, 8);
cpu_abort(CPU(cpu), "v7m_msr %d\n", reg);
switch (reg) {
case 0 ... 7: /* xPSR sub-fields */
v7m_msr_xpsr(env, mask, reg, val);
break;
case 20: /* CONTROL */
/* There are no sub-fields that are actually writable from EL0. */
break;
default:
/* Unprivileged writes to other registers are ignored */
break;
}
}
uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
{
ARMCPU *cpu = env_archcpu(env);
cpu_abort(CPU(cpu), "v7m_mrs %d\n", reg);
return 0;
switch (reg) {
case 0 ... 7: /* xPSR sub-fields */
return v7m_mrs_xpsr(env, reg, 0);
case 20: /* CONTROL */
return v7m_mrs_control(env, 0);
default:
/* Unprivileged reads others as zero. */
return 0;
}
}
void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
@ -2196,35 +2256,14 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
{
uint32_t mask;
unsigned el = arm_current_el(env);
/* First handle registers which unprivileged can read */
switch (reg) {
case 0 ... 7: /* xPSR sub-fields */
mask = 0;
if ((reg & 1) && el) {
mask |= XPSR_EXCP; /* IPSR (unpriv. reads as zero) */
}
if (!(reg & 4)) {
mask |= XPSR_NZCV | XPSR_Q; /* APSR */
if (arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
mask |= XPSR_GE;
}
}
/* EPSR reads as zero */
return xpsr_read(env) & mask;
break;
return v7m_mrs_xpsr(env, reg, el);
case 20: /* CONTROL */
{
uint32_t value = env->v7m.control[env->v7m.secure];
if (!env->v7m.secure) {
/* SFPA is RAZ/WI from NS; FPCA is stored in the M_REG_S bank */
value |= env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK;
}
return value;
}
return v7m_mrs_control(env, env->v7m.secure);
case 0x94: /* CONTROL_NS */
/*
* We have to handle this here because unprivileged Secure code
@ -2454,18 +2493,7 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
switch (reg) {
case 0 ... 7: /* xPSR sub-fields */
/* only APSR is actually writable */
if (!(reg & 4)) {
uint32_t apsrmask = 0;
if (mask & 8) {
apsrmask |= XPSR_NZCV | XPSR_Q;
}
if ((mask & 4) && arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
apsrmask |= XPSR_GE;
}
xpsr_write(env, val, apsrmask);
}
v7m_msr_xpsr(env, mask, reg, val);
break;
case 8: /* MSP */
if (v7m_using_psp(env)) {

View File

@ -8927,15 +8927,17 @@ static bool trans_SWPB(DisasContext *s, arg_SWP *a)
static bool op_strex(DisasContext *s, arg_STREX *a, MemOp mop, bool rel)
{
TCGv_i32 addr;
/* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
/* We UNDEF for these UNPREDICTABLE cases. */
if (a->rd == 15 || a->rn == 15 || a->rt == 15
|| a->rd == a->rn || a->rd == a->rt
|| (s->thumb && (a->rd == 13 || a->rt == 13))
|| (!v8a && s->thumb && (a->rd == 13 || a->rt == 13))
|| (mop == MO_64
&& (a->rt2 == 15
|| a->rd == a->rt2 || a->rt == a->rt2
|| (s->thumb && a->rt2 == 13)))) {
|| a->rd == a->rt2
|| (!v8a && s->thumb && a->rt2 == 13)))) {
unallocated_encoding(s);
return true;
}
@ -9084,13 +9086,15 @@ static bool trans_STLH(DisasContext *s, arg_STL *a)
static bool op_ldrex(DisasContext *s, arg_LDREX *a, MemOp mop, bool acq)
{
TCGv_i32 addr;
/* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
/* We UNDEF for these UNPREDICTABLE cases. */
if (a->rn == 15 || a->rt == 15
|| (s->thumb && a->rt == 13)
|| (!v8a && s->thumb && a->rt == 13)
|| (mop == MO_64
&& (a->rt2 == 15 || a->rt == a->rt2
|| (s->thumb && a->rt2 == 13)))) {
|| (!v8a && s->thumb && a->rt2 == 13)))) {
unallocated_encoding(s);
return true;
}