Skip to content

Commit d8f0b35

Browse files
KAGA-KOKOsuryasaimadhu
authored andcommitted
x86/cpu: Uninline CR4 accessors
cpu_tlbstate is exported because various TLB-related functions need access to it, but cpu_tlbstate is sensitive information which should only be accessed by well-contained kernel functions and not be directly exposed to modules. The various CR4 accessors require cpu_tlbstate as the CR4 shadow cache is located there. In preparation for unexporting cpu_tlbstate, create a builtin function for manipulating CR4 and rework the various helpers to use it. No functional change. [ bp: push the export of native_write_cr4() only when CONFIG_LKTDM=m to the last patch in the series. ] Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Reviewed-by: Alexandre Chartre <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 8c5cc19 commit d8f0b35

File tree

3 files changed

+38
-32
lines changed

3 files changed

+38
-32
lines changed

arch/x86/include/asm/tlbflush.h

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -276,37 +276,25 @@ static inline bool nmi_uaccess_okay(void)
276276

277277
#define nmi_uaccess_okay nmi_uaccess_okay
278278

279+
void cr4_update_irqsoff(unsigned long set, unsigned long clear);
280+
unsigned long cr4_read_shadow(void);
281+
279282
/* Initialize cr4 shadow for this CPU. */
280283
static inline void cr4_init_shadow(void)
281284
{
282285
this_cpu_write(cpu_tlbstate.cr4, __read_cr4());
283286
}
284287

285-
static inline void __cr4_set(unsigned long cr4)
286-
{
287-
lockdep_assert_irqs_disabled();
288-
this_cpu_write(cpu_tlbstate.cr4, cr4);
289-
__write_cr4(cr4);
290-
}
291-
292288
/* Set in this cpu's CR4. */
293289
static inline void cr4_set_bits_irqsoff(unsigned long mask)
294290
{
295-
unsigned long cr4;
296-
297-
cr4 = this_cpu_read(cpu_tlbstate.cr4);
298-
if ((cr4 | mask) != cr4)
299-
__cr4_set(cr4 | mask);
291+
cr4_update_irqsoff(mask, 0);
300292
}
301293

302294
/* Clear in this cpu's CR4. */
303295
static inline void cr4_clear_bits_irqsoff(unsigned long mask)
304296
{
305-
unsigned long cr4;
306-
307-
cr4 = this_cpu_read(cpu_tlbstate.cr4);
308-
if ((cr4 & ~mask) != cr4)
309-
__cr4_set(cr4 & ~mask);
297+
cr4_update_irqsoff(0, mask);
310298
}
311299

312300
/* Set in this cpu's CR4. */
@@ -329,20 +317,6 @@ static inline void cr4_clear_bits(unsigned long mask)
329317
local_irq_restore(flags);
330318
}
331319

332-
static inline void cr4_toggle_bits_irqsoff(unsigned long mask)
333-
{
334-
unsigned long cr4;
335-
336-
cr4 = this_cpu_read(cpu_tlbstate.cr4);
337-
__cr4_set(cr4 ^ mask);
338-
}
339-
340-
/* Read the CR4 shadow. */
341-
static inline unsigned long cr4_read_shadow(void)
342-
{
343-
return this_cpu_read(cpu_tlbstate.cr4);
344-
}
345-
346320
/*
347321
* Mark all other ASIDs as invalid, preserves the current.
348322
*/

arch/x86/kernel/cpu/common.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,28 @@ void native_write_cr4(unsigned long val)
387387
bits_missing);
388388
}
389389
}
390-
EXPORT_SYMBOL(native_write_cr4);
390+
EXPORT_SYMBOL_GPL(native_write_cr4);
391+
392+
void cr4_update_irqsoff(unsigned long set, unsigned long clear)
393+
{
394+
unsigned long newval, cr4 = this_cpu_read(cpu_tlbstate.cr4);
395+
396+
lockdep_assert_irqs_disabled();
397+
398+
newval = (cr4 & ~clear) | set;
399+
if (newval != cr4) {
400+
this_cpu_write(cpu_tlbstate.cr4, newval);
401+
__write_cr4(newval);
402+
}
403+
}
404+
EXPORT_SYMBOL(cr4_update_irqsoff);
405+
406+
/* Read the CR4 shadow. */
407+
unsigned long cr4_read_shadow(void)
408+
{
409+
return this_cpu_read(cpu_tlbstate.cr4);
410+
}
411+
EXPORT_SYMBOL_GPL(cr4_read_shadow);
391412

392413
void cr4_init(void)
393414
{

arch/x86/kernel/process.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,17 @@ void speculation_ctrl_update_current(void)
612612
preempt_enable();
613613
}
614614

615+
static inline void cr4_toggle_bits_irqsoff(unsigned long mask)
616+
{
617+
unsigned long newval, cr4 = this_cpu_read(cpu_tlbstate.cr4);
618+
619+
newval = cr4 ^ mask;
620+
if (newval != cr4) {
621+
this_cpu_write(cpu_tlbstate.cr4, newval);
622+
__write_cr4(newval);
623+
}
624+
}
625+
615626
void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
616627
{
617628
unsigned long tifp, tifn;

0 commit comments

Comments
 (0)