aboutsummaryrefslogtreecommitdiff
path: root/linux-user/x86_64
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user/x86_64')
-rw-r--r--linux-user/x86_64/elfload.c73
-rw-r--r--linux-user/x86_64/target_elf.h24
-rw-r--r--linux-user/x86_64/target_ptrace.h40
-rw-r--r--linux-user/x86_64/target_syscall.h28
4 files changed, 133 insertions, 32 deletions
diff --git a/linux-user/x86_64/elfload.c b/linux-user/x86_64/elfload.c
new file mode 100644
index 0000000..5914f76
--- /dev/null
+++ b/linux-user/x86_64/elfload.c
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qemu.h"
+#include "loader.h"
+#include "target_elf.h"
+
+
+const char *get_elf_cpu_model(uint32_t eflags)
+{
+ return "max";
+}
+
+abi_ulong get_elf_hwcap(CPUState *cs)
+{
+ return cpu_env(cs)->features[FEAT_1_EDX];
+}
+
+const char *get_elf_platform(CPUState *cs)
+{
+ return "x86_64";
+}
+
+bool init_guest_commpage(void)
+{
+ /*
+ * The vsyscall page is at a high negative address aka kernel space,
+ * which means that we cannot actually allocate it with target_mmap.
+ * We still should be able to use page_set_flags, unless the user
+ * has specified -R reserved_va, which would trigger an assert().
+ */
+ if (reserved_va != 0 &&
+ TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE - 1 > reserved_va) {
+ error_report("Cannot allocate vsyscall page");
+ exit(EXIT_FAILURE);
+ }
+ page_set_flags(TARGET_VSYSCALL_PAGE,
+ TARGET_VSYSCALL_PAGE | ~TARGET_PAGE_MASK,
+ PAGE_EXEC | PAGE_VALID, PAGE_VALID);
+ return true;
+}
+
+void elf_core_copy_regs(target_elf_gregset_t *r, const CPUX86State *env)
+{
+ r->pt.r15 = tswapal(env->regs[15]);
+ r->pt.r14 = tswapal(env->regs[14]);
+ r->pt.r13 = tswapal(env->regs[13]);
+ r->pt.r12 = tswapal(env->regs[12]);
+ r->pt.bp = tswapal(env->regs[R_EBP]);
+ r->pt.bx = tswapal(env->regs[R_EBX]);
+ r->pt.r11 = tswapal(env->regs[11]);
+ r->pt.r10 = tswapal(env->regs[10]);
+ r->pt.r9 = tswapal(env->regs[9]);
+ r->pt.r8 = tswapal(env->regs[8]);
+ r->pt.ax = tswapal(env->regs[R_EAX]);
+ r->pt.cx = tswapal(env->regs[R_ECX]);
+ r->pt.dx = tswapal(env->regs[R_EDX]);
+ r->pt.si = tswapal(env->regs[R_ESI]);
+ r->pt.di = tswapal(env->regs[R_EDI]);
+ r->pt.orig_ax = tswapal(get_task_state(env_cpu_const(env))->orig_ax);
+ r->pt.ip = tswapal(env->eip);
+ r->pt.cs = tswapal(env->segs[R_CS].selector & 0xffff);
+ r->pt.flags = tswapal(env->eflags);
+ r->pt.sp = tswapal(env->regs[R_ESP]);
+ r->pt.ss = tswapal(env->segs[R_SS].selector & 0xffff);
+ r->pt.fs_base = tswapal(env->segs[R_FS].base);
+ r->pt.gs_base = tswapal(env->segs[R_GS].base);
+ r->pt.ds = tswapal(env->segs[R_DS].selector & 0xffff);
+ r->pt.es = tswapal(env->segs[R_ES].selector & 0xffff);
+ r->pt.fs = tswapal(env->segs[R_FS].selector & 0xffff);
+ r->pt.gs = tswapal(env->segs[R_GS].selector & 0xffff);
+}
diff --git a/linux-user/x86_64/target_elf.h b/linux-user/x86_64/target_elf.h
index 3f628f8..840bddf 100644
--- a/linux-user/x86_64/target_elf.h
+++ b/linux-user/x86_64/target_elf.h
@@ -7,8 +7,24 @@
#ifndef X86_64_TARGET_ELF_H
#define X86_64_TARGET_ELF_H
-static inline const char *cpu_get_model(uint32_t eflags)
-{
- return "max";
-}
+
+#include "target_ptrace.h"
+
+#define ELF_CLASS ELFCLASS64
+#define ELF_MACHINE EM_X86_64
+#define VDSO_HEADER "vdso.c.inc"
+
+#define HAVE_ELF_HWCAP 1
+#define HAVE_ELF_PLATFORM 1
+#define HAVE_ELF_CORE_DUMP 1
+#define HAVE_GUEST_COMMPAGE 1
+
+/*
+ * See linux kernel: arch/x86/include/asm/elf.h, where
+ * elf_gregset_t is mapped to struct user_regs_struct via sizeof.
+ */
+typedef struct target_elf_gregset_t {
+ struct target_user_regs_struct pt;
+} target_elf_gregset_t;
+
#endif
diff --git a/linux-user/x86_64/target_ptrace.h b/linux-user/x86_64/target_ptrace.h
new file mode 100644
index 0000000..3352712
--- /dev/null
+++ b/linux-user/x86_64/target_ptrace.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef X86_64_TARGET_PTRACE_H
+#define X86_64_TARGET_PTRACE_H
+
+/*
+ * The struct pt_regs in arch/x86/include/uapi/asm/ptrace.h has missing
+ * register values and is not used. See arch/x86/include/asm/user_64.h.
+ */
+struct target_user_regs_struct {
+ abi_ulong r15;
+ abi_ulong r14;
+ abi_ulong r13;
+ abi_ulong r12;
+ abi_ulong bp;
+ abi_ulong bx;
+ abi_ulong r11;
+ abi_ulong r10;
+ abi_ulong r9;
+ abi_ulong r8;
+ abi_ulong ax;
+ abi_ulong cx;
+ abi_ulong dx;
+ abi_ulong si;
+ abi_ulong di;
+ abi_ulong orig_ax;
+ abi_ulong ip;
+ abi_ulong cs;
+ abi_ulong flags;
+ abi_ulong sp;
+ abi_ulong ss;
+ abi_ulong fs_base;
+ abi_ulong gs_base;
+ abi_ulong ds;
+ abi_ulong es;
+ abi_ulong fs;
+ abi_ulong gs;
+};
+
+#endif /* X86_64_TARGET_PTRACE_H */
diff --git a/linux-user/x86_64/target_syscall.h b/linux-user/x86_64/target_syscall.h
index fb55834..68f55f8 100644
--- a/linux-user/x86_64/target_syscall.h
+++ b/linux-user/x86_64/target_syscall.h
@@ -4,34 +4,6 @@
#define __USER_CS (0x33)
#define __USER_DS (0x2B)
-struct target_pt_regs {
- abi_ulong r15;
- abi_ulong r14;
- abi_ulong r13;
- abi_ulong r12;
- abi_ulong rbp;
- abi_ulong rbx;
-/* arguments: non interrupts/non tracing syscalls only save up to here */
- abi_ulong r11;
- abi_ulong r10;
- abi_ulong r9;
- abi_ulong r8;
- abi_ulong rax;
- abi_ulong rcx;
- abi_ulong rdx;
- abi_ulong rsi;
- abi_ulong rdi;
- abi_ulong orig_rax;
-/* end of arguments */
-/* cpu exception frame or undefined */
- abi_ulong rip;
- abi_ulong cs;
- abi_ulong eflags;
- abi_ulong rsp;
- abi_ulong ss;
-/* top of stack page */
-};
-
/* Maximum number of LDT entries supported. */
#define TARGET_LDT_ENTRIES 8192
/* The size of each LDT entry. */