Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-2…
Browse files Browse the repository at this point in the history
…0160226' into staging

target-arm queue:
 * Clean up handling of bad mode switches writing to CPSR, and implement
   the ARMv8 requirement that they set PSTATE.IL
 * Implement MDCR_EL3.TPM and MDCR_EL2.TPM traps on perf monitor
   register accesses
 * Don't implement stellaris-pl061-only registers on generic-pl061
 * Fix SD card handling for raspi
 * Add missing include files to MAINTAINERS
 * Mark CNTHP_TVAL_EL2 as ARM_CP_NO_RAW
 * Make reserved ranges in ID_AA64* spaces RAZ, not UNDEF

# gpg: Signature made Fri 26 Feb 2016 15:19:07 GMT using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"

* remotes/pmaydell/tags/pull-target-arm-20160226:
  target-arm: Make reserved ranges in ID_AA64* spaces RAZ, not UNDEF
  target-arm: Mark CNTHP_TVAL_EL2 as ARM_CP_NO_RAW
  sdhci: add quirk property for card insert interrupt status on Raspberry Pi
  sdhci: Revert "add optional quirk property to disable card insertion/removal interrupts"
  MAINTAINERS: Add some missing ARM related header files
  raspi: fix SD card with recent sdhci changes
  ARM: PL061: Checking register r/w accesses to reserved area
  target-arm: Implement MDCR_EL3.TPM and MDCR_EL2.TPM traps
  target-arm: Fix handling of SDCR for 32-bit code
  target-arm: Make Monitor->NS PL1 mode changes illegal if HCR.TGE is 1
  target-arm: Make mode switches from Hyp via CPS and MRS illegal
  target-arm: In v8, make illegal AArch32 mode changes set PSTATE.IL
  target-arm: Forbid mode switch to Mon from Secure EL1
  target-arm: Add Hyp mode checks to bad_mode_switch()
  target-arm: Add comment about not implementing NSACR.RFR
  target-arm: In cpsr_write() ignore mode switches from User mode
  linux-user: Use restrictive mask when calling cpsr_write()
  target-arm: Raw CPSR writes should skip checks and bank switching
  target-arm: Add write_type argument to cpsr_write()
  target-arm: Give CPSR setting on 32-bit exception return its own helper

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Feb 26, 2016
2 parents aa53d5b + e20d84c commit 6e378dd
Show file tree
Hide file tree
Showing 20 changed files with 359 additions and 69 deletions.
4 changes: 4 additions & 0 deletions MAINTAINERS
Expand Up @@ -363,6 +363,7 @@ M: Dmitry Solodkiy <d.solodkiy@samsung.com>
L: qemu-arm@nongnu.org
S: Maintained
F: hw/*/exynos*
F: include/hw/arm/exynos4210.h

Calxeda Highbank
M: Rob Herring <robh@kernel.org>
Expand Down Expand Up @@ -390,6 +391,7 @@ L: qemu-arm@nongnu.org
S: Odd fixes
F: hw/*/imx*
F: hw/arm/kzm.c
F: include/hw/arm/fsl-imx31.h

Integrator CP
M: Peter Maydell <peter.maydell@linaro.org>
Expand Down Expand Up @@ -432,6 +434,7 @@ F: hw/arm/spitz.c
F: hw/arm/tosa.c
F: hw/arm/z2.c
F: hw/*/pxa2xx*
F: include/hw/arm/pxa.h

Stellaris
M: Peter Maydell <peter.maydell@linaro.org>
Expand Down Expand Up @@ -768,6 +771,7 @@ OMAP
M: Peter Maydell <peter.maydell@linaro.org>
S: Maintained
F: hw/*/omap*
F: include/hw/arm/omap.h

IPack
M: Alberto Garcia <berto@igalia.com>
Expand Down
7 changes: 7 additions & 0 deletions hw/arm/bcm2835_peripherals.c
Expand Up @@ -182,6 +182,13 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
INTERRUPT_ARASANSDIO));
object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->sdhci), "sd-bus",
&err);
if (err) {
error_propagate(errp, err);
return;
}

}

static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
Expand Down
7 changes: 7 additions & 0 deletions hw/arm/bcm2836.c
Expand Up @@ -73,6 +73,13 @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
return;
}

object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->peripherals),
"sd-bus", &err);
if (err) {
error_propagate(errp, err);
return;
}

sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0,
BCM2836_PERI_BASE, 1);

Expand Down
16 changes: 16 additions & 0 deletions hw/arm/raspi.c
Expand Up @@ -113,6 +113,10 @@ static void setup_boot(MachineState *machine, int version, size_t ram_size)
static void raspi2_init(MachineState *machine)
{
RasPiState *s = g_new0(RasPiState, 1);
DriveInfo *di;
BlockBackend *blk;
BusState *bus;
DeviceState *carddev;

object_initialize(&s->soc, sizeof(s->soc), TYPE_BCM2836);
object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
Expand All @@ -133,6 +137,18 @@ static void raspi2_init(MachineState *machine)
&error_abort);
object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort);

/* Create and plug in the SD cards */
di = drive_get_next(IF_SD);
blk = di ? blk_by_legacy_dinfo(di) : NULL;
bus = qdev_get_child_bus(DEVICE(&s->soc), "sd-bus");
if (bus == NULL) {
error_report("No SD bus found in SOC object");
exit(1);
}
carddev = qdev_create(bus, TYPE_SD_CARD);
qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
object_property_set_bool(OBJECT(carddev), true, "realized", &error_fatal);

setup_boot(machine, 2, machine->ram_size);
}

Expand Down
30 changes: 22 additions & 8 deletions hw/gpio/pl061.c
Expand Up @@ -60,6 +60,7 @@ typedef struct PL061State {
qemu_irq irq;
qemu_irq out[8];
const unsigned char *id;
uint32_t rsvd_start; /* reserved area: [rsvd_start, 0xfcc] */
} PL061State;

static const VMStateDescription vmstate_pl061 = {
Expand Down Expand Up @@ -152,12 +153,15 @@ static uint64_t pl061_read(void *opaque, hwaddr offset,
{
PL061State *s = (PL061State *)opaque;

if (offset >= 0xfd0 && offset < 0x1000) {
return s->id[(offset - 0xfd0) >> 2];
}
if (offset < 0x400) {
return s->data & (offset >> 2);
}
if (offset >= s->rsvd_start && offset <= 0xfcc) {
goto err_out;
}
if (offset >= 0xfd0 && offset < 0x1000) {
return s->id[(offset - 0xfd0) >> 2];
}
switch (offset) {
case 0x400: /* Direction */
return s->dir;
Expand Down Expand Up @@ -198,10 +202,12 @@ static uint64_t pl061_read(void *opaque, hwaddr offset,
case 0x528: /* Analog mode select */
return s->amsel;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"pl061_read: Bad offset %x\n", (int)offset);
return 0;
break;
}
err_out:
qemu_log_mask(LOG_GUEST_ERROR,
"pl061_read: Bad offset %x\n", (int)offset);
return 0;
}

static void pl061_write(void *opaque, hwaddr offset,
Expand All @@ -216,6 +222,9 @@ static void pl061_write(void *opaque, hwaddr offset,
pl061_update(s);
return;
}
if (offset >= s->rsvd_start) {
goto err_out;
}
switch (offset) {
case 0x400: /* Direction */
s->dir = value & 0xff;
Expand Down Expand Up @@ -274,10 +283,13 @@ static void pl061_write(void *opaque, hwaddr offset,
s->amsel = value & 0xff;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"pl061_write: Bad offset %x\n", (int)offset);
goto err_out;
}
pl061_update(s);
return;
err_out:
qemu_log_mask(LOG_GUEST_ERROR,
"pl061_write: Bad offset %x\n", (int)offset);
}

static void pl061_reset(DeviceState *dev)
Expand Down Expand Up @@ -347,13 +359,15 @@ static void pl061_luminary_init(Object *obj)
PL061State *s = PL061(obj);

s->id = pl061_id_luminary;
s->rsvd_start = 0x52c;
}

static void pl061_init(Object *obj)
{
PL061State *s = PL061(obj);

s->id = pl061_id;
s->rsvd_start = 0x424;
}

static void pl061_class_init(ObjectClass *klass, void *data)
Expand Down
47 changes: 40 additions & 7 deletions hw/sd/sdhci.c
Expand Up @@ -198,14 +198,13 @@ static void sdhci_reset(SDHCIState *s)
* initialization */
memset(&s->sdmasysad, 0, (uintptr_t)&s->capareg - (uintptr_t)&s->sdmasysad);

if (!s->noeject_quirk) {
/* Reset other state based on current card insertion/readonly status */
sdhci_set_inserted(dev, sdbus_get_inserted(&s->sdbus));
sdhci_set_readonly(dev, sdbus_get_readonly(&s->sdbus));
}
/* Reset other state based on current card insertion/readonly status */
sdhci_set_inserted(dev, sdbus_get_inserted(&s->sdbus));
sdhci_set_readonly(dev, sdbus_get_readonly(&s->sdbus));

s->data_count = 0;
s->stopped_state = sdhc_not_stopped;
s->pending_insert_state = false;
}

static void sdhci_data_transfer(void *opaque);
Expand Down Expand Up @@ -1097,6 +1096,13 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
} else {
s->norintsts &= ~SDHC_NIS_ERR;
}
/* Quirk for Raspberry Pi: pending card insert interrupt
* appears when first enabled after power on */
if ((s->norintstsen & SDHC_NISEN_INSERT) && s->pending_insert_state) {
assert(s->pending_insert_quirk);
s->norintsts |= SDHC_NIS_INSERT;
s->pending_insert_state = false;
}
sdhci_update_irq(s);
break;
case SDHC_NORINTSIGEN:
Expand Down Expand Up @@ -1183,6 +1189,24 @@ static void sdhci_uninitfn(SDHCIState *s)
s->fifo_buffer = NULL;
}

static bool sdhci_pending_insert_vmstate_needed(void *opaque)
{
SDHCIState *s = opaque;

return s->pending_insert_state;
}

static const VMStateDescription sdhci_pending_insert_vmstate = {
.name = "sdhci/pending-insert",
.version_id = 1,
.minimum_version_id = 1,
.needed = sdhci_pending_insert_vmstate_needed,
.fields = (VMStateField[]) {
VMSTATE_BOOL(pending_insert_state, SDHCIState),
VMSTATE_END_OF_LIST()
},
};

const VMStateDescription sdhci_vmstate = {
.name = "sdhci",
.version_id = 1,
Expand Down Expand Up @@ -1217,7 +1241,11 @@ const VMStateDescription sdhci_vmstate = {
VMSTATE_TIMER_PTR(insert_timer, SDHCIState),
VMSTATE_TIMER_PTR(transfer_timer, SDHCIState),
VMSTATE_END_OF_LIST()
}
},
.subsections = (const VMStateDescription*[]) {
&sdhci_pending_insert_vmstate,
NULL
},
};

/* Capabilities registers provide information on supported features of this
Expand Down Expand Up @@ -1275,7 +1303,8 @@ static Property sdhci_sysbus_properties[] = {
DEFINE_PROP_UINT32("capareg", SDHCIState, capareg,
SDHC_CAPAB_REG_DEFAULT),
DEFINE_PROP_UINT32("maxcurr", SDHCIState, maxcurr, 0),
DEFINE_PROP_BOOL("noeject-quirk", SDHCIState, noeject_quirk, false),
DEFINE_PROP_BOOL("pending-insert-quirk", SDHCIState, pending_insert_quirk,
false),
DEFINE_PROP_END_OF_LIST(),
};

Expand Down Expand Up @@ -1303,6 +1332,10 @@ static void sdhci_sysbus_realize(DeviceState *dev, Error ** errp)
memory_region_init_io(&s->iomem, OBJECT(s), &sdhci_mmio_ops, s, "sdhci",
SDHC_REGISTERS_MAP_SIZE);
sysbus_init_mmio(sbd, &s->iomem);

if (s->pending_insert_quirk) {
s->pending_insert_state = true;
}
}

static void sdhci_sysbus_class_init(ObjectClass *klass, void *data)
Expand Down
3 changes: 2 additions & 1 deletion include/hw/sd/sdhci.h
Expand Up @@ -76,7 +76,8 @@ typedef struct SDHCIState {
uint32_t buf_maxsz;
uint16_t data_count; /* current element in FIFO buffer */
uint8_t stopped_state;/* Current SDHC state */
bool noeject_quirk;/* Quirk to disable card insert/remove interrupts */
bool pending_insert_quirk;/* Quirk for Raspberry Pi card insert int */
bool pending_insert_state;
/* Buffer Data Port Register - virtual access point to R and W buffers */
/* Software Reset Register - always reads as 0 */
/* Force Event Auto CMD12 Error Interrupt Reg - write only */
Expand Down
2 changes: 1 addition & 1 deletion linux-user/arm/nwfpe/fpa11.h
Expand Up @@ -105,7 +105,7 @@ static inline void writeRegister(unsigned int x, unsigned int y)

static inline void writeConditionCodes(unsigned int x)
{
cpsr_write(user_registers,x,CPSR_NZCV);
cpsr_write(user_registers, x, CPSR_NZCV, CPSRWriteByInstr);
}

#define ARM_REG_PC 15
Expand Down
7 changes: 4 additions & 3 deletions linux-user/main.c
Expand Up @@ -513,7 +513,7 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
env->regs[0] = -1;
cpsr &= ~CPSR_C;
}
cpsr_write(env, cpsr, CPSR_C);
cpsr_write(env, cpsr, CPSR_C, CPSRWriteByInstr);
end_exclusive();
return;

Expand Down Expand Up @@ -562,7 +562,7 @@ do_kernel_trap(CPUARMState *env)
env->regs[0] = -1;
cpsr &= ~CPSR_C;
}
cpsr_write(env, cpsr, CPSR_C);
cpsr_write(env, cpsr, CPSR_C, CPSRWriteByInstr);
end_exclusive();
break;
case 0xffff0fe0: /* __kernel_get_tls */
Expand Down Expand Up @@ -4446,7 +4446,8 @@ int main(int argc, char **argv, char **envp)
#elif defined(TARGET_ARM)
{
int i;
cpsr_write(env, regs->uregs[16], 0xffffffff);
cpsr_write(env, regs->uregs[16], CPSR_USER | CPSR_EXEC,
CPSRWriteByInstr);
for(i = 0; i < 16; i++) {
env->regs[i] = regs->uregs[i];
}
Expand Down
4 changes: 2 additions & 2 deletions linux-user/signal.c
Expand Up @@ -1611,7 +1611,7 @@ setup_return(CPUARMState *env, struct target_sigaction *ka,
env->regs[13] = frame_addr;
env->regs[14] = retcode;
env->regs[15] = handler & (thumb ? ~1 : ~3);
cpsr_write(env, cpsr, 0xffffffff);
cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
}

static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
Expand Down Expand Up @@ -1843,7 +1843,7 @@ restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
__get_user(env->regs[15], &sc->arm_pc);
#ifdef TARGET_CONFIG_CPU_32
__get_user(cpsr, &sc->arm_cpsr);
cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC);
cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
#endif

err |= !valid_user_regs(env);
Expand Down
1 change: 1 addition & 0 deletions target-arm/cpu-qom.h
Expand Up @@ -155,6 +155,7 @@ typedef struct ARMCPU {
uint32_t id_mmfr1;
uint32_t id_mmfr2;
uint32_t id_mmfr3;
uint32_t id_mmfr4;
uint32_t id_isar0;
uint32_t id_isar1;
uint32_t id_isar2;
Expand Down
17 changes: 15 additions & 2 deletions target-arm/cpu.h
Expand Up @@ -598,6 +598,7 @@ void pmccntr_sync(CPUARMState *env);
#define MDCR_EDAD (1U << 20)
#define MDCR_SPME (1U << 17)
#define MDCR_SDD (1U << 16)
#define MDCR_SPD (3U << 14)
#define MDCR_TDRA (1U << 11)
#define MDCR_TDOSA (1U << 10)
#define MDCR_TDA (1U << 9)
Expand All @@ -606,6 +607,9 @@ void pmccntr_sync(CPUARMState *env);
#define MDCR_TPM (1U << 6)
#define MDCR_TPMCR (1U << 5)

/* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */
#define SDCR_VALID_MASK (MDCR_EPMAD | MDCR_EDAD | MDCR_SPME | MDCR_SPD)

#define CPSR_M (0x1fU)
#define CPSR_T (1U << 5)
#define CPSR_F (1U << 6)
Expand Down Expand Up @@ -718,8 +722,17 @@ static inline void pstate_write(CPUARMState *env, uint32_t val)

/* Return the current CPSR value. */
uint32_t cpsr_read(CPUARMState *env);
/* Set the CPSR. Note that some bits of mask must be all-set or all-clear. */
void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask);

typedef enum CPSRWriteType {
CPSRWriteByInstr = 0, /* from guest MSR or CPS */
CPSRWriteExceptionReturn = 1, /* from guest exception return insn */
CPSRWriteRaw = 2, /* trust values, do not switch reg banks */
CPSRWriteByGDBStub = 3, /* from the GDB stub */
} CPSRWriteType;

/* Set the CPSR. Note that some bits of mask must be all-set or all-clear.*/
void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
CPSRWriteType write_type);

/* Return the current xPSR value. */
static inline uint32_t xpsr_read(CPUARMState *env)
Expand Down
2 changes: 1 addition & 1 deletion target-arm/gdbstub.c
Expand Up @@ -94,7 +94,7 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
return 4;
case 25:
/* CPSR */
cpsr_write(env, tmp, 0xffffffff);
cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub);
return 4;
}
/* Unknown register. */
Expand Down

0 comments on commit 6e378dd

Please sign in to comment.