aboutsummaryrefslogtreecommitdiff
path: root/linux-user/hppa
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user/hppa')
-rw-r--r--linux-user/hppa/cpu_loop.c32
-rw-r--r--linux-user/hppa/elfload.c47
-rw-r--r--linux-user/hppa/target_elf.h15
-rw-r--r--linux-user/hppa/target_syscall.h18
-rw-r--r--linux-user/hppa/vdso.S2
-rwxr-xr-xlinux-user/hppa/vdso.sobin2104 -> 2224 bytes
6 files changed, 82 insertions, 32 deletions
diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c
index 890e758..356cb48 100644
--- a/linux-user/hppa/cpu_loop.c
+++ b/linux-user/hppa/cpu_loop.c
@@ -112,14 +112,14 @@ static abi_ulong hppa_lws(CPUHPPAState *env)
void cpu_loop(CPUHPPAState *env)
{
CPUState *cs = env_cpu(env);
- abi_ulong ret;
+ abi_ulong ret, si_code = 0;
int trapnr;
while (1) {
cpu_exec_start(cs);
trapnr = cpu_exec(cs);
cpu_exec_end(cs);
- process_queued_cpu_work(cs);
+ qemu_process_cpu_events(cs);
switch (trapnr) {
case EXCP_SYSCALL:
@@ -169,7 +169,15 @@ void cpu_loop(CPUHPPAState *env)
force_sig_fault(TARGET_SIGFPE, TARGET_FPE_CONDTRAP, env->iaoq_f);
break;
case EXCP_ASSIST:
- force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f);
+ #define set_si_code(mask, val) \
+ if (env->fr[0] & mask) { si_code = val; }
+ set_si_code(R_FPSR_FLG_I_MASK, TARGET_FPE_FLTRES);
+ set_si_code(R_FPSR_FLG_U_MASK, TARGET_FPE_FLTUND);
+ set_si_code(R_FPSR_FLG_O_MASK, TARGET_FPE_FLTOVF);
+ set_si_code(R_FPSR_FLG_Z_MASK, TARGET_FPE_FLTDIV);
+ set_si_code(R_FPSR_FLG_V_MASK, TARGET_FPE_FLTINV);
+ #undef set_si_code
+ force_sig_fault(TARGET_SIGFPE, si_code, env->iaoq_f);
break;
case EXCP_BREAK:
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f);
@@ -188,12 +196,16 @@ void cpu_loop(CPUHPPAState *env)
}
}
-void target_cpu_copy_regs(CPUArchState *env, target_pt_regs *regs)
+void init_main_thread(CPUState *cs, struct image_info *info)
{
- int i;
- for (i = 1; i < 32; i++) {
- env->gr[i] = regs->gr[i];
- }
- env->iaoq_f = regs->iaoq[0];
- env->iaoq_b = regs->iaoq[1];
+ CPUArchState *env = cpu_env(cs);
+
+ env->iaoq_f = info->entry | PRIV_USER;
+ env->iaoq_b = env->iaoq_f + 4;
+ env->gr[23] = 0;
+ env->gr[24] = info->argv;
+ env->gr[25] = info->argc;
+ /* The top-of-stack contains a linkage buffer. */
+ env->gr[30] = info->start_stack + 64;
+ env->gr[31] = info->entry;
}
diff --git a/linux-user/hppa/elfload.c b/linux-user/hppa/elfload.c
new file mode 100644
index 0000000..4600708
--- /dev/null
+++ b/linux-user/hppa/elfload.c
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "qemu/osdep.h"
+#include "qemu.h"
+#include "loader.h"
+#include "target_elf.h"
+
+
+const char *get_elf_cpu_model(uint32_t eflags)
+{
+ return "hppa";
+}
+
+const char *get_elf_platform(CPUState *cs)
+{
+ return "PARISC";
+}
+
+bool init_guest_commpage(void)
+{
+ /* If reserved_va, then we have already mapped 0 page on the host. */
+ if (!reserved_va) {
+ void *want, *addr;
+
+ want = g2h_untagged(LO_COMMPAGE);
+ addr = mmap(want, TARGET_PAGE_SIZE, PROT_NONE,
+ MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0);
+ if (addr == MAP_FAILED) {
+ perror("Allocating guest commpage");
+ exit(EXIT_FAILURE);
+ }
+ if (addr != want) {
+ return false;
+ }
+ }
+
+ /*
+ * On Linux, page zero is normally marked execute only + gateway.
+ * Normal read or write is supposed to fail (thus PROT_NONE above),
+ * but specific offsets have kernel code mapped to raise permissions
+ * and implement syscalls. Here, simply mark the page executable.
+ * Special case the entry points during translation (see do_page_zero).
+ */
+ page_set_flags(LO_COMMPAGE, LO_COMMPAGE | ~TARGET_PAGE_MASK,
+ PAGE_EXEC | PAGE_VALID, PAGE_VALID);
+ return true;
+}
diff --git a/linux-user/hppa/target_elf.h b/linux-user/hppa/target_elf.h
index 19cae8b..76930c9 100644
--- a/linux-user/hppa/target_elf.h
+++ b/linux-user/hppa/target_elf.h
@@ -7,8 +7,15 @@
#ifndef HPPA_TARGET_ELF_H
#define HPPA_TARGET_ELF_H
-static inline const char *cpu_get_model(uint32_t eflags)
-{
- return "hppa";
-}
+
+#define ELF_CLASS ELFCLASS32
+#define ELF_MACHINE EM_PARISC
+
+#define HAVE_ELF_PLATFORM 1
+
+#define LO_COMMPAGE 0
+#define STACK_GROWS_DOWN 0
+#define STACK_ALIGNMENT 64
+#define VDSO_HEADER "vdso.c.inc"
+
#endif
diff --git a/linux-user/hppa/target_syscall.h b/linux-user/hppa/target_syscall.h
index 9a8f8ca..4b21e85 100644
--- a/linux-user/hppa/target_syscall.h
+++ b/linux-user/hppa/target_syscall.h
@@ -1,24 +1,6 @@
#ifndef HPPA_TARGET_SYSCALL_H
#define HPPA_TARGET_SYSCALL_H
-struct target_pt_regs {
- target_ulong gr[32];
- uint64_t fr[32];
- target_ulong sr[8];
- target_ulong iasq[2];
- target_ulong iaoq[2];
- target_ulong cr27;
- target_ulong __pad0;
- target_ulong orig_r28;
- target_ulong ksp;
- target_ulong kpc;
- target_ulong sar;
- target_ulong iir;
- target_ulong isr;
- target_ulong ior;
- target_ulong ipsw;
-};
-
#define UNAME_MACHINE "parisc"
#define UNAME_MINIMUM_RELEASE "2.6.32"
#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/hppa/vdso.S b/linux-user/hppa/vdso.S
index 5be14d2..a6f8da2 100644
--- a/linux-user/hppa/vdso.S
+++ b/linux-user/hppa/vdso.S
@@ -156,8 +156,10 @@
__kernel_sigtramp_rt:
ldi 0, %r25
ldi __NR_rt_sigreturn, %r20
+sigreturn_region_start:
be,l 0x100(%sr2, %r0), %sr0, %r31
nop
+sigreturn_region_end:
.cfi_endproc
.size __kernel_sigtramp_rt, . - __kernel_sigtramp_rt
diff --git a/linux-user/hppa/vdso.so b/linux-user/hppa/vdso.so
index e1ddd70..68baf80 100755
--- a/linux-user/hppa/vdso.so
+++ b/linux-user/hppa/vdso.so
Binary files differ