summaryrefslogtreecommitdiffstats
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/alpha/sys_helper.c4
-rw-r--r--target/arm/psci.c4
-rw-r--r--target/i386/excp_helper.c2
-rw-r--r--target/i386/hax-all.c6
-rw-r--r--target/i386/helper.c2
-rw-r--r--target/i386/kvm.c2
-rw-r--r--target/ppc/excp_helper.c3
-rw-r--r--target/s390x/cpu.c7
-rw-r--r--target/s390x/cpu.h16
-rw-r--r--target/s390x/helper.c2
-rw-r--r--target/s390x/ioinst.c9
-rw-r--r--target/s390x/kvm.c4
-rw-r--r--target/s390x/misc_helper.c4
-rw-r--r--target/sh4/cpu.h12
-rw-r--r--target/sh4/helper.c28
-rw-r--r--target/sh4/translate.c25
-rw-r--r--target/sparc/int32_helper.c2
17 files changed, 92 insertions, 40 deletions
diff --git a/target/alpha/sys_helper.c b/target/alpha/sys_helper.c
index 652195de6f..ac22323191 100644
--- a/target/alpha/sys_helper.c
+++ b/target/alpha/sys_helper.c
@@ -60,9 +60,9 @@ void helper_tb_flush(CPUAlphaState *env)
void helper_halt(uint64_t restart)
{
if (restart) {
- qemu_system_reset_request();
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
} else {
- qemu_system_shutdown_request();
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
}
}
diff --git a/target/arm/psci.c b/target/arm/psci.c
index ade9fe2ede..fc34b263d3 100644
--- a/target/arm/psci.c
+++ b/target/arm/psci.c
@@ -137,7 +137,7 @@ void arm_handle_psci_call(ARMCPU *cpu)
}
break;
case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
- qemu_system_reset_request();
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
/* QEMU reset and shutdown are async requests, but PSCI
* mandates that we never return from the reset/shutdown
* call, so power the CPU off now so it doesn't execute
@@ -145,7 +145,7 @@ void arm_handle_psci_call(ARMCPU *cpu)
*/
goto cpu_off;
case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
- qemu_system_shutdown_request();
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
goto cpu_off;
case QEMU_PSCI_0_1_FN_CPU_ON:
case QEMU_PSCI_0_2_FN_CPU_ON:
diff --git a/target/i386/excp_helper.c b/target/i386/excp_helper.c
index ee596c6082..b76977243f 100644
--- a/target/i386/excp_helper.c
+++ b/target/i386/excp_helper.c
@@ -59,7 +59,7 @@ static int check_exception(CPUX86State *env, int intno, int *error_code,
qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
- qemu_system_reset_request();
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
return EXCP_HLT;
}
#endif
diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c
index ef13015215..73469311d6 100644
--- a/target/i386/hax-all.c
+++ b/target/i386/hax-all.c
@@ -540,14 +540,14 @@ static int hax_vcpu_hax_exec(CPUArchState *env)
/* Guest state changed, currently only for shutdown */
case HAX_EXIT_STATECHANGE:
fprintf(stdout, "VCPU shutdown request\n");
- qemu_system_shutdown_request();
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
hax_vcpu_sync_state(env, 0);
ret = 1;
break;
case HAX_EXIT_UNKNOWN_VMEXIT:
fprintf(stderr, "Unknown VMX exit %x from guest\n",
ht->_exit_reason);
- qemu_system_reset_request();
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
hax_vcpu_sync_state(env, 0);
cpu_dump_state(cpu, stderr, fprintf, 0);
ret = -1;
@@ -578,7 +578,7 @@ static int hax_vcpu_hax_exec(CPUArchState *env)
break;
default:
fprintf(stderr, "Unknown exit %x from HAX\n", ht->_exit_status);
- qemu_system_reset_request();
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
hax_vcpu_sync_state(env, 0);
cpu_dump_state(cpu, stderr, fprintf, 0);
ret = 1;
diff --git a/target/i386/helper.c b/target/i386/helper.c
index f11cac63a1..ee7eff2f6f 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -1212,7 +1212,7 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data)
" triple fault\n",
cs->cpu_index);
qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
- qemu_system_reset_request();
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
return;
}
if (banks[1] & MCI_STATUS_VAL) {
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 011d4a55b1..49b6115eae 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -2930,7 +2930,7 @@ int kvm_arch_process_async_events(CPUState *cs)
if (env->exception_injected == EXCP08_DBLE) {
/* this means triple fault */
- qemu_system_reset_request();
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
cs->exit_request = 1;
return 0;
}
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index a6bcb47aa2..9cb2123187 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -995,6 +995,9 @@ static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
*/
cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
+ /* Reset the reservation */
+ env->reserve_addr = -1;
+
/* Context synchronizing: check if TCG TLB needs flush */
check_tlb_flush(env, false);
}
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index a1bf2ba5a7..a69005d9b5 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -92,9 +92,10 @@ static void s390_cpu_initial_reset(CPUState *s)
int i;
s390_cpu_reset(s);
- /* initial reset does not touch regs,fregs and aregs */
- memset(&env->fpc, 0, offsetof(CPUS390XState, end_reset_fields) -
- offsetof(CPUS390XState, fpc));
+ /* initial reset does not clear everything! */
+ memset(&env->start_initial_reset_fields, 0,
+ offsetof(CPUS390XState, end_reset_fields) -
+ offsetof(CPUS390XState, start_initial_reset_fields));
/* architectured initial values for CR 0 and 14 */
env->cregs[0] = CR0_RESET;
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index 240b8a5c22..c74b4193ee 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -88,6 +88,10 @@ typedef struct CPUS390XState {
*/
CPU_DoubleU vregs[32][2]; /* vector registers */
uint32_t aregs[16]; /* access registers */
+ uint8_t riccb[64]; /* runtime instrumentation control */
+
+ /* Fields up to this point are not cleared by initial CPU reset */
+ struct {} start_initial_reset_fields;
uint32_t fpc; /* floating-point control register */
uint32_t cc_op;
@@ -137,8 +141,6 @@ typedef struct CPUS390XState {
uint64_t gbea;
uint64_t pp;
- uint8_t riccb[64];
-
/* Fields up to this point are cleared by a CPU reset */
struct {} end_reset_fields;
@@ -1256,6 +1258,16 @@ static inline void s390_crypto_reset(void)
}
}
+static inline bool s390_get_squash_mcss(void)
+{
+ if (object_property_get_bool(OBJECT(qdev_get_machine()), "s390-squash-mcss",
+ NULL)) {
+ return true;
+ }
+
+ return false;
+}
+
/* machine check interruption code */
/* subclasses */
diff --git a/target/s390x/helper.c b/target/s390x/helper.c
index 997849008f..4f8aadf305 100644
--- a/target/s390x/helper.c
+++ b/target/s390x/helper.c
@@ -266,7 +266,7 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
S390CPU *cpu = s390_env_get_cpu(env);
if (s390_cpu_halt(cpu) == 0) {
#ifndef CONFIG_USER_ONLY
- qemu_system_shutdown_request();
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
#endif
}
}
diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c
index 590bfa4f12..62a777100c 100644
--- a/target/s390x/ioinst.c
+++ b/target/s390x/ioinst.c
@@ -244,6 +244,15 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
case -EBUSY:
cc = 2;
break;
+ case -EFAULT:
+ /*
+ * TODO:
+ * I'm wondering whether there is something better
+ * to do for us here (like setting some device or
+ * subchannel status).
+ */
+ program_interrupt(env, PGM_ADDRESSING, 4);
+ return;
case 0:
cc = 0;
break;
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
index fb105429be..ba1e60f8a6 100644
--- a/target/s390x/kvm.c
+++ b/target/s390x/kvm.c
@@ -1927,7 +1927,7 @@ static int handle_intercept(S390CPU *cpu)
cpu_synchronize_state(cs);
if (s390_cpu_halt(cpu) == 0) {
if (is_special_wait_psw(cs)) {
- qemu_system_shutdown_request();
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
} else {
qemu_system_guest_panicked(NULL);
}
@@ -1936,7 +1936,7 @@ static int handle_intercept(S390CPU *cpu)
break;
case ICPT_CPU_STOP:
if (s390_cpu_set_state(CPU_STATE_STOPPED, cpu) == 0) {
- qemu_system_shutdown_request();
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
}
if (cpu->env.sigp_order == SIGP_STOP_STORE_STATUS) {
kvm_s390_store_status(cpu, KVM_S390_STORE_STATUS_DEF_ADDR,
diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c
index 23ec52cf35..1b9f448875 100644
--- a/target/s390x/misc_helper.c
+++ b/target/s390x/misc_helper.c
@@ -532,11 +532,11 @@ uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1,
break;
#if !defined(CONFIG_USER_ONLY)
case SIGP_RESTART:
- qemu_system_reset_request();
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
cpu_loop_exit(CPU(s390_env_get_cpu(env)));
break;
case SIGP_STOP:
- qemu_system_shutdown_request();
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
cpu_loop_exit(CPU(s390_env_get_cpu(env)));
break;
#endif
diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h
index 6c07c6b24b..ffb91687b8 100644
--- a/target/sh4/cpu.h
+++ b/target/sh4/cpu.h
@@ -91,8 +91,10 @@
#define FPSCR_RM_NEAREST (0 << 0)
#define FPSCR_RM_ZERO (1 << 0)
+#define DELAY_SLOT_MASK 0x7
#define DELAY_SLOT (1 << 0)
#define DELAY_SLOT_CONDITIONAL (1 << 1)
+#define DELAY_SLOT_RTE (1 << 2)
typedef struct tlb_t {
uint32_t vpn; /* virtual page number */
@@ -263,7 +265,13 @@ void cpu_load_tlb(CPUSH4State * env);
#define MMU_USER_IDX 1
static inline int cpu_mmu_index (CPUSH4State *env, bool ifetch)
{
- return (env->sr & (1u << SR_MD)) == 0 ? 1 : 0;
+ /* The instruction in a RTE delay slot is fetched in privileged
+ mode, but executed in user mode. */
+ if (ifetch && (env->flags & DELAY_SLOT_RTE)) {
+ return 0;
+ } else {
+ return (env->sr & (1u << SR_MD)) == 0 ? 1 : 0;
+ }
}
#include "exec/cpu-all.h"
@@ -380,7 +388,7 @@ static inline void cpu_get_tb_cpu_state(CPUSH4State *env, target_ulong *pc,
{
*pc = env->pc;
*cs_base = 0;
- *flags = (env->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) /* Bits 0-1 */
+ *flags = (env->flags & DELAY_SLOT_MASK) /* Bits 0- 2 */
| (env->fpscr & (FPSCR_FR | FPSCR_SZ | FPSCR_PR)) /* Bits 19-21 */
| (env->sr & ((1u << SR_MD) | (1u << SR_RB))) /* Bits 29-30 */
| (env->sr & (1u << SR_FD)) /* Bit 15 */
diff --git a/target/sh4/helper.c b/target/sh4/helper.c
index 8f8ce81401..28d93c2543 100644
--- a/target/sh4/helper.c
+++ b/target/sh4/helper.c
@@ -21,6 +21,7 @@
#include "cpu.h"
#include "exec/exec-all.h"
#include "exec/log.h"
+#include "sysemu/sysemu.h"
#if !defined(CONFIG_USER_ONLY)
#include "hw/sh4/sh_intc.h"
@@ -92,7 +93,14 @@ void superh_cpu_do_interrupt(CPUState *cs)
if (env->sr & (1u << SR_BL)) {
if (do_exp && cs->exception_index != 0x1e0) {
- cs->exception_index = 0x000; /* masked exception -> reset */
+ /* In theory a masked exception generates a reset exception,
+ which in turn jumps to the reset vector. However this only
+ works when using a bootloader. When using a kernel and an
+ initrd, they need to be reloaded and the program counter
+ should be loaded with the kernel entry point.
+ qemu_system_reset_request takes care of that. */
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+ return;
}
if (do_irq && !env->in_sleep) {
return; /* masked */
@@ -164,11 +172,11 @@ void superh_cpu_do_interrupt(CPUState *cs)
env->sgr = env->gregs[15];
env->sr |= (1u << SR_BL) | (1u << SR_MD) | (1u << SR_RB);
- if (env->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
+ if (env->flags & DELAY_SLOT_MASK) {
/* Branch instruction should be executed again before delay slot. */
env->spc -= 2;
/* Clear flags for exception/interrupt routine. */
- env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
+ env->flags &= ~DELAY_SLOT_MASK;
}
if (do_exp) {
@@ -420,7 +428,7 @@ static int get_physical_address(CPUSH4State * env, target_ulong * physical,
if (!(env->sr & (1u << SR_MD))
&& (address < 0xe0000000 || address >= 0xe4000000)) {
/* Unauthorized access in user mode (only store queues are available) */
- fprintf(stderr, "Unauthorized access\n");
+ qemu_log_mask(LOG_GUEST_ERROR, "Unauthorized access\n");
if (rw == 0)
return MMU_DADDR_ERROR_READ;
else if (rw == 1)
@@ -863,8 +871,16 @@ int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr)
bool superh_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
if (interrupt_request & CPU_INTERRUPT_HARD) {
- superh_cpu_do_interrupt(cs);
- return true;
+ SuperHCPU *cpu = SUPERH_CPU(cs);
+ CPUSH4State *env = &cpu->env;
+
+ /* Delay slots are indivisible, ignore interrupts */
+ if (env->flags & DELAY_SLOT_MASK) {
+ return false;
+ } else {
+ superh_cpu_do_interrupt(cs);
+ return true;
+ }
}
return false;
}
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
index 0bc2f9ff19..8bc132b27b 100644
--- a/target/sh4/translate.c
+++ b/target/sh4/translate.c
@@ -185,6 +185,9 @@ void superh_cpu_dump_state(CPUState *cs, FILE *f,
} else if (env->flags & DELAY_SLOT_CONDITIONAL) {
cpu_fprintf(f, "in conditional delay slot (delayed_pc=0x%08x)\n",
env->delayed_pc);
+ } else if (env->flags & DELAY_SLOT_RTE) {
+ cpu_fprintf(f, "in rte delay slot (delayed_pc=0x%08x)\n",
+ env->delayed_pc);
}
}
@@ -217,8 +220,7 @@ static inline void gen_save_cpu_state(DisasContext *ctx, bool save_pc)
if (ctx->delayed_pc != (uint32_t) -1) {
tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
}
- if ((ctx->tbflags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL))
- != ctx->envflags) {
+ if ((ctx->tbflags & DELAY_SLOT_MASK) != ctx->envflags) {
tcg_gen_movi_i32(cpu_flags, ctx->envflags);
}
}
@@ -329,7 +331,7 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
#define DREG(x) FREG(x) /* Assumes lsb of (x) is always 0 */
#define CHECK_NOT_DELAY_SLOT \
- if (ctx->envflags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
+ if (ctx->envflags & DELAY_SLOT_MASK) { \
gen_save_cpu_state(ctx, true); \
gen_helper_raise_slot_illegal_instruction(cpu_env); \
ctx->bstate = BS_EXCP; \
@@ -339,7 +341,7 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
#define CHECK_PRIVILEGED \
if (IS_USER(ctx)) { \
gen_save_cpu_state(ctx, true); \
- if (ctx->envflags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
+ if (ctx->envflags & DELAY_SLOT_MASK) { \
gen_helper_raise_slot_illegal_instruction(cpu_env); \
} else { \
gen_helper_raise_illegal_instruction(cpu_env); \
@@ -351,7 +353,7 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
#define CHECK_FPU_ENABLED \
if (ctx->tbflags & (1u << SR_FD)) { \
gen_save_cpu_state(ctx, true); \
- if (ctx->envflags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
+ if (ctx->envflags & DELAY_SLOT_MASK) { \
gen_helper_raise_slot_fpu_disable(cpu_env); \
} else { \
gen_helper_raise_fpu_disable(cpu_env); \
@@ -428,8 +430,9 @@ static void _decode_opc(DisasContext * ctx)
CHECK_NOT_DELAY_SLOT
gen_write_sr(cpu_ssr);
tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
- ctx->envflags |= DELAY_SLOT;
+ ctx->envflags |= DELAY_SLOT_RTE;
ctx->delayed_pc = (uint32_t) - 1;
+ ctx->bstate = BS_STOP;
return;
case 0x0058: /* sets */
tcg_gen_ori_i32(cpu_sr, cpu_sr, (1u << SR_S));
@@ -1784,7 +1787,7 @@ static void _decode_opc(DisasContext * ctx)
fflush(stderr);
#endif
gen_save_cpu_state(ctx, true);
- if (ctx->envflags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
+ if (ctx->envflags & DELAY_SLOT_MASK) {
gen_helper_raise_slot_illegal_instruction(cpu_env);
} else {
gen_helper_raise_illegal_instruction(cpu_env);
@@ -1798,14 +1801,14 @@ static void decode_opc(DisasContext * ctx)
_decode_opc(ctx);
- if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
+ if (old_flags & DELAY_SLOT_MASK) {
/* go out of the delay slot */
- ctx->envflags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
+ ctx->envflags &= ~DELAY_SLOT_MASK;
tcg_gen_movi_i32(cpu_flags, ctx->envflags);
ctx->bstate = BS_BRANCH;
if (old_flags & DELAY_SLOT_CONDITIONAL) {
gen_delayed_conditional_jump(ctx);
- } else if (old_flags & DELAY_SLOT) {
+ } else {
gen_jump(ctx);
}
@@ -1824,7 +1827,7 @@ void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
pc_start = tb->pc;
ctx.pc = pc_start;
ctx.tbflags = (uint32_t)tb->flags;
- ctx.envflags = tb->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
+ ctx.envflags = tb->flags & DELAY_SLOT_MASK;
ctx.bstate = BS_NONE;
ctx.memidx = (ctx.tbflags & (1u << SR_MD)) == 0 ? 1 : 0;
/* We don't know if the delayed pc came from a dynamic or static branch,
diff --git a/target/sparc/int32_helper.c b/target/sparc/int32_helper.c
index 09afe136e5..eec9a4d49f 100644
--- a/target/sparc/int32_helper.c
+++ b/target/sparc/int32_helper.c
@@ -109,7 +109,7 @@ void sparc_cpu_do_interrupt(CPUState *cs)
if (env->psret == 0) {
if (cs->exception_index == 0x80 &&
env->def->features & CPU_FEATURE_TA0_SHUTDOWN) {
- qemu_system_shutdown_request();
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
} else {
cpu_abort(cs, "Trap 0x%02x while interrupts disabled, Error state",
cs->exception_index);