Author: nwhitehorn
Date: Mon Nov 23 17:07:51 2015
New Revision: 291211
URL: https://svnweb.freebsd.org/changeset/base/291211

Log:
  Provide support for userland binaries using the new ELFv2 ABI. This is a
  new, simplified, ELF ABI that avoids some of the stranger aspects of the
  existing 64-bit PowerPC ABI (function descriptors, in particular). Actually
  generating such executables requires a new version of binutils and a newer
  compiler (either GCC or clang) than GCC 4.2.1.

Modified:
  head/sys/powerpc/include/asm.h
  head/sys/powerpc/include/md_var.h
  head/sys/powerpc/include/profile.h
  head/sys/powerpc/powerpc/elf64_machdep.c
  head/sys/powerpc/powerpc/exec_machdep.c
  head/sys/powerpc/powerpc/sigcode64.S

Modified: head/sys/powerpc/include/asm.h
==============================================================================
--- head/sys/powerpc/include/asm.h      Mon Nov 23 17:05:28 2015        
(r291210)
+++ head/sys/powerpc/include/asm.h      Mon Nov 23 17:07:51 2015        
(r291211)
@@ -85,7 +85,9 @@
        .section ".toc","aw"; \
        TOC_REF(name): \
         .tc name[TC],name
+#endif
 
+#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1)
 #define        _ENTRY(name) \
        .section ".text"; \
        .p2align 2; \

Modified: head/sys/powerpc/include/md_var.h
==============================================================================
--- head/sys/powerpc/include/md_var.h   Mon Nov 23 17:05:28 2015        
(r291210)
+++ head/sys/powerpc/include/md_var.h   Mon Nov 23 17:07:51 2015        
(r291211)
@@ -37,8 +37,8 @@ extern        char    sigcode32[];
 extern int     szsigcode32;
 
 #ifdef __powerpc64__
-extern char    sigcode64[];
-extern int     szsigcode64;
+extern char    sigcode64[], sigcode64_elfv2[];
+extern int     szsigcode64, szsigcode64_elfv2;
 #endif
 
 extern long    Maxmem;

Modified: head/sys/powerpc/include/profile.h
==============================================================================
--- head/sys/powerpc/include/profile.h  Mon Nov 23 17:05:28 2015        
(r291210)
+++ head/sys/powerpc/include/profile.h  Mon Nov 23 17:07:51 2015        
(r291211)
@@ -75,9 +75,10 @@ typedef __ptrdiff_t  fptrdiff_t;
  * to be restored to what it was on entry to the profiled routine.
  */
 
-#ifdef __powerpc64__
-#define        MCOUNT                                  \
-__asm( "       .text                           \n" \
+#if defined(__powerpc64__)
+
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
+#define MCOUNT_PREAMBLE \
        "       .align  2                       \n" \
        "       .globl  _mcount                 \n" \
        "       .section \".opd\",\"aw\"        \n" \
@@ -88,7 +89,17 @@ __asm(       "       .text                           \n" \
        "       .size   _mcount,24              \n" \
        "       .type   _mcount,@function       \n" \
        "       .align  4                       \n" \
-       ".L._mcount:                            \n" \
+       ".L._mcount:                            \n" 
+#else
+#define MCOUNT_PREAMBLE \
+       "       .globl  _mcount                 \n" \
+       "       .type   _mcount,@function       \n" \
+       "       .align  4                       \n" \
+       "_mcount:                               \n"
+#endif
+
+#define        MCOUNT                                  \
+__asm( MCOUNT_PREAMBLE \
        "       stdu    %r1,-(288+128)(%r1)     \n" \
        "       std     %r3,48(%r1)             \n" \
        "       std     %r4,56(%r1)             \n" \

Modified: head/sys/powerpc/powerpc/elf64_machdep.c
==============================================================================
--- head/sys/powerpc/powerpc/elf64_machdep.c    Mon Nov 23 17:05:28 2015        
(r291210)
+++ head/sys/powerpc/powerpc/elf64_machdep.c    Mon Nov 23 17:07:51 2015        
(r291211)
@@ -49,7 +49,10 @@
 #include <machine/elf.h>
 #include <machine/md_var.h>
 
-struct sysentvec elf64_freebsd_sysvec = {
+static void exec_setregs_funcdesc(struct thread *td, struct image_params *imgp,
+    u_long stack);
+
+struct sysentvec elf64_freebsd_sysvec_v1 = {
        .sv_size        = SYS_MAXSYSCALL,
        .sv_table       = sysent,
        .sv_mask        = 0,
@@ -74,6 +77,45 @@ struct sysentvec elf64_freebsd_sysvec = 
        .sv_psstrings   = PS_STRINGS,
        .sv_stackprot   = VM_PROT_ALL,
        .sv_copyout_strings = exec_copyout_strings,
+       .sv_setregs     = exec_setregs_funcdesc,
+       .sv_fixlimit    = NULL,
+       .sv_maxssiz     = NULL,
+       .sv_flags       = SV_ABI_FREEBSD | SV_LP64 | SV_SHP,
+       .sv_set_syscall_retval = cpu_set_syscall_retval,
+       .sv_fetch_syscall_args = cpu_fetch_syscall_args,
+       .sv_syscallnames = syscallnames,
+       .sv_shared_page_base = SHAREDPAGE,
+       .sv_shared_page_len = PAGE_SIZE,
+       .sv_schedtail   = NULL,
+       .sv_thread_detach = NULL,
+};
+INIT_SYSENTVEC(elf64_sysvec_v1, &elf64_freebsd_sysvec_v1);
+
+struct sysentvec elf64_freebsd_sysvec_v2 = {
+       .sv_size        = SYS_MAXSYSCALL,
+       .sv_table       = sysent,
+       .sv_mask        = 0,
+       .sv_sigsize     = 0,
+       .sv_sigtbl      = NULL,
+       .sv_errsize     = 0,
+       .sv_errtbl      = NULL,
+       .sv_transtrap   = NULL,
+       .sv_fixup       = __elfN(freebsd_fixup),
+       .sv_sendsig     = sendsig,
+       .sv_sigcode     = sigcode64_elfv2,
+       .sv_szsigcode   = &szsigcode64_elfv2,
+       .sv_prepsyscall = NULL,
+       .sv_name        = "FreeBSD ELF64 V2",
+       .sv_coredump    = __elfN(coredump),
+       .sv_imgact_try  = NULL,
+       .sv_minsigstksz = MINSIGSTKSZ,
+       .sv_pagesize    = PAGE_SIZE,
+       .sv_minuser     = VM_MIN_ADDRESS,
+       .sv_maxuser     = VM_MAXUSER_ADDRESS,
+       .sv_usrstack    = USRSTACK,
+       .sv_psstrings   = PS_STRINGS,
+       .sv_stackprot   = VM_PROT_ALL,
+       .sv_copyout_strings = exec_copyout_strings,
        .sv_setregs     = exec_setregs,
        .sv_fixlimit    = NULL,
        .sv_maxssiz     = NULL,
@@ -86,23 +128,44 @@ struct sysentvec elf64_freebsd_sysvec = 
        .sv_schedtail   = NULL,
        .sv_thread_detach = NULL,
 };
-INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
+INIT_SYSENTVEC(elf64_sysvec_v2, &elf64_freebsd_sysvec_v2);
+
+static boolean_t ppc64_elfv1_header_match(struct image_params *params);
+static boolean_t ppc64_elfv2_header_match(struct image_params *params);
+
+static Elf64_Brandinfo freebsd_brand_info_elfv1 = {
+       .brand          = ELFOSABI_FREEBSD,
+       .machine        = EM_PPC64,
+       .compat_3_brand = "FreeBSD",
+       .emul_path      = NULL,
+       .interp_path    = "/libexec/ld-elf.so.1",
+       .sysvec         = &elf64_freebsd_sysvec_v1,
+       .interp_newpath = NULL,
+       .brand_note     = &elf64_freebsd_brandnote,
+       .flags          = BI_CAN_EXEC_DYN | BI_BRAND_NOTE,
+       .header_supported = &ppc64_elfv1_header_match
+};
+
+SYSINIT(elf64v1, SI_SUB_EXEC, SI_ORDER_ANY,
+    (sysinit_cfunc_t) elf64_insert_brand_entry,
+    &freebsd_brand_info_elfv1);
 
-static Elf64_Brandinfo freebsd_brand_info = {
+static Elf64_Brandinfo freebsd_brand_info_elfv2 = {
        .brand          = ELFOSABI_FREEBSD,
        .machine        = EM_PPC64,
        .compat_3_brand = "FreeBSD",
        .emul_path      = NULL,
        .interp_path    = "/libexec/ld-elf.so.1",
-       .sysvec         = &elf64_freebsd_sysvec,
+       .sysvec         = &elf64_freebsd_sysvec_v2,
        .interp_newpath = NULL,
        .brand_note     = &elf64_freebsd_brandnote,
-       .flags          = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+       .flags          = BI_CAN_EXEC_DYN | BI_BRAND_NOTE,
+       .header_supported = &ppc64_elfv2_header_match
 };
 
-SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
+SYSINIT(elf64v2, SI_SUB_EXEC, SI_ORDER_ANY,
     (sysinit_cfunc_t) elf64_insert_brand_entry,
-    &freebsd_brand_info);
+    &freebsd_brand_info_elfv2);
 
 static Elf64_Brandinfo freebsd_brand_oinfo = {
        .brand          = ELFOSABI_FREEBSD,
@@ -110,10 +173,11 @@ static Elf64_Brandinfo freebsd_brand_oin
        .compat_3_brand = "FreeBSD",
        .emul_path      = NULL,
        .interp_path    = "/usr/libexec/ld-elf.so.1",
-       .sysvec         = &elf64_freebsd_sysvec,
+       .sysvec         = &elf64_freebsd_sysvec_v1,
        .interp_newpath = NULL,
        .brand_note     = &elf64_freebsd_brandnote,
-       .flags          = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+       .flags          = BI_CAN_EXEC_DYN | BI_BRAND_NOTE,
+       .header_supported = &ppc64_elfv1_header_match
 };
 
 SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
@@ -122,6 +186,50 @@ SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_AN
 
 void elf_reloc_self(Elf_Dyn *dynp, Elf_Addr relocbase);
 
+static boolean_t
+ppc64_elfv1_header_match(struct image_params *params)
+{
+       const Elf64_Ehdr *hdr = (const Elf64_Ehdr *)params->image_header;
+       int abi = (hdr->e_flags & 3);
+
+       return (abi == 0 || abi == 1);
+}
+
+static boolean_t
+ppc64_elfv2_header_match(struct image_params *params)
+{
+       const Elf64_Ehdr *hdr = (const Elf64_Ehdr *)params->image_header;
+       int abi = (hdr->e_flags & 3);
+
+       return (abi == 2);
+}
+
+static void  
+exec_setregs_funcdesc(struct thread *td, struct image_params *imgp,
+    u_long stack)
+{
+       struct trapframe *tf;
+       register_t entry_desc[3];
+
+       tf = trapframe(td);
+       exec_setregs(td, imgp, stack);
+
+       /*
+        * For 64-bit ELFv1, we need to disentangle the function
+        * descriptor
+        *
+        * 0. entry point
+        * 1. TOC value (r2)
+        * 2. Environment pointer (r11)
+        */
+
+       (void)copyin((void *)imgp->entry_addr, entry_desc,
+           sizeof(entry_desc));
+       tf->srr0 = entry_desc[0] + imgp->reloc_base;
+       tf->fixreg[2] = entry_desc[1] + imgp->reloc_base;
+       tf->fixreg[11] = entry_desc[2] + imgp->reloc_base;
+}
+
 void
 elf64_dump_thread(struct thread *td, void *dst, size_t *off)
 {
@@ -190,7 +298,11 @@ elf_reloc_internal(linker_file_t lf, Elf
 
        case R_PPC_JMP_SLOT:    /* function descriptor copy */
                lookup(lf, symidx, 1, &addr);
+#if !defined(_CALL_ELF) || _CALL_ELF == 1
                memcpy(where, (Elf_Addr *)addr, 3*sizeof(Elf_Addr));
+#else
+               memcpy(where, (Elf_Addr *)addr, sizeof(Elf_Addr));
+#endif
                __asm __volatile("dcbst 0,%0; sync" :: "r"(where) : "memory");
                break;
 

Modified: head/sys/powerpc/powerpc/exec_machdep.c
==============================================================================
--- head/sys/powerpc/powerpc/exec_machdep.c     Mon Nov 23 17:05:28 2015        
(r291210)
+++ head/sys/powerpc/powerpc/exec_machdep.c     Mon Nov 23 17:07:51 2015        
(r291211)
@@ -501,9 +501,6 @@ exec_setregs(struct thread *td, struct i
 {
        struct trapframe        *tf;
        register_t              argc;
-       #ifdef __powerpc64__
-       register_t              entry_desc[3];
-       #endif
 
        tf = trapframe(td);
        bzero(tf, sizeof *tf);
@@ -546,24 +543,13 @@ exec_setregs(struct thread *td, struct i
        tf->fixreg[7] = 0;                              /* termination vector */
        tf->fixreg[8] = (register_t)imgp->ps_strings;   /* NetBSD extension */
 
+       tf->srr0 = imgp->entry_addr;
        #ifdef __powerpc64__
-       /*
-        * For 64-bit, we need to disentangle the function descriptor
-        * 
-        * 0. entry point
-        * 1. TOC value (r2)
-        * 2. Environment pointer (r11)
-        */
-
-       (void)copyin((void *)imgp->entry_addr, entry_desc, sizeof(entry_desc));
-       tf->srr0 = entry_desc[0] + imgp->reloc_base;
-       tf->fixreg[2] = entry_desc[1] + imgp->reloc_base;
-       tf->fixreg[11] = entry_desc[2] + imgp->reloc_base;
+       tf->fixreg[12] = imgp->entry_addr;
        tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT;
        if (mfmsr() & PSL_HV)
                tf->srr1 |= PSL_HV;
        #else
-       tf->srr0 = imgp->entry_addr;
        tf->srr1 = PSL_USERSET | PSL_FE_DFLT;
        #endif
        td->td_pcb->pcb_flags = 0;

Modified: head/sys/powerpc/powerpc/sigcode64.S
==============================================================================
--- head/sys/powerpc/powerpc/sigcode64.S        Mon Nov 23 17:05:28 2015        
(r291210)
+++ head/sys/powerpc/powerpc/sigcode64.S        Mon Nov 23 17:07:51 2015        
(r291211)
@@ -42,15 +42,21 @@
  *
  * On entry r1 points to a struct sigframe at bottom of current stack.
  * All other registers are unchanged.
+ *
+ * Entered midway through for v2 ELF binaries that don't need to deal with
+ * function descriptors.
+ *
  */
        .globl  CNAME(sigcode64),CNAME(szsigcode64)
+       .globl  CNAME(sigcode64_elfv2),CNAME(szsigcode64_elfv2)
 CNAME(sigcode64):
-       addi    1,1,-112                /* reserved space for callee */
        mflr    2                       /* resolve function descriptor */
        ld      0,0(2)                  
        ld      2,8(2)
        mtlr    0
 
+CNAME(sigcode64_elfv2):
+       addi    1,1,-112                /* reserved space for callee */
        blrl
 
        addi    3,1,112+SF_UC           /* restore sp, and get &frame->sf_uc */
@@ -64,3 +70,6 @@ endsigcode64:
        .data
 CNAME(szsigcode64):
        .long   endsigcode64 - CNAME(sigcode64)
+CNAME(szsigcode64_elfv2):
+       .long   endsigcode64 - CNAME(sigcode64_elfv2)
+
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to