|
@@ -164,6 +164,9 @@ ENTRY(entry_SYSCALL_64_trampoline)
|
|
|
/* Stash the user RSP. */
|
|
|
movq %rsp, RSP_SCRATCH
|
|
|
|
|
|
+ /* Note: using %rsp as a scratch reg. */
|
|
|
+ SWITCH_TO_KERNEL_CR3 scratch_reg=%rsp
|
|
|
+
|
|
|
/* Load the top of the task stack into RSP */
|
|
|
movq CPU_ENTRY_AREA_tss + TSS_sp1 + CPU_ENTRY_AREA, %rsp
|
|
|
|
|
@@ -203,6 +206,10 @@ ENTRY(entry_SYSCALL_64)
|
|
|
*/
|
|
|
|
|
|
swapgs
|
|
|
+ /*
|
|
|
+ * This path is not taken when PAGE_TABLE_ISOLATION is disabled so it
|
|
|
+ * is not required to switch CR3.
|
|
|
+ */
|
|
|
movq %rsp, PER_CPU_VAR(rsp_scratch)
|
|
|
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
|
|
|
|
|
@@ -399,6 +406,7 @@ syscall_return_via_sysret:
|
|
|
* We are on the trampoline stack. All regs except RDI are live.
|
|
|
* We can do future final exit work right here.
|
|
|
*/
|
|
|
+ SWITCH_TO_USER_CR3 scratch_reg=%rdi
|
|
|
|
|
|
popq %rdi
|
|
|
popq %rsp
|
|
@@ -736,6 +744,8 @@ GLOBAL(swapgs_restore_regs_and_return_to_usermode)
|
|
|
* We can do future final exit work right here.
|
|
|
*/
|
|
|
|
|
|
+ SWITCH_TO_USER_CR3 scratch_reg=%rdi
|
|
|
+
|
|
|
/* Restore RDI. */
|
|
|
popq %rdi
|
|
|
SWAPGS
|
|
@@ -818,7 +828,9 @@ native_irq_return_ldt:
|
|
|
*/
|
|
|
|
|
|
pushq %rdi /* Stash user RDI */
|
|
|
- SWAPGS
|
|
|
+ SWAPGS /* to kernel GS */
|
|
|
+ SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi /* to kernel CR3 */
|
|
|
+
|
|
|
movq PER_CPU_VAR(espfix_waddr), %rdi
|
|
|
movq %rax, (0*8)(%rdi) /* user RAX */
|
|
|
movq (1*8)(%rsp), %rax /* user RIP */
|
|
@@ -834,7 +846,6 @@ native_irq_return_ldt:
|
|
|
/* Now RAX == RSP. */
|
|
|
|
|
|
andl $0xffff0000, %eax /* RAX = (RSP & 0xffff0000) */
|
|
|
- popq %rdi /* Restore user RDI */
|
|
|
|
|
|
/*
|
|
|
* espfix_stack[31:16] == 0. The page tables are set up such that
|
|
@@ -845,7 +856,11 @@ native_irq_return_ldt:
|
|
|
* still points to an RO alias of the ESPFIX stack.
|
|
|
*/
|
|
|
orq PER_CPU_VAR(espfix_stack), %rax
|
|
|
- SWAPGS
|
|
|
+
|
|
|
+ SWITCH_TO_USER_CR3 scratch_reg=%rdi /* to user CR3 */
|
|
|
+ SWAPGS /* to user GS */
|
|
|
+ popq %rdi /* Restore user RDI */
|
|
|
+
|
|
|
movq %rax, %rsp
|
|
|
UNWIND_HINT_IRET_REGS offset=8
|
|
|
|
|
@@ -945,6 +960,8 @@ ENTRY(switch_to_thread_stack)
|
|
|
UNWIND_HINT_FUNC
|
|
|
|
|
|
pushq %rdi
|
|
|
+ /* Need to switch before accessing the thread stack. */
|
|
|
+ SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi
|
|
|
movq %rsp, %rdi
|
|
|
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
|
|
|
UNWIND_HINT sp_offset=16 sp_reg=ORC_REG_DI
|
|
@@ -1244,7 +1261,11 @@ ENTRY(paranoid_entry)
|
|
|
js 1f /* negative -> in kernel */
|
|
|
SWAPGS
|
|
|
xorl %ebx, %ebx
|
|
|
-1: ret
|
|
|
+
|
|
|
+1:
|
|
|
+ SAVE_AND_SWITCH_TO_KERNEL_CR3 scratch_reg=%rax save_reg=%r14
|
|
|
+
|
|
|
+ ret
|
|
|
END(paranoid_entry)
|
|
|
|
|
|
/*
|
|
@@ -1266,6 +1287,7 @@ ENTRY(paranoid_exit)
|
|
|
testl %ebx, %ebx /* swapgs needed? */
|
|
|
jnz .Lparanoid_exit_no_swapgs
|
|
|
TRACE_IRQS_IRETQ
|
|
|
+ RESTORE_CR3 save_reg=%r14
|
|
|
SWAPGS_UNSAFE_STACK
|
|
|
jmp .Lparanoid_exit_restore
|
|
|
.Lparanoid_exit_no_swapgs:
|
|
@@ -1293,6 +1315,8 @@ ENTRY(error_entry)
|
|
|
* from user mode due to an IRET fault.
|
|
|
*/
|
|
|
SWAPGS
|
|
|
+ /* We have user CR3. Change to kernel CR3. */
|
|
|
+ SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
|
|
|
|
|
|
.Lerror_entry_from_usermode_after_swapgs:
|
|
|
/* Put us onto the real thread stack. */
|
|
@@ -1339,6 +1363,7 @@ ENTRY(error_entry)
|
|
|
* .Lgs_change's error handler with kernel gsbase.
|
|
|
*/
|
|
|
SWAPGS
|
|
|
+ SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
|
|
|
jmp .Lerror_entry_done
|
|
|
|
|
|
.Lbstep_iret:
|
|
@@ -1348,10 +1373,11 @@ ENTRY(error_entry)
|
|
|
|
|
|
.Lerror_bad_iret:
|
|
|
/*
|
|
|
- * We came from an IRET to user mode, so we have user gsbase.
|
|
|
- * Switch to kernel gsbase:
|
|
|
+ * We came from an IRET to user mode, so we have user
|
|
|
+ * gsbase and CR3. Switch to kernel gsbase and CR3:
|
|
|
*/
|
|
|
SWAPGS
|
|
|
+ SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
|
|
|
|
|
|
/*
|
|
|
* Pretend that the exception came from user mode: set up pt_regs
|
|
@@ -1383,6 +1409,10 @@ END(error_exit)
|
|
|
/*
|
|
|
* Runs on exception stack. Xen PV does not go through this path at all,
|
|
|
* so we can use real assembly here.
|
|
|
+ *
|
|
|
+ * Registers:
|
|
|
+ * %r14: Used to save/restore the CR3 of the interrupted context
|
|
|
+ * when PAGE_TABLE_ISOLATION is in use. Do not clobber.
|
|
|
*/
|
|
|
ENTRY(nmi)
|
|
|
UNWIND_HINT_IRET_REGS
|
|
@@ -1446,6 +1476,7 @@ ENTRY(nmi)
|
|
|
|
|
|
swapgs
|
|
|
cld
|
|
|
+ SWITCH_TO_KERNEL_CR3 scratch_reg=%rdx
|
|
|
movq %rsp, %rdx
|
|
|
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
|
|
|
UNWIND_HINT_IRET_REGS base=%rdx offset=8
|
|
@@ -1698,6 +1729,8 @@ end_repeat_nmi:
|
|
|
movq $-1, %rsi
|
|
|
call do_nmi
|
|
|
|
|
|
+ RESTORE_CR3 save_reg=%r14
|
|
|
+
|
|
|
testl %ebx, %ebx /* swapgs needed? */
|
|
|
jnz nmi_restore
|
|
|
nmi_swapgs:
|