diff mbox series

[31/45] linux-user/hppa: Force all code addresses to PRIV_USER

Message ID 20240425000023.1002026-32-richard.henderson@linaro.org
State Superseded
Headers show
Series target/hppa: Misc improvements | expand

Commit Message

Richard Henderson April 25, 2024, midnight UTC
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(-)
diff mbox series

Patch

diff --git a/linux-user/hppa/target_cpu.h b/linux-user/hppa/target_cpu.h
index aacf3e9e02..4b84422a90 100644
--- a/linux-user/hppa/target_cpu.h
+++ b/linux-user/hppa/target_cpu.h
@@ -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)
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index c0da9e9af6..4514bc63dc 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -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  */
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 60cf55b36c..b551cbcb03 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -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;
diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c
index d5232f37fe..bc093b8fe8 100644
--- a/linux-user/hppa/cpu_loop.c
+++ b/linux-user/hppa/cpu_loop.c
@@ -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);
diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c
index 682ba25922..f6f094c960 100644
--- a/linux-user/hppa/signal.c
+++ b/linux-user/hppa/signal.c
@@ -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;
 
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 7315567910..8c8c6181de 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -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;
diff --git a/target/hppa/gdbstub.c b/target/hppa/gdbstub.c
index 4a965b38d7..0daa52f7af 100644
--- a/target/hppa/gdbstub.c
+++ b/target/hppa/gdbstub.c
@@ -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:
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 5b0304d0d5..273691fd6a 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -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;