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:
Lai Jiangshan
2020-08-04 18:27:32 +08:00
committed by Lai Jiangshan
parent 5104bc5d60
commit 5a0f2f6e49
6 changed files with 17 additions and 34 deletions
+3
View File
@@ -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
+12 -4
View File
@@ -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)
+1 -2
View File
@@ -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.
-6
View File
@@ -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
-22
View File
@@ -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())