@@ -28,8 +28,8 @@ static inline void cpu_clone_regs_child(CPUHPPAState *env, target_ulong newsp,
/* Indicate child in return value. */
env->gr[28] = 0;
/* Return from the syscall. */
- env->iaoq_f = env->gr[31];
- env->iaoq_b = env->gr[31] + 4;
+ env->iaoq_f = env->gr[31] | PRIV_USER;
+ env->iaoq_b = env->iaoq_f + 4;
}
static inline void cpu_clone_regs_parent(CPUHPPAState *env, unsigned flags)
@@ -48,6 +48,9 @@
#define MMU_IDX_TO_P(MIDX) (((MIDX) - MMU_KERNEL_IDX) & 1)
#define PRIV_P_TO_MMU_IDX(PRIV, P) ((PRIV) * 2 + !!(P) + MMU_KERNEL_IDX)
+#define PRIV_KERNEL 0
+#define PRIV_USER 3
+
#define TARGET_INSN_START_EXTRA_WORDS 2
/* No need to flush MMU_ABS*_IDX */
@@ -1963,8 +1963,8 @@ static inline void init_thread(struct target_pt_regs *regs,
static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop)
{
- regs->iaoq[0] = infop->entry;
- regs->iaoq[1] = infop->entry + 4;
+ regs->iaoq[0] = infop->entry | PRIV_USER;
+ regs->iaoq[1] = regs->iaoq[0] + 4;
regs->gr[23] = 0;
regs->gr[24] = infop->argv;
regs->gr[25] = infop->argc;
@@ -129,8 +129,8 @@ void cpu_loop(CPUHPPAState *env)
default:
env->gr[28] = ret;
/* We arrived here by faking the gateway page. Return. */
- env->iaoq_f = env->gr[31];
- env->iaoq_b = env->gr[31] + 4;
+ env->iaoq_f = env->gr[31] | PRIV_USER;
+ env->iaoq_b = env->iaoq_f + 4;
break;
case -QEMU_ERESTARTSYS:
case -QEMU_ESIGRETURN:
@@ -140,8 +140,8 @@ void cpu_loop(CPUHPPAState *env)
case EXCP_SYSCALL_LWS:
env->gr[21] = hppa_lws(env);
/* We arrived here by faking the gateway page. Return. */
- env->iaoq_f = env->gr[31];
- env->iaoq_b = env->gr[31] + 4;
+ env->iaoq_f = env->gr[31] | PRIV_USER;
+ env->iaoq_b = env->iaoq_f + 4;
break;
case EXCP_IMP:
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->iaoq_f);
@@ -152,9 +152,9 @@ void cpu_loop(CPUHPPAState *env)
case EXCP_PRIV_OPR:
/* check for glibc ABORT_INSTRUCTION "iitlbp %r0,(%sr0, %r0)" */
if (env->cr[CR_IIR] == 0x04000000) {
- force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->iaoq_f);
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->iaoq_f);
} else {
- force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f);
+ force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f);
}
break;
case EXCP_PRIV_REG:
@@ -170,7 +170,7 @@ void cpu_loop(CPUHPPAState *env)
force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f);
break;
case EXCP_BREAK:
- force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f & ~3);
+ force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f);
break;
case EXCP_DEBUG:
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f);
@@ -101,7 +101,9 @@ static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
cpu_hppa_loaded_fr0(env);
__get_user(env->iaoq_f, &sc->sc_iaoq[0]);
+ env->iaoq_f |= PRIV_USER;
__get_user(env->iaoq_b, &sc->sc_iaoq[1]);
+ env->iaoq_b |= PRIV_USER;
__get_user(env->cr[CR_SAR], &sc->sc_sar);
}
@@ -162,8 +164,8 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
unlock_user(fdesc, haddr, 0);
haddr = dest;
}
- env->iaoq_f = haddr;
- env->iaoq_b = haddr + 4;
+ env->iaoq_f = haddr | PRIV_USER;
+ env->iaoq_b = env->iaoq_f + 4;
env->psw_n = 0;
return;
@@ -32,6 +32,9 @@ static void hppa_cpu_set_pc(CPUState *cs, vaddr value)
{
HPPACPU *cpu = HPPA_CPU(cs);
+#ifdef CONFIG_USER_ONLY
+ value |= PRIV_USER;
+#endif
cpu->env.iaoq_f = value;
cpu->env.iaoq_b = value + 4;
}
@@ -93,8 +96,8 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
#ifdef CONFIG_USER_ONLY
- cpu->env.iaoq_f = tb->pc;
- cpu->env.iaoq_b = tb->cs_base;
+ cpu->env.iaoq_f = tb->pc | PRIV_USER;
+ cpu->env.iaoq_b = tb->cs_base | PRIV_USER;
#else
/* Recover the IAOQ values from the GVA + PRIV. */
uint32_t priv = (tb->flags >> TB_FLAG_PRIV_SHIFT) & 3;
@@ -163,12 +163,18 @@ int hppa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
env->cr[CR_SAR] = val & (hppa_is_pa20(env) ? 63 : 31);
break;
case 33:
+#ifdef CONFIG_USER_ONLY
+ val |= PRIV_USER;
+#endif
env->iaoq_f = val;
break;
case 34:
env->iasq_f = (uint64_t)val << 32;
break;
case 35:
+#ifdef CONFIG_USER_ONLY
+ val |= PRIV_USER;
+#endif
env->iaoq_b = val;
break;
case 36:
@@ -2052,7 +2052,7 @@ static void do_page_zero(DisasContext *ctx)
tcg_gen_st_i64(cpu_gr[26], tcg_env,
offsetof(CPUHPPAState, cr[27]));
- tcg_gen_ori_i64(next.base, cpu_gr[31], 3);
+ tcg_gen_ori_i64(next.base, cpu_gr[31], PRIV_USER);
install_iaq_entries(ctx, &next, NULL);
ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
}
@@ -4581,7 +4581,7 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->is_pa20 = hppa_is_pa20(cpu_env(cs));
#ifdef CONFIG_USER_ONLY
- ctx->privilege = MMU_IDX_TO_PRIV(MMU_USER_IDX);
+ ctx->privilege = PRIV_USER;
ctx->mmu_idx = MMU_USER_IDX;
ctx->iaoq_first = ctx->base.pc_first | ctx->privilege;
ctx->iaq_b.disp = ctx->base.tb->cs_base - ctx->base.pc_first;
The kernel does this along the return path to user mode. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- linux-user/hppa/target_cpu.h | 4 ++-- target/hppa/cpu.h | 3 +++ linux-user/elfload.c | 4 ++-- linux-user/hppa/cpu_loop.c | 14 +++++++------- linux-user/hppa/signal.c | 6 ++++-- target/hppa/cpu.c | 7 +++++-- target/hppa/gdbstub.c | 6 ++++++ target/hppa/translate.c | 4 ++-- 8 files changed, 31 insertions(+), 17 deletions(-)