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
…0160211' into staging

target-arm queue:
 * fix some missing traps for EL3 support
 * enable EL3 on Cortex-A53 and Cortex-A57
 * fix syndrome IL bit for Thumb coprocessor, VFP and Neon traps
 * fix mishandling of architectural watchpoints
 * avoid buffer overflow in sd.c
 * fix max-cpus check in virt board
 * implement 'get board revision' query for BCM2835

# gpg: Signature made Thu 11 Feb 2016 11:23:47 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-20160211:
  bcm2835_property: implement "get board revision" query
  hw/arm/virt: fix max-cpus check
  sd: limit 'req.cmd' while using as an array index
  target-arm: Implement checking of fired watchpoint
  cpu: Add callback to check architectural watchpoint match
  target-arm: Fix IL bit reported for Thumb VFP and Neon traps
  target-arm: Fix IL bit reported for Thumb coprocessor traps
  target-arm: Correct misleading 'is_thumb' syn_* parameter names
  target-arm: Enable EL3 for Cortex-A53 and Cortex-A57
  target-arm: Implement NSACR trapping behaviour
  target-arm: Add isread parameter to CPAccessFns
  target-arm: Update arm_generate_debug_exceptions() to handle EL2/EL3
  target-arm: Use access_trap_aa32s_el1() for SCR and MVBAR
  target-arm: Implement MDCR_EL3 and SDCR
  target-arm: Fix typo in comment in arm_is_secure_below_el3()

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Feb 11, 2016
2 parents 88c73d1 + f0afa73 commit 36a9abd
Show file tree
Hide file tree
Showing 19 changed files with 288 additions and 94 deletions.
6 changes: 6 additions & 0 deletions exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -2070,6 +2070,7 @@ static const MemoryRegionOps notdirty_mem_ops = {
static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
{
CPUState *cpu = current_cpu;
CPUClass *cc = CPU_GET_CLASS(cpu);
CPUArchState *env = cpu->env_ptr;
target_ulong pc, cs_base;
target_ulong vaddr;
Expand All @@ -2095,6 +2096,11 @@ static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
wp->hitaddr = vaddr;
wp->hitattrs = attrs;
if (!cpu->watchpoint_hit) {
if (wp->flags & BP_CPU &&
!cc->debug_check_watchpoint(cpu, wp)) {
wp->flags &= ~BP_WATCHPOINT_HIT;
continue;
}
cpu->watchpoint_hit = wp;
tb_check_watchpoint(cpu);
if (wp->flags & BP_STOP_BEFORE_ACCESS) {
Expand Down
2 changes: 2 additions & 0 deletions hw/arm/bcm2835_peripherals.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ static void bcm2835_peripherals_init(Object *obj)
/* Property channel */
object_initialize(&s->property, sizeof(s->property), TYPE_BCM2835_PROPERTY);
object_property_add_child(obj, "property", OBJECT(&s->property), NULL);
object_property_add_alias(obj, "board-rev", OBJECT(&s->property),
"board-rev", &error_abort);
qdev_set_parent_bus(DEVICE(&s->property), sysbus_get_default());

object_property_add_const_link(OBJECT(&s->property), "dma-mr",
Expand Down
2 changes: 2 additions & 0 deletions hw/arm/bcm2836.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ static void bcm2836_init(Object *obj)
TYPE_BCM2835_PERIPHERALS);
object_property_add_child(obj, "peripherals", OBJECT(&s->peripherals),
&error_abort);
object_property_add_alias(obj, "board-rev", OBJECT(&s->peripherals),
"board-rev", &error_abort);
qdev_set_parent_bus(DEVICE(&s->peripherals), sysbus_get_default());
}

Expand Down
2 changes: 2 additions & 0 deletions hw/arm/raspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ static void raspi2_init(MachineState *machine)
&error_abort);
object_property_set_int(OBJECT(&s->soc), smp_cpus, "enabled-cpus",
&error_abort);
object_property_set_int(OBJECT(&s->soc), 0xa21041, "board-rev",
&error_abort);
object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort);

setup_boot(machine, 2, machine->ram_size);
Expand Down
10 changes: 5 additions & 5 deletions hw/arm/virt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1013,7 +1013,7 @@ static void machvirt_init(MachineState *machine)
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *secure_sysmem = NULL;
int gic_version = vms->gic_version;
int n, max_cpus;
int n, virt_max_cpus;
MemoryRegion *ram = g_new(MemoryRegion, 1);
const char *cpu_model = machine->cpu_model;
VirtBoardInfo *vbi;
Expand Down Expand Up @@ -1051,15 +1051,15 @@ static void machvirt_init(MachineState *machine)
* many redistributors we can fit into the memory map.
*/
if (gic_version == 3) {
max_cpus = vbi->memmap[VIRT_GIC_REDIST].size / 0x20000;
virt_max_cpus = vbi->memmap[VIRT_GIC_REDIST].size / 0x20000;
} else {
max_cpus = GIC_NCPU;
virt_max_cpus = GIC_NCPU;
}

if (smp_cpus > max_cpus) {
if (max_cpus > virt_max_cpus) {
error_report("Number of SMP CPUs requested (%d) exceeds max CPUs "
"supported by machine 'mach-virt' (%d)",
smp_cpus, max_cpus);
max_cpus, virt_max_cpus);
exit(1);
}

Expand Down
4 changes: 2 additions & 2 deletions hw/misc/bcm2835_property.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
resplen = 4;
break;
case 0x00010002: /* Get board revision */
qemu_log_mask(LOG_UNIMP,
"bcm2835_property: %x get board revision NYI\n", tag);
stl_phys(&s->dma_as, value + 12, s->board_rev);
resplen = 4;
break;
case 0x00010003: /* Get board MAC address */
Expand Down Expand Up @@ -258,6 +257,7 @@ static void bcm2835_property_realize(DeviceState *dev, Error **errp)
}

static Property bcm2835_property_props[] = {
DEFINE_PROP_UINT32("board-rev", BCM2835PropertyState, board_rev, 0),
DEFINE_PROP_UINT32("ram-size", BCM2835PropertyState, ram_size, 0),
DEFINE_PROP_END_OF_LIST()
};
Expand Down
7 changes: 5 additions & 2 deletions hw/sd/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -669,8 +669,10 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
/* Not interpreting this as an app command */
sd->card_status &= ~APP_CMD;

if (sd_cmd_type[req.cmd] == sd_ac || sd_cmd_type[req.cmd] == sd_adtc)
if (sd_cmd_type[req.cmd & 0x3F] == sd_ac
|| sd_cmd_type[req.cmd & 0x3F] == sd_adtc) {
rca = req.arg >> 16;
}

DPRINTF("CMD%d 0x%08x state %d\n", req.cmd, req.arg, sd->state);
switch (req.cmd) {
Expand Down Expand Up @@ -1341,7 +1343,8 @@ static int cmd_valid_while_locked(SDState *sd, SDRequest *req)
if (req->cmd == 16 || req->cmd == 55) {
return 1;
}
return sd_cmd_class[req->cmd] == 0 || sd_cmd_class[req->cmd] == 7;
return sd_cmd_class[req->cmd & 0x3F] == 0
|| sd_cmd_class[req->cmd & 0x3F] == 7;
}

int sd_do_command(SDState *sd, SDRequest *req,
Expand Down
1 change: 1 addition & 0 deletions include/hw/misc/bcm2835_property.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ typedef struct {
MemoryRegion iomem;
qemu_irq mbox_irq;
MACAddr macaddr;
uint32_t board_rev;
uint32_t ram_size;
uint32_t addr;
bool pending;
Expand Down
8 changes: 6 additions & 2 deletions include/qom/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ typedef uint64_t vaddr;
#define CPU_GET_CLASS(obj) OBJECT_GET_CLASS(CPUClass, (obj), TYPE_CPU)

typedef struct CPUState CPUState;
typedef struct CPUWatchpoint CPUWatchpoint;

typedef void (*CPUUnassignedAccess)(CPUState *cpu, hwaddr addr,
bool is_write, bool is_exec, int opaque,
Expand Down Expand Up @@ -106,6 +107,8 @@ struct TranslationBlock;
* a memory access with the specified memory transaction attributes.
* @gdb_read_register: Callback for letting GDB read a register.
* @gdb_write_register: Callback for letting GDB write a register.
* @debug_check_watchpoint: Callback: return true if the architectural
* watchpoint whose address has matched should really fire.
* @debug_excp_handler: Callback for handling debug exceptions.
* @write_elf64_note: Callback for writing a CPU-specific ELF note to a
* 64-bit VM coredump.
Expand Down Expand Up @@ -165,6 +168,7 @@ typedef struct CPUClass {
int (*asidx_from_attrs)(CPUState *cpu, MemTxAttrs attrs);
int (*gdb_read_register)(CPUState *cpu, uint8_t *buf, int reg);
int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
bool (*debug_check_watchpoint)(CPUState *cpu, CPUWatchpoint *wp);
void (*debug_excp_handler)(CPUState *cpu);

int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
Expand Down Expand Up @@ -207,14 +211,14 @@ typedef struct CPUBreakpoint {
QTAILQ_ENTRY(CPUBreakpoint) entry;
} CPUBreakpoint;

typedef struct CPUWatchpoint {
struct CPUWatchpoint {
vaddr vaddr;
vaddr len;
vaddr hitaddr;
MemTxAttrs hitattrs;
int flags; /* BP_* */
QTAILQ_ENTRY(CPUWatchpoint) entry;
} CPUWatchpoint;
};

struct KVMState;
struct kvm_run;
Expand Down
9 changes: 9 additions & 0 deletions qom/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,14 @@ static int cpu_common_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg)
return 0;
}

static bool cpu_common_debug_check_watchpoint(CPUState *cpu, CPUWatchpoint *wp)
{
/* If no extra check is required, QEMU watchpoint match can be considered
* as an architectural match.
*/
return true;
}

bool target_words_bigendian(void);
static bool cpu_common_virtio_is_big_endian(CPUState *cpu)
{
Expand Down Expand Up @@ -353,6 +361,7 @@ static void cpu_class_init(ObjectClass *klass, void *data)
k->gdb_write_register = cpu_common_gdb_write_register;
k->virtio_is_big_endian = cpu_common_virtio_is_big_endian;
k->debug_excp_handler = cpu_common_noop;
k->debug_check_watchpoint = cpu_common_debug_check_watchpoint;
k->cpu_exec_enter = cpu_common_noop;
k->cpu_exec_exit = cpu_common_noop;
k->cpu_exec_interrupt = cpu_common_exec_interrupt;
Expand Down
1 change: 1 addition & 0 deletions target-arm/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1483,6 +1483,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_arch_name = arm_gdb_arch_name;
cc->gdb_stop_before_watchpoint = true;
cc->debug_excp_handler = arm_debug_excp_handler;
cc->debug_check_watchpoint = arm_debug_check_watchpoint;

cc->disas_set_info = arm_disas_set_info;

Expand Down
55 changes: 48 additions & 7 deletions target-arm/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ typedef struct CPUARMState {
uint64_t mdscr_el1;
uint64_t oslsr_el1; /* OS Lock Status */
uint64_t mdcr_el2;
uint64_t mdcr_el3;
/* If the counter is enabled, this stores the last time the counter
* was reset. Otherwise it stores the counter value
*/
Expand Down Expand Up @@ -931,7 +932,7 @@ static inline bool arm_is_secure_below_el3(CPUARMState *env)
if (arm_feature(env, ARM_FEATURE_EL3)) {
return !(env->cp15.scr_el3 & SCR_NS);
} else {
/* If EL2 is not supported then the secure state is implementation
/* If EL3 is not supported then the secure state is implementation
* defined, in which case QEMU defaults to non-secure.
*/
return false;
Expand Down Expand Up @@ -1318,7 +1319,9 @@ typedef uint64_t CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque);
typedef void CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque,
uint64_t value);
/* Access permission check functions for coprocessor registers. */
typedef CPAccessResult CPAccessFn(CPUARMState *env, const ARMCPRegInfo *opaque);
typedef CPAccessResult CPAccessFn(CPUARMState *env,
const ARMCPRegInfo *opaque,
bool isread);
/* Hook function for register reset */
typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque);

Expand Down Expand Up @@ -1741,9 +1744,7 @@ typedef enum ARMASIdx {
ARMASIdx_S = 1,
} ARMASIdx;

/* Return the Exception Level targeted by debug exceptions;
* currently always EL1 since we don't implement EL2 or EL3.
*/
/* Return the Exception Level targeted by debug exceptions. */
static inline int arm_debug_target_el(CPUARMState *env)
{
bool secure = arm_is_secure(env);
Expand All @@ -1766,6 +1767,14 @@ static inline int arm_debug_target_el(CPUARMState *env)

static inline bool aa64_generate_debug_exceptions(CPUARMState *env)
{
if (arm_is_secure(env)) {
/* MDCR_EL3.SDD disables debug events from Secure state */
if (extract32(env->cp15.mdcr_el3, 16, 1) != 0
|| arm_current_el(env) == 3) {
return false;
}
}

if (arm_current_el(env) == arm_debug_target_el(env)) {
if ((extract32(env->cp15.mdscr_el1, 13, 1) == 0)
|| (env->daif & PSTATE_D)) {
Expand All @@ -1777,10 +1786,42 @@ static inline bool aa64_generate_debug_exceptions(CPUARMState *env)

static inline bool aa32_generate_debug_exceptions(CPUARMState *env)
{
if (arm_current_el(env) == 0 && arm_el_is_aa64(env, 1)) {
int el = arm_current_el(env);

if (el == 0 && arm_el_is_aa64(env, 1)) {
return aa64_generate_debug_exceptions(env);
}
return arm_current_el(env) != 2;

if (arm_is_secure(env)) {
int spd;

if (el == 0 && (env->cp15.sder & 1)) {
/* SDER.SUIDEN means debug exceptions from Secure EL0
* are always enabled. Otherwise they are controlled by
* SDCR.SPD like those from other Secure ELs.
*/
return true;
}

spd = extract32(env->cp15.mdcr_el3, 14, 2);
switch (spd) {
case 1:
/* SPD == 0b01 is reserved, but behaves as 0b00. */
case 0:
/* For 0b00 we return true if external secure invasive debug
* is enabled. On real hardware this is controlled by external
* signals to the core. QEMU always permits debug, and behaves
* as if DBGEN, SPIDEN, NIDEN and SPNIDEN are all tied high.
*/
return true;
case 2:
return false;
case 3:
return true;
}
}

return el != 2;
}

/* Return true if debugging exceptions are currently enabled.
Expand Down
2 changes: 2 additions & 0 deletions target-arm/cpu64.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ static void aarch64_a57_initfn(Object *obj)
set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
set_feature(&cpu->env, ARM_FEATURE_CRC);
set_feature(&cpu->env, ARM_FEATURE_EL3);
cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A57;
cpu->midr = 0x411fd070;
cpu->revidr = 0x00000000;
Expand Down Expand Up @@ -161,6 +162,7 @@ static void aarch64_a53_initfn(Object *obj)
set_feature(&cpu->env, ARM_FEATURE_V8_SHA256);
set_feature(&cpu->env, ARM_FEATURE_V8_PMULL);
set_feature(&cpu->env, ARM_FEATURE_CRC);
set_feature(&cpu->env, ARM_FEATURE_EL3);
cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A53;
cpu->midr = 0x410fd034;
cpu->revidr = 0x00000000;
Expand Down
Loading

0 comments on commit 36a9abd

Please sign in to comment.