Merge tag '20231119-xtensa-1' of https://github.com/OSLL/qemu-xtensa into staging

target/xtensa fixes for v8.2:

- fix signal delivery in FDPIC

# -----BEGIN PGP SIGNATURE-----
#
# iQJHBAABCgAxFiEEK2eFS5jlMn3N6xfYUfnMkfg/oEQFAmVaXU4THGpjbXZia2Jj
# QGdtYWlsLmNvbQAKCRBR+cyR+D+gRF13EACXNP0MPn2iWqxLPvxW9mDXaQu9cSlJ
# BcAlHKbi21CDdqLYpyMoenRONtHMDKjEhR4Atv+DRhc2qQYKNogLgCM1PtGkb6+z
# rNS6HBaUFsAKovS03JGcBDDYWS97bfN1AQRrrEzCV+SKq5Gq8Tr23LSgFHred0hS
# OlGmb7/S+uMh1Uo+rqLKFvSkcWLyaPxOhw1BoaNWdifSotfRwK++PZUvv7slQk+/
# J2ePbjU/ZTBTmumn0tg8BP66UHmGQ+TcvGOdD0m6qlQoq5XaqAYgNb6/Cm16xIPJ
# GQtmB1m74Dl1cQGYXlg3YFGluOJGidkT6In6dYzOEzjvOg9Rku+9bdCxIyRgQK7g
# gXcQJaEdpBiex3c21XWhMfjpM1pQruRgIQ3xqYETBMKXXqvbgYdUT09JpuaoTUkP
# oTymnBVL+9hyrlhPWXzn8M6IPUlyT7Hmnb0uVmHfTi8UNBhiGBRSN4x3CMDNi9oL
# ziE3xKgEkii9WEY+qSCodLMvLJBzShpKTjmUhfJMYdK07uVzazhGhmtQ8qSi3Rm7
# 6hDfnnBwrnX/CBE1IMca280Aax3TMf8Sn1pJqsTHwlNFb3O5vcixRajJw7xNprkP
# 5CcS+G2fRK7JIb18FI2aBf7DXD4kfasF8UAaiyQfkmD1/LITSGiDKfKFvaqjA7Ln
# wVrNbrGvDRvdEw==
# =sZPo
# -----END PGP SIGNATURE-----
# gpg: Signature made Sun 19 Nov 2023 14:09:02 EST
# gpg:                using RSA key 2B67854B98E5327DCDEB17D851F9CC91F83FA044
# gpg:                issuer "jcmvbkbc@gmail.com"
# gpg: Good signature from "Max Filippov <filippov@cadence.com>" [unknown]
# gpg:                 aka "Max Filippov <max.filippov@cogentembedded.com>" [unknown]
# gpg:                 aka "Max Filippov <jcmvbkbc@gmail.com>" [unknown]
# gpg: WARNING: The key's User ID is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 2B67 854B 98E5 327D CDEB  17D8 51F9 CC91 F83F A044

* tag '20231119-xtensa-1' of https://github.com/OSLL/qemu-xtensa:
  linux-user: xtensa: fix signal delivery in FDPIC

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c
index f5fb8b5..32dcfa5 100644
--- a/linux-user/xtensa/signal.c
+++ b/linux-user/xtensa/signal.c
@@ -157,6 +157,9 @@
 {
     abi_ulong frame_addr;
     struct target_rt_sigframe *frame;
+    int is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info);
+    abi_ulong handler = 0;
+    abi_ulong handler_fdpic_GOT = 0;
     uint32_t ra;
     bool abi_call0;
     unsigned base;
@@ -165,6 +168,17 @@
     frame_addr = get_sigframe(ka, env, sizeof(*frame));
     trace_user_setup_rt_frame(env, frame_addr);
 
+    if (is_fdpic) {
+        abi_ulong funcdesc_ptr = ka->_sa_handler;
+
+        if (get_user_ual(handler, funcdesc_ptr)
+            || get_user_ual(handler_fdpic_GOT, funcdesc_ptr + 4)) {
+            goto give_sigsegv;
+        }
+    } else {
+        handler = ka->_sa_handler;
+    }
+
     if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
         goto give_sigsegv;
     }
@@ -185,14 +199,21 @@
     }
 
     if (ka->sa_flags & TARGET_SA_RESTORER) {
-        ra = ka->sa_restorer;
+        if (is_fdpic) {
+            if (get_user_ual(ra, ka->sa_restorer)) {
+                unlock_user_struct(frame, frame_addr, 0);
+                goto give_sigsegv;
+            }
+        } else {
+            ra = ka->sa_restorer;
+        }
     } else {
         /* Not used, but retain for ABI compatibility. */
         install_sigtramp(frame->retcode);
         ra = default_rt_sigreturn;
     }
     memset(env->regs, 0, sizeof(env->regs));
-    env->pc = ka->_sa_handler;
+    env->pc = handler;
     env->regs[1] = frame_addr;
     env->sregs[WINDOW_BASE] = 0;
     env->sregs[WINDOW_START] = 1;
@@ -212,6 +233,9 @@
     env->regs[base + 3] = frame_addr + offsetof(struct target_rt_sigframe,
                                                 info);
     env->regs[base + 4] = frame_addr + offsetof(struct target_rt_sigframe, uc);
+    if (is_fdpic) {
+        env->regs[base + 11] = handler_fdpic_GOT;
+    }
     unlock_user_struct(frame, frame_addr, 1);
     return;