mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-25 02:45:51 +07:00
fc290a114f
This fixes another cause of random segfaults and bus errors that may occur while running perf with the callgraph option. Critical sections beginning with spin_lock_irqsave() raise the interrupt level to PIL_NORMAL_MAX (14) and intentionally do not block performance counter interrupts, which arrive at PIL_NMI (15). But some sections of code are "super critical" with respect to perf because the perf_callchain_user() path accesses user space and may cause TLB activity as well as faults as it unwinds the user stack. One particular critical section occurs in switch_mm: spin_lock_irqsave(&mm->context.lock, flags); ... load_secondary_context(mm); tsb_context_switch(mm); ... spin_unlock_irqrestore(&mm->context.lock, flags); If a perf interrupt arrives in between load_secondary_context() and tsb_context_switch(), then perf_callchain_user() could execute with the context ID of one process, but with an active TSB for a different process. When the user stack is accessed, it is very likely to incur a TLB miss, since the h/w context ID has been changed. The TLB will then be reloaded with a translation from the TSB for one process, but using a context ID for another process. This exposes memory from one process to another, and since it is a mapping for stack memory, this usually causes the new process to crash quickly. This super critical section needs more protection than is provided by spin_lock_irqsave() since perf interrupts must not be allowed in. Since __tsb_context_switch already goes through the trouble of disabling interrupts completely, we fix this by moving the secondary context load down into this better protected region. Orabug: 25577560 Signed-off-by: Dave Aldridge <david.j.aldridge@oracle.com> Signed-off-by: Rob Gardner <rob.gardner@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
40 lines
828 B
C
40 lines
828 B
C
/*
|
|
* hibernate.c: Hibernaton support specific for sparc64.
|
|
*
|
|
* Copyright (C) 2013 Kirill V Tkhai (tkhai@yandex.ru)
|
|
*/
|
|
|
|
#include <linux/mm.h>
|
|
|
|
#include <asm/hibernate.h>
|
|
#include <asm/visasm.h>
|
|
#include <asm/page.h>
|
|
#include <asm/sections.h>
|
|
#include <asm/tlb.h>
|
|
|
|
struct saved_context saved_context;
|
|
|
|
/*
|
|
* pfn_is_nosave - check if given pfn is in the 'nosave' section
|
|
*/
|
|
|
|
int pfn_is_nosave(unsigned long pfn)
|
|
{
|
|
unsigned long nosave_begin_pfn = PFN_DOWN((unsigned long)&__nosave_begin);
|
|
unsigned long nosave_end_pfn = PFN_DOWN((unsigned long)&__nosave_end);
|
|
|
|
return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
|
|
}
|
|
|
|
void save_processor_state(void)
|
|
{
|
|
save_and_clear_fpu();
|
|
}
|
|
|
|
void restore_processor_state(void)
|
|
{
|
|
struct mm_struct *mm = current->active_mm;
|
|
|
|
tsb_context_switch_ctx(mm, CTX_HWBITS(mm->context));
|
|
}
|