e500 port: getcontext / setcontext / swapcontext

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

e500 port: getcontext / setcontext / swapcontext

Joseph Myers
This patch adds e500 support to powerpc getcontext / setcontext /
swapcontext.  Like setjmp/longjmp, it's compile-time conditional
rather than using HWCAPs.  Unlike setjmp/longjmp, this is following an
external ABI: the context layout used by the Linux kernel.  Nothing is
done about the ACC register; as it's call-clobbered and not used for
argument passing, only the signal context case needs to handle it and
that does it via a syscall.  (But as is generally usual for context
code in glibc, this code doesn't otherwise try to limit GPR saving /
restoring to avoid call-clobbered registers for which it isn't
actually needed.)

To avoid duplication of the code sequences between getcontext /
setcontext and swapcontext, they are put in assembler macros defined
in a single place, and those macros are then used as needed under the
__CONTEXT_ENABLE_E500 conditional.

Tested with a build for e500.

2013-09-18  Joseph Myers  <[hidden email]>

        * sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S
        (__CONTEXT_FUNC_NAME) [__CONTEXT_ENABLE_E500]: Use
        getcontext_e500.
        * sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S
        (__CONTEXT_FUNC_NAME) [__CONTEXT_ENABLE_E500]: Use
        setcontext_e500.
        * sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S
        (__CONTEXT_FUNC_NAME) [__CONTEXT_ENABLE_E500]: Use getcontext_e500
        and setcontext_e500.

ports/ChangeLog.powerpc:
2013-09-18  Joseph Myers  <[hidden email]>

        * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/context-e500.h:
        New file.
        * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/getcontext.S:
        Include <context-e500.h>.
        * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/setcontext.S:
        Likewise.
        * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/swapcontext.S:
        Likewise.

diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/context-e500.h b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/context-e500.h
new file mode 100644
index 0000000..9eb1a95
--- /dev/null
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/context-e500.h
@@ -0,0 +1,144 @@
+/* getcontext/setcontext/makecontext support for e500 high parts of registers.
+   Copyright (C) 2006-2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _CONTEXT_E500_H
+#define _CONTEXT_E500_H 1
+
+#if defined __SPE__ || (defined __NO_FPRS__ && !defined _SOFT_FLOAT)
+
+# define __CONTEXT_ENABLE_E500 1
+
+/* We follow the kernel's layout, which saves the high parts of the
+   SPE registers in the vregs area, immediately followed by the ACC
+   value (call-clobbered, not handled here) and the SPEFSCR value.  */
+
+.macro getcontext_e500
+ la r10,(_UC_VREGS)(r3)
+ evstwwe r0,(0*4)(r10)
+ evstwwe r1,(1*4)(r10)
+ evstwwe r2,(2*4)(r10)
+ evstwwe r3,(3*4)(r10)
+ evstwwe r4,(4*4)(r10)
+ evstwwe r5,(5*4)(r10)
+ evstwwe r6,(6*4)(r10)
+ evstwwe r7,(7*4)(r10)
+ evstwwe r8,(8*4)(r10)
+ evstwwe r9,(9*4)(r10)
+ evstwwe r10,(10*4)(r10)
+ evstwwe r11,(11*4)(r10)
+ evstwwe r12,(12*4)(r10)
+ evstwwe r13,(13*4)(r10)
+ evstwwe r14,(14*4)(r10)
+ evstwwe r15,(15*4)(r10)
+ evstwwe r16,(16*4)(r10)
+ evstwwe r17,(17*4)(r10)
+ evstwwe r18,(18*4)(r10)
+ evstwwe r19,(19*4)(r10)
+ evstwwe r20,(20*4)(r10)
+ evstwwe r21,(21*4)(r10)
+ evstwwe r22,(22*4)(r10)
+ evstwwe r23,(23*4)(r10)
+ evstwwe r24,(24*4)(r10)
+ evstwwe r25,(25*4)(r10)
+ evstwwe r26,(26*4)(r10)
+ evstwwe r27,(27*4)(r10)
+ evstwwe r28,(28*4)(r10)
+ evstwwe r29,(29*4)(r10)
+ evstwwe r30,(30*4)(r10)
+ evstwwe r31,(31*4)(r10)
+ mfspefscr r9
+ stw r9,(34*4)(r10)
+.endm
+
+.macro setcontext_e500
+ lwz r3,_UC_VREGS+(0*4)(r31)
+ evmergelo r0,r3,r0
+ lwz r3,_UC_VREGS+(1*4)(r31)
+ evmergelo r1,r3,r1
+ lwz r3,_UC_VREGS+(2*4)(r31)
+ evmergelo r2,r3,r2
+ lwz r3,_UC_VREGS+(1*4)(r31)
+ evmergelo r1,r3,r1
+ lwz r3,_UC_VREGS+(2*4)(r31)
+ evmergelo r2,r3,r2
+ lwz r3,_UC_VREGS+(3*4)(r31)
+ evmergelo r3,r3,r3
+ lwz r3,_UC_VREGS+(4*4)(r31)
+ evmergelo r4,r3,r4
+ lwz r3,_UC_VREGS+(5*4)(r31)
+ evmergelo r5,r3,r5
+ lwz r3,_UC_VREGS+(6*4)(r31)
+ evmergelo r6,r3,r6
+ lwz r3,_UC_VREGS+(7*4)(r31)
+ evmergelo r7,r3,r7
+ lwz r3,_UC_VREGS+(8*4)(r31)
+ evmergelo r8,r3,r8
+ lwz r3,_UC_VREGS+(9*4)(r31)
+ evmergelo r9,r3,r9
+ lwz r3,_UC_VREGS+(10*4)(r31)
+ evmergelo r10,r3,r10
+ lwz r3,_UC_VREGS+(11*4)(r31)
+ evmergelo r11,r3,r11
+ lwz r3,_UC_VREGS+(12*4)(r31)
+ evmergelo r12,r3,r12
+ lwz r3,_UC_VREGS+(13*4)(r31)
+ evmergelo r13,r3,r13
+ lwz r3,_UC_VREGS+(14*4)(r31)
+ evmergelo r14,r3,r14
+ lwz r3,_UC_VREGS+(15*4)(r31)
+ evmergelo r15,r3,r15
+ lwz r3,_UC_VREGS+(16*4)(r31)
+ evmergelo r16,r3,r16
+ lwz r3,_UC_VREGS+(17*4)(r31)
+ evmergelo r17,r3,r17
+ lwz r3,_UC_VREGS+(18*4)(r31)
+ evmergelo r18,r3,r18
+ lwz r3,_UC_VREGS+(19*4)(r31)
+ evmergelo r19,r3,r19
+ lwz r3,_UC_VREGS+(20*4)(r31)
+ evmergelo r20,r3,r20
+ lwz r3,_UC_VREGS+(21*4)(r31)
+ evmergelo r21,r3,r21
+ lwz r3,_UC_VREGS+(22*4)(r31)
+ evmergelo r22,r3,r22
+ lwz r3,_UC_VREGS+(23*4)(r31)
+ evmergelo r23,r3,r23
+ lwz r3,_UC_VREGS+(24*4)(r31)
+ evmergelo r24,r3,r24
+ lwz r3,_UC_VREGS+(25*4)(r31)
+ evmergelo r25,r3,r25
+ lwz r3,_UC_VREGS+(26*4)(r31)
+ evmergelo r26,r3,r26
+ lwz r3,_UC_VREGS+(27*4)(r31)
+ evmergelo r27,r3,r27
+ lwz r3,_UC_VREGS+(28*4)(r31)
+ evmergelo r28,r3,r28
+ lwz r3,_UC_VREGS+(29*4)(r31)
+ evmergelo r29,r3,r29
+ lwz r3,_UC_VREGS+(30*4)(r31)
+ evmergelo r30,r3,r30
+ lwz r3,_UC_VREGS+(31*4)(r31)
+ evmergelo r31,r3,r31
+ lwz r3,_UC_VREGS+(34*4)(r31)
+ mtspefscr r3
+.endm
+#else
+# undef __CONTEXT_ENABLE_E500
+#endif
+
+#endif /* context-e500.h */
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/getcontext.S b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/getcontext.S
index 90d9dcd..8bc3c7a 100644
--- a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/getcontext.S
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/getcontext.S
@@ -24,6 +24,8 @@
 #include <asm/ptrace.h>
 #include "ucontext_i.h"
 
+#include <context-e500.h>
+
 #define __CONTEXT_FUNC_NAME __getcontext
 #undef __CONTEXT_ENABLE_FPRS
 #undef __CONTEXT_ENABLE_VRS
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/setcontext.S b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/setcontext.S
index 06061ea..5f8653f 100644
--- a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/setcontext.S
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/setcontext.S
@@ -24,6 +24,8 @@
 #include <asm/ptrace.h>
 #include "ucontext_i.h"
 
+#include <context-e500.h>
+
 #define __CONTEXT_FUNC_NAME __setcontext
 #undef __CONTEXT_ENABLE_FPRS
 #undef __CONTEXT_ENABLE_VRS
diff --git a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/swapcontext.S b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/swapcontext.S
index 2150eec..de6d56f 100644
--- a/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/swapcontext.S
+++ b/ports/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/swapcontext.S
@@ -24,6 +24,8 @@
 #include <asm/ptrace.h>
 #include "ucontext_i.h"
 
+#include <context-e500.h>
+
 #define __CONTEXT_FUNC_NAME __swapcontext
 #undef __CONTEXT_ENABLE_FPRS
 #undef __CONTEXT_ENABLE_VRS
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S
index 6330780..b396b22 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S
@@ -261,6 +261,11 @@ ENTRY(__CONTEXT_FUNC_NAME)
 2: /* L(no_vec): */
 # endif
 #endif
+
+#ifdef __CONTEXT_ENABLE_E500
+ getcontext_e500
+#endif
+
 /* We need to set up parms and call sigprocmask which will clobber
    volatile registers. So before the call we need to retrieve the
    original ucontext ptr (parm1) from stack and store the UC_REGS_PTR
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S
index bedebf0..ba25092 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S
@@ -243,6 +243,10 @@ ENTRY(__CONTEXT_FUNC_NAME)
  lfd fp31,_UC_FREGS+(31*8)(r31)
 #endif /* __CONTEXT_ENABLE_FPRS */
 
+#ifdef __CONTEXT_ENABLE_E500
+ setcontext_e500
+#endif
+
  /* Restore LR and CCR, and set CTR to the NIP value */
  lwz r3,_UC_GREGS+(PT_LNK*4)(r31)
  lwz r4,_UC_GREGS+(PT_NIP*4)(r31)
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S
index 21c2e1f..f3e7741 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S
@@ -265,6 +265,10 @@ ENTRY(__CONTEXT_FUNC_NAME)
 # endif /* __CONTEXT_ENABLE_VRS */
 #endif /* __CONTEXT_ENABLE_FPRS */
 
+#ifdef __CONTEXT_ENABLE_E500
+ getcontext_e500
+#endif
+
 /* Restore ucontext (parm1) from stack.  */
  lwz r12,_FRAME_PARM_SAVE1(r1)
  li r4,0
@@ -468,6 +472,10 @@ ENTRY(__CONTEXT_FUNC_NAME)
  lfd fp31,_UC_FREGS+(31*8)(r31)
 #endif /* __CONTEXT_ENABLE_FPRS */
 
+#ifdef __CONTEXT_ENABLE_E500
+ setcontext_e500
+#endif
+
  /* Restore LR and CCR, and set CTR to the NIP value */
  lwz r3,_UC_GREGS+(PT_LNK*4)(r31)
  lwz r4,_UC_GREGS+(PT_NIP*4)(r31)

--
Joseph S. Myers
[hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: e500 port: getcontext / setcontext / swapcontext

Steven Munroe-2
On Wed, 2013-09-18 at 17:29 +0000, Joseph S. Myers wrote:

> This patch adds e500 support to powerpc getcontext / setcontext /
> swapcontext.  Like setjmp/longjmp, it's compile-time conditional
> rather than using HWCAPs.  Unlike setjmp/longjmp, this is following an
> external ABI: the context layout used by the Linux kernel.  Nothing is
> done about the ACC register; as it's call-clobbered and not used for
> argument passing, only the signal context case needs to handle it and
> that does it via a syscall.  (But as is generally usual for context
> code in glibc, this code doesn't otherwise try to limit GPR saving /
> restoring to avoid call-clobbered registers for which it isn't
> actually needed.)
>
> To avoid duplication of the code sequences between getcontext /
> setcontext and swapcontext, they are put in assembler macros defined
> in a single place, and those macros are then used as needed under the
> __CONTEXT_ENABLE_E500 conditional.
>

Joseph I must really question the wisdom of merging the e500 into the
same source with the "classical" PPC32 code.

The unified GPR/FPR set of the e500 impacts the ABI in many different
ways from the classic PPC32 soft-float or hard-float that I fear this
will be a constant source of misunderstanding and error in the future.

I am much more comfortable keeping the e500 specific codes in different
source files and different parts of the tree.


Reply | Threaded
Open this post in threaded view
|

Re: e500 port: getcontext / setcontext / swapcontext

Joseph Myers
On Wed, 18 Sep 2013, Steven Munroe wrote:

> Joseph I must really question the wisdom of merging the e500 into the
> same source with the "classical" PPC32 code.
>
> The unified GPR/FPR set of the e500 impacts the ABI in many different
> ways from the classic PPC32 soft-float or hard-float that I fear this
> will be a constant source of misunderstanding and error in the future.
>
> I am much more comfortable keeping the e500 specific codes in different
> source files and different parts of the tree.

The design is detailed at
<https://sourceware.org/ml/libc-alpha/2013-09/msg00485.html>.  The
function-calling ABI is identical to soft-float (the only case in which
register high parts are used in argument passing / return is for
e500-specific vector types).  With this port version, the other aspects of
the glibc ABI also match soft-float, so soft-float binaries can run with
glibc built for e500; this avoids an unnecessary proliferation of ABI
variants (requiring their own ABI test baselines etc.).  The present
getcontext / setcontext / swapcontext patch follows the same approach as
the support in those functions for other optional features, with a macro
__CONTEXT_ENABLE_E500 conditioning the e500-specific code, and in fact the
substance of the e500 implementation is in a separate file context-e500.h
in this case because that was the natural way to avoid code duplication in
the swapcontext sources.

--
Joseph S. Myers
[hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: e500 port: getcontext / setcontext / swapcontext

Ryan S. Arnold
In reply to this post by Joseph Myers
On Wed, Sep 18, 2013 at 12:29 PM, Joseph S. Myers
<[hidden email]> wrote:

> This patch adds e500 support to powerpc getcontext / setcontext /
> swapcontext.  Like setjmp/longjmp, it's compile-time conditional
> rather than using HWCAPs.  Unlike setjmp/longjmp, this is following an
> external ABI: the context layout used by the Linux kernel.  Nothing is
> done about the ACC register; as it's call-clobbered and not used for
> argument passing, only the signal context case needs to handle it and
> that does it via a syscall.  (But as is generally usual for context
> code in glibc, this code doesn't otherwise try to limit GPR saving /
> restoring to avoid call-clobbered registers for which it isn't
> actually needed.)
>
> To avoid duplication of the code sequences between getcontext /
> setcontext and swapcontext, they are put in assembler macros defined
> in a single place, and those macros are then used as needed under the
> __CONTEXT_ENABLE_E500 conditional.
>
> Tested with a build for e500.
>
> 2013-09-18  Joseph Myers  <[hidden email]>
>
>         * sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S
>         (__CONTEXT_FUNC_NAME) [__CONTEXT_ENABLE_E500]: Use
>         getcontext_e500.
>         * sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S
>         (__CONTEXT_FUNC_NAME) [__CONTEXT_ENABLE_E500]: Use
>         setcontext_e500.
>         * sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S
>         (__CONTEXT_FUNC_NAME) [__CONTEXT_ENABLE_E500]: Use getcontext_e500
>         and setcontext_e500.
>
> ports/ChangeLog.powerpc:
> 2013-09-18  Joseph Myers  <[hidden email]>
>
>         * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/context-e500.h:
>         New file.
>         * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/getcontext.S:
>         Include <context-e500.h>.
>         * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/setcontext.S:
>         Likewise.
>         * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/swapcontext.S:
>         Likewise.

Structurally I'm fine with this patch.  It's as non-invasive as can be expected.

Ryan
Reply | Threaded
Open this post in threaded view
|

Re: e500 port: getcontext / setcontext / swapcontext

Joseph Myers
On Thu, 19 Sep 2013, Ryan S. Arnold wrote:

> Structurally I'm fine with this patch.  It's as non-invasive as can be
> expected.

What about the substance of the patch - is that OK?

--
Joseph S. Myers
[hidden email]