• P
    powerpc: Allow perf_counters to access user memory at interrupt time · 9c1e1052
    Paul Mackerras 提交于
    This provides a mechanism to allow the perf_counters code to access
    user memory in a PMU interrupt routine.  Such an access can cause
    various kinds of interrupt: SLB miss, MMU hash table miss, segment
    table miss, or TLB miss, depending on the processor.  This commit
    only deals with 64-bit classic/server processors, which use an MMU
    hash table.  32-bit processors are already able to access user memory
    at interrupt time.  Since we don't soft-disable on 32-bit, we avoid
    the possibility of reentering hash_page or the TLB miss handlers,
    since they run with interrupts disabled.
    
    On 64-bit processors, an SLB miss interrupt on a user address will
    update the slb_cache and slb_cache_ptr fields in the paca.  This is
    OK except in the case where a PMU interrupt occurs in switch_slb,
    which also accesses those fields.  To prevent this, we hard-disable
    interrupts in switch_slb.  Interrupts are already soft-disabled at
    this point, and will get hard-enabled when they get soft-enabled
    later.
    
    This also reworks slb_flush_and_rebolt: to avoid hard-disabling twice,
    and to make sure that it clears the slb_cache_ptr when called from
    other callers than switch_slb, the existing routine is renamed to
    __slb_flush_and_rebolt, which is called by switch_slb and the new
    version of slb_flush_and_rebolt.
    
    Similarly, switch_stab (used on POWER3 and RS64 processors) gets a
    hard_irq_disable() to protect the per-cpu variables used there and
    in ste_allocate.
    
    If a MMU hashtable miss interrupt occurs, normally we would call
    hash_page to look up the Linux PTE for the address and create a HPTE.
    However, hash_page is fairly complex and takes some locks, so to
    avoid the possibility of deadlock, we check the preemption count
    to see if we are in a (pseudo-)NMI handler, and if so, we don't call
    hash_page but instead treat it like a bad access that will get
    reported up through the exception table mechanism.  An interrupt
    whose handler runs even though the interrupt occurred when
    soft-disabled (such as the PMU interrupt) is considered a pseudo-NMI
    handler, which should use nmi_enter()/nmi_exit() rather than
    irq_enter()/irq_exit().
    Acked-by: NBenjamin Herrenschmidt <benh@kernel.crashing.org>
    Signed-off-by: NPaul Mackerras <paulus@samba.org>
    9c1e1052
asm-offsets.c 18.4 KB