Blob Blame History Raw
From ffa7c8b7f8033413d7088edcd9947bf782b9d3fd Mon Sep 17 00:00:00 2001
From: Andreas Krebbel <krebbel@linux.ibm.com>
Date: Mon, 23 Mar 2020 09:04:54 +0100
Subject: [PATCH 1/4] S390x: Add Support for s390x arch

---
 build/Jamfile.v2                   |  13 +++
 build/architecture.jam             |   4 +
 src/asm/jump_s390x_sysv_elf_gas.S  | 145 +++++++++++++++++++++++++++++
 src/asm/make_s390x_sysv_elf_gas.S  |  97 +++++++++++++++++++
 src/asm/ontop_s390x_sysv_elf_gas.S | 143 ++++++++++++++++++++++++++++
 5 files changed, 402 insertions(+)
 create mode 100644 src/asm/jump_s390x_sysv_elf_gas.S
 create mode 100644 src/asm/make_s390x_sysv_elf_gas.S
 create mode 100644 src/asm/ontop_s390x_sysv_elf_gas.S

diff --git a/build/Jamfile.v2 b/build/Jamfile.v2
index 719ca91..08f1675 100644
--- a/libs/context/build/Jamfile.v2
+++ b/libs/context/build/Jamfile.v2
@@ -447,6 +447,19 @@ alias asm_sources
      <binary-format>mach-o
    ;
 
+# S390X
+# S390X/SYSV/ELF
+alias asm_sources
+   : asm/make_s390x_sysv_elf_gas.S
+     asm/jump_s390x_sysv_elf_gas.S
+     asm/ontop_s390x_sysv_elf_gas.S
+   : <abi>sysv
+     <address-model>64
+     <architecture>s390x
+     <binary-format>elf
+     <toolset>gcc
+   ;
+
 # X86
 # X86/SYSV/ELF
 alias asm_sources
diff --git a/build/architecture.jam b/build/architecture.jam
index 81dcb49..f62806d 100644
--- a/libs/context/build/architecture.jam
+++ b/libs/context/build/architecture.jam
@@ -63,6 +63,10 @@ rule deduce-architecture ( properties * )
         {
             return <architecture>power ;
         }
+        else if [ configure.builds /boost/architecture//s390x : $(properties) : s390x ]
+        {
+            return <architecture>s390x ;
+        }
         else if [ configure.builds /boost/architecture//sparc : $(properties) : sparc ]
         {
             return <architecture>sparc ;
diff --git a/src/asm/jump_s390x_sysv_elf_gas.S b/src/asm/jump_s390x_sysv_elf_gas.S
new file mode 100644
index 0000000..c011d53
--- /dev/null
+++ b/libs/context/src/asm/jump_s390x_sysv_elf_gas.S
@@ -0,0 +1,145 @@
+/*******************************************************
+*                                                     *
+*  -------------------------------------------------  *
+*  |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  *
+*  -------------------------------------------------  *
+*  |     0     |     8     |    16     |     24    |  *
+*  -------------------------------------------------  *
+*  |    R6     |    R7     |    R8     |    R9     |  *
+*  -------------------------------------------------  *
+*  -------------------------------------------------  *
+*  |  8  |  9  |  10 |  11 |  12 |  13 |  14 |  15 |  *
+*  -------------------------------------------------  *
+*  |     32    |    40     |     48    |     56    |  *
+*  -------------------------------------------------  *
+*  |    R10    |    R11    |     R12   |     R13   |  *
+*  -------------------------------------------------  *
+*  -------------------------------------------------  *
+*  |  16 |  17 |  18 |  19 |  20 |  21 |  22 |  23 |  *
+*  -------------------------------------------------  *
+*  |     64    |    72     |     80    |     88    |  *
+*  -------------------------------------------------  *
+*  |   R14/LR  |    R15    |     F1    |     F3    |  *
+*  -------------------------------------------------  *
+*  -------------------------------------------------  *
+*  |  24 |  25 |  26 |  27 |  28 | 29  |           |  *
+*  -------------------------------------------------  *
+*  |     96    |    104    |    112    |    120    |  *
+*  -------------------------------------------------  *
+*  |    F5     |    F7     |     PC    |           |  *
+*  -------------------------------------------------  *
+* *****************************************************/
+
+.file  "jump_s390x_sysv_elf_gas.S"
+.text
+.align  4 # According to the sample code in the ELF ABI docs
+.global jump_fcontext
+.type   jump_fcontext, @function
+
+jump_fcontext:
+    
+    # Reserved the space for stack to store the data of current context
+    # before we jump to the new context.
+    lay 15,-120(15)
+
+    # save the registers to the stack
+    stg 6,  0(15)       # save R6     
+    stg 7,  8(15)       # save R7     
+    stg 8,  16(15)      # save R8
+    stg 9,  24(15)      # save R9
+    stg 10, 32(15)      # save R10
+    stg 11, 40(15)      # save R11
+    stg 12, 48(15)      # save R12
+    stg 13, 56(15)      # save R13
+    stg 14, 64(15)      # save R14
+    stg 15, 72(15)      # save R15
+
+    # save the floating point registers
+    # Load the FPR into R0 then save it to the stack
+    # Load F1 into R0
+    lgdr 0,1 
+    stg  0,80(15)       # save F1
+
+    # Load F3 into R0
+    lgdr 0,3
+    stg  0,88(15)       # save F3
+
+    # Load F5 into R0
+    lgdr 0,5
+    stg  0,96(15)       # save F5
+
+    # Load F7 into R0
+    lgdr 0,7
+    stg  0,104(15)      # save F7
+
+    # Save LR as PC
+    stg 14,112(15)
+
+    # Store the SP pointing to the old context-data into R0
+    lgr 0,15
+
+    # Get the SP pointing to the new context-data
+    # Note: Since the return type of the jump_fcontext is struct whose
+    # size is more than 8. The compiler automatically passes the 
+    # address of the transfer_t where the data needs to store into R2.
+
+    # Hence the first param passed to the jump_fcontext which represent
+    # the fctx we want to switch to is present in R3
+    # R2 --> Address of the return transfer_t struct
+    # R3 --> Context we want to switch to
+    # R4 --> Data
+    lgr 15,3
+
+    # Load the registers with the data present in context-data of the
+    # context we are going to switch to
+    lg 6,  0(15)       # restore R6     
+    lg 7,  8(15)       # restore R7     
+    lg 8,  16(15)      # restore R8
+    lg 9,  24(15)      # restore R9
+    lg 10, 32(15)      # restore R10
+    lg 11, 40(15)      # restore R11
+    lg 12, 48(15)      # restore R12
+    lg 13, 56(15)      # restore R13
+    lg 14, 64(15)      # restore R14
+
+    # Restore Floating point registers
+    lg   1,80(15)
+    ldgr 1,1            # restore F1
+
+    lg   1,88(15)
+    ldgr 1,3            # restore F3
+
+    lg   1,96(15)
+    ldgr 1,5            # restore F5
+
+    lg   1,104(15)
+    ldgr 1,7            # restore F7
+
+    # Load PC
+    lg  1,112(15)
+
+    # Adjust the stack
+    lay 15, 120(15)
+
+    # R2 --> Address where the return transfer_t is stored
+    # R0 --> FCTX
+    # R4 --> DATA
+
+    # Store the elements to return transfer_t
+    stg 15, 0(2)
+    stg 4, 8(2)
+
+    # Note: The address in R2 points to the place where the return
+    # transfer_t is stored. Since context_function take transfer_t
+    # as first parameter. And R2 is the register which holds the
+    # first parameter value.
+
+    #jump to context
+    br 1
+
+.size   jump_fcontext,.-jump_fcontext
+# Mark that we don't need executable stack.
+.section .note.GNU-stack,"",%progbits
+
+
+
diff --git a/src/asm/make_s390x_sysv_elf_gas.S b/src/asm/make_s390x_sysv_elf_gas.S
new file mode 100644
index 0000000..f566533
--- /dev/null
+++ b/libs/context/src/asm/make_s390x_sysv_elf_gas.S
@@ -0,0 +1,97 @@
+/*******************************************************
+*                                                     *
+*  -------------------------------------------------  *
+*  |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  *
+*  -------------------------------------------------  *
+*  |     0     |     8     |    16     |     24    |  *
+*  -------------------------------------------------  *
+*  |    R6     |    R7     |    R8     |    R9     |  *
+*  -------------------------------------------------  *
+*  -------------------------------------------------  *
+*  |  8  |  9  |  10 |  11 |  12 |  13 |  14 |  15 |  *
+*  -------------------------------------------------  *
+*  |     32    |    40     |     48    |     56    |  *
+*  -------------------------------------------------  *
+*  |    R10    |    R11    |     R12   |     R13   |  *
+*  -------------------------------------------------  *
+*  -------------------------------------------------  *
+*  |  16 |  17 |  18 |  19 |  20 |  21 |  22 |  23 |  *
+*  -------------------------------------------------  *
+*  |     64    |    72     |     80    |     88    |  *
+*  -------------------------------------------------  *
+*  |   R14/LR  |    R15    |     F1    |     F3    |  *
+*  -------------------------------------------------  *
+*  -------------------------------------------------  *
+*  |  24 |  25 |  26 |  27 |  28 | 29  |           |  *
+*  -------------------------------------------------  *
+*  |     96    |    104    |    112    |    120    |  *
+*  -------------------------------------------------  *
+*  |    F5     |    F7     |     PC    |           |  *
+*  -------------------------------------------------  *
+* *****************************************************/
+
+.file  "make_s390x_sysv_elf_gas.S"
+.text
+.align  4 # According to the sample code in the ELF ABI docs
+.global make_fcontext
+.type 	 make_fcontext, @function
+
+make_fcontext:
+
+		# make_fcontext takes in 3 arguments
+		# arg1 --> The address where the context needs to be made
+		# arg2 --> The size of the context
+		# arg3 --> The address of the context function
+
+		# According to the ELF ABI, the register R2 holds the first arg.
+		# R2 also acts as the register which holds return value
+		# Register R3 holds the second, R4 the third so on.
+
+		# Shift the address in R2 to a lower 8 byte boundary
+
+		# This is done because according to the ELF ABI Doc, the stack needs
+		# to be 8 byte aligned.
+		# In order to do so, we need to make sure that the address is divisible
+		# by 8. We can check this, by checking if the the last 3 bits of the
+		# address is zero or not. If not AND it with `-8`. 
+
+		# Here we AND the lower 16 bits of the memory address present in the 
+		# R2 with the bits 1111 1111 1111 1000 which when converted into
+		# decimal is 65528
+		nill    2,65528
+
+		# Reserve space for context-data on context-stack.
+		# This is done by shifting the SP/address by 112 bytes.
+		lay 2,-120(2)
+
+		# third arg of make_fcontext() == address of the context-function
+		# Store the address as a PC to jump in, whenever we call the 
+		# make_fcontext.
+		stg 4,112(2)
+
+		# Save the address of finish as return-address for context-function
+		# This will be entered after context-function return
+		# The address of finish will be saved in Link register, this register
+		# specifies where we need to jump after the function executes
+		# completely.
+		larl 1,finish
+		stg  1,64(2)
+
+		# Return pointer to context data
+		# R14 acts as the link register
+		# R2 holds the address of the context stack. When we return from the
+		# make_fcontext, R2 is passed back.
+		br 14 
+
+	finish:
+
+		# In finish tasks, you load the exit code and exit the make_fcontext
+		# This is called when the context-function is entirely executed
+
+		lghi 2,0
+		brasl 14,_exit
+
+.size   make_fcontext,.-make_fcontext
+# Mark that we don't need executable stack.
+.section .note.GNU-stack,"",%progbits
+
diff --git a/src/asm/ontop_s390x_sysv_elf_gas.S b/src/asm/ontop_s390x_sysv_elf_gas.S
new file mode 100644
index 0000000..7ab2cf5
--- /dev/null
+++ b/libs/context/src/asm/ontop_s390x_sysv_elf_gas.S
@@ -0,0 +1,143 @@
+/*******************************************************
+*                                                     *
+*  -------------------------------------------------  *
+*  |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  *
+*  -------------------------------------------------  *
+*  |     0     |     8     |    16     |     24    |  *
+*  -------------------------------------------------  *
+*  |    R6     |    R7     |    R8     |    R9     |  *
+*  -------------------------------------------------  *
+*  -------------------------------------------------  *
+*  |  8  |  9  |  10 |  11 |  12 |  13 |  14 |  15 |  *
+*  -------------------------------------------------  *
+*  |     32    |    40     |     48    |     56    |  *
+*  -------------------------------------------------  *
+*  |    R10    |    R11    |     R12   |     R13   |  *
+*  -------------------------------------------------  *
+*  -------------------------------------------------  *
+*  |  16 |  17 |  18 |  19 |  20 |  21 |  22 |  23 |  *
+*  -------------------------------------------------  *
+*  |     64    |    72     |     80    |     88    |  *
+*  -------------------------------------------------  *
+*  |   R14/LR  |    R15    |     F1    |     F3    |  *
+*  -------------------------------------------------  *
+*  -------------------------------------------------  *
+*  |  24 |  25 |  26 |  27 |  28 | 29  |           |  *
+*  -------------------------------------------------  *
+*  |     96    |    104    |    112    |    120    |  *
+*  -------------------------------------------------  *
+*  |    F5     |    F7     |     PC    |           |  *
+*  -------------------------------------------------  *
+* *****************************************************/
+
+.file  "ontop_s390x_sysv_elf_gas.S"
+.text
+.align  4 # According to the sample code in the ELF ABI docs
+.global ontop_fcontext
+.type   ontop_fcontext, @function
+
+ontop_fcontext:
+    
+    # Reserved the space for stack to store the data of current context
+    # before we jump to the new context.
+    lay 15,-120(15)
+
+    # save the registers to the stack
+    stg 6,  0(15)       # save R6     
+    stg 7,  8(15)       # save R7     
+    stg 8,  16(15)      # save R8
+    stg 9,  24(15)      # save R9
+    stg 10, 32(15)      # save R10
+    stg 11, 40(15)      # save R11
+    stg 12, 48(15)      # save R12
+    stg 13, 56(15)      # save R13
+    stg 14, 64(15)      # save R14
+    stg 15, 72(15)      # save R15
+
+    # save the floating point registers
+    # Load the FPR into R0 then save it to the stack
+    # Load F1 into R0
+    lgdr 0,1 
+    stg  0,80(15)       # save F1
+
+    # Load F3 into R0
+    lgdr 0,3
+    stg  0,88(15)       # save F3
+
+    # Load F5 into R0
+    lgdr 0,5
+    stg  0,96(15)       # save F5
+
+    # Load F7 into R0
+    lgdr 0,7
+    stg  0,104(15)      # save F7
+
+    # Save LR as PC
+    stg 14,112(15)
+
+    # Store the SP pointing to the old context-data into R0
+    lgr 0,15
+
+    # Get the SP pointing to the new context-data
+    # Note: Since the return type of the jump_fcontext is struct whose
+    # size is more than 8. The compiler automatically passes the 
+    # address of the transfer_t where the data needs to store into R2.
+
+    # Hence the first param passed to the jump_fcontext which represent
+    # the fctx we want to switch to is present in R3
+    # R2 --> Address of the return transfer_t struct
+    # R3 --> Context we want to switch to
+    # R4 --> Data
+    lgr 15,3
+
+    # Load the registers with the data present in context-data of the
+    # context we are going to switch to
+    lg 6,  0(15)       # restore R6     
+    lg 7,  8(15)       # restore R7     
+    lg 8,  16(15)      # restore R8
+    lg 9,  24(15)      # restore R9
+    lg 10, 32(15)      # restore R10
+    lg 11, 40(15)      # restore R11
+    lg 12, 48(15)      # restore R12
+    lg 13, 56(15)      # restore R13
+    lg 14, 64(15)      # restore R14
+    lg 15, 72(15)      # restore R15
+
+    # Restore Floating point registers
+    lg   1,80(15)
+    ldgr 1,1            # restore F1
+
+    lg   1,88(15)
+    ldgr 1,3            # restore F3
+
+    lg   1,96(15)
+    ldgr 1,5            # restore F5
+
+    lg   1,104(15)
+    ldgr 1,7            # restore F7
+
+    # Skip PC
+
+    # Adjust the stack
+    lay 15, 120(15)
+
+    # R2 --> Address where the return transfer_t is stored
+    # R0 --> FCTX
+    # R4 --> DATA
+    # R5 --> Context function
+
+    # Store the elements to return transfer_t
+    stg 15, 0(2)
+    stg 4, 8(2)
+
+    # Note: The address in R2 points to the place where the return
+    # transfer_t is stored. Since context_function take transfer_t
+    # as first parameter. And R2 is the register which holds the
+    # first parameter value.
+
+    #jump to context function
+    br 5
+
+.size   ontop_fcontext,.-ontop_fcontext
+# Mark that we don't need executable stack.
+.section .note.GNU-stack,"",%progbits
-- 
2.18.1