mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
amd64: switch to kernelCR3 when just return to gr0
KernelCR3 takes effect as early as possible so that less code is in the userCR3 environment. It is prepared for the next patches that make less code and data in the upper half, which 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
5104bc5d60
commit
5a0f2f6e49
@@ -85,6 +85,9 @@ type CPUArchState struct {
|
||||
// stack is the stack used for interrupts on this CPU.
|
||||
stack [256]byte
|
||||
|
||||
// kernelCR3 is the cr3 used for sentry kernel.
|
||||
kernelCR3 uintptr
|
||||
|
||||
// errorCode is the error code from the last exception.
|
||||
errorCode uintptr
|
||||
|
||||
|
||||
@@ -189,10 +189,14 @@ TEXT ·sysenter(SB),NOSPLIT,$0
|
||||
|
||||
user:
|
||||
SWAP_GS()
|
||||
MOVQ AX, CPU_REGISTERS+PTRACE_RCX(GS) // Save user AX on scratch.
|
||||
MOVQ CPU_KERNEL_CR3(GS), AX // Get kernel cr3 on AX.
|
||||
WRITE_CR3() // Switch to kernel cr3.
|
||||
|
||||
XCHGQ CPU_REGISTERS+PTRACE_RSP(GS), SP // Swap stacks.
|
||||
XCHGQ CPU_REGISTERS+PTRACE_RAX(GS), AX // Swap for AX (regs).
|
||||
MOVQ CPU_REGISTERS+PTRACE_RAX(GS), AX // Get user regs.
|
||||
REGISTERS_SAVE(AX, 0) // Save all except IP, FLAGS, SP, AX.
|
||||
MOVQ CPU_REGISTERS+PTRACE_RAX(GS), BX // Load saved AX value.
|
||||
MOVQ CPU_REGISTERS+PTRACE_RCX(GS), BX // Load saved user AX value.
|
||||
MOVQ BX, PTRACE_RAX(AX) // Save everything else.
|
||||
MOVQ BX, PTRACE_ORIGRAX(AX)
|
||||
MOVQ CX, PTRACE_RIP(AX)
|
||||
@@ -263,9 +267,13 @@ user:
|
||||
SWAP_GS()
|
||||
ADDQ $-8, SP // Adjust for flags.
|
||||
MOVQ $_KERNEL_FLAGS, 0(SP); BYTE $0x9d; // Reset flags (POPFQ).
|
||||
XCHGQ CPU_REGISTERS+PTRACE_RAX(GS), AX // Swap for user regs.
|
||||
PUSHQ AX // Save user AX on stack.
|
||||
MOVQ CPU_KERNEL_CR3(GS), AX // Get kernel cr3 on AX.
|
||||
WRITE_CR3() // Switch to kernel cr3.
|
||||
|
||||
MOVQ CPU_REGISTERS+PTRACE_RAX(GS), AX // Get user regs.
|
||||
REGISTERS_SAVE(AX, 0) // Save all except IP, FLAGS, SP, AX.
|
||||
MOVQ CPU_REGISTERS+PTRACE_RAX(GS), BX // Restore original AX.
|
||||
POPQ BX // Restore original AX.
|
||||
MOVQ BX, PTRACE_RAX(AX) // Save it.
|
||||
MOVQ BX, PTRACE_ORIGRAX(AX)
|
||||
MOVQ 16(SP), BX; MOVQ BX, PTRACE_RIP(AX)
|
||||
|
||||
@@ -183,7 +183,7 @@ func IsCanonical(addr uint64) bool {
|
||||
//go:nosplit
|
||||
func (c *CPU) SwitchToUser(switchOpts SwitchOpts) (vector Vector) {
|
||||
userCR3 := switchOpts.PageTables.CR3(!switchOpts.Flush, switchOpts.UserPCID)
|
||||
kernelCR3 := c.kernel.PageTables.CR3(true, switchOpts.KernelPCID)
|
||||
c.kernelCR3 = uintptr(c.kernel.PageTables.CR3(true, switchOpts.KernelPCID))
|
||||
|
||||
// Sanitize registers.
|
||||
regs := switchOpts.Registers
|
||||
@@ -203,7 +203,6 @@ func (c *CPU) SwitchToUser(switchOpts SwitchOpts) (vector Vector) {
|
||||
} else {
|
||||
vector = sysret(c, regs, uintptr(userCR3))
|
||||
}
|
||||
writeCR3(uintptr(kernelCR3)) // Return to kernel address space.
|
||||
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.
|
||||
|
||||
@@ -61,12 +61,6 @@ func wrgsbase(addr uintptr)
|
||||
// wrgsmsr writes to the GS_BASE MSR.
|
||||
func wrgsmsr(addr uintptr)
|
||||
|
||||
// writeCR3 writes the CR3 value.
|
||||
func writeCR3(phys uintptr)
|
||||
|
||||
// readCR3 reads the current CR3 value.
|
||||
func readCR3() uintptr
|
||||
|
||||
// readCR2 reads the current CR2 value.
|
||||
func readCR2() uintptr
|
||||
|
||||
|
||||
@@ -152,28 +152,6 @@ TEXT ·jumpToKernel(SB),NOSPLIT,$0
|
||||
MOVQ AX, 0(SP)
|
||||
RET
|
||||
|
||||
// writeCR3 writes the given CR3 value.
|
||||
//
|
||||
// The code corresponds to:
|
||||
//
|
||||
// mov %rax, %cr3
|
||||
//
|
||||
TEXT ·writeCR3(SB),NOSPLIT,$0-8
|
||||
MOVQ cr3+0(FP), AX
|
||||
BYTE $0x0f; BYTE $0x22; BYTE $0xd8;
|
||||
RET
|
||||
|
||||
// readCR3 reads the current CR3 value.
|
||||
//
|
||||
// The code corresponds to:
|
||||
//
|
||||
// mov %cr3, %rax
|
||||
//
|
||||
TEXT ·readCR3(SB),NOSPLIT,$0-8
|
||||
BYTE $0x0f; BYTE $0x20; BYTE $0xd8;
|
||||
MOVQ AX, ret+0(FP)
|
||||
RET
|
||||
|
||||
// readCR2 reads the current CR2 value.
|
||||
//
|
||||
// The code corresponds to:
|
||||
|
||||
@@ -33,6 +33,7 @@ func Emit(w io.Writer) {
|
||||
fmt.Fprintf(w, "#define CPU_SELF 0x%02x\n", reflect.ValueOf(&c.self).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_REGISTERS 0x%02x\n", reflect.ValueOf(&c.registers).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_STACK_TOP 0x%02x\n", reflect.ValueOf(&c.stack[0]).Pointer()-reflect.ValueOf(c).Pointer()+uintptr(len(c.stack)))
|
||||
fmt.Fprintf(w, "#define CPU_KERNEL_CR3 0x%02x\n", reflect.ValueOf(&c.kernelCR3).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_ERROR_CODE 0x%02x\n", reflect.ValueOf(&c.errorCode).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
fmt.Fprintf(w, "#define CPU_ERROR_TYPE 0x%02x\n", reflect.ValueOf(&c.errorType).Pointer()-reflect.ValueOf(c).Pointer())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user