From ffa7c8b7f8033413d7088edcd9947bf782b9d3fd Mon Sep 17 00:00:00 2001 From: Andreas Krebbel 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 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 + : sysv + 64 + s390x + elf + 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 power ; } + else if [ configure.builds /boost/architecture//s390x : $(properties) : s390x ] + { + return s390x ; + } else if [ configure.builds /boost/architecture//sparc : $(properties) : sparc ] { return 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