diff options
| author | Boris Ostrovsky <boris.ostrovsky@oracle.com> | 2013-03-23 09:36:36 -0400 |
|---|---|---|
| committer | H. Peter Anvin <hpa@linux.intel.com> | 2013-04-10 14:25:10 -0400 |
| commit | 511ba86e1d386f671084b5d0e6f110bb30b8eeb2 (patch) | |
| tree | 1fe3621ebaf43ad5fb5ab644500676f2f158153f | |
| parent | 1160c2779b826c6f5c08e5cc542de58fd1f667d5 (diff) | |
x86, mm: Patch out arch_flush_lazy_mmu_mode() when running on bare metal
Invoking arch_flush_lazy_mmu_mode() results in calls to
preempt_enable()/disable() which may have performance impact.
Since lazy MMU is not used on bare metal we can patch away
arch_flush_lazy_mmu_mode() so that it is never called in such
environment.
[ hpa: the previous patch "Fix vmalloc_fault oops during lazy MMU
updates" may cause a minor performance regression on
bare metal. This patch resolves that performance regression. It is
somewhat unclear to me if this is a good -stable candidate. ]
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Link: http://lkml.kernel.org/r/1364045796-10720-2-git-send-email-konrad.wilk@oracle.com
Tested-by: Josh Boyer <jwboyer@redhat.com>
Tested-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Acked-by: Borislav Petkov <bp@suse.de>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: <stable@vger.kernel.org> SEE NOTE ABOVE
| -rw-r--r-- | arch/x86/include/asm/paravirt.h | 5 | ||||
| -rw-r--r-- | arch/x86/include/asm/paravirt_types.h | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/paravirt.c | 25 | ||||
| -rw-r--r-- | arch/x86/lguest/boot.c | 1 | ||||
| -rw-r--r-- | arch/x86/xen/mmu.c | 1 |
5 files changed, 21 insertions, 13 deletions
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 5edd1742cfd0..7361e47db79f 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h | |||
| @@ -703,7 +703,10 @@ static inline void arch_leave_lazy_mmu_mode(void) | |||
| 703 | PVOP_VCALL0(pv_mmu_ops.lazy_mode.leave); | 703 | PVOP_VCALL0(pv_mmu_ops.lazy_mode.leave); |
| 704 | } | 704 | } |
| 705 | 705 | ||
| 706 | void arch_flush_lazy_mmu_mode(void); | 706 | static inline void arch_flush_lazy_mmu_mode(void) |
| 707 | { | ||
| 708 | PVOP_VCALL0(pv_mmu_ops.lazy_mode.flush); | ||
| 709 | } | ||
| 707 | 710 | ||
| 708 | static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx, | 711 | static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx, |
| 709 | phys_addr_t phys, pgprot_t flags) | 712 | phys_addr_t phys, pgprot_t flags) |
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index 142236ed83af..b3b0ec1dac86 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h | |||
| @@ -91,6 +91,7 @@ struct pv_lazy_ops { | |||
| 91 | /* Set deferred update mode, used for batching operations. */ | 91 | /* Set deferred update mode, used for batching operations. */ |
| 92 | void (*enter)(void); | 92 | void (*enter)(void); |
| 93 | void (*leave)(void); | 93 | void (*leave)(void); |
| 94 | void (*flush)(void); | ||
| 94 | }; | 95 | }; |
| 95 | 96 | ||
| 96 | struct pv_time_ops { | 97 | struct pv_time_ops { |
| @@ -679,6 +680,7 @@ void paravirt_end_context_switch(struct task_struct *next); | |||
| 679 | 680 | ||
| 680 | void paravirt_enter_lazy_mmu(void); | 681 | void paravirt_enter_lazy_mmu(void); |
| 681 | void paravirt_leave_lazy_mmu(void); | 682 | void paravirt_leave_lazy_mmu(void); |
| 683 | void paravirt_flush_lazy_mmu(void); | ||
| 682 | 684 | ||
| 683 | void _paravirt_nop(void); | 685 | void _paravirt_nop(void); |
| 684 | u32 _paravirt_ident_32(u32); | 686 | u32 _paravirt_ident_32(u32); |
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 17fff18a1031..8bfb335f74bb 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c | |||
| @@ -263,6 +263,18 @@ void paravirt_leave_lazy_mmu(void) | |||
| 263 | leave_lazy(PARAVIRT_LAZY_MMU); | 263 | leave_lazy(PARAVIRT_LAZY_MMU); |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | void paravirt_flush_lazy_mmu(void) | ||
| 267 | { | ||
| 268 | preempt_disable(); | ||
| 269 | |||
| 270 | if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) { | ||
| 271 | arch_leave_lazy_mmu_mode(); | ||
| 272 | arch_enter_lazy_mmu_mode(); | ||
| 273 | } | ||
| 274 | |||
| 275 | preempt_enable(); | ||
| 276 | } | ||
| 277 | |||
| 266 | void paravirt_start_context_switch(struct task_struct *prev) | 278 | void paravirt_start_context_switch(struct task_struct *prev) |
| 267 | { | 279 | { |
| 268 | BUG_ON(preemptible()); | 280 | BUG_ON(preemptible()); |
| @@ -292,18 +304,6 @@ enum paravirt_lazy_mode paravirt_get_lazy_mode(void) | |||
| 292 | return this_cpu_read(paravirt_lazy_mode); | 304 | return this_cpu_read(paravirt_lazy_mode); |
| 293 | } | 305 | } |
| 294 | 306 | ||
| 295 | void arch_flush_lazy_mmu_mode(void) | ||
| 296 | { | ||
| 297 | preempt_disable(); | ||
| 298 | |||
| 299 | if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) { | ||
| 300 | arch_leave_lazy_mmu_mode(); | ||
| 301 | arch_enter_lazy_mmu_mode(); | ||
| 302 | } | ||
| 303 | |||
| 304 | preempt_enable(); | ||
| 305 | } | ||
| 306 | |||
| 307 | struct pv_info pv_info = { | 307 | struct pv_info pv_info = { |
| 308 | .name = "bare hardware", | 308 | .name = "bare hardware", |
| 309 | .paravirt_enabled = 0, | 309 | .paravirt_enabled = 0, |
| @@ -475,6 +475,7 @@ struct pv_mmu_ops pv_mmu_ops = { | |||
| 475 | .lazy_mode = { | 475 | .lazy_mode = { |
| 476 | .enter = paravirt_nop, | 476 | .enter = paravirt_nop, |
| 477 | .leave = paravirt_nop, | 477 | .leave = paravirt_nop, |
| 478 | .flush = paravirt_nop, | ||
| 478 | }, | 479 | }, |
| 479 | 480 | ||
| 480 | .set_fixmap = native_set_fixmap, | 481 | .set_fixmap = native_set_fixmap, |
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 1cbd89ca5569..7114c63f047d 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c | |||
| @@ -1334,6 +1334,7 @@ __init void lguest_init(void) | |||
| 1334 | pv_mmu_ops.read_cr3 = lguest_read_cr3; | 1334 | pv_mmu_ops.read_cr3 = lguest_read_cr3; |
| 1335 | pv_mmu_ops.lazy_mode.enter = paravirt_enter_lazy_mmu; | 1335 | pv_mmu_ops.lazy_mode.enter = paravirt_enter_lazy_mmu; |
| 1336 | pv_mmu_ops.lazy_mode.leave = lguest_leave_lazy_mmu_mode; | 1336 | pv_mmu_ops.lazy_mode.leave = lguest_leave_lazy_mmu_mode; |
| 1337 | pv_mmu_ops.lazy_mode.flush = paravirt_flush_lazy_mmu; | ||
| 1337 | pv_mmu_ops.pte_update = lguest_pte_update; | 1338 | pv_mmu_ops.pte_update = lguest_pte_update; |
| 1338 | pv_mmu_ops.pte_update_defer = lguest_pte_update; | 1339 | pv_mmu_ops.pte_update_defer = lguest_pte_update; |
| 1339 | 1340 | ||
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 6afbb2ca9a0a..2f5d6875555e 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
| @@ -2196,6 +2196,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = { | |||
| 2196 | .lazy_mode = { | 2196 | .lazy_mode = { |
| 2197 | .enter = paravirt_enter_lazy_mmu, | 2197 | .enter = paravirt_enter_lazy_mmu, |
| 2198 | .leave = xen_leave_lazy_mmu, | 2198 | .leave = xen_leave_lazy_mmu, |
| 2199 | .flush = paravirt_flush_lazy_mmu, | ||
| 2199 | }, | 2200 | }, |
| 2200 | 2201 | ||
| 2201 | .set_fixmap = xen_set_fixmap, | 2202 | .set_fixmap = xen_set_fixmap, |
