mirror of
https://github.com/golang/sys.git
synced 2026-02-09 04:06:04 +03:00
This change syncs the IBM internal version of sys/unix with the public repository. There are a variety of new syscalls and const definitions that have been accumulated over the past few years to support developers using Go on the platform. Old simulations of calls like 'epoll' and 'fstatfs' have been replaced with their real counterparts. The zos/s390x syscalls also have extensive trampolining to handle zos systems that might not have support for some of these new system calls. Closes golang/go#67071 Change-Id: I973d9e0abca2b05365308cf2b890438e50ae5957 Reviewed-on: https://go-review.googlesource.com/c/sys/+/582035 Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Bill O'Farrell <billotosyr@gmail.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
383 lines
11 KiB
ArmAsm
383 lines
11 KiB
ArmAsm
// Copyright 2020 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
//go:build zos && s390x && gc
|
|
|
|
#include "textflag.h"
|
|
|
|
#define PSALAA 1208(R0)
|
|
#define GTAB64(x) 80(x)
|
|
#define LCA64(x) 88(x)
|
|
#define SAVSTACK_ASYNC(x) 336(x) // in the LCA
|
|
#define CAA(x) 8(x)
|
|
#define CEECAATHDID(x) 976(x) // in the CAA
|
|
#define EDCHPXV(x) 1016(x) // in the CAA
|
|
#define GOCB(x) 1104(x) // in the CAA
|
|
|
|
// SS_*, where x=SAVSTACK_ASYNC
|
|
#define SS_LE(x) 0(x)
|
|
#define SS_GO(x) 8(x)
|
|
#define SS_ERRNO(x) 16(x)
|
|
#define SS_ERRNOJR(x) 20(x)
|
|
|
|
// Function Descriptor Offsets
|
|
#define __errno 0x156*16
|
|
#define __err2ad 0x16C*16
|
|
|
|
// Call Instructions
|
|
#define LE_CALL BYTE $0x0D; BYTE $0x76 // BL R7, R6
|
|
#define SVC_LOAD BYTE $0x0A; BYTE $0x08 // SVC 08 LOAD
|
|
#define SVC_DELETE BYTE $0x0A; BYTE $0x09 // SVC 09 DELETE
|
|
|
|
DATA zosLibVec<>(SB)/8, $0
|
|
GLOBL zosLibVec<>(SB), NOPTR, $8
|
|
|
|
TEXT ·initZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
|
|
MOVW PSALAA, R8
|
|
MOVD LCA64(R8), R8
|
|
MOVD CAA(R8), R8
|
|
MOVD EDCHPXV(R8), R8
|
|
MOVD R8, zosLibVec<>(SB)
|
|
RET
|
|
|
|
TEXT ·GetZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
|
|
MOVD zosLibVec<>(SB), R8
|
|
MOVD R8, ret+0(FP)
|
|
RET
|
|
|
|
TEXT ·clearErrno(SB), NOSPLIT, $0-0
|
|
BL addrerrno<>(SB)
|
|
MOVD $0, 0(R3)
|
|
RET
|
|
|
|
// Returns the address of errno in R3.
|
|
TEXT addrerrno<>(SB), NOSPLIT|NOFRAME, $0-0
|
|
// Get library control area (LCA).
|
|
MOVW PSALAA, R8
|
|
MOVD LCA64(R8), R8
|
|
|
|
// Get __errno FuncDesc.
|
|
MOVD CAA(R8), R9
|
|
MOVD EDCHPXV(R9), R9
|
|
ADD $(__errno), R9
|
|
LMG 0(R9), R5, R6
|
|
|
|
// Switch to saved LE stack.
|
|
MOVD SAVSTACK_ASYNC(R8), R9
|
|
MOVD 0(R9), R4
|
|
MOVD $0, 0(R9)
|
|
|
|
// Call __errno function.
|
|
LE_CALL
|
|
NOPH
|
|
|
|
// Switch back to Go stack.
|
|
XOR R0, R0 // Restore R0 to $0.
|
|
MOVD R4, 0(R9) // Save stack pointer.
|
|
RET
|
|
|
|
// func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
|
|
TEXT ·svcCall(SB), NOSPLIT, $0
|
|
BL runtime·save_g(SB) // Save g and stack pointer
|
|
MOVW PSALAA, R8
|
|
MOVD LCA64(R8), R8
|
|
MOVD SAVSTACK_ASYNC(R8), R9
|
|
MOVD R15, 0(R9)
|
|
|
|
MOVD argv+8(FP), R1 // Move function arguments into registers
|
|
MOVD dsa+16(FP), g
|
|
MOVD fnptr+0(FP), R15
|
|
|
|
BYTE $0x0D // Branch to function
|
|
BYTE $0xEF
|
|
|
|
BL runtime·load_g(SB) // Restore g and stack pointer
|
|
MOVW PSALAA, R8
|
|
MOVD LCA64(R8), R8
|
|
MOVD SAVSTACK_ASYNC(R8), R9
|
|
MOVD 0(R9), R15
|
|
|
|
RET
|
|
|
|
// func svcLoad(name *byte) unsafe.Pointer
|
|
TEXT ·svcLoad(SB), NOSPLIT, $0
|
|
MOVD R15, R2 // Save go stack pointer
|
|
MOVD name+0(FP), R0 // Move SVC args into registers
|
|
MOVD $0x80000000, R1
|
|
MOVD $0, R15
|
|
SVC_LOAD
|
|
MOVW R15, R3 // Save return code from SVC
|
|
MOVD R2, R15 // Restore go stack pointer
|
|
CMP R3, $0 // Check SVC return code
|
|
BNE error
|
|
|
|
MOVD $-2, R3 // Reset last bit of entry point to zero
|
|
AND R0, R3
|
|
MOVD R3, ret+8(FP) // Return entry point returned by SVC
|
|
CMP R0, R3 // Check if last bit of entry point was set
|
|
BNE done
|
|
|
|
MOVD R15, R2 // Save go stack pointer
|
|
MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08)
|
|
SVC_DELETE
|
|
MOVD R2, R15 // Restore go stack pointer
|
|
|
|
error:
|
|
MOVD $0, ret+8(FP) // Return 0 on failure
|
|
|
|
done:
|
|
XOR R0, R0 // Reset r0 to 0
|
|
RET
|
|
|
|
// func svcUnload(name *byte, fnptr unsafe.Pointer) int64
|
|
TEXT ·svcUnload(SB), NOSPLIT, $0
|
|
MOVD R15, R2 // Save go stack pointer
|
|
MOVD name+0(FP), R0 // Move SVC args into registers
|
|
MOVD fnptr+8(FP), R15
|
|
SVC_DELETE
|
|
XOR R0, R0 // Reset r0 to 0
|
|
MOVD R15, R1 // Save SVC return code
|
|
MOVD R2, R15 // Restore go stack pointer
|
|
MOVD R1, ret+16(FP) // Return SVC return code
|
|
RET
|
|
|
|
// func gettid() uint64
|
|
TEXT ·gettid(SB), NOSPLIT, $0
|
|
// Get library control area (LCA).
|
|
MOVW PSALAA, R8
|
|
MOVD LCA64(R8), R8
|
|
|
|
// Get CEECAATHDID
|
|
MOVD CAA(R8), R9
|
|
MOVD CEECAATHDID(R9), R9
|
|
MOVD R9, ret+0(FP)
|
|
|
|
RET
|
|
|
|
//
|
|
// Call LE function, if the return is -1
|
|
// errno and errno2 is retrieved
|
|
//
|
|
TEXT ·CallLeFuncWithErr(SB), NOSPLIT, $0
|
|
MOVW PSALAA, R8
|
|
MOVD LCA64(R8), R8
|
|
MOVD CAA(R8), R9
|
|
MOVD g, GOCB(R9)
|
|
|
|
// Restore LE stack.
|
|
MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address
|
|
MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer
|
|
|
|
MOVD parms_base+8(FP), R7 // R7 -> argument array
|
|
MOVD parms_len+16(FP), R8 // R8 number of arguments
|
|
|
|
// arg 1 ---> R1
|
|
CMP R8, $0
|
|
BEQ docall
|
|
SUB $1, R8
|
|
MOVD 0(R7), R1
|
|
|
|
// arg 2 ---> R2
|
|
CMP R8, $0
|
|
BEQ docall
|
|
SUB $1, R8
|
|
ADD $8, R7
|
|
MOVD 0(R7), R2
|
|
|
|
// arg 3 --> R3
|
|
CMP R8, $0
|
|
BEQ docall
|
|
SUB $1, R8
|
|
ADD $8, R7
|
|
MOVD 0(R7), R3
|
|
|
|
CMP R8, $0
|
|
BEQ docall
|
|
MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument
|
|
|
|
repeat:
|
|
ADD $8, R7
|
|
MOVD 0(R7), R0 // advance arg pointer by 8 byte
|
|
ADD $8, R6 // advance LE argument address by 8 byte
|
|
MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame
|
|
SUB $1, R8
|
|
CMP R8, $0
|
|
BNE repeat
|
|
|
|
docall:
|
|
MOVD funcdesc+0(FP), R8 // R8-> function descriptor
|
|
LMG 0(R8), R5, R6
|
|
MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC
|
|
LE_CALL // balr R7, R6 (return #1)
|
|
NOPH
|
|
MOVD R3, ret+32(FP)
|
|
CMP R3, $-1 // compare result to -1
|
|
BNE done
|
|
|
|
// retrieve errno and errno2
|
|
MOVD zosLibVec<>(SB), R8
|
|
ADD $(__errno), R8
|
|
LMG 0(R8), R5, R6
|
|
LE_CALL // balr R7, R6 __errno (return #3)
|
|
NOPH
|
|
MOVWZ 0(R3), R3
|
|
MOVD R3, err+48(FP)
|
|
MOVD zosLibVec<>(SB), R8
|
|
ADD $(__err2ad), R8
|
|
LMG 0(R8), R5, R6
|
|
LE_CALL // balr R7, R6 __err2ad (return #2)
|
|
NOPH
|
|
MOVW (R3), R2 // retrieve errno2
|
|
MOVD R2, errno2+40(FP) // store in return area
|
|
|
|
done:
|
|
MOVD R4, 0(R9) // Save stack pointer.
|
|
RET
|
|
|
|
//
|
|
// Call LE function, if the return is 0
|
|
// errno and errno2 is retrieved
|
|
//
|
|
TEXT ·CallLeFuncWithPtrReturn(SB), NOSPLIT, $0
|
|
MOVW PSALAA, R8
|
|
MOVD LCA64(R8), R8
|
|
MOVD CAA(R8), R9
|
|
MOVD g, GOCB(R9)
|
|
|
|
// Restore LE stack.
|
|
MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address
|
|
MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer
|
|
|
|
MOVD parms_base+8(FP), R7 // R7 -> argument array
|
|
MOVD parms_len+16(FP), R8 // R8 number of arguments
|
|
|
|
// arg 1 ---> R1
|
|
CMP R8, $0
|
|
BEQ docall
|
|
SUB $1, R8
|
|
MOVD 0(R7), R1
|
|
|
|
// arg 2 ---> R2
|
|
CMP R8, $0
|
|
BEQ docall
|
|
SUB $1, R8
|
|
ADD $8, R7
|
|
MOVD 0(R7), R2
|
|
|
|
// arg 3 --> R3
|
|
CMP R8, $0
|
|
BEQ docall
|
|
SUB $1, R8
|
|
ADD $8, R7
|
|
MOVD 0(R7), R3
|
|
|
|
CMP R8, $0
|
|
BEQ docall
|
|
MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument
|
|
|
|
repeat:
|
|
ADD $8, R7
|
|
MOVD 0(R7), R0 // advance arg pointer by 8 byte
|
|
ADD $8, R6 // advance LE argument address by 8 byte
|
|
MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame
|
|
SUB $1, R8
|
|
CMP R8, $0
|
|
BNE repeat
|
|
|
|
docall:
|
|
MOVD funcdesc+0(FP), R8 // R8-> function descriptor
|
|
LMG 0(R8), R5, R6
|
|
MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC
|
|
LE_CALL // balr R7, R6 (return #1)
|
|
NOPH
|
|
MOVD R3, ret+32(FP)
|
|
CMP R3, $0 // compare result to 0
|
|
BNE done
|
|
|
|
// retrieve errno and errno2
|
|
MOVD zosLibVec<>(SB), R8
|
|
ADD $(__errno), R8
|
|
LMG 0(R8), R5, R6
|
|
LE_CALL // balr R7, R6 __errno (return #3)
|
|
NOPH
|
|
MOVWZ 0(R3), R3
|
|
MOVD R3, err+48(FP)
|
|
MOVD zosLibVec<>(SB), R8
|
|
ADD $(__err2ad), R8
|
|
LMG 0(R8), R5, R6
|
|
LE_CALL // balr R7, R6 __err2ad (return #2)
|
|
NOPH
|
|
MOVW (R3), R2 // retrieve errno2
|
|
MOVD R2, errno2+40(FP) // store in return area
|
|
XOR R2, R2
|
|
MOVWZ R2, (R3) // clear errno2
|
|
|
|
done:
|
|
MOVD R4, 0(R9) // Save stack pointer.
|
|
RET
|
|
|
|
//
|
|
// function to test if a pointer can be safely dereferenced (content read)
|
|
// return 0 for succces
|
|
//
|
|
TEXT ·ptrtest(SB), NOSPLIT, $0-16
|
|
MOVD arg+0(FP), R10 // test pointer in R10
|
|
|
|
// set up R2 to point to CEECAADMC
|
|
BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208
|
|
BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2
|
|
BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767
|
|
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2)
|
|
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2)
|
|
BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2)
|
|
|
|
// set up R5 to point to the "shunt" path which set 1 to R3 (failure)
|
|
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3
|
|
BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1
|
|
BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1
|
|
|
|
// if r3 is not zero (failed) then branch to finish
|
|
BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3
|
|
BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2
|
|
|
|
// stomic store shunt address in R5 into CEECAADMC
|
|
BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2)
|
|
|
|
// now try reading from the test pointer in R10, if it fails it branches to the "lghi" instruction above
|
|
BYTE $0xE3; BYTE $0x9A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 9,0(10)
|
|
|
|
// finish here, restore 0 into CEECAADMC
|
|
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9
|
|
BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2)
|
|
MOVD R3, ret+8(FP) // result in R3
|
|
RET
|
|
|
|
//
|
|
// function to test if a untptr can be loaded from a pointer
|
|
// return 1: the 8-byte content
|
|
// 2: 0 for success, 1 for failure
|
|
//
|
|
// func safeload(ptr uintptr) ( value uintptr, error uintptr)
|
|
TEXT ·safeload(SB), NOSPLIT, $0-24
|
|
MOVD ptr+0(FP), R10 // test pointer in R10
|
|
MOVD $0x0, R6
|
|
BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208
|
|
BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2
|
|
BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767
|
|
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2)
|
|
BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2)
|
|
BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2)
|
|
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3
|
|
BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1
|
|
BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1
|
|
BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3
|
|
BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2
|
|
BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2)
|
|
BYTE $0xE3; BYTE $0x6A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 6,0(10)
|
|
BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9
|
|
BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2)
|
|
MOVD R6, value+8(FP) // result in R6
|
|
MOVD R3, error+16(FP) // error in R3
|
|
RET
|