Skip to content

Commit

Permalink
linux-user/ppc: Add vdso
Browse files Browse the repository at this point in the history
Add support in gen-vdso-elfn.c.inc for the DT_PPC64_OPT
dynamic tag: this is an integer, so does not need relocation.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed Oct 30, 2023
1 parent 00cc293 commit e34136d
Show file tree
Hide file tree
Showing 12 changed files with 467 additions and 8 deletions.
8 changes: 8 additions & 0 deletions linux-user/elfload.c
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,14 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en
#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096

#ifndef TARGET_PPC64
# define VDSO_HEADER "vdso-32.c.inc"
#elif TARGET_BIG_ENDIAN
# define VDSO_HEADER "vdso-64.c.inc"
#else
# define VDSO_HEADER "vdso-64le.c.inc"
#endif

#endif

#ifdef TARGET_LOONGARCH64
Expand Down
7 changes: 7 additions & 0 deletions linux-user/gen-vdso-elfn.c.inc
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,14 @@ static void elfN(process)(FILE *outf, void *buf, bool need_bswap)
errors++;
break;

case PT_LOPROC + 3:
if (ehdr->e_machine == EM_PPC64) {
break; /* DT_PPC64_OPT: integer bitmask */
}
goto do_default;

default:
do_default:
/* This is probably something target specific. */
fprintf(stderr, "VDSO has unknown DYNAMIC entry (%lx)\n",
(unsigned long)tag);
Expand Down
20 changes: 20 additions & 0 deletions linux-user/ppc/Makefile.vdso
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
include $(BUILD_DIR)/tests/tcg/ppc64-linux-user/config-target.mak

SUBDIR = $(SRC_PATH)/linux-user/ppc
VPATH += $(SUBDIR)

all: $(SUBDIR)/vdso-32.so $(SUBDIR)/vdso-64.so $(SUBDIR)/vdso-64le.so

LDFLAGS32 = -nostdlib -shared -Wl,-T,$(SUBDIR)/vdso-32.ld \
-Wl,-h,linux-vdso32.so.1 -Wl,--hash-style=both -Wl,--build-id=sha1
LDFLAGS64 = -nostdlib -shared -Wl,-T,$(SUBDIR)/vdso-64.ld \
-Wl,-h,linux-vdso64.so.1 -Wl,--hash-style=both -Wl,--build-id=sha1

$(SUBDIR)/vdso-32.so: vdso.S vdso-32.ld vdso-asmoffset.h
$(CC) -o $@ $(LDFLAGS32) -m32 $<

$(SUBDIR)/vdso-64.so: vdso.S vdso-64.ld vdso-asmoffset.h
$(CC) -o $@ $(LDFLAGS64) -mbig-endian $<

$(SUBDIR)/vdso-64le.so: vdso.S vdso-64.ld vdso-asmoffset.h
$(CC) -o $@ $(LDFLAGS64) -mlittle-endian $<
12 changes: 12 additions & 0 deletions linux-user/ppc/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,15 @@ syscall_nr_generators += {
arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
output: '@BASENAME@_nr.h')
}

vdso_32_inc = gen_vdso.process('vdso-32.so', extra_args: [
'-s', '__kernel_sigtramp32',
'-r', '__kernel_sigtramp_rt32'
])
linux_user_ss.add(when: 'TARGET_PPC', if_true: vdso_32_inc)

vdso_64_inc = gen_vdso.process('vdso-64.so',
extra_args: ['-r', '__kernel_sigtramp_rt64'])
vdso_64le_inc = gen_vdso.process('vdso-64le.so',
extra_args: ['-r', '__kernel_sigtramp_rt64'])
linux_user_ss.add(when: 'TARGET_PPC64', if_true: [vdso_64_inc, vdso_64le_inc])
31 changes: 23 additions & 8 deletions linux-user/ppc/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,7 @@
#include "user-internals.h"
#include "signal-common.h"
#include "linux-user/trace.h"

/* Size of dummy stack frame allocated when calling signal handler.
See arch/powerpc/include/asm/ptrace.h. */
#if defined(TARGET_PPC64)
#define SIGNAL_FRAMESIZE 128
#else
#define SIGNAL_FRAMESIZE 64
#endif
#include "vdso-asmoffset.h"

/* See arch/powerpc/include/asm/ucontext.h. Only used for 32-bit PPC;
on 64-bit PPC, sigcontext and mcontext are one and the same. */
Expand Down Expand Up @@ -73,6 +66,16 @@ struct target_mcontext {
#endif
};

QEMU_BUILD_BUG_ON(offsetof(struct target_mcontext, mc_fregs)
!= offsetof_mcontext_fregs);
#if defined(TARGET_PPC64)
QEMU_BUILD_BUG_ON(offsetof(struct target_mcontext, v_regs)
!= offsetof_mcontext_vregs_ptr);
#else
QEMU_BUILD_BUG_ON(offsetof(struct target_mcontext, mc_vregs)
!= offsetof_mcontext_vregs);
#endif

/* See arch/powerpc/include/asm/sigcontext.h. */
struct target_sigcontext {
target_ulong _unused[4];
Expand Down Expand Up @@ -161,13 +164,18 @@ struct target_ucontext {
#endif
};

#if !defined(TARGET_PPC64)
/* See arch/powerpc/kernel/signal_32.c. */
struct target_sigframe {
struct target_sigcontext sctx;
struct target_mcontext mctx;
int32_t abigap[56];
};

QEMU_BUILD_BUG_ON(offsetof(struct target_sigframe, mctx)
!= offsetof_sigframe_mcontext);
#endif

#if defined(TARGET_PPC64)

#define TARGET_TRAMP_SIZE 6
Expand All @@ -184,6 +192,10 @@ struct target_rt_sigframe {
char abigap[288];
} __attribute__((aligned(16)));

QEMU_BUILD_BUG_ON(offsetof(struct target_rt_sigframe,
uc.tuc_sigcontext.mcontext)
!= offsetof_rt_sigframe_mcontext);

#else

struct target_rt_sigframe {
Expand All @@ -192,6 +204,9 @@ struct target_rt_sigframe {
int32_t abigap[56];
};

QEMU_BUILD_BUG_ON(offsetof(struct target_rt_sigframe, uc.tuc_mcontext)
!= offsetof_rt_sigframe_mcontext);

#endif

#if defined(TARGET_PPC64)
Expand Down
70 changes: 70 additions & 0 deletions linux-user/ppc/vdso-32.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Linker script for linux powerpc64 replacement vdso.
*
* Copyright 2023 Linaro, Ltd.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/

VERSION {
LINUX_2.6.15 {
global:
__kernel_gettimeofday;
__kernel_clock_gettime;
__kernel_clock_gettime64;
__kernel_clock_getres;
__kernel_time;
__kernel_sync_dicache;
__kernel_sigtramp32;
__kernel_sigtramp_rt32;
__kernel_getcpu;
local: *;
};
}

PHDRS {
phdr PT_PHDR FLAGS(4) PHDRS;
load PT_LOAD FLAGS(7) FILEHDR PHDRS; /* FLAGS=RWX */
dynamic PT_DYNAMIC FLAGS(4);
eh_frame_hdr PT_GNU_EH_FRAME;
note PT_NOTE FLAGS(4);
}

SECTIONS {
. = SIZEOF_HEADERS;

/*
* The following, including the FILEHDRS and PHDRS, are modified
* when we relocate the binary. We want them to be initially
* writable for the relocation; we'll force them read-only after.
*/
.note : { *(.note*) } :load :note
.dynamic : { *(.dynamic) } :load :dynamic
.dynsym : { *(.dynsym) } :load
.data : {
/*
* There ought not be any real read-write data.
* But since we manipulated the segment layout,
* we have to put these sections somewhere.
*/
*(.data*)
*(.sdata*)
*(.got.plt) *(.got)
*(.gnu.linkonce.d.*)
*(.bss*)
*(.dynbss*)
*(.gnu.linkonce.b.*)
}

.rodata : { *(.rodata*) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.eh_frame_hdr : { *(.eh_frame_hdr) } :load :eh_frame_hdr
.eh_frame : { *(.eh_frame) } :load

.text : { *(.text*) } :load
}
Binary file added linux-user/ppc/vdso-32.so
Binary file not shown.
68 changes: 68 additions & 0 deletions linux-user/ppc/vdso-64.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Linker script for linux powerpc64 replacement vdso.
*
* Copyright 2023 Linaro, Ltd.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/

VERSION {
LINUX_2.6.15 {
global:
__kernel_gettimeofday;
__kernel_clock_gettime;
__kernel_clock_getres;
__kernel_sync_dicache;
__kernel_sigtramp_rt64;
__kernel_getcpu;
__kernel_time;
local: *;
};
}

PHDRS {
phdr PT_PHDR FLAGS(4) PHDRS;
load PT_LOAD FLAGS(7) FILEHDR PHDRS; /* FLAGS=RWX */
dynamic PT_DYNAMIC FLAGS(4);
eh_frame_hdr PT_GNU_EH_FRAME;
note PT_NOTE FLAGS(4);
}

SECTIONS {
. = SIZEOF_HEADERS;

/*
* The following, including the FILEHDRS and PHDRS, are modified
* when we relocate the binary. We want them to be initially
* writable for the relocation; we'll force them read-only after.
*/
.note : { *(.note*) } :load :note
.dynamic : { *(.dynamic) } :load :dynamic
.dynsym : { *(.dynsym) } :load
.data : {
/*
* There ought not be any real read-write data.
* But since we manipulated the segment layout,
* we have to put these sections somewhere.
*/
*(.data*)
*(.sdata*)
*(.got.plt) *(.got)
*(.gnu.linkonce.d.*)
*(.bss*)
*(.dynbss*)
*(.gnu.linkonce.b.*)
}

.rodata : { *(.rodata*) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.eh_frame_hdr : { *(.eh_frame_hdr) } :load :eh_frame_hdr
.eh_frame : { *(.eh_frame) } :load

.text : { *(.text*) } :load
}
Binary file added linux-user/ppc/vdso-64.so
Binary file not shown.
Binary file added linux-user/ppc/vdso-64le.so
Binary file not shown.
20 changes: 20 additions & 0 deletions linux-user/ppc/vdso-asmoffset.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Size of dummy stack frame allocated when calling signal handler.
* See arch/powerpc/include/asm/ptrace.h.
*/
#ifdef TARGET_ABI32
# define SIGNAL_FRAMESIZE 64
#else
# define SIGNAL_FRAMESIZE 128
#endif

#ifdef TARGET_ABI32
# define offsetof_sigframe_mcontext 0x20
# define offsetof_rt_sigframe_mcontext 0x140
# define offsetof_mcontext_fregs 0xc0
# define offsetof_mcontext_vregs 0x1d0
#else
# define offsetof_rt_sigframe_mcontext 0xe8
# define offsetof_mcontext_fregs 0x180
# define offsetof_mcontext_vregs_ptr 0x288
#endif

0 comments on commit e34136d

Please sign in to comment.