mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
amd64: less code and data in the upper half
Call jumpToKernel() in sysret()/iret() so that there is less code and data in the upper half, and, especially, current goroutine's stack and user regs will not be accessed from the upper half (also with the help from previous patches which make less code in userCR3 context). jumpToUser() will not be needed, because current goroutine's stack and return value in the stack is lower half address. It is prepared for KPTI for gvisor. Signed-off-by: Lai Jiangshan <jiangshan.ljs@antfin.com> Signed-off-by: Lai Jiangshan <laijs@linux.alibaba.com>
This commit is contained in:
committed by
Lai Jiangshan
parent
5a0f2f6e49
commit
c4d364c7ce
@@ -36,6 +36,9 @@ func sysenter()
|
||||
// This must be called prior to sysret/iret.
|
||||
func swapgs()
|
||||
|
||||
// jumpToKernel jumps to the kernel version of the current RIP.
|
||||
func jumpToKernel()
|
||||
|
||||
// sysret returns to userspace from a system call.
|
||||
//
|
||||
// The return code is the vector that interrupted execution.
|
||||
|
||||
@@ -104,11 +104,24 @@ TEXT ·swapgs(SB),NOSPLIT,$0
|
||||
SWAP_GS()
|
||||
RET
|
||||
|
||||
// jumpToKernel changes execution to the kernel address space.
|
||||
//
|
||||
// This works by changing the return value to the kernel version.
|
||||
TEXT ·jumpToKernel(SB),NOSPLIT,$0
|
||||
MOVQ 0(SP), AX
|
||||
ORQ ·KernelStartAddress(SB), AX // Future return value.
|
||||
MOVQ AX, 0(SP)
|
||||
RET
|
||||
|
||||
// See entry_amd64.go.
|
||||
TEXT ·sysret(SB),NOSPLIT,$0-24
|
||||
// Save original state.
|
||||
LOAD_KERNEL_ADDRESS(cpu+0(FP), BX)
|
||||
LOAD_KERNEL_ADDRESS(regs+8(FP), AX)
|
||||
CALL ·jumpToKernel(SB)
|
||||
// Save original state and stack. sysenter() or exception()
|
||||
// from APP(gr3) will switch to this stack, set the return
|
||||
// value (vector: 32(SP)) and then do RET, which will also
|
||||
// automatically return to the lower half.
|
||||
MOVQ cpu+0(FP), BX
|
||||
MOVQ regs+8(FP), AX
|
||||
MOVQ userCR3+16(FP), CX
|
||||
MOVQ SP, CPU_REGISTERS+PTRACE_RSP(BX)
|
||||
MOVQ BP, CPU_REGISTERS+PTRACE_RBP(BX)
|
||||
@@ -134,9 +147,13 @@ TEXT ·sysret(SB),NOSPLIT,$0-24
|
||||
|
||||
// See entry_amd64.go.
|
||||
TEXT ·iret(SB),NOSPLIT,$0-24
|
||||
// Save original state.
|
||||
LOAD_KERNEL_ADDRESS(cpu+0(FP), BX)
|
||||
LOAD_KERNEL_ADDRESS(regs+8(FP), AX)
|
||||
CALL ·jumpToKernel(SB)
|
||||
// Save original state and stack. sysenter() or exception()
|
||||
// from APP(gr3) will switch to this stack, set the return
|
||||
// value (vector: 32(SP)) and then do RET, which will also
|
||||
// automatically return to the lower half.
|
||||
MOVQ cpu+0(FP), BX
|
||||
MOVQ regs+8(FP), AX
|
||||
MOVQ userCR3+16(FP), CX
|
||||
MOVQ SP, CPU_REGISTERS+PTRACE_RSP(BX)
|
||||
MOVQ BP, CPU_REGISTERS+PTRACE_RBP(BX)
|
||||
|
||||
@@ -197,13 +197,11 @@ func (c *CPU) SwitchToUser(switchOpts SwitchOpts) (vector Vector) {
|
||||
WriteFS(uintptr(regs.Fs_base)) // escapes: no. Set application FS.
|
||||
WriteGS(uintptr(regs.Gs_base)) // escapes: no. Set application GS.
|
||||
LoadFloatingPoint(switchOpts.FloatingPointState) // escapes: no. Copy in floating point.
|
||||
jumpToKernel() // Switch to upper half.
|
||||
if switchOpts.FullRestore {
|
||||
vector = iret(c, regs, uintptr(userCR3))
|
||||
} else {
|
||||
vector = sysret(c, regs, uintptr(userCR3))
|
||||
}
|
||||
jumpToUser() // Return to lower half.
|
||||
SaveFloatingPoint(switchOpts.FloatingPointState) // escapes: no. Copy out floating point.
|
||||
WriteFS(uintptr(c.registers.Fs_base)) // escapes: no. Restore kernel FS.
|
||||
return
|
||||
|
||||
@@ -64,12 +64,6 @@ func wrgsmsr(addr uintptr)
|
||||
// readCR2 reads the current CR2 value.
|
||||
func readCR2() uintptr
|
||||
|
||||
// jumpToKernel jumps to the kernel version of the current RIP.
|
||||
func jumpToKernel()
|
||||
|
||||
// jumpToUser jumps to the user version of the current RIP.
|
||||
func jumpToUser()
|
||||
|
||||
// fninit initializes the floating point unit.
|
||||
func fninit()
|
||||
|
||||
|
||||
@@ -127,31 +127,6 @@ TEXT ·wrgsmsr(SB),NOSPLIT,$0-8
|
||||
BYTE $0x0f; BYTE $0x30; // WRMSR
|
||||
RET
|
||||
|
||||
// jumpToUser changes execution to the user address.
|
||||
//
|
||||
// This works by changing the return value to the user version.
|
||||
TEXT ·jumpToUser(SB),NOSPLIT,$0
|
||||
MOVQ 0(SP), AX
|
||||
MOVQ ·KernelStartAddress(SB), BX
|
||||
NOTQ BX
|
||||
ANDQ BX, SP // Switch the stack.
|
||||
ANDQ BX, BP // Switch the frame pointer.
|
||||
ANDQ BX, AX // Future return value.
|
||||
MOVQ AX, 0(SP)
|
||||
RET
|
||||
|
||||
// jumpToKernel changes execution to the kernel address space.
|
||||
//
|
||||
// This works by changing the return value to the kernel version.
|
||||
TEXT ·jumpToKernel(SB),NOSPLIT,$0
|
||||
MOVQ 0(SP), AX
|
||||
MOVQ ·KernelStartAddress(SB), BX
|
||||
ORQ BX, SP // Switch the stack.
|
||||
ORQ BX, BP // Switch the frame pointer.
|
||||
ORQ BX, AX // Future return value.
|
||||
MOVQ AX, 0(SP)
|
||||
RET
|
||||
|
||||
// readCR2 reads the current CR2 value.
|
||||
//
|
||||
// The code corresponds to:
|
||||
|
||||
Reference in New Issue
Block a user