2006-09-27 14:13:36 +08:00
|
|
|
/*
|
|
|
|
* Page fault handler for SH with an MMU.
|
2005-04-17 06:20:36 +08:00
|
|
|
*
|
|
|
|
* Copyright (C) 1999 Niibe Yutaka
|
2009-07-05 02:18:47 +08:00
|
|
|
* Copyright (C) 2003 - 2009 Paul Mundt
|
2005-04-17 06:20:36 +08:00
|
|
|
*
|
|
|
|
* Based on linux/arch/i386/mm/fault.c:
|
|
|
|
* Copyright (C) 1995 Linus Torvalds
|
2006-09-27 14:13:36 +08:00
|
|
|
*
|
|
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
|
|
* License. See the file "COPYING" in the main directory of this archive
|
|
|
|
* for more details.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/mm.h>
|
2006-09-27 16:03:56 +08:00
|
|
|
#include <linux/hardirq.h>
|
|
|
|
#include <linux/kprobes.h>
|
perf: Do the big rename: Performance Counters -> Performance Events
Bye-bye Performance Counters, welcome Performance Events!
In the past few months the perfcounters subsystem has grown out its
initial role of counting hardware events, and has become (and is
becoming) a much broader generic event enumeration, reporting, logging,
monitoring, analysis facility.
Naming its core object 'perf_counter' and naming the subsystem
'perfcounters' has become more and more of a misnomer. With pending
code like hw-breakpoints support the 'counter' name is less and
less appropriate.
All in one, we've decided to rename the subsystem to 'performance
events' and to propagate this rename through all fields, variables
and API names. (in an ABI compatible fashion)
The word 'event' is also a bit shorter than 'counter' - which makes
it slightly more convenient to write/handle as well.
Thanks goes to Stephane Eranian who first observed this misnomer and
suggested a rename.
User-space tooling and ABI compatibility is not affected - this patch
should be function-invariant. (Also, defconfigs were not touched to
keep the size down.)
This patch has been generated via the following script:
FILES=$(find * -type f | grep -vE 'oprofile|[^K]config')
sed -i \
-e 's/PERF_EVENT_/PERF_RECORD_/g' \
-e 's/PERF_COUNTER/PERF_EVENT/g' \
-e 's/perf_counter/perf_event/g' \
-e 's/nb_counters/nb_events/g' \
-e 's/swcounter/swevent/g' \
-e 's/tpcounter_event/tp_event/g' \
$FILES
for N in $(find . -name perf_counter.[ch]); do
M=$(echo $N | sed 's/perf_counter/perf_event/g')
mv $N $M
done
FILES=$(find . -name perf_event.*)
sed -i \
-e 's/COUNTER_MASK/REG_MASK/g' \
-e 's/COUNTER/EVENT/g' \
-e 's/\<event\>/event_id/g' \
-e 's/counter/event/g' \
-e 's/Counter/Event/g' \
$FILES
... to keep it as correct as possible. This script can also be
used by anyone who has pending perfcounters patches - it converts
a Linux kernel tree over to the new naming. We tried to time this
change to the point in time where the amount of pending patches
is the smallest: the end of the merge window.
Namespace clashes were fixed up in a preparatory patch - and some
stylistic fallout will be fixed up in a subsequent patch.
( NOTE: 'counters' are still the proper terminology when we deal
with hardware registers - and these sed scripts are a bit
over-eager in renaming them. I've undone some of that, but
in case there's something left where 'counter' would be
better than 'event' we can undo that on an individual basis
instead of touching an otherwise nicely automated patch. )
Suggested-by: Stephane Eranian <eranian@google.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Paul Mackerras <paulus@samba.org>
Reviewed-by: Arjan van de Ven <arjan@linux.intel.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: David Howells <dhowells@redhat.com>
Cc: Kyle McMartin <kyle@mcmartin.ca>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: <linux-arch@vger.kernel.org>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-09-21 18:02:48 +08:00
|
|
|
#include <linux/perf_event.h>
|
2008-02-07 19:18:21 +08:00
|
|
|
#include <asm/io_trapped.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <asm/system.h>
|
|
|
|
#include <asm/mmu_context.h>
|
2007-02-14 13:13:10 +08:00
|
|
|
#include <asm/tlbflush.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-06-25 01:30:10 +08:00
|
|
|
static inline int notify_page_fault(struct pt_regs *regs, int trap)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
2009-07-05 01:50:10 +08:00
|
|
|
if (kprobes_built_in() && !user_mode(regs)) {
|
2009-06-25 01:30:10 +08:00
|
|
|
preempt_disable();
|
|
|
|
if (kprobe_running() && kprobe_fault_handler(regs, trap))
|
|
|
|
ret = 1;
|
|
|
|
preempt_enable();
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-07-05 02:18:47 +08:00
|
|
|
static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
|
|
|
|
{
|
|
|
|
unsigned index = pgd_index(address);
|
|
|
|
pgd_t *pgd_k;
|
|
|
|
pud_t *pud, *pud_k;
|
|
|
|
pmd_t *pmd, *pmd_k;
|
|
|
|
|
|
|
|
pgd += index;
|
|
|
|
pgd_k = init_mm.pgd + index;
|
|
|
|
|
|
|
|
if (!pgd_present(*pgd_k))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
pud = pud_offset(pgd, address);
|
|
|
|
pud_k = pud_offset(pgd_k, address);
|
|
|
|
if (!pud_present(*pud_k))
|
|
|
|
return NULL;
|
|
|
|
|
2009-12-13 22:38:50 +08:00
|
|
|
if (!pud_present(*pud))
|
|
|
|
set_pud(pud, *pud_k);
|
|
|
|
|
2009-07-05 02:18:47 +08:00
|
|
|
pmd = pmd_offset(pud, address);
|
|
|
|
pmd_k = pmd_offset(pud_k, address);
|
|
|
|
if (!pmd_present(*pmd_k))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!pmd_present(*pmd))
|
|
|
|
set_pmd(pmd, *pmd_k);
|
2009-07-13 19:38:04 +08:00
|
|
|
else {
|
|
|
|
/*
|
|
|
|
* The page tables are fully synchronised so there must
|
|
|
|
* be another reason for the fault. Return NULL here to
|
|
|
|
* signal that we have not taken care of the fault.
|
|
|
|
*/
|
2009-07-05 02:18:47 +08:00
|
|
|
BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
|
2009-07-13 19:38:04 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
2009-07-05 02:18:47 +08:00
|
|
|
|
|
|
|
return pmd_k;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle a fault on the vmalloc or module mapping area
|
|
|
|
*/
|
|
|
|
static noinline int vmalloc_fault(unsigned long address)
|
|
|
|
{
|
|
|
|
pgd_t *pgd_k;
|
|
|
|
pmd_t *pmd_k;
|
|
|
|
pte_t *pte_k;
|
|
|
|
|
2009-09-03 16:21:10 +08:00
|
|
|
/* Make sure we are in vmalloc/module/P3 area: */
|
|
|
|
if (!(address >= VMALLOC_START && address < P3_ADDR_MAX))
|
2009-07-05 02:18:47 +08:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Synchronize this task's top level page-table
|
|
|
|
* with the 'reference' page table.
|
|
|
|
*
|
|
|
|
* Do _not_ use "current" here. We might be inside
|
|
|
|
* an interrupt in the middle of a task switch..
|
|
|
|
*/
|
|
|
|
pgd_k = get_TTB();
|
2009-07-13 19:38:04 +08:00
|
|
|
pmd_k = vmalloc_sync_one(pgd_k, address);
|
2009-07-05 02:18:47 +08:00
|
|
|
if (!pmd_k)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
pte_k = pte_offset_kernel(pmd_k, address);
|
|
|
|
if (!pte_present(*pte_k))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int fault_in_kernel_space(unsigned long address)
|
|
|
|
{
|
|
|
|
return address >= TASK_SIZE;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* This routine handles page faults. It determines the address,
|
|
|
|
* and the problem, and then passes it off to one of the appropriate
|
|
|
|
* routines.
|
|
|
|
*/
|
2006-11-21 12:34:04 +08:00
|
|
|
asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
|
|
|
|
unsigned long writeaccess,
|
|
|
|
unsigned long address)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2009-07-05 02:18:47 +08:00
|
|
|
unsigned long vec;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct task_struct *tsk;
|
|
|
|
struct mm_struct *mm;
|
|
|
|
struct vm_area_struct * vma;
|
2006-11-21 12:34:04 +08:00
|
|
|
int si_code;
|
2007-07-19 16:47:05 +08:00
|
|
|
int fault;
|
2006-11-21 12:34:04 +08:00
|
|
|
siginfo_t info;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
tsk = current;
|
2009-07-05 02:18:47 +08:00
|
|
|
mm = tsk->mm;
|
2006-11-21 12:34:04 +08:00
|
|
|
si_code = SEGV_MAPERR;
|
2009-07-05 02:18:47 +08:00
|
|
|
vec = lookup_exception_vector();
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2009-07-05 02:18:47 +08:00
|
|
|
/*
|
|
|
|
* We fault-in kernel-space virtual memory on-demand. The
|
|
|
|
* 'reference' page table is init_mm.pgd.
|
|
|
|
*
|
|
|
|
* NOTE! We MUST NOT take any locks for this case. We may
|
|
|
|
* be in an interrupt or a critical region, and should
|
|
|
|
* only copy the information from the master page table,
|
|
|
|
* nothing more.
|
|
|
|
*/
|
|
|
|
if (unlikely(fault_in_kernel_space(address))) {
|
|
|
|
if (vmalloc_fault(address) >= 0)
|
2006-11-21 14:38:05 +08:00
|
|
|
return;
|
2009-07-05 02:18:47 +08:00
|
|
|
if (notify_page_fault(regs, vec))
|
2008-09-05 15:17:15 +08:00
|
|
|
return;
|
2006-11-21 14:38:05 +08:00
|
|
|
|
2009-07-05 02:18:47 +08:00
|
|
|
goto bad_area_nosemaphore;
|
2006-11-21 14:38:05 +08:00
|
|
|
}
|
|
|
|
|
2009-07-05 02:18:47 +08:00
|
|
|
if (unlikely(notify_page_fault(regs, vec)))
|
2009-06-25 01:30:10 +08:00
|
|
|
return;
|
|
|
|
|
2008-07-02 16:51:23 +08:00
|
|
|
/* Only enable interrupts if they were on before the fault */
|
2009-06-25 01:30:10 +08:00
|
|
|
if ((regs->sr & SR_IMASK) != SR_IMASK)
|
2008-07-02 16:51:23 +08:00
|
|
|
local_irq_enable();
|
|
|
|
|
perf: Do the big rename: Performance Counters -> Performance Events
Bye-bye Performance Counters, welcome Performance Events!
In the past few months the perfcounters subsystem has grown out its
initial role of counting hardware events, and has become (and is
becoming) a much broader generic event enumeration, reporting, logging,
monitoring, analysis facility.
Naming its core object 'perf_counter' and naming the subsystem
'perfcounters' has become more and more of a misnomer. With pending
code like hw-breakpoints support the 'counter' name is less and
less appropriate.
All in one, we've decided to rename the subsystem to 'performance
events' and to propagate this rename through all fields, variables
and API names. (in an ABI compatible fashion)
The word 'event' is also a bit shorter than 'counter' - which makes
it slightly more convenient to write/handle as well.
Thanks goes to Stephane Eranian who first observed this misnomer and
suggested a rename.
User-space tooling and ABI compatibility is not affected - this patch
should be function-invariant. (Also, defconfigs were not touched to
keep the size down.)
This patch has been generated via the following script:
FILES=$(find * -type f | grep -vE 'oprofile|[^K]config')
sed -i \
-e 's/PERF_EVENT_/PERF_RECORD_/g' \
-e 's/PERF_COUNTER/PERF_EVENT/g' \
-e 's/perf_counter/perf_event/g' \
-e 's/nb_counters/nb_events/g' \
-e 's/swcounter/swevent/g' \
-e 's/tpcounter_event/tp_event/g' \
$FILES
for N in $(find . -name perf_counter.[ch]); do
M=$(echo $N | sed 's/perf_counter/perf_event/g')
mv $N $M
done
FILES=$(find . -name perf_event.*)
sed -i \
-e 's/COUNTER_MASK/REG_MASK/g' \
-e 's/COUNTER/EVENT/g' \
-e 's/\<event\>/event_id/g' \
-e 's/counter/event/g' \
-e 's/Counter/Event/g' \
$FILES
... to keep it as correct as possible. This script can also be
used by anyone who has pending perfcounters patches - it converts
a Linux kernel tree over to the new naming. We tried to time this
change to the point in time where the amount of pending patches
is the smallest: the end of the merge window.
Namespace clashes were fixed up in a preparatory patch - and some
stylistic fallout will be fixed up in a subsequent patch.
( NOTE: 'counters' are still the proper terminology when we deal
with hardware registers - and these sed scripts are a bit
over-eager in renaming them. I've undone some of that, but
in case there's something left where 'counter' would be
better than 'event' we can undo that on an individual basis
instead of touching an otherwise nicely automated patch. )
Suggested-by: Stephane Eranian <eranian@google.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Paul Mackerras <paulus@samba.org>
Reviewed-by: Arjan van de Ven <arjan@linux.intel.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: David Howells <dhowells@redhat.com>
Cc: Kyle McMartin <kyle@mcmartin.ca>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: <linux-arch@vger.kernel.org>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-09-21 18:02:48 +08:00
|
|
|
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
|
2008-07-02 16:51:23 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
2009-07-05 02:18:47 +08:00
|
|
|
* If we're in an interrupt, have no user context or are running
|
|
|
|
* in an atomic region then we must not take the fault:
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
if (in_atomic() || !mm)
|
|
|
|
goto no_context;
|
|
|
|
|
|
|
|
down_read(&mm->mmap_sem);
|
|
|
|
|
|
|
|
vma = find_vma(mm, address);
|
|
|
|
if (!vma)
|
|
|
|
goto bad_area;
|
|
|
|
if (vma->vm_start <= address)
|
|
|
|
goto good_area;
|
|
|
|
if (!(vma->vm_flags & VM_GROWSDOWN))
|
|
|
|
goto bad_area;
|
|
|
|
if (expand_stack(vma, address))
|
|
|
|
goto bad_area;
|
2009-07-05 02:18:47 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Ok, we have a good vm_area for this memory access, so
|
|
|
|
* we can handle it..
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
good_area:
|
2006-11-21 12:34:04 +08:00
|
|
|
si_code = SEGV_ACCERR;
|
2005-04-17 06:20:36 +08:00
|
|
|
if (writeaccess) {
|
|
|
|
if (!(vma->vm_flags & VM_WRITE))
|
|
|
|
goto bad_area;
|
|
|
|
} else {
|
[PATCH] make PROT_WRITE imply PROT_READ
Make PROT_WRITE imply PROT_READ for a number of architectures which don't
support write only in hardware.
While looking at this, I noticed that some architectures which do not
support write only mappings already take the exact same approach. For
example, in arch/alpha/mm/fault.c:
"
if (cause < 0) {
if (!(vma->vm_flags & VM_EXEC))
goto bad_area;
} else if (!cause) {
/* Allow reads even for write-only mappings */
if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
goto bad_area;
} else {
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
}
"
Thus, this patch brings other architectures which do not support write only
mappings in-line and consistent with the rest. I've verified the patch on
ia64, x86_64 and x86.
Additional discussion:
Several architectures, including x86, can not support write-only mappings.
The pte for x86 reserves a single bit for protection and its two states are
read only or read/write. Thus, write only is not supported in h/w.
Currently, if i 'mmap' a page write-only, the first read attempt on that page
creates a page fault and will SEGV. That check is enforced in
arch/blah/mm/fault.c. However, if i first write that page it will fault in
and the pte will be set to read/write. Thus, any subsequent reads to the page
will succeed. It is this inconsistency in behavior that this patch is
attempting to address. Furthermore, if the page is swapped out, and then
brought back the first read will also cause a SEGV. Thus, any arbitrary read
on a page can potentially result in a SEGV.
According to the SuSv3 spec, "if the application requests only PROT_WRITE, the
implementation may also allow read access." Also as mentioned, some
archtectures, such as alpha, shown above already take the approach that i am
suggesting.
The counter-argument to this raised by Arjan, is that the kernel is enforcing
the write only mapping the best it can given the h/w limitations. This is
true, however Alan Cox, and myself would argue that the inconsitency in
behavior, that is applications can sometimes work/sometimes fails is highly
undesireable. If you read through the thread, i think people, came to an
agreement on the last patch i posted, as nobody has objected to it...
Signed-off-by: Jason Baron <jbaron@redhat.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Hugh Dickins <hugh@veritas.com>
Cc: Roman Zippel <zippel@linux-m68k.org>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Andi Kleen <ak@muc.de>
Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Acked-by: Paul Mundt <lethal@linux-sh.org>
Cc: Kazumoto Kojima <kkojima@rr.iij4u.or.jp>
Cc: Ian Molton <spyro@f2s.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-09-29 16:58:58 +08:00
|
|
|
if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
|
2005-04-17 06:20:36 +08:00
|
|
|
goto bad_area;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If for any reason at all we couldn't handle the fault,
|
|
|
|
* make sure we exit gracefully rather than endlessly redo
|
|
|
|
* the fault.
|
|
|
|
*/
|
|
|
|
survive:
|
2009-04-11 00:01:23 +08:00
|
|
|
fault = handle_mm_fault(mm, vma, address, writeaccess ? FAULT_FLAG_WRITE : 0);
|
2007-07-19 16:47:05 +08:00
|
|
|
if (unlikely(fault & VM_FAULT_ERROR)) {
|
|
|
|
if (fault & VM_FAULT_OOM)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out_of_memory;
|
2007-07-19 16:47:05 +08:00
|
|
|
else if (fault & VM_FAULT_SIGBUS)
|
|
|
|
goto do_sigbus;
|
|
|
|
BUG();
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2009-06-25 01:30:10 +08:00
|
|
|
if (fault & VM_FAULT_MAJOR) {
|
2007-07-19 16:47:05 +08:00
|
|
|
tsk->maj_flt++;
|
perf: Do the big rename: Performance Counters -> Performance Events
Bye-bye Performance Counters, welcome Performance Events!
In the past few months the perfcounters subsystem has grown out its
initial role of counting hardware events, and has become (and is
becoming) a much broader generic event enumeration, reporting, logging,
monitoring, analysis facility.
Naming its core object 'perf_counter' and naming the subsystem
'perfcounters' has become more and more of a misnomer. With pending
code like hw-breakpoints support the 'counter' name is less and
less appropriate.
All in one, we've decided to rename the subsystem to 'performance
events' and to propagate this rename through all fields, variables
and API names. (in an ABI compatible fashion)
The word 'event' is also a bit shorter than 'counter' - which makes
it slightly more convenient to write/handle as well.
Thanks goes to Stephane Eranian who first observed this misnomer and
suggested a rename.
User-space tooling and ABI compatibility is not affected - this patch
should be function-invariant. (Also, defconfigs were not touched to
keep the size down.)
This patch has been generated via the following script:
FILES=$(find * -type f | grep -vE 'oprofile|[^K]config')
sed -i \
-e 's/PERF_EVENT_/PERF_RECORD_/g' \
-e 's/PERF_COUNTER/PERF_EVENT/g' \
-e 's/perf_counter/perf_event/g' \
-e 's/nb_counters/nb_events/g' \
-e 's/swcounter/swevent/g' \
-e 's/tpcounter_event/tp_event/g' \
$FILES
for N in $(find . -name perf_counter.[ch]); do
M=$(echo $N | sed 's/perf_counter/perf_event/g')
mv $N $M
done
FILES=$(find . -name perf_event.*)
sed -i \
-e 's/COUNTER_MASK/REG_MASK/g' \
-e 's/COUNTER/EVENT/g' \
-e 's/\<event\>/event_id/g' \
-e 's/counter/event/g' \
-e 's/Counter/Event/g' \
$FILES
... to keep it as correct as possible. This script can also be
used by anyone who has pending perfcounters patches - it converts
a Linux kernel tree over to the new naming. We tried to time this
change to the point in time where the amount of pending patches
is the smallest: the end of the merge window.
Namespace clashes were fixed up in a preparatory patch - and some
stylistic fallout will be fixed up in a subsequent patch.
( NOTE: 'counters' are still the proper terminology when we deal
with hardware registers - and these sed scripts are a bit
over-eager in renaming them. I've undone some of that, but
in case there's something left where 'counter' would be
better than 'event' we can undo that on an individual basis
instead of touching an otherwise nicely automated patch. )
Suggested-by: Stephane Eranian <eranian@google.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Paul Mackerras <paulus@samba.org>
Reviewed-by: Arjan van de Ven <arjan@linux.intel.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: David Howells <dhowells@redhat.com>
Cc: Kyle McMartin <kyle@mcmartin.ca>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: <linux-arch@vger.kernel.org>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-09-21 18:02:48 +08:00
|
|
|
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
|
2009-06-25 01:30:10 +08:00
|
|
|
regs, address);
|
|
|
|
} else {
|
2007-07-19 16:47:05 +08:00
|
|
|
tsk->min_flt++;
|
perf: Do the big rename: Performance Counters -> Performance Events
Bye-bye Performance Counters, welcome Performance Events!
In the past few months the perfcounters subsystem has grown out its
initial role of counting hardware events, and has become (and is
becoming) a much broader generic event enumeration, reporting, logging,
monitoring, analysis facility.
Naming its core object 'perf_counter' and naming the subsystem
'perfcounters' has become more and more of a misnomer. With pending
code like hw-breakpoints support the 'counter' name is less and
less appropriate.
All in one, we've decided to rename the subsystem to 'performance
events' and to propagate this rename through all fields, variables
and API names. (in an ABI compatible fashion)
The word 'event' is also a bit shorter than 'counter' - which makes
it slightly more convenient to write/handle as well.
Thanks goes to Stephane Eranian who first observed this misnomer and
suggested a rename.
User-space tooling and ABI compatibility is not affected - this patch
should be function-invariant. (Also, defconfigs were not touched to
keep the size down.)
This patch has been generated via the following script:
FILES=$(find * -type f | grep -vE 'oprofile|[^K]config')
sed -i \
-e 's/PERF_EVENT_/PERF_RECORD_/g' \
-e 's/PERF_COUNTER/PERF_EVENT/g' \
-e 's/perf_counter/perf_event/g' \
-e 's/nb_counters/nb_events/g' \
-e 's/swcounter/swevent/g' \
-e 's/tpcounter_event/tp_event/g' \
$FILES
for N in $(find . -name perf_counter.[ch]); do
M=$(echo $N | sed 's/perf_counter/perf_event/g')
mv $N $M
done
FILES=$(find . -name perf_event.*)
sed -i \
-e 's/COUNTER_MASK/REG_MASK/g' \
-e 's/COUNTER/EVENT/g' \
-e 's/\<event\>/event_id/g' \
-e 's/counter/event/g' \
-e 's/Counter/Event/g' \
$FILES
... to keep it as correct as possible. This script can also be
used by anyone who has pending perfcounters patches - it converts
a Linux kernel tree over to the new naming. We tried to time this
change to the point in time where the amount of pending patches
is the smallest: the end of the merge window.
Namespace clashes were fixed up in a preparatory patch - and some
stylistic fallout will be fixed up in a subsequent patch.
( NOTE: 'counters' are still the proper terminology when we deal
with hardware registers - and these sed scripts are a bit
over-eager in renaming them. I've undone some of that, but
in case there's something left where 'counter' would be
better than 'event' we can undo that on an individual basis
instead of touching an otherwise nicely automated patch. )
Suggested-by: Stephane Eranian <eranian@google.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Paul Mackerras <paulus@samba.org>
Reviewed-by: Arjan van de Ven <arjan@linux.intel.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: David Howells <dhowells@redhat.com>
Cc: Kyle McMartin <kyle@mcmartin.ca>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: <linux-arch@vger.kernel.org>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-09-21 18:02:48 +08:00
|
|
|
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
|
2009-06-25 01:30:10 +08:00
|
|
|
regs, address);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
up_read(&mm->mmap_sem);
|
|
|
|
return;
|
|
|
|
|
2009-07-05 02:18:47 +08:00
|
|
|
/*
|
|
|
|
* Something tried to access memory that isn't in our memory map..
|
|
|
|
* Fix it, but check if it's kernel or user first..
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
bad_area:
|
|
|
|
up_read(&mm->mmap_sem);
|
|
|
|
|
2006-11-21 14:38:05 +08:00
|
|
|
bad_area_nosemaphore:
|
2005-04-17 06:20:36 +08:00
|
|
|
if (user_mode(regs)) {
|
2006-11-21 12:34:04 +08:00
|
|
|
info.si_signo = SIGSEGV;
|
|
|
|
info.si_errno = 0;
|
|
|
|
info.si_code = si_code;
|
|
|
|
info.si_addr = (void *) address;
|
|
|
|
force_sig_info(SIGSEGV, &info, tsk);
|
2005-04-17 06:20:36 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
no_context:
|
|
|
|
/* Are we prepared to handle this kernel fault? */
|
|
|
|
if (fixup_exception(regs))
|
|
|
|
return;
|
|
|
|
|
2008-02-07 19:18:21 +08:00
|
|
|
if (handle_trapped_io(regs, address))
|
|
|
|
return;
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Oops. The kernel tried to access some bad page. We'll have to
|
|
|
|
* terminate things with extreme prejudice.
|
|
|
|
*
|
|
|
|
*/
|
2007-06-18 18:02:47 +08:00
|
|
|
|
|
|
|
bust_spinlocks(1);
|
|
|
|
|
|
|
|
if (oops_may_print()) {
|
2008-01-10 13:07:03 +08:00
|
|
|
unsigned long page;
|
2007-06-18 18:02:47 +08:00
|
|
|
|
|
|
|
if (address < PAGE_SIZE)
|
|
|
|
printk(KERN_ALERT "Unable to handle kernel NULL "
|
|
|
|
"pointer dereference");
|
|
|
|
else
|
|
|
|
printk(KERN_ALERT "Unable to handle kernel paging "
|
|
|
|
"request");
|
|
|
|
printk(" at virtual address %08lx\n", address);
|
|
|
|
printk(KERN_ALERT "pc = %08lx\n", regs->pc);
|
|
|
|
page = (unsigned long)get_TTB();
|
|
|
|
if (page) {
|
2007-08-01 15:39:51 +08:00
|
|
|
page = ((__typeof__(page) *)page)[address >> PGDIR_SHIFT];
|
2007-06-18 18:02:47 +08:00
|
|
|
printk(KERN_ALERT "*pde = %08lx\n", page);
|
|
|
|
if (page & _PAGE_PRESENT) {
|
|
|
|
page &= PAGE_MASK;
|
|
|
|
address &= 0x003ff000;
|
|
|
|
page = ((__typeof__(page) *)
|
|
|
|
__va(page))[address >>
|
|
|
|
PAGE_SHIFT];
|
|
|
|
printk(KERN_ALERT "*pte = %08lx\n", page);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
2007-06-18 18:02:47 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
die("Oops", regs, writeaccess);
|
2007-06-18 18:02:47 +08:00
|
|
|
bust_spinlocks(0);
|
2005-04-17 06:20:36 +08:00
|
|
|
do_exit(SIGKILL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We ran out of memory, or some other thing happened to us that made
|
|
|
|
* us unable to handle the page fault gracefully.
|
|
|
|
*/
|
|
|
|
out_of_memory:
|
|
|
|
up_read(&mm->mmap_sem);
|
2007-10-19 14:39:52 +08:00
|
|
|
if (is_global_init(current)) {
|
2005-04-17 06:20:36 +08:00
|
|
|
yield();
|
|
|
|
down_read(&mm->mmap_sem);
|
|
|
|
goto survive;
|
|
|
|
}
|
|
|
|
printk("VM: killing process %s\n", tsk->comm);
|
|
|
|
if (user_mode(regs))
|
2007-10-16 16:24:18 +08:00
|
|
|
do_group_exit(SIGKILL);
|
2005-04-17 06:20:36 +08:00
|
|
|
goto no_context;
|
|
|
|
|
|
|
|
do_sigbus:
|
|
|
|
up_read(&mm->mmap_sem);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send a sigbus, regardless of whether we were in kernel
|
|
|
|
* or user mode.
|
|
|
|
*/
|
2006-11-21 12:34:04 +08:00
|
|
|
info.si_signo = SIGBUS;
|
|
|
|
info.si_errno = 0;
|
|
|
|
info.si_code = BUS_ADRERR;
|
|
|
|
info.si_addr = (void *)address;
|
|
|
|
force_sig_info(SIGBUS, &info, tsk);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* Kernel mode? Handle exceptions or die */
|
|
|
|
if (!user_mode(regs))
|
|
|
|
goto no_context;
|
|
|
|
}
|
2007-02-14 13:13:10 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Called with interrupts disabled.
|
|
|
|
*/
|
2009-08-15 01:49:40 +08:00
|
|
|
asmlinkage int __kprobes
|
|
|
|
handle_tlbmiss(struct pt_regs *regs, unsigned long writeaccess,
|
|
|
|
unsigned long address)
|
2007-02-14 13:13:10 +08:00
|
|
|
{
|
|
|
|
pgd_t *pgd;
|
|
|
|
pud_t *pud;
|
|
|
|
pmd_t *pmd;
|
|
|
|
pte_t *pte;
|
|
|
|
pte_t entry;
|
2008-09-21 12:56:39 +08:00
|
|
|
|
2007-02-14 13:13:10 +08:00
|
|
|
/*
|
|
|
|
* We don't take page faults for P1, P2, and parts of P4, these
|
|
|
|
* are always mapped, whether it be due to legacy behaviour in
|
|
|
|
* 29-bit mode, or due to PMB configuration in 32-bit mode.
|
|
|
|
*/
|
|
|
|
if (address >= P3SEG && address < P3_ADDR_MAX) {
|
|
|
|
pgd = pgd_offset_k(address);
|
|
|
|
} else {
|
2007-11-19 12:05:18 +08:00
|
|
|
if (unlikely(address >= TASK_SIZE || !current->mm))
|
2009-08-15 02:06:41 +08:00
|
|
|
return 1;
|
2007-02-14 13:13:10 +08:00
|
|
|
|
2007-11-19 12:05:18 +08:00
|
|
|
pgd = pgd_offset(current->mm, address);
|
2007-02-14 13:13:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pud = pud_offset(pgd, address);
|
|
|
|
if (pud_none_or_clear_bad(pud))
|
2009-08-15 02:06:41 +08:00
|
|
|
return 1;
|
2007-02-14 13:13:10 +08:00
|
|
|
pmd = pmd_offset(pud, address);
|
|
|
|
if (pmd_none_or_clear_bad(pmd))
|
2009-08-15 02:06:41 +08:00
|
|
|
return 1;
|
2007-11-19 12:05:18 +08:00
|
|
|
pte = pte_offset_kernel(pmd, address);
|
2007-02-14 13:13:10 +08:00
|
|
|
entry = *pte;
|
|
|
|
if (unlikely(pte_none(entry) || pte_not_present(entry)))
|
2009-08-15 02:06:41 +08:00
|
|
|
return 1;
|
2007-02-14 13:13:10 +08:00
|
|
|
if (unlikely(writeaccess && !pte_write(entry)))
|
2009-08-15 02:06:41 +08:00
|
|
|
return 1;
|
2007-02-14 13:13:10 +08:00
|
|
|
|
|
|
|
if (writeaccess)
|
|
|
|
entry = pte_mkdirty(entry);
|
|
|
|
entry = pte_mkyoung(entry);
|
|
|
|
|
2009-08-15 02:06:41 +08:00
|
|
|
set_pte(pte, entry);
|
|
|
|
|
2008-02-14 13:45:08 +08:00
|
|
|
#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SMP)
|
|
|
|
/*
|
2009-08-15 02:06:41 +08:00
|
|
|
* SH-4 does not set MMUCR.RC to the corresponding TLB entry in
|
|
|
|
* the case of an initial page write exception, so we need to
|
|
|
|
* flush it in order to avoid potential TLB entry duplication.
|
2008-02-14 13:45:08 +08:00
|
|
|
*/
|
2009-08-15 02:06:41 +08:00
|
|
|
if (writeaccess == 2)
|
|
|
|
local_flush_tlb_one(get_asid(), address & PAGE_MASK);
|
2008-02-14 13:45:08 +08:00
|
|
|
#endif
|
|
|
|
|
MM: Pass a PTE pointer to update_mmu_cache() rather than the PTE itself
On VIVT ARM, when we have multiple shared mappings of the same file
in the same MM, we need to ensure that we have coherency across all
copies. We do this via make_coherent() by making the pages
uncacheable.
This used to work fine, until we allowed highmem with highpte - we
now have a page table which is mapped as required, and is not available
for modification via update_mmu_cache().
Ralf Beache suggested getting rid of the PTE value passed to
update_mmu_cache():
On MIPS update_mmu_cache() calls __update_tlb() which walks pagetables
to construct a pointer to the pte again. Passing a pte_t * is much
more elegant. Maybe we might even replace the pte argument with the
pte_t?
Ben Herrenschmidt would also like the pte pointer for PowerPC:
Passing the ptep in there is exactly what I want. I want that
-instead- of the PTE value, because I have issue on some ppc cases,
for I$/D$ coherency, where set_pte_at() may decide to mask out the
_PAGE_EXEC.
So, pass in the mapped page table pointer into update_mmu_cache(), and
remove the PTE value, updating all implementations and call sites to
suit.
Includes a fix from Stephen Rothwell:
sparc: fix fallout from update_mmu_cache API change
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2009-12-19 00:40:18 +08:00
|
|
|
update_mmu_cache(NULL, address, pte);
|
2007-11-19 12:05:18 +08:00
|
|
|
|
2009-08-15 02:06:41 +08:00
|
|
|
return 0;
|
2007-02-14 13:13:10 +08:00
|
|
|
}
|