target-arm queue:
* fix bugs in gdb singlestep handling and breakpoints * minor code cleanup in arm_gic * clean up error messages in hw/arm/virt * fix highbank kernel booting by adding a board-setup blob -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJWQfSYAAoJEDwlJe0UNgzeKCQP/iGo+RGRvZZqWdQ+eftoTMEk 7nZfOYCqeO+mLn5sBWQFhn+b35syS3dBmLhDy21hgnEAYJBWG+28KoYL0QW4nUJO KdSOT1WLrgZ4dptlrgI4rc0+m01gzt9XfPm3l/UKzvBHrKCFYkYFEzb41s1soEzF qN4VgOAuuJ8TqXS1djHbmY1zz9TR0QQ4gjcA+cuyAmiSx9hs0KDHTStal9b2GiI5 meDAmf11FSGAwJ6C9+52yudpiZ2wSnrVh7N1UTidAUMrhJ5pjZ4vMXrlSwoCIdkp 6MYG7qW9ZPmT/wK+EiGvx3HznqQ2gGQgMADAAFQcyBAdExSLCIhN46Jcqja0E1zy brHuaUp8NU09bam4R+dTcbKo76EMsU41BeHIXMH2CY/gVl8ojh9Nz+Qkcuwipixl QunGIAgGaQkExY7WAWvDKEle/0/9iOCH4m4UC8mco8mzj7Svc7a/kQyHOdF6RbW+ OpAeLtRV0ACDg/oq+GHK0/NF1SwRPHJWB7tnEotgSqhFb/tN93jCGiviEqNFPo/G z3zW254toA93x+mIE9Tvobrsi9os/sE/CAYZi3R2JaBoqnv3rcn1JRMFyAUm44eH EXOceCTg071bRpcowNNu2OivLYt37Q1GUDhbLo56EIEh+1ZVBlFJHegVp4f2HtzG ZjmkgJGdMXr1tNTEE5/a =2qsJ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20151110' into staging target-arm queue: * fix bugs in gdb singlestep handling and breakpoints * minor code cleanup in arm_gic * clean up error messages in hw/arm/virt * fix highbank kernel booting by adding a board-setup blob # gpg: Signature made Tue 10 Nov 2015 13:43:52 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-20151110: target-arm: Clean up DISAS_UPDATE usage in AArch32 translation code hw/arm/virt: error_report cleanups arm: highbank: Implement PSCI and dummy monitor arm: highbank: Defeature CPU override arm: boot: Add secure_board_setup flag hw/intc/arm_gic: Remove the definition of NUM_CPU target-arm: Fix gdb singlestep handling in arm_debug_excp_handler() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
a1a88589dc
@ -11,6 +11,7 @@
|
||||
#include "hw/hw.h"
|
||||
#include "hw/arm/arm.h"
|
||||
#include "hw/arm/linux-boot-if.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/loader.h"
|
||||
@ -495,7 +496,8 @@ static void do_cpu_reset(void *opaque)
|
||||
}
|
||||
|
||||
/* Set to non-secure if not a secure boot */
|
||||
if (!info->secure_boot) {
|
||||
if (!info->secure_boot &&
|
||||
(cs != first_cpu || !info->secure_board_setup)) {
|
||||
/* Linux expects non-secure state */
|
||||
env->cp15.scr_el3 |= SCR_NS;
|
||||
}
|
||||
@ -598,6 +600,12 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
|
||||
struct arm_boot_info *info =
|
||||
container_of(n, struct arm_boot_info, load_kernel_notifier);
|
||||
|
||||
/* The board code is not supposed to set secure_board_setup unless
|
||||
* running its code in secure mode is actually possible, and KVM
|
||||
* doesn't support secure.
|
||||
*/
|
||||
assert(!(info->secure_board_setup && kvm_enabled()));
|
||||
|
||||
/* Load the kernel. */
|
||||
if (!info->kernel_filename || info->firmware_loaded) {
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "hw/devices.h"
|
||||
#include "hw/loader.h"
|
||||
#include "net/net.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
@ -32,10 +33,52 @@
|
||||
#define SMP_BOOT_REG 0x40
|
||||
#define MPCORE_PERIPHBASE 0xfff10000
|
||||
|
||||
#define MVBAR_ADDR 0x200
|
||||
|
||||
#define NIRQ_GIC 160
|
||||
|
||||
/* Board init. */
|
||||
|
||||
/* MVBAR_ADDR is limited by precision of movw */
|
||||
|
||||
QEMU_BUILD_BUG_ON(MVBAR_ADDR >= (1 << 16));
|
||||
|
||||
#define ARMV7_IMM16(x) (extract32((x), 0, 12) | \
|
||||
extract32((x), 12, 4) << 16)
|
||||
|
||||
static void hb_write_board_setup(ARMCPU *cpu,
|
||||
const struct arm_boot_info *info)
|
||||
{
|
||||
int n;
|
||||
uint32_t board_setup_blob[] = {
|
||||
/* MVBAR_ADDR */
|
||||
/* Default unimplemented and unused vectors to spin. Makes it
|
||||
* easier to debug (as opposed to the CPU running away).
|
||||
*/
|
||||
0xeafffffe, /* notused1: b notused */
|
||||
0xeafffffe, /* notused2: b notused */
|
||||
0xe1b0f00e, /* smc: movs pc, lr - exception return */
|
||||
0xeafffffe, /* prefetch_abort: b prefetch_abort */
|
||||
0xeafffffe, /* data_abort: b data_abort */
|
||||
0xeafffffe, /* notused3: b notused3 */
|
||||
0xeafffffe, /* irq: b irq */
|
||||
0xeafffffe, /* fiq: b fiq */
|
||||
#define BOARD_SETUP_ADDR (MVBAR_ADDR + 8 * sizeof(uint32_t))
|
||||
0xe3000000 + ARMV7_IMM16(MVBAR_ADDR), /* movw r0, MVBAR_ADDR */
|
||||
0xee0c0f30, /* mcr p15, 0, r0, c12, c0, 1 - set MVBAR */
|
||||
0xee110f11, /* mrc p15, 0, r0, c1 , c1, 0 - get SCR */
|
||||
0xe3810001, /* orr r0, #1 - set NS */
|
||||
0xee010f11, /* mcr p15, 0, r0, c1 , c1, 0 - set SCR */
|
||||
0xe1600070, /* smc - go to monitor mode to flush NS change */
|
||||
0xe12fff1e, /* bx lr - return to caller */
|
||||
};
|
||||
for (n = 0; n < ARRAY_SIZE(board_setup_blob); n++) {
|
||||
board_setup_blob[n] = tswap32(board_setup_blob[n]);
|
||||
}
|
||||
rom_add_blob_fixed("board-setup", board_setup_blob,
|
||||
sizeof(board_setup_blob), MVBAR_ADDR);
|
||||
}
|
||||
|
||||
static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
|
||||
{
|
||||
int n;
|
||||
@ -223,15 +266,13 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
|
||||
MemoryRegion *sysmem;
|
||||
char *sysboot_filename;
|
||||
|
||||
if (!cpu_model) {
|
||||
switch (machine_id) {
|
||||
case CALXEDA_HIGHBANK:
|
||||
cpu_model = "cortex-a9";
|
||||
break;
|
||||
case CALXEDA_MIDWAY:
|
||||
cpu_model = "cortex-a15";
|
||||
break;
|
||||
}
|
||||
switch (machine_id) {
|
||||
case CALXEDA_HIGHBANK:
|
||||
cpu_model = "cortex-a9";
|
||||
break;
|
||||
case CALXEDA_MIDWAY:
|
||||
cpu_model = "cortex-a15";
|
||||
break;
|
||||
}
|
||||
|
||||
for (n = 0; n < smp_cpus; n++) {
|
||||
@ -240,24 +281,16 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
|
||||
ARMCPU *cpu;
|
||||
Error *err = NULL;
|
||||
|
||||
if (!oc) {
|
||||
error_report("Unable to find CPU definition");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cpuobj = object_new(object_class_get_name(oc));
|
||||
cpu = ARM_CPU(cpuobj);
|
||||
|
||||
/* By default A9 and A15 CPUs have EL3 enabled. This board does not
|
||||
* currently support EL3 so the CPU EL3 property is disabled before
|
||||
* realization.
|
||||
*/
|
||||
if (object_property_find(cpuobj, "has_el3", NULL)) {
|
||||
object_property_set_bool(cpuobj, false, "has_el3", &err);
|
||||
if (err) {
|
||||
error_report_err(err);
|
||||
exit(1);
|
||||
}
|
||||
object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_SMC,
|
||||
"psci-conduit", &error_abort);
|
||||
|
||||
if (n) {
|
||||
/* Secondary CPUs start in PSCI powered-down state */
|
||||
object_property_set_bool(cpuobj, true,
|
||||
"start-powered-off", &error_abort);
|
||||
}
|
||||
|
||||
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
|
||||
@ -378,6 +411,16 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
|
||||
highbank_binfo.loader_start = 0;
|
||||
highbank_binfo.write_secondary_boot = hb_write_secondary;
|
||||
highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
|
||||
if (!kvm_enabled()) {
|
||||
highbank_binfo.board_setup_addr = BOARD_SETUP_ADDR;
|
||||
highbank_binfo.write_board_setup = hb_write_board_setup;
|
||||
highbank_binfo.secure_board_setup = true;
|
||||
} else {
|
||||
error_report("WARNING: cannot load built-in Monitor support "
|
||||
"if KVM is enabled. Some guests (such as Linux) "
|
||||
"may not boot.");
|
||||
}
|
||||
|
||||
arm_load_kernel(ARM_CPU(first_cpu), &highbank_binfo);
|
||||
}
|
||||
|
||||
|
@ -941,8 +941,8 @@ static void machvirt_init(MachineState *machine)
|
||||
if (!gic_version) {
|
||||
gic_version = kvm_arm_vgic_probe();
|
||||
if (!gic_version) {
|
||||
error_report("Unable to determine GIC version supported by host\n"
|
||||
"Probably KVM acceleration is not supported\n");
|
||||
error_report("Unable to determine GIC version supported by host");
|
||||
error_printf("KVM acceleration is probably not supported\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -990,7 +990,7 @@ static void machvirt_init(MachineState *machine)
|
||||
char *cpuopts = g_strdup(cpustr[1]);
|
||||
|
||||
if (!oc) {
|
||||
fprintf(stderr, "Unable to find CPU definition\n");
|
||||
error_report("Unable to find CPU definition");
|
||||
exit(1);
|
||||
}
|
||||
cpuobj = object_new(object_class_get_name(oc));
|
||||
@ -1126,8 +1126,8 @@ static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
|
||||
} else if (!strcmp(value, "host")) {
|
||||
vms->gic_version = 0; /* Will probe later */
|
||||
} else {
|
||||
error_report("Invalid gic-version option value\n"
|
||||
"Allowed values are: 3, 2, host\n");
|
||||
error_report("Invalid gic-version option value");
|
||||
error_printf("Allowed gic-version values are: 3, 2, host\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -35,8 +35,6 @@ static const uint8_t gic_id[] = {
|
||||
0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1
|
||||
};
|
||||
|
||||
#define NUM_CPU(s) ((s)->num_cpu)
|
||||
|
||||
static inline int gic_get_current_cpu(GICState *s)
|
||||
{
|
||||
if (s->num_cpu > 1) {
|
||||
@ -64,7 +62,7 @@ void gic_update(GICState *s)
|
||||
int cpu;
|
||||
int cm;
|
||||
|
||||
for (cpu = 0; cpu < NUM_CPU(s); cpu++) {
|
||||
for (cpu = 0; cpu < s->num_cpu; cpu++) {
|
||||
cm = 1 << cpu;
|
||||
s->current_pending[cpu] = 1023;
|
||||
if (!(s->ctlr & (GICD_CTLR_EN_GRP0 | GICD_CTLR_EN_GRP1))
|
||||
@ -567,7 +565,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset, MemTxAttrs attrs)
|
||||
if (offset == 4)
|
||||
/* Interrupt Controller Type Register */
|
||||
return ((s->num_irq / 32) - 1)
|
||||
| ((NUM_CPU(s) - 1) << 5)
|
||||
| ((s->num_cpu - 1) << 5)
|
||||
| (s->security_extn << 10);
|
||||
if (offset < 0x08)
|
||||
return 0;
|
||||
@ -1284,7 +1282,7 @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
|
||||
* GIC v2 defines a larger memory region (0x1000) so this will need
|
||||
* to be extended when we implement A15.
|
||||
*/
|
||||
for (i = 0; i < NUM_CPU(s); i++) {
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
s->backref[i] = s;
|
||||
memory_region_init_io(&s->cpuiomem[i+1], OBJECT(s), &gic_cpu_ops,
|
||||
&s->backref[i], "gic_cpu", 0x100);
|
||||
|
@ -97,6 +97,12 @@ struct arm_boot_info {
|
||||
hwaddr board_setup_addr;
|
||||
void (*write_board_setup)(ARMCPU *cpu,
|
||||
const struct arm_boot_info *info);
|
||||
|
||||
/* If set, the board specific loader/setup blob will be run from secure
|
||||
* mode, regardless of secure_boot. The blob becomes responsible for
|
||||
* changing to non-secure state if implementing a non-secure boot
|
||||
*/
|
||||
bool secure_board_setup;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -917,7 +917,13 @@ void arm_debug_excp_handler(CPUState *cs)
|
||||
uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
|
||||
bool same_el = (arm_debug_target_el(env) == arm_current_el(env));
|
||||
|
||||
if (cpu_breakpoint_test(cs, pc, BP_GDB)) {
|
||||
/* (1) GDB breakpoints should be handled first.
|
||||
* (2) Do not raise a CPU exception if no CPU breakpoint has fired,
|
||||
* since singlestep is also done by generating a debug internal
|
||||
* exception.
|
||||
*/
|
||||
if (cpu_breakpoint_test(cs, pc, BP_GDB)
|
||||
|| !cpu_breakpoint_test(cs, pc, BP_CPU)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -870,7 +870,7 @@ static inline void gen_bx_im(DisasContext *s, uint32_t addr)
|
||||
{
|
||||
TCGv_i32 tmp;
|
||||
|
||||
s->is_jmp = DISAS_UPDATE;
|
||||
s->is_jmp = DISAS_JUMP;
|
||||
if (s->thumb != (addr & 1)) {
|
||||
tmp = tcg_temp_new_i32();
|
||||
tcg_gen_movi_i32(tmp, addr & 1);
|
||||
@ -883,7 +883,7 @@ static inline void gen_bx_im(DisasContext *s, uint32_t addr)
|
||||
/* Set PC and Thumb state from var. var is marked as dead. */
|
||||
static inline void gen_bx(DisasContext *s, TCGv_i32 var)
|
||||
{
|
||||
s->is_jmp = DISAS_UPDATE;
|
||||
s->is_jmp = DISAS_JUMP;
|
||||
tcg_gen_andi_i32(cpu_R[15], var, ~1);
|
||||
tcg_gen_andi_i32(var, var, 1);
|
||||
store_cpu_field(var, thumb);
|
||||
@ -1062,7 +1062,7 @@ static void gen_exception_insn(DisasContext *s, int offset, int excp,
|
||||
static inline void gen_lookup_tb(DisasContext *s)
|
||||
{
|
||||
tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
|
||||
s->is_jmp = DISAS_UPDATE;
|
||||
s->is_jmp = DISAS_JUMP;
|
||||
}
|
||||
|
||||
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
|
||||
@ -4096,7 +4096,7 @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
|
||||
tmp = load_cpu_field(spsr);
|
||||
gen_set_cpsr(tmp, CPSR_ERET_MASK);
|
||||
tcg_temp_free_i32(tmp);
|
||||
s->is_jmp = DISAS_UPDATE;
|
||||
s->is_jmp = DISAS_JUMP;
|
||||
}
|
||||
|
||||
/* Generate a v6 exception return. Marks both values as dead. */
|
||||
@ -4105,7 +4105,7 @@ static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
|
||||
gen_set_cpsr(cpsr, CPSR_ERET_MASK);
|
||||
tcg_temp_free_i32(cpsr);
|
||||
store_reg(s, 15, pc);
|
||||
s->is_jmp = DISAS_UPDATE;
|
||||
s->is_jmp = DISAS_JUMP;
|
||||
}
|
||||
|
||||
static void gen_nop_hint(DisasContext *s, int val)
|
||||
@ -9035,7 +9035,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
|
||||
tmp = load_cpu_field(spsr);
|
||||
gen_set_cpsr(tmp, CPSR_ERET_MASK);
|
||||
tcg_temp_free_i32(tmp);
|
||||
s->is_jmp = DISAS_UPDATE;
|
||||
s->is_jmp = DISAS_JUMP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -11355,7 +11355,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
|
||||
/* We always get here via a jump, so know we are not in a
|
||||
conditional execution block. */
|
||||
gen_exception_internal(EXCP_KERNEL_TRAP);
|
||||
dc->is_jmp = DISAS_UPDATE;
|
||||
dc->is_jmp = DISAS_EXC;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
@ -11363,7 +11363,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
|
||||
/* We always get here via a jump, so know we are not in a
|
||||
conditional execution block. */
|
||||
gen_exception_internal(EXCP_EXCEPTION_EXIT);
|
||||
dc->is_jmp = DISAS_UPDATE;
|
||||
dc->is_jmp = DISAS_EXC;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@ -11497,7 +11497,8 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
|
||||
}
|
||||
gen_set_label(dc->condlabel);
|
||||
}
|
||||
if (dc->condjmp || !dc->is_jmp) {
|
||||
if (dc->condjmp || dc->is_jmp == DISAS_NEXT ||
|
||||
dc->is_jmp == DISAS_UPDATE) {
|
||||
gen_set_pc_im(dc, dc->pc);
|
||||
dc->condjmp = 0;
|
||||
}
|
||||
@ -11533,9 +11534,11 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
|
||||
case DISAS_NEXT:
|
||||
gen_goto_tb(dc, 1, dc->pc);
|
||||
break;
|
||||
default:
|
||||
case DISAS_JUMP:
|
||||
case DISAS_UPDATE:
|
||||
gen_set_pc_im(dc, dc->pc);
|
||||
/* fall through */
|
||||
case DISAS_JUMP:
|
||||
default:
|
||||
/* indicate that the hash table must be used to find the next TB */
|
||||
tcg_gen_exit_tb(0);
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user