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