diff options
Diffstat (limited to 'arch/x86/kernel/paravirt.c')
| -rw-r--r-- | arch/x86/kernel/paravirt.c | 73 | 
1 files changed, 45 insertions, 28 deletions
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index c5b250011fd..548d25f00c9 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -23,9 +23,11 @@  #include <linux/efi.h>  #include <linux/bcd.h>  #include <linux/highmem.h> +#include <linux/kprobes.h>  #include <asm/bug.h>  #include <asm/paravirt.h> +#include <asm/debugreg.h>  #include <asm/desc.h>  #include <asm/setup.h>  #include <asm/pgtable.h> @@ -37,6 +39,7 @@  #include <asm/apic.h>  #include <asm/tlbflush.h>  #include <asm/timer.h> +#include <asm/special_insns.h>  /* nop stub */  void _paravirt_nop(void) @@ -60,11 +63,6 @@ void __init default_banner(void)  	       pv_info.name);  } -/* Simple instruction patching code. */ -#define DEF_NATIVE(ops, name, code)					\ -	extern const char start_##ops##_##name[], end_##ops##_##name[];	\ -	asm("start_" #ops "_" #name ": " code "; end_" #ops "_" #name ":") -  /* Undefined instruction for dealing with missing ops pointers. */  static const unsigned char ud2a[] = { 0x0f, 0x0b }; @@ -202,6 +200,14 @@ static void native_flush_tlb_single(unsigned long addr)  	__native_flush_tlb_single(addr);  } +struct static_key paravirt_steal_enabled; +struct static_key paravirt_steal_rq_enabled; + +static u64 native_steal_clock(int cpu) +{ +	return 0; +} +  /* These are in entry.S */  extern void native_iret(void);  extern void native_irq_enable_sysexit(void); @@ -231,16 +237,16 @@ static DEFINE_PER_CPU(enum paravirt_lazy_mode, paravirt_lazy_mode) = PARAVIRT_LA  static inline void enter_lazy(enum paravirt_lazy_mode mode)  { -	BUG_ON(percpu_read(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE); +	BUG_ON(this_cpu_read(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE); -	percpu_write(paravirt_lazy_mode, mode); +	this_cpu_write(paravirt_lazy_mode, mode);  }  static void leave_lazy(enum paravirt_lazy_mode mode)  { -	BUG_ON(percpu_read(paravirt_lazy_mode) != mode); +	BUG_ON(this_cpu_read(paravirt_lazy_mode) != mode); -	percpu_write(paravirt_lazy_mode, PARAVIRT_LAZY_NONE); +	this_cpu_write(paravirt_lazy_mode, PARAVIRT_LAZY_NONE);  }  void paravirt_enter_lazy_mmu(void) @@ -253,11 +259,23 @@ void paravirt_leave_lazy_mmu(void)  	leave_lazy(PARAVIRT_LAZY_MMU);  } +void paravirt_flush_lazy_mmu(void) +{ +	preempt_disable(); + +	if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) { +		arch_leave_lazy_mmu_mode(); +		arch_enter_lazy_mmu_mode(); +	} + +	preempt_enable(); +} +  void paravirt_start_context_switch(struct task_struct *prev)  {  	BUG_ON(preemptible()); -	if (percpu_read(paravirt_lazy_mode) == PARAVIRT_LAZY_MMU) { +	if (this_cpu_read(paravirt_lazy_mode) == PARAVIRT_LAZY_MMU) {  		arch_leave_lazy_mmu_mode();  		set_ti_thread_flag(task_thread_info(prev), TIF_LAZY_MMU_UPDATES);  	} @@ -279,19 +297,7 @@ enum paravirt_lazy_mode paravirt_get_lazy_mode(void)  	if (in_interrupt())  		return PARAVIRT_LAZY_NONE; -	return percpu_read(paravirt_lazy_mode); -} - -void arch_flush_lazy_mmu_mode(void) -{ -	preempt_disable(); - -	if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) { -		arch_leave_lazy_mmu_mode(); -		arch_enter_lazy_mmu_mode(); -	} - -	preempt_enable(); +	return this_cpu_read(paravirt_lazy_mode);  }  struct pv_info pv_info = { @@ -299,6 +305,10 @@ struct pv_info pv_info = {  	.paravirt_enabled = 0,  	.kernel_rpl = 0,  	.shared_kernel_pmd = 1,	/* Only used when CONFIG_X86_PAE is set */ + +#ifdef CONFIG_X86_64 +	.extra_user_64bit_cs = __USER_CS, +#endif  };  struct pv_init_ops pv_init_ops = { @@ -307,9 +317,10 @@ struct pv_init_ops pv_init_ops = {  struct pv_time_ops pv_time_ops = {  	.sched_clock = native_sched_clock, +	.steal_clock = native_steal_clock,  }; -struct pv_irq_ops pv_irq_ops = { +__visible struct pv_irq_ops pv_irq_ops = {  	.save_fl = __PV_IS_CALLEE_SAVE(native_save_fl),  	.restore_fl = __PV_IS_CALLEE_SAVE(native_restore_fl),  	.irq_disable = __PV_IS_CALLEE_SAVE(native_irq_disable), @@ -321,7 +332,7 @@ struct pv_irq_ops pv_irq_ops = {  #endif  }; -struct pv_cpu_ops pv_cpu_ops = { +__visible struct pv_cpu_ops pv_cpu_ops = {  	.cpuid = native_cpuid,  	.get_debugreg = native_get_debugreg,  	.set_debugreg = native_set_debugreg, @@ -337,9 +348,7 @@ struct pv_cpu_ops pv_cpu_ops = {  #endif  	.wbinvd = native_wbinvd,  	.read_msr = native_read_msr_safe, -	.rdmsr_regs = native_rdmsr_safe_regs,  	.write_msr = native_write_msr_safe, -	.wrmsr_regs = native_wrmsr_safe_regs,  	.read_tsc = native_read_tsc,  	.read_pmc = native_read_pmc,  	.read_tscp = native_read_tscp, @@ -347,7 +356,6 @@ struct pv_cpu_ops pv_cpu_ops = {  	.set_ldt = native_set_ldt,  	.load_gdt = native_load_gdt,  	.load_idt = native_load_idt, -	.store_gdt = native_store_gdt,  	.store_idt = native_store_idt,  	.store_tr = native_store_tr,  	.load_tls = native_load_tls, @@ -382,6 +390,11 @@ struct pv_cpu_ops pv_cpu_ops = {  	.end_context_switch = paravirt_nop,  }; +/* At this point, native_get/set_debugreg has real function entries */ +NOKPROBE_SYMBOL(native_get_debugreg); +NOKPROBE_SYMBOL(native_set_debugreg); +NOKPROBE_SYMBOL(native_load_idt); +  struct pv_apic_ops pv_apic_ops = {  #ifdef CONFIG_X86_LOCAL_APIC  	.startup_ipi_hook = paravirt_nop, @@ -421,8 +434,11 @@ struct pv_mmu_ops pv_mmu_ops = {  	.set_pte = native_set_pte,  	.set_pte_at = native_set_pte_at,  	.set_pmd = native_set_pmd, +	.set_pmd_at = native_set_pmd_at,  	.pte_update = paravirt_nop,  	.pte_update_defer = paravirt_nop, +	.pmd_update = paravirt_nop, +	.pmd_update_defer = paravirt_nop,  	.ptep_modify_prot_start = __ptep_modify_prot_start,  	.ptep_modify_prot_commit = __ptep_modify_prot_commit, @@ -459,6 +475,7 @@ struct pv_mmu_ops pv_mmu_ops = {  	.lazy_mode = {  		.enter = paravirt_nop,  		.leave = paravirt_nop, +		.flush = paravirt_nop,  	},  	.set_fixmap = native_set_fixmap,  | 
