Skip to content

Commit 86833ae

Browse files
committed
Merge tag 'x86-entry-2024-03-11' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 entry update from Thomas Gleixner: "A single update for the x86 entry code: The current CR3 handling for kernel page table isolation in the paranoid return paths which are relevant for #NMI, #MCE, #VC, #DB and #DF is unconditionally writing CR3 with the value retrieved on exception entry. In the vast majority of cases when returning to the kernel this is a pointless exercise because CR3 was not modified on exception entry. The only situation where this is necessary is when the exception interrupts a entry from user before switching to kernel CR3 or interrupts an exit to user after switching back to user CR3. As CR3 writes can be expensive on some systems this becomes measurable overhead with high frequency #NMIs such as perf. Avoid this overhead by checking the CR3 value, which was saved on entry, and write it back to CR3 only when it is a user CR3" * tag 'x86-entry-2024-03-11' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/entry: Avoid redundant CR3 write on paranoid returns
2 parents 720c857 + bb99836 commit 86833ae

File tree

2 files changed

+13
-20
lines changed

2 files changed

+13
-20
lines changed

arch/x86/entry/calling.h

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -244,38 +244,32 @@ For 32-bit we have the following conventions - kernel is built with
244244
.Ldone_\@:
245245
.endm
246246

247-
.macro RESTORE_CR3 scratch_reg:req save_reg:req
247+
/* Restore CR3 from a kernel context. May restore a user CR3 value. */
248+
.macro PARANOID_RESTORE_CR3 scratch_reg:req save_reg:req
248249
ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_PTI
249250

250-
ALTERNATIVE "jmp .Lwrcr3_\@", "", X86_FEATURE_PCID
251-
252251
/*
253-
* KERNEL pages can always resume with NOFLUSH as we do
254-
* explicit flushes.
252+
* If CR3 contained the kernel page tables at the paranoid exception
253+
* entry, then there is nothing to restore as CR3 is not modified while
254+
* handling the exception.
255255
*/
256256
bt $PTI_USER_PGTABLE_BIT, \save_reg
257-
jnc .Lnoflush_\@
257+
jnc .Lend_\@
258+
259+
ALTERNATIVE "jmp .Lwrcr3_\@", "", X86_FEATURE_PCID
258260

259261
/*
260262
* Check if there's a pending flush for the user ASID we're
261263
* about to set.
262264
*/
263265
movq \save_reg, \scratch_reg
264266
andq $(0x7FF), \scratch_reg
265-
bt \scratch_reg, THIS_CPU_user_pcid_flush_mask
266-
jnc .Lnoflush_\@
267-
268267
btr \scratch_reg, THIS_CPU_user_pcid_flush_mask
269-
jmp .Lwrcr3_\@
268+
jc .Lwrcr3_\@
270269

271-
.Lnoflush_\@:
272270
SET_NOFLUSH_BIT \save_reg
273271

274272
.Lwrcr3_\@:
275-
/*
276-
* The CR3 write could be avoided when not changing its value,
277-
* but would require a CR3 read *and* a scratch register.
278-
*/
279273
movq \save_reg, %cr3
280274
.Lend_\@:
281275
.endm
@@ -290,7 +284,7 @@ For 32-bit we have the following conventions - kernel is built with
290284
.endm
291285
.macro SAVE_AND_SWITCH_TO_KERNEL_CR3 scratch_reg:req save_reg:req
292286
.endm
293-
.macro RESTORE_CR3 scratch_reg:req save_reg:req
287+
.macro PARANOID_RESTORE_CR3 scratch_reg:req save_reg:req
294288
.endm
295289

296290
#endif

arch/x86/entry/entry_64.S

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -970,14 +970,14 @@ SYM_CODE_START_LOCAL(paranoid_exit)
970970
IBRS_EXIT save_reg=%r15
971971

972972
/*
973-
* The order of operations is important. RESTORE_CR3 requires
973+
* The order of operations is important. PARANOID_RESTORE_CR3 requires
974974
* kernel GSBASE.
975975
*
976976
* NB to anyone to try to optimize this code: this code does
977977
* not execute at all for exceptions from user mode. Those
978978
* exceptions go through error_return instead.
979979
*/
980-
RESTORE_CR3 scratch_reg=%rax save_reg=%r14
980+
PARANOID_RESTORE_CR3 scratch_reg=%rax save_reg=%r14
981981

982982
/* Handle the three GSBASE cases */
983983
ALTERNATIVE "jmp .Lparanoid_exit_checkgs", "", X86_FEATURE_FSGSBASE
@@ -1406,8 +1406,7 @@ end_repeat_nmi:
14061406
/* Always restore stashed SPEC_CTRL value (see paranoid_entry) */
14071407
IBRS_EXIT save_reg=%r15
14081408

1409-
/* Always restore stashed CR3 value (see paranoid_entry) */
1410-
RESTORE_CR3 scratch_reg=%r15 save_reg=%r14
1409+
PARANOID_RESTORE_CR3 scratch_reg=%r15 save_reg=%r14
14111410

14121411
/*
14131412
* The above invocation of paranoid_entry stored the GSBASE

0 commit comments

Comments
 (0)