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 <tglx@linutronix.de> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Alexandre Chartre <alexandre.chartre@oracle.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lkml.kernel.org/r/20200421092558.939985695@linutronix.de
This commit is contained in:
parent
8c5cc19e94
commit
d8f0b35331
@ -276,37 +276,25 @@ static inline bool nmi_uaccess_okay(void)
|
||||
|
||||
#define nmi_uaccess_okay nmi_uaccess_okay
|
||||
|
||||
void cr4_update_irqsoff(unsigned long set, unsigned long clear);
|
||||
unsigned long cr4_read_shadow(void);
|
||||
|
||||
/* Initialize cr4 shadow for this CPU. */
|
||||
static inline void cr4_init_shadow(void)
|
||||
{
|
||||
this_cpu_write(cpu_tlbstate.cr4, __read_cr4());
|
||||
}
|
||||
|
||||
static inline void __cr4_set(unsigned long cr4)
|
||||
{
|
||||
lockdep_assert_irqs_disabled();
|
||||
this_cpu_write(cpu_tlbstate.cr4, cr4);
|
||||
__write_cr4(cr4);
|
||||
}
|
||||
|
||||
/* Set in this cpu's CR4. */
|
||||
static inline void cr4_set_bits_irqsoff(unsigned long mask)
|
||||
{
|
||||
unsigned long cr4;
|
||||
|
||||
cr4 = this_cpu_read(cpu_tlbstate.cr4);
|
||||
if ((cr4 | mask) != cr4)
|
||||
__cr4_set(cr4 | mask);
|
||||
cr4_update_irqsoff(mask, 0);
|
||||
}
|
||||
|
||||
/* Clear in this cpu's CR4. */
|
||||
static inline void cr4_clear_bits_irqsoff(unsigned long mask)
|
||||
{
|
||||
unsigned long cr4;
|
||||
|
||||
cr4 = this_cpu_read(cpu_tlbstate.cr4);
|
||||
if ((cr4 & ~mask) != cr4)
|
||||
__cr4_set(cr4 & ~mask);
|
||||
cr4_update_irqsoff(0, mask);
|
||||
}
|
||||
|
||||
/* Set in this cpu's CR4. */
|
||||
@ -329,20 +317,6 @@ static inline void cr4_clear_bits(unsigned long mask)
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static inline void cr4_toggle_bits_irqsoff(unsigned long mask)
|
||||
{
|
||||
unsigned long cr4;
|
||||
|
||||
cr4 = this_cpu_read(cpu_tlbstate.cr4);
|
||||
__cr4_set(cr4 ^ mask);
|
||||
}
|
||||
|
||||
/* Read the CR4 shadow. */
|
||||
static inline unsigned long cr4_read_shadow(void)
|
||||
{
|
||||
return this_cpu_read(cpu_tlbstate.cr4);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark all other ASIDs as invalid, preserves the current.
|
||||
*/
|
||||
|
@ -387,7 +387,28 @@ set_register:
|
||||
bits_missing);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(native_write_cr4);
|
||||
EXPORT_SYMBOL_GPL(native_write_cr4);
|
||||
|
||||
void cr4_update_irqsoff(unsigned long set, unsigned long clear)
|
||||
{
|
||||
unsigned long newval, cr4 = this_cpu_read(cpu_tlbstate.cr4);
|
||||
|
||||
lockdep_assert_irqs_disabled();
|
||||
|
||||
newval = (cr4 & ~clear) | set;
|
||||
if (newval != cr4) {
|
||||
this_cpu_write(cpu_tlbstate.cr4, newval);
|
||||
__write_cr4(newval);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(cr4_update_irqsoff);
|
||||
|
||||
/* Read the CR4 shadow. */
|
||||
unsigned long cr4_read_shadow(void)
|
||||
{
|
||||
return this_cpu_read(cpu_tlbstate.cr4);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cr4_read_shadow);
|
||||
|
||||
void cr4_init(void)
|
||||
{
|
||||
|
@ -612,6 +612,17 @@ void speculation_ctrl_update_current(void)
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
static inline void cr4_toggle_bits_irqsoff(unsigned long mask)
|
||||
{
|
||||
unsigned long newval, cr4 = this_cpu_read(cpu_tlbstate.cr4);
|
||||
|
||||
newval = cr4 ^ mask;
|
||||
if (newval != cr4) {
|
||||
this_cpu_write(cpu_tlbstate.cr4, newval);
|
||||
__write_cr4(newval);
|
||||
}
|
||||
}
|
||||
|
||||
void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
|
||||
{
|
||||
unsigned long tifp, tifn;
|
||||
|
Loading…
Reference in New Issue
Block a user