diff options
Diffstat (limited to 'arch/parisc')
26 files changed, 501 insertions, 98 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 378b64944dc0..9038f39d9d73 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig | |||
@@ -9,9 +9,13 @@ config PARISC | |||
9 | def_bool y | 9 | def_bool y |
10 | select HAVE_IDE | 10 | select HAVE_IDE |
11 | select HAVE_OPROFILE | 11 | select HAVE_OPROFILE |
12 | select HAVE_FUNCTION_TRACER if 64BIT | ||
13 | select HAVE_FUNCTION_GRAPH_TRACER if 64BIT | ||
14 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST if 64BIT | ||
12 | select RTC_CLASS | 15 | select RTC_CLASS |
13 | select RTC_DRV_GENERIC | 16 | select RTC_DRV_GENERIC |
14 | select INIT_ALL_POSSIBLE | 17 | select INIT_ALL_POSSIBLE |
18 | select BUG | ||
15 | help | 19 | help |
16 | The PA-RISC microprocessor is designed by Hewlett-Packard and used | 20 | The PA-RISC microprocessor is designed by Hewlett-Packard and used |
17 | in many of their workstations & servers (HP9000 700 and 800 series, | 21 | in many of their workstations & servers (HP9000 700 and 800 series, |
@@ -75,6 +79,9 @@ config GENERIC_HARDIRQS | |||
75 | config GENERIC_IRQ_PROBE | 79 | config GENERIC_IRQ_PROBE |
76 | def_bool y | 80 | def_bool y |
77 | 81 | ||
82 | config HAVE_LATENCYTOP_SUPPORT | ||
83 | def_bool y | ||
84 | |||
78 | config IRQ_PER_CPU | 85 | config IRQ_PER_CPU |
79 | bool | 86 | bool |
80 | default y | 87 | default y |
@@ -83,6 +90,9 @@ config IRQ_PER_CPU | |||
83 | config PM | 90 | config PM |
84 | bool | 91 | bool |
85 | 92 | ||
93 | config STACKTRACE_SUPPORT | ||
94 | def_bool y | ||
95 | |||
86 | config ISA_DMA_API | 96 | config ISA_DMA_API |
87 | bool | 97 | bool |
88 | 98 | ||
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index 0d428278356d..da6f66901c92 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile | |||
@@ -56,7 +56,9 @@ cflags-y += -mdisable-fpregs | |||
56 | 56 | ||
57 | # Without this, "ld -r" results in .text sections that are too big | 57 | # Without this, "ld -r" results in .text sections that are too big |
58 | # (> 0x40000) for branches to reach stubs. | 58 | # (> 0x40000) for branches to reach stubs. |
59 | cflags-y += -ffunction-sections | 59 | ifndef CONFIG_FUNCTION_TRACER |
60 | cflags-y += -ffunction-sections | ||
61 | endif | ||
60 | 62 | ||
61 | # select which processor to optimise for | 63 | # select which processor to optimise for |
62 | cflags-$(CONFIG_PA7100) += -march=1.1 -mschedule=7100 | 64 | cflags-$(CONFIG_PA7100) += -march=1.1 -mschedule=7100 |
diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h index edbfe25c5fc1..ada3e5364d82 100644 --- a/arch/parisc/include/asm/atomic.h +++ b/arch/parisc/include/asm/atomic.h | |||
@@ -25,7 +25,7 @@ | |||
25 | * Since "a" is usually an address, use one spinlock per cacheline. | 25 | * Since "a" is usually an address, use one spinlock per cacheline. |
26 | */ | 26 | */ |
27 | # define ATOMIC_HASH_SIZE 4 | 27 | # define ATOMIC_HASH_SIZE 4 |
28 | # define ATOMIC_HASH(a) (&(__atomic_hash[ (((unsigned long) a)/L1_CACHE_BYTES) & (ATOMIC_HASH_SIZE-1) ])) | 28 | # define ATOMIC_HASH(a) (&(__atomic_hash[ (((unsigned long) (a))/L1_CACHE_BYTES) & (ATOMIC_HASH_SIZE-1) ])) |
29 | 29 | ||
30 | extern raw_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned; | 30 | extern raw_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned; |
31 | 31 | ||
@@ -222,13 +222,13 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u) | |||
222 | 222 | ||
223 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | 223 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) |
224 | 224 | ||
225 | #define atomic_add(i,v) ((void)(__atomic_add_return( ((int)i),(v)))) | 225 | #define atomic_add(i,v) ((void)(__atomic_add_return( ((int)(i)),(v)))) |
226 | #define atomic_sub(i,v) ((void)(__atomic_add_return(-((int)i),(v)))) | 226 | #define atomic_sub(i,v) ((void)(__atomic_add_return(-((int)(i)),(v)))) |
227 | #define atomic_inc(v) ((void)(__atomic_add_return( 1,(v)))) | 227 | #define atomic_inc(v) ((void)(__atomic_add_return( 1,(v)))) |
228 | #define atomic_dec(v) ((void)(__atomic_add_return( -1,(v)))) | 228 | #define atomic_dec(v) ((void)(__atomic_add_return( -1,(v)))) |
229 | 229 | ||
230 | #define atomic_add_return(i,v) (__atomic_add_return( ((int)i),(v))) | 230 | #define atomic_add_return(i,v) (__atomic_add_return( ((int)(i)),(v))) |
231 | #define atomic_sub_return(i,v) (__atomic_add_return(-((int)i),(v))) | 231 | #define atomic_sub_return(i,v) (__atomic_add_return(-((int)(i)),(v))) |
232 | #define atomic_inc_return(v) (__atomic_add_return( 1,(v))) | 232 | #define atomic_inc_return(v) (__atomic_add_return( 1,(v))) |
233 | #define atomic_dec_return(v) (__atomic_add_return( -1,(v))) | 233 | #define atomic_dec_return(v) (__atomic_add_return( -1,(v))) |
234 | 234 | ||
@@ -289,13 +289,13 @@ atomic64_read(const atomic64_t *v) | |||
289 | return v->counter; | 289 | return v->counter; |
290 | } | 290 | } |
291 | 291 | ||
292 | #define atomic64_add(i,v) ((void)(__atomic64_add_return( ((s64)i),(v)))) | 292 | #define atomic64_add(i,v) ((void)(__atomic64_add_return( ((s64)(i)),(v)))) |
293 | #define atomic64_sub(i,v) ((void)(__atomic64_add_return(-((s64)i),(v)))) | 293 | #define atomic64_sub(i,v) ((void)(__atomic64_add_return(-((s64)(i)),(v)))) |
294 | #define atomic64_inc(v) ((void)(__atomic64_add_return( 1,(v)))) | 294 | #define atomic64_inc(v) ((void)(__atomic64_add_return( 1,(v)))) |
295 | #define atomic64_dec(v) ((void)(__atomic64_add_return( -1,(v)))) | 295 | #define atomic64_dec(v) ((void)(__atomic64_add_return( -1,(v)))) |
296 | 296 | ||
297 | #define atomic64_add_return(i,v) (__atomic64_add_return( ((s64)i),(v))) | 297 | #define atomic64_add_return(i,v) (__atomic64_add_return( ((s64)(i)),(v))) |
298 | #define atomic64_sub_return(i,v) (__atomic64_add_return(-((s64)i),(v))) | 298 | #define atomic64_sub_return(i,v) (__atomic64_add_return(-((s64)(i)),(v))) |
299 | #define atomic64_inc_return(v) (__atomic64_add_return( 1,(v))) | 299 | #define atomic64_inc_return(v) (__atomic64_add_return( 1,(v))) |
300 | #define atomic64_dec_return(v) (__atomic64_add_return( -1,(v))) | 300 | #define atomic64_dec_return(v) (__atomic64_add_return( -1,(v))) |
301 | 301 | ||
diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h index b7ca6dc7fddc..724395143f26 100644 --- a/arch/parisc/include/asm/cacheflush.h +++ b/arch/parisc/include/asm/cacheflush.h | |||
@@ -97,6 +97,9 @@ void mark_rodata_ro(void); | |||
97 | 97 | ||
98 | #ifdef CONFIG_PA8X00 | 98 | #ifdef CONFIG_PA8X00 |
99 | /* Only pa8800, pa8900 needs this */ | 99 | /* Only pa8800, pa8900 needs this */ |
100 | |||
101 | #include <asm/kmap_types.h> | ||
102 | |||
100 | #define ARCH_HAS_KMAP | 103 | #define ARCH_HAS_KMAP |
101 | 104 | ||
102 | void kunmap_parisc(void *addr); | 105 | void kunmap_parisc(void *addr); |
diff --git a/arch/parisc/include/asm/elf.h b/arch/parisc/include/asm/elf.h index 7fa675799e6d..9c802eb4be84 100644 --- a/arch/parisc/include/asm/elf.h +++ b/arch/parisc/include/asm/elf.h | |||
@@ -168,6 +168,16 @@ typedef struct elf64_fdesc { | |||
168 | __u64 gp; | 168 | __u64 gp; |
169 | } Elf64_Fdesc; | 169 | } Elf64_Fdesc; |
170 | 170 | ||
171 | #ifdef __KERNEL__ | ||
172 | |||
173 | #ifdef CONFIG_64BIT | ||
174 | #define Elf_Fdesc Elf64_Fdesc | ||
175 | #else | ||
176 | #define Elf_Fdesc Elf32_Fdesc | ||
177 | #endif /*CONFIG_64BIT*/ | ||
178 | |||
179 | #endif /*__KERNEL__*/ | ||
180 | |||
171 | /* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ | 181 | /* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ |
172 | 182 | ||
173 | #define PT_HP_TLS (PT_LOOS + 0x0) | 183 | #define PT_HP_TLS (PT_LOOS + 0x0) |
diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h new file mode 100644 index 000000000000..2fa05dd6aeee --- /dev/null +++ b/arch/parisc/include/asm/ftrace.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef _ASM_PARISC_FTRACE_H | ||
2 | #define _ASM_PARISC_FTRACE_H | ||
3 | |||
4 | #ifndef __ASSEMBLY__ | ||
5 | extern void mcount(void); | ||
6 | |||
7 | /* | ||
8 | * Stack of return addresses for functions of a thread. | ||
9 | * Used in struct thread_info | ||
10 | */ | ||
11 | struct ftrace_ret_stack { | ||
12 | unsigned long ret; | ||
13 | unsigned long func; | ||
14 | unsigned long long calltime; | ||
15 | }; | ||
16 | |||
17 | /* | ||
18 | * Primary handler of a function return. | ||
19 | * It relays on ftrace_return_to_handler. | ||
20 | * Defined in entry.S | ||
21 | */ | ||
22 | extern void return_to_handler(void); | ||
23 | #endif /* __ASSEMBLY__ */ | ||
24 | |||
25 | #endif /* _ASM_PARISC_FTRACE_H */ | ||
diff --git a/arch/parisc/include/asm/page.h b/arch/parisc/include/asm/page.h index c3941f09a878..7bc5125d7d4c 100644 --- a/arch/parisc/include/asm/page.h +++ b/arch/parisc/include/asm/page.h | |||
@@ -36,16 +36,7 @@ void clear_user_page(void *page, unsigned long vaddr, struct page *pg); | |||
36 | */ | 36 | */ |
37 | #define STRICT_MM_TYPECHECKS | 37 | #define STRICT_MM_TYPECHECKS |
38 | #ifdef STRICT_MM_TYPECHECKS | 38 | #ifdef STRICT_MM_TYPECHECKS |
39 | typedef struct { unsigned long pte; | 39 | typedef struct { unsigned long pte; } pte_t; /* either 32 or 64bit */ |
40 | #if !defined(CONFIG_64BIT) | ||
41 | unsigned long future_flags; | ||
42 | /* XXX: it's possible to remove future_flags and change BITS_PER_PTE_ENTRY | ||
43 | to 2, but then strangely the identical 32bit kernel boots on a | ||
44 | c3000(pa20), but not any longer on a 715(pa11). | ||
45 | Still investigating... HelgeD. | ||
46 | */ | ||
47 | #endif | ||
48 | } pte_t; /* either 32 or 64bit */ | ||
49 | 40 | ||
50 | /* NOTE: even on 64 bits, these entries are __u32 because we allocate | 41 | /* NOTE: even on 64 bits, these entries are __u32 because we allocate |
51 | * the pmd and pgd in ZONE_DMA (i.e. under 4GB) */ | 42 | * the pmd and pgd in ZONE_DMA (i.e. under 4GB) */ |
@@ -111,7 +102,7 @@ extern int npmem_ranges; | |||
111 | #define BITS_PER_PMD_ENTRY 2 | 102 | #define BITS_PER_PMD_ENTRY 2 |
112 | #define BITS_PER_PGD_ENTRY 2 | 103 | #define BITS_PER_PGD_ENTRY 2 |
113 | #else | 104 | #else |
114 | #define BITS_PER_PTE_ENTRY 3 | 105 | #define BITS_PER_PTE_ENTRY 2 |
115 | #define BITS_PER_PMD_ENTRY 2 | 106 | #define BITS_PER_PMD_ENTRY 2 |
116 | #define BITS_PER_PGD_ENTRY BITS_PER_PMD_ENTRY | 107 | #define BITS_PER_PGD_ENTRY BITS_PER_PMD_ENTRY |
117 | #endif | 108 | #endif |
diff --git a/arch/parisc/include/asm/pdc.h b/arch/parisc/include/asm/pdc.h index 430f1aeea0b8..4ca510b3c6f8 100644 --- a/arch/parisc/include/asm/pdc.h +++ b/arch/parisc/include/asm/pdc.h | |||
@@ -49,6 +49,8 @@ | |||
49 | #define PDC_MODEL_CPU_ID 6 /* returns cpu-id (only newer machines!) */ | 49 | #define PDC_MODEL_CPU_ID 6 /* returns cpu-id (only newer machines!) */ |
50 | #define PDC_MODEL_CAPABILITIES 7 /* returns OS32/OS64-flags */ | 50 | #define PDC_MODEL_CAPABILITIES 7 /* returns OS32/OS64-flags */ |
51 | /* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */ | 51 | /* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */ |
52 | #define PDC_MODEL_OS64 (1 << 0) | ||
53 | #define PDC_MODEL_OS32 (1 << 1) | ||
52 | #define PDC_MODEL_IOPDIR_FDC (1 << 2) | 54 | #define PDC_MODEL_IOPDIR_FDC (1 << 2) |
53 | #define PDC_MODEL_NVA_MASK (3 << 4) | 55 | #define PDC_MODEL_NVA_MASK (3 << 4) |
54 | #define PDC_MODEL_NVA_SUPPORTED (0 << 4) | 56 | #define PDC_MODEL_NVA_SUPPORTED (0 << 4) |
@@ -341,6 +343,8 @@ | |||
341 | 343 | ||
342 | #ifdef __KERNEL__ | 344 | #ifdef __KERNEL__ |
343 | 345 | ||
346 | #include <asm/page.h> /* for __PAGE_OFFSET */ | ||
347 | |||
344 | extern int pdc_type; | 348 | extern int pdc_type; |
345 | 349 | ||
346 | /* Values for pdc_type */ | 350 | /* Values for pdc_type */ |
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index 470a4b88124d..a27d2e200fb2 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h | |||
@@ -50,11 +50,7 @@ | |||
50 | printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, (unsigned long)pgd_val(e)) | 50 | printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, (unsigned long)pgd_val(e)) |
51 | 51 | ||
52 | /* This is the size of the initially mapped kernel memory */ | 52 | /* This is the size of the initially mapped kernel memory */ |
53 | #ifdef CONFIG_64BIT | ||
54 | #define KERNEL_INITIAL_ORDER 24 /* 0 to 1<<24 = 16MB */ | 53 | #define KERNEL_INITIAL_ORDER 24 /* 0 to 1<<24 = 16MB */ |
55 | #else | ||
56 | #define KERNEL_INITIAL_ORDER 23 /* 0 to 1<<23 = 8MB */ | ||
57 | #endif | ||
58 | #define KERNEL_INITIAL_SIZE (1 << KERNEL_INITIAL_ORDER) | 54 | #define KERNEL_INITIAL_SIZE (1 << KERNEL_INITIAL_ORDER) |
59 | 55 | ||
60 | #if defined(CONFIG_64BIT) && defined(CONFIG_PARISC_PAGE_SIZE_4KB) | 56 | #if defined(CONFIG_64BIT) && defined(CONFIG_PARISC_PAGE_SIZE_4KB) |
@@ -91,16 +87,25 @@ | |||
91 | 87 | ||
92 | /* Definitions for 1st level */ | 88 | /* Definitions for 1st level */ |
93 | #define PGDIR_SHIFT (PMD_SHIFT + BITS_PER_PMD) | 89 | #define PGDIR_SHIFT (PMD_SHIFT + BITS_PER_PMD) |
90 | #if (PGDIR_SHIFT + PAGE_SHIFT + PGD_ORDER - BITS_PER_PGD_ENTRY) > BITS_PER_LONG | ||
91 | #define BITS_PER_PGD (BITS_PER_LONG - PGDIR_SHIFT) | ||
92 | #else | ||
94 | #define BITS_PER_PGD (PAGE_SHIFT + PGD_ORDER - BITS_PER_PGD_ENTRY) | 93 | #define BITS_PER_PGD (PAGE_SHIFT + PGD_ORDER - BITS_PER_PGD_ENTRY) |
94 | #endif | ||
95 | #define PGDIR_SIZE (1UL << PGDIR_SHIFT) | 95 | #define PGDIR_SIZE (1UL << PGDIR_SHIFT) |
96 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | 96 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) |
97 | #define PTRS_PER_PGD (1UL << BITS_PER_PGD) | 97 | #define PTRS_PER_PGD (1UL << BITS_PER_PGD) |
98 | #define USER_PTRS_PER_PGD PTRS_PER_PGD | 98 | #define USER_PTRS_PER_PGD PTRS_PER_PGD |
99 | 99 | ||
100 | #ifdef CONFIG_64BIT | ||
100 | #define MAX_ADDRBITS (PGDIR_SHIFT + BITS_PER_PGD) | 101 | #define MAX_ADDRBITS (PGDIR_SHIFT + BITS_PER_PGD) |
101 | #define MAX_ADDRESS (1UL << MAX_ADDRBITS) | 102 | #define MAX_ADDRESS (1UL << MAX_ADDRBITS) |
102 | |||
103 | #define SPACEID_SHIFT (MAX_ADDRBITS - 32) | 103 | #define SPACEID_SHIFT (MAX_ADDRBITS - 32) |
104 | #else | ||
105 | #define MAX_ADDRBITS (BITS_PER_LONG) | ||
106 | #define MAX_ADDRESS (1UL << MAX_ADDRBITS) | ||
107 | #define SPACEID_SHIFT 0 | ||
108 | #endif | ||
104 | 109 | ||
105 | /* This calculates the number of initial pages we need for the initial | 110 | /* This calculates the number of initial pages we need for the initial |
106 | * page tables */ | 111 | * page tables */ |
diff --git a/arch/parisc/include/asm/smp.h b/arch/parisc/include/asm/smp.h index 6ef4b7867b1b..21eb45a52629 100644 --- a/arch/parisc/include/asm/smp.h +++ b/arch/parisc/include/asm/smp.h | |||
@@ -29,7 +29,8 @@ extern void smp_send_reschedule(int cpu); | |||
29 | extern void smp_send_all_nop(void); | 29 | extern void smp_send_all_nop(void); |
30 | 30 | ||
31 | extern void arch_send_call_function_single_ipi(int cpu); | 31 | extern void arch_send_call_function_single_ipi(int cpu); |
32 | extern void arch_send_call_function_ipi(cpumask_t mask); | 32 | extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); |
33 | #define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask | ||
33 | 34 | ||
34 | #endif /* !ASSEMBLY */ | 35 | #endif /* !ASSEMBLY */ |
35 | 36 | ||
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile index 016d3fc4111c..67db0722e6ca 100644 --- a/arch/parisc/kernel/Makefile +++ b/arch/parisc/kernel/Makefile | |||
@@ -11,10 +11,25 @@ obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \ | |||
11 | process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \ | 11 | process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \ |
12 | topology.o | 12 | topology.o |
13 | 13 | ||
14 | ifdef CONFIG_FUNCTION_TRACER | ||
15 | # Do not profile debug and lowlevel utilities | ||
16 | CFLAGS_REMOVE_ftrace.o = -pg | ||
17 | CFLAGS_REMOVE_cache.o = -pg | ||
18 | CFLAGS_REMOVE_irq.o = -pg | ||
19 | CFLAGS_REMOVE_pacache.o = -pg | ||
20 | CFLAGS_REMOVE_perf.o = -pg | ||
21 | CFLAGS_REMOVE_traps.o = -pg | ||
22 | CFLAGS_REMOVE_unaligned.o = -pg | ||
23 | CFLAGS_REMOVE_unwind.o = -pg | ||
24 | endif | ||
25 | |||
14 | obj-$(CONFIG_SMP) += smp.o | 26 | obj-$(CONFIG_SMP) += smp.o |
15 | obj-$(CONFIG_PA11) += pci-dma.o | 27 | obj-$(CONFIG_PA11) += pci-dma.o |
16 | obj-$(CONFIG_PCI) += pci.o | 28 | obj-$(CONFIG_PCI) += pci.o |
17 | obj-$(CONFIG_MODULES) += module.o | 29 | obj-$(CONFIG_MODULES) += module.o |
18 | obj-$(CONFIG_64BIT) += binfmt_elf32.o sys_parisc32.o signal32.o | 30 | obj-$(CONFIG_64BIT) += binfmt_elf32.o sys_parisc32.o signal32.o |
31 | obj-$(CONFIG_STACKTRACE)+= stacktrace.o | ||
19 | # only supported for PCX-W/U in 64-bit mode at the moment | 32 | # only supported for PCX-W/U in 64-bit mode at the moment |
20 | obj-$(CONFIG_64BIT) += perf.o perf_asm.o | 33 | obj-$(CONFIG_64BIT) += perf.o perf_asm.o |
34 | obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o | ||
35 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o | ||
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 0db9fdcb7709..ae3e70cd1e14 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
@@ -505,6 +505,18 @@ | |||
505 | STREG \pte,0(\ptep) | 505 | STREG \pte,0(\ptep) |
506 | .endm | 506 | .endm |
507 | 507 | ||
508 | /* bitshift difference between a PFN (based on kernel's PAGE_SIZE) | ||
509 | * to a CPU TLB 4k PFN (4k => 12 bits to shift) */ | ||
510 | #define PAGE_ADD_SHIFT (PAGE_SHIFT-12) | ||
511 | |||
512 | /* Drop prot bits and convert to page addr for iitlbt and idtlbt */ | ||
513 | .macro convert_for_tlb_insert20 pte | ||
514 | extrd,u \pte,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\ | ||
515 | 64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte | ||
516 | depdi _PAGE_SIZE_ENCODING_DEFAULT,63,\ | ||
517 | (63-58)+PAGE_ADD_SHIFT,\pte | ||
518 | .endm | ||
519 | |||
508 | /* Convert the pte and prot to tlb insertion values. How | 520 | /* Convert the pte and prot to tlb insertion values. How |
509 | * this happens is quite subtle, read below */ | 521 | * this happens is quite subtle, read below */ |
510 | .macro make_insert_tlb spc,pte,prot | 522 | .macro make_insert_tlb spc,pte,prot |
@@ -544,8 +556,7 @@ | |||
544 | depi 1,12,1,\prot | 556 | depi 1,12,1,\prot |
545 | 557 | ||
546 | /* Drop prot bits and convert to page addr for iitlbt and idtlbt */ | 558 | /* Drop prot bits and convert to page addr for iitlbt and idtlbt */ |
547 | extrd,u \pte,(63-ASM_PFN_PTE_SHIFT)+(63-58),64-PAGE_SHIFT,\pte | 559 | convert_for_tlb_insert20 \pte |
548 | depdi _PAGE_SIZE_ENCODING_DEFAULT,63,63-58,\pte | ||
549 | .endm | 560 | .endm |
550 | 561 | ||
551 | /* Identical macro to make_insert_tlb above, except it | 562 | /* Identical macro to make_insert_tlb above, except it |
@@ -563,8 +574,8 @@ | |||
563 | 574 | ||
564 | /* Get rid of prot bits and convert to page addr for iitlba */ | 575 | /* Get rid of prot bits and convert to page addr for iitlba */ |
565 | 576 | ||
566 | depi _PAGE_SIZE_ENCODING_DEFAULT,31,ASM_PFN_PTE_SHIFT,\pte | 577 | depi 0,31,ASM_PFN_PTE_SHIFT,\pte |
567 | extru \pte,24,25,\pte | 578 | SHRREG \pte,(ASM_PFN_PTE_SHIFT-(31-26)),\pte |
568 | .endm | 579 | .endm |
569 | 580 | ||
570 | /* This is for ILP32 PA2.0 only. The TLB insertion needs | 581 | /* This is for ILP32 PA2.0 only. The TLB insertion needs |
@@ -1244,10 +1255,9 @@ nadtlb_check_flush_20w: | |||
1244 | depdi,z 7,7,3,prot | 1255 | depdi,z 7,7,3,prot |
1245 | depdi 1,10,1,prot | 1256 | depdi 1,10,1,prot |
1246 | 1257 | ||
1247 | /* Get rid of prot bits and convert to page addr for idtlbt */ | 1258 | /* Drop prot bits from pte and convert to page addr for idtlbt */ |
1259 | convert_for_tlb_insert20 pte | ||
1248 | 1260 | ||
1249 | depdi 0,63,12,pte | ||
1250 | extrd,u pte,56,52,pte | ||
1251 | idtlbt pte,prot | 1261 | idtlbt pte,prot |
1252 | 1262 | ||
1253 | rfir | 1263 | rfir |
@@ -1337,8 +1347,8 @@ nadtlb_check_flush_11: | |||
1337 | 1347 | ||
1338 | /* Get rid of prot bits and convert to page addr for idtlba */ | 1348 | /* Get rid of prot bits and convert to page addr for idtlba */ |
1339 | 1349 | ||
1340 | depi 0,31,12,pte | 1350 | depi 0,31,ASM_PFN_PTE_SHIFT,pte |
1341 | extru pte,24,25,pte | 1351 | SHRREG pte,(ASM_PFN_PTE_SHIFT-(31-26)),pte |
1342 | 1352 | ||
1343 | mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ | 1353 | mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ |
1344 | mtsp spc,%sr1 | 1354 | mtsp spc,%sr1 |
@@ -1403,10 +1413,9 @@ nadtlb_check_flush_20: | |||
1403 | depdi,z 7,7,3,prot | 1413 | depdi,z 7,7,3,prot |
1404 | depdi 1,10,1,prot | 1414 | depdi 1,10,1,prot |
1405 | 1415 | ||
1406 | /* Get rid of prot bits and convert to page addr for idtlbt */ | 1416 | /* Drop prot bits from pte and convert to page addr for idtlbt */ |
1417 | convert_for_tlb_insert20 pte | ||
1407 | 1418 | ||
1408 | depdi 0,63,12,pte | ||
1409 | extrd,u pte,56,32,pte | ||
1410 | idtlbt pte,prot | 1419 | idtlbt pte,prot |
1411 | 1420 | ||
1412 | rfir | 1421 | rfir |
@@ -2176,6 +2185,33 @@ syscall_do_resched: | |||
2176 | ENDPROC(syscall_exit) | 2185 | ENDPROC(syscall_exit) |
2177 | 2186 | ||
2178 | 2187 | ||
2188 | #ifdef CONFIG_FUNCTION_TRACER | ||
2189 | .import ftrace_function_trampoline,code | ||
2190 | ENTRY(_mcount) | ||
2191 | copy %r3, %arg2 | ||
2192 | b ftrace_function_trampoline | ||
2193 | nop | ||
2194 | ENDPROC(_mcount) | ||
2195 | |||
2196 | ENTRY(return_to_handler) | ||
2197 | load32 return_trampoline, %rp | ||
2198 | copy %ret0, %arg0 | ||
2199 | copy %ret1, %arg1 | ||
2200 | b ftrace_return_to_handler | ||
2201 | nop | ||
2202 | return_trampoline: | ||
2203 | copy %ret0, %rp | ||
2204 | copy %r23, %ret0 | ||
2205 | copy %r24, %ret1 | ||
2206 | |||
2207 | .globl ftrace_stub | ||
2208 | ftrace_stub: | ||
2209 | bv %r0(%rp) | ||
2210 | nop | ||
2211 | ENDPROC(return_to_handler) | ||
2212 | #endif /* CONFIG_FUNCTION_TRACER */ | ||
2213 | |||
2214 | |||
2179 | get_register: | 2215 | get_register: |
2180 | /* | 2216 | /* |
2181 | * get_register is used by the non access tlb miss handlers to | 2217 | * get_register is used by the non access tlb miss handlers to |
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index f6d241238a78..4c247e02d9b1 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c | |||
@@ -527,7 +527,11 @@ int pdc_model_capabilities(unsigned long *capabilities) | |||
527 | pdc_result[0] = 0; /* preset zero (call may not be implemented!) */ | 527 | pdc_result[0] = 0; /* preset zero (call may not be implemented!) */ |
528 | retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0); | 528 | retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0); |
529 | convert_to_wide(pdc_result); | 529 | convert_to_wide(pdc_result); |
530 | *capabilities = pdc_result[0]; | 530 | if (retval == PDC_OK) { |
531 | *capabilities = pdc_result[0]; | ||
532 | } else { | ||
533 | *capabilities = PDC_MODEL_OS32; | ||
534 | } | ||
531 | spin_unlock_irqrestore(&pdc_lock, flags); | 535 | spin_unlock_irqrestore(&pdc_lock, flags); |
532 | 536 | ||
533 | return retval; | 537 | return retval; |
diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c new file mode 100644 index 000000000000..9877372ffdba --- /dev/null +++ b/arch/parisc/kernel/ftrace.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /* | ||
2 | * Code for tracing calls in Linux kernel. | ||
3 | * Copyright (C) 2009 Helge Deller <deller@gmx.de> | ||
4 | * | ||
5 | * based on code for x86 which is: | ||
6 | * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> | ||
7 | * | ||
8 | * future possible enhancements: | ||
9 | * - add CONFIG_DYNAMIC_FTRACE | ||
10 | * - add CONFIG_STACK_TRACER | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/ftrace.h> | ||
15 | |||
16 | #include <asm/sections.h> | ||
17 | #include <asm/ftrace.h> | ||
18 | |||
19 | |||
20 | |||
21 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
22 | |||
23 | /* Add a function return address to the trace stack on thread info.*/ | ||
24 | static int push_return_trace(unsigned long ret, unsigned long long time, | ||
25 | unsigned long func, int *depth) | ||
26 | { | ||
27 | int index; | ||
28 | |||
29 | if (!current->ret_stack) | ||
30 | return -EBUSY; | ||
31 | |||
32 | /* The return trace stack is full */ | ||
33 | if (current->curr_ret_stack == FTRACE_RETFUNC_DEPTH - 1) { | ||
34 | atomic_inc(¤t->trace_overrun); | ||
35 | return -EBUSY; | ||
36 | } | ||
37 | |||
38 | index = ++current->curr_ret_stack; | ||
39 | barrier(); | ||
40 | current->ret_stack[index].ret = ret; | ||
41 | current->ret_stack[index].func = func; | ||
42 | current->ret_stack[index].calltime = time; | ||
43 | *depth = index; | ||
44 | |||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | /* Retrieve a function return address to the trace stack on thread info.*/ | ||
49 | static void pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret) | ||
50 | { | ||
51 | int index; | ||
52 | |||
53 | index = current->curr_ret_stack; | ||
54 | |||
55 | if (unlikely(index < 0)) { | ||
56 | ftrace_graph_stop(); | ||
57 | WARN_ON(1); | ||
58 | /* Might as well panic, otherwise we have no where to go */ | ||
59 | *ret = (unsigned long) | ||
60 | dereference_function_descriptor(&panic); | ||
61 | return; | ||
62 | } | ||
63 | |||
64 | *ret = current->ret_stack[index].ret; | ||
65 | trace->func = current->ret_stack[index].func; | ||
66 | trace->calltime = current->ret_stack[index].calltime; | ||
67 | trace->overrun = atomic_read(¤t->trace_overrun); | ||
68 | trace->depth = index; | ||
69 | barrier(); | ||
70 | current->curr_ret_stack--; | ||
71 | |||
72 | } | ||
73 | |||
74 | /* | ||
75 | * Send the trace to the ring-buffer. | ||
76 | * @return the original return address. | ||
77 | */ | ||
78 | unsigned long ftrace_return_to_handler(unsigned long retval0, | ||
79 | unsigned long retval1) | ||
80 | { | ||
81 | struct ftrace_graph_ret trace; | ||
82 | unsigned long ret; | ||
83 | |||
84 | pop_return_trace(&trace, &ret); | ||
85 | trace.rettime = cpu_clock(raw_smp_processor_id()); | ||
86 | ftrace_graph_return(&trace); | ||
87 | |||
88 | if (unlikely(!ret)) { | ||
89 | ftrace_graph_stop(); | ||
90 | WARN_ON(1); | ||
91 | /* Might as well panic. What else to do? */ | ||
92 | ret = (unsigned long) | ||
93 | dereference_function_descriptor(&panic); | ||
94 | } | ||
95 | |||
96 | /* HACK: we hand over the old functions' return values | ||
97 | in %r23 and %r24. Assembly in entry.S will take care | ||
98 | and move those to their final registers %ret0 and %ret1 */ | ||
99 | asm( "copy %0, %%r23 \n\t" | ||
100 | "copy %1, %%r24 \n" : : "r" (retval0), "r" (retval1) ); | ||
101 | |||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * Hook the return address and push it in the stack of return addrs | ||
107 | * in current thread info. | ||
108 | */ | ||
109 | void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) | ||
110 | { | ||
111 | unsigned long old; | ||
112 | unsigned long long calltime; | ||
113 | struct ftrace_graph_ent trace; | ||
114 | |||
115 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) | ||
116 | return; | ||
117 | |||
118 | old = *parent; | ||
119 | *parent = (unsigned long) | ||
120 | dereference_function_descriptor(&return_to_handler); | ||
121 | |||
122 | if (unlikely(!__kernel_text_address(old))) { | ||
123 | ftrace_graph_stop(); | ||
124 | *parent = old; | ||
125 | WARN_ON(1); | ||
126 | return; | ||
127 | } | ||
128 | |||
129 | calltime = cpu_clock(raw_smp_processor_id()); | ||
130 | |||
131 | if (push_return_trace(old, calltime, | ||
132 | self_addr, &trace.depth) == -EBUSY) { | ||
133 | *parent = old; | ||
134 | return; | ||
135 | } | ||
136 | |||
137 | trace.func = self_addr; | ||
138 | |||
139 | /* Only trace if the calling function expects to */ | ||
140 | if (!ftrace_graph_entry(&trace)) { | ||
141 | current->curr_ret_stack--; | ||
142 | *parent = old; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | ||
147 | |||
148 | |||
149 | void ftrace_function_trampoline(unsigned long parent, | ||
150 | unsigned long self_addr, | ||
151 | unsigned long org_sp_gr3) | ||
152 | { | ||
153 | extern ftrace_func_t ftrace_trace_function; | ||
154 | |||
155 | if (function_trace_stop) | ||
156 | return; | ||
157 | |||
158 | if (ftrace_trace_function != ftrace_stub) { | ||
159 | ftrace_trace_function(parent, self_addr); | ||
160 | return; | ||
161 | } | ||
162 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
163 | if (ftrace_graph_entry && ftrace_graph_return) { | ||
164 | unsigned long sp; | ||
165 | unsigned long *parent_rp; | ||
166 | |||
167 | asm volatile ("copy %%r30, %0" : "=r"(sp)); | ||
168 | /* sanity check: is stack pointer which we got from | ||
169 | assembler function in entry.S in a reasonable | ||
170 | range compared to current stack pointer? */ | ||
171 | if ((sp - org_sp_gr3) > 0x400) | ||
172 | return; | ||
173 | |||
174 | /* calculate pointer to %rp in stack */ | ||
175 | parent_rp = (unsigned long *) org_sp_gr3 - 0x10; | ||
176 | /* sanity check: parent_rp should hold parent */ | ||
177 | if (*parent_rp != parent) | ||
178 | return; | ||
179 | |||
180 | prepare_ftrace_return(parent_rp, self_addr); | ||
181 | return; | ||
182 | } | ||
183 | #endif | ||
184 | } | ||
185 | |||
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 1c740f5cbd63..4ea4229d765c 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c | |||
@@ -311,12 +311,12 @@ unsigned long txn_alloc_addr(unsigned int virt_irq) | |||
311 | next_cpu++; /* assign to "next" CPU we want this bugger on */ | 311 | next_cpu++; /* assign to "next" CPU we want this bugger on */ |
312 | 312 | ||
313 | /* validate entry */ | 313 | /* validate entry */ |
314 | while ((next_cpu < NR_CPUS) && | 314 | while ((next_cpu < nr_cpu_ids) && |
315 | (!per_cpu(cpu_data, next_cpu).txn_addr || | 315 | (!per_cpu(cpu_data, next_cpu).txn_addr || |
316 | !cpu_online(next_cpu))) | 316 | !cpu_online(next_cpu))) |
317 | next_cpu++; | 317 | next_cpu++; |
318 | 318 | ||
319 | if (next_cpu >= NR_CPUS) | 319 | if (next_cpu >= nr_cpu_ids) |
320 | next_cpu = 0; /* nothing else, assign monarch */ | 320 | next_cpu = 0; /* nothing else, assign monarch */ |
321 | 321 | ||
322 | return txn_affinity_addr(virt_irq, next_cpu); | 322 | return txn_affinity_addr(virt_irq, next_cpu); |
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index 9013243cecca..ecd1c5024447 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c | |||
@@ -61,9 +61,7 @@ | |||
61 | #include <linux/string.h> | 61 | #include <linux/string.h> |
62 | #include <linux/kernel.h> | 62 | #include <linux/kernel.h> |
63 | #include <linux/bug.h> | 63 | #include <linux/bug.h> |
64 | #include <linux/uaccess.h> | ||
65 | 64 | ||
66 | #include <asm/sections.h> | ||
67 | #include <asm/unwind.h> | 65 | #include <asm/unwind.h> |
68 | 66 | ||
69 | #if 0 | 67 | #if 0 |
@@ -115,8 +113,6 @@ struct got_entry { | |||
115 | Elf32_Addr addr; | 113 | Elf32_Addr addr; |
116 | }; | 114 | }; |
117 | 115 | ||
118 | #define Elf_Fdesc Elf32_Fdesc | ||
119 | |||
120 | struct stub_entry { | 116 | struct stub_entry { |
121 | Elf32_Word insns[2]; /* each stub entry has two insns */ | 117 | Elf32_Word insns[2]; /* each stub entry has two insns */ |
122 | }; | 118 | }; |
@@ -125,8 +121,6 @@ struct got_entry { | |||
125 | Elf64_Addr addr; | 121 | Elf64_Addr addr; |
126 | }; | 122 | }; |
127 | 123 | ||
128 | #define Elf_Fdesc Elf64_Fdesc | ||
129 | |||
130 | struct stub_entry { | 124 | struct stub_entry { |
131 | Elf64_Word insns[4]; /* each stub entry has four insns */ | 125 | Elf64_Word insns[4]; /* each stub entry has four insns */ |
132 | }; | 126 | }; |
@@ -916,15 +910,3 @@ void module_arch_cleanup(struct module *mod) | |||
916 | deregister_unwind_table(mod); | 910 | deregister_unwind_table(mod); |
917 | module_bug_cleanup(mod); | 911 | module_bug_cleanup(mod); |
918 | } | 912 | } |
919 | |||
920 | #ifdef CONFIG_64BIT | ||
921 | void *dereference_function_descriptor(void *ptr) | ||
922 | { | ||
923 | Elf64_Fdesc *desc = ptr; | ||
924 | void *p; | ||
925 | |||
926 | if (!probe_kernel_address(&desc->addr, p)) | ||
927 | ptr = p; | ||
928 | return ptr; | ||
929 | } | ||
930 | #endif | ||
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index 0eecfbbc59cd..df653663d3db 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c | |||
@@ -153,5 +153,10 @@ EXPORT_SYMBOL(node_data); | |||
153 | EXPORT_SYMBOL(pfnnid_map); | 153 | EXPORT_SYMBOL(pfnnid_map); |
154 | #endif | 154 | #endif |
155 | 155 | ||
156 | #ifdef CONFIG_FUNCTION_TRACER | ||
157 | extern void _mcount(void); | ||
158 | EXPORT_SYMBOL(_mcount); | ||
159 | #endif | ||
160 | |||
156 | /* from pacache.S -- needed for copy_page */ | 161 | /* from pacache.S -- needed for copy_page */ |
157 | EXPORT_SYMBOL(copy_user_page_asm); | 162 | EXPORT_SYMBOL(copy_user_page_asm); |
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 8aa591ed9127..6f69101f90bb 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c | |||
@@ -46,14 +46,15 @@ | |||
46 | #include <linux/stddef.h> | 46 | #include <linux/stddef.h> |
47 | #include <linux/unistd.h> | 47 | #include <linux/unistd.h> |
48 | #include <linux/kallsyms.h> | 48 | #include <linux/kallsyms.h> |
49 | #include <linux/uaccess.h> | ||
49 | 50 | ||
50 | #include <asm/io.h> | 51 | #include <asm/io.h> |
51 | #include <asm/asm-offsets.h> | 52 | #include <asm/asm-offsets.h> |
52 | #include <asm/pdc.h> | 53 | #include <asm/pdc.h> |
53 | #include <asm/pdc_chassis.h> | 54 | #include <asm/pdc_chassis.h> |
54 | #include <asm/pgalloc.h> | 55 | #include <asm/pgalloc.h> |
55 | #include <asm/uaccess.h> | ||
56 | #include <asm/unwind.h> | 56 | #include <asm/unwind.h> |
57 | #include <asm/sections.h> | ||
57 | 58 | ||
58 | /* | 59 | /* |
59 | * The idle thread. There's no useful work to be | 60 | * The idle thread. There's no useful work to be |
@@ -231,8 +232,8 @@ sys_clone(unsigned long clone_flags, unsigned long usp, | |||
231 | 232 | ||
232 | However, these last 3 args are only examined | 233 | However, these last 3 args are only examined |
233 | if the proper flags are set. */ | 234 | if the proper flags are set. */ |
234 | int __user *child_tidptr; | 235 | int __user *parent_tidptr = (int __user *)regs->gr[24]; |
235 | int __user *parent_tidptr; | 236 | int __user *child_tidptr = (int __user *)regs->gr[22]; |
236 | 237 | ||
237 | /* usp must be word aligned. This also prevents users from | 238 | /* usp must be word aligned. This also prevents users from |
238 | * passing in the value 1 (which is the signal for a special | 239 | * passing in the value 1 (which is the signal for a special |
@@ -243,16 +244,6 @@ sys_clone(unsigned long clone_flags, unsigned long usp, | |||
243 | if (usp == 0) | 244 | if (usp == 0) |
244 | usp = regs->gr[30]; | 245 | usp = regs->gr[30]; |
245 | 246 | ||
246 | if (clone_flags & CLONE_PARENT_SETTID) | ||
247 | parent_tidptr = (int __user *)regs->gr[24]; | ||
248 | else | ||
249 | parent_tidptr = NULL; | ||
250 | |||
251 | if (clone_flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) | ||
252 | child_tidptr = (int __user *)regs->gr[22]; | ||
253 | else | ||
254 | child_tidptr = NULL; | ||
255 | |||
256 | return do_fork(clone_flags, usp, regs, 0, parent_tidptr, child_tidptr); | 247 | return do_fork(clone_flags, usp, regs, 0, parent_tidptr, child_tidptr); |
257 | } | 248 | } |
258 | 249 | ||
@@ -400,3 +391,15 @@ get_wchan(struct task_struct *p) | |||
400 | } while (count++ < 16); | 391 | } while (count++ < 16); |
401 | return 0; | 392 | return 0; |
402 | } | 393 | } |
394 | |||
395 | #ifdef CONFIG_64BIT | ||
396 | void *dereference_function_descriptor(void *ptr) | ||
397 | { | ||
398 | Elf64_Fdesc *desc = ptr; | ||
399 | void *p; | ||
400 | |||
401 | if (!probe_kernel_address(&desc->addr, p)) | ||
402 | ptr = p; | ||
403 | return ptr; | ||
404 | } | ||
405 | #endif | ||
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index ecb609342feb..e09d0f7fb6b0 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c | |||
@@ -100,8 +100,8 @@ static int __cpuinit processor_probe(struct parisc_device *dev) | |||
100 | struct cpuinfo_parisc *p; | 100 | struct cpuinfo_parisc *p; |
101 | 101 | ||
102 | #ifdef CONFIG_SMP | 102 | #ifdef CONFIG_SMP |
103 | if (num_online_cpus() >= NR_CPUS) { | 103 | if (num_online_cpus() >= nr_cpu_ids) { |
104 | printk(KERN_INFO "num_online_cpus() >= NR_CPUS\n"); | 104 | printk(KERN_INFO "num_online_cpus() >= nr_cpu_ids\n"); |
105 | return 1; | 105 | return 1; |
106 | } | 106 | } |
107 | #else | 107 | #else |
@@ -214,7 +214,7 @@ static int __cpuinit processor_probe(struct parisc_device *dev) | |||
214 | */ | 214 | */ |
215 | #ifdef CONFIG_SMP | 215 | #ifdef CONFIG_SMP |
216 | if (cpuid) { | 216 | if (cpuid) { |
217 | cpu_set(cpuid, cpu_present_map); | 217 | set_cpu_present(cpuid, true); |
218 | cpu_up(cpuid); | 218 | cpu_up(cpuid); |
219 | } | 219 | } |
220 | #endif | 220 | #endif |
@@ -364,6 +364,13 @@ show_cpuinfo (struct seq_file *m, void *v) | |||
364 | boot_cpu_data.cpu_hz / 1000000, | 364 | boot_cpu_data.cpu_hz / 1000000, |
365 | boot_cpu_data.cpu_hz % 1000000 ); | 365 | boot_cpu_data.cpu_hz % 1000000 ); |
366 | 366 | ||
367 | seq_printf(m, "capabilities\t:"); | ||
368 | if (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS32) | ||
369 | seq_printf(m, " os32"); | ||
370 | if (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS64) | ||
371 | seq_printf(m, " os64"); | ||
372 | seq_printf(m, "\n"); | ||
373 | |||
367 | seq_printf(m, "model\t\t: %s\n" | 374 | seq_printf(m, "model\t\t: %s\n" |
368 | "model name\t: %s\n", | 375 | "model name\t: %s\n", |
369 | boot_cpu_data.pdc.sys_model_name, | 376 | boot_cpu_data.pdc.sys_model_name, |
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 9995d7ed5819..1fd0f0cec037 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/err.h> | 31 | #include <linux/err.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/bitops.h> | 33 | #include <linux/bitops.h> |
34 | #include <linux/ftrace.h> | ||
34 | 35 | ||
35 | #include <asm/system.h> | 36 | #include <asm/system.h> |
36 | #include <asm/atomic.h> | 37 | #include <asm/atomic.h> |
@@ -113,14 +114,14 @@ halt_processor(void) | |||
113 | { | 114 | { |
114 | /* REVISIT : redirect I/O Interrupts to another CPU? */ | 115 | /* REVISIT : redirect I/O Interrupts to another CPU? */ |
115 | /* REVISIT : does PM *know* this CPU isn't available? */ | 116 | /* REVISIT : does PM *know* this CPU isn't available? */ |
116 | cpu_clear(smp_processor_id(), cpu_online_map); | 117 | set_cpu_online(smp_processor_id(), false); |
117 | local_irq_disable(); | 118 | local_irq_disable(); |
118 | for (;;) | 119 | for (;;) |
119 | ; | 120 | ; |
120 | } | 121 | } |
121 | 122 | ||
122 | 123 | ||
123 | irqreturn_t | 124 | irqreturn_t __irq_entry |
124 | ipi_interrupt(int irq, void *dev_id) | 125 | ipi_interrupt(int irq, void *dev_id) |
125 | { | 126 | { |
126 | int this_cpu = smp_processor_id(); | 127 | int this_cpu = smp_processor_id(); |
@@ -214,11 +215,11 @@ ipi_send(int cpu, enum ipi_message_type op) | |||
214 | } | 215 | } |
215 | 216 | ||
216 | static void | 217 | static void |
217 | send_IPI_mask(cpumask_t mask, enum ipi_message_type op) | 218 | send_IPI_mask(const struct cpumask *mask, enum ipi_message_type op) |
218 | { | 219 | { |
219 | int cpu; | 220 | int cpu; |
220 | 221 | ||
221 | for_each_cpu_mask(cpu, mask) | 222 | for_each_cpu(cpu, mask) |
222 | ipi_send(cpu, op); | 223 | ipi_send(cpu, op); |
223 | } | 224 | } |
224 | 225 | ||
@@ -257,7 +258,7 @@ smp_send_all_nop(void) | |||
257 | send_IPI_allbutself(IPI_NOP); | 258 | send_IPI_allbutself(IPI_NOP); |
258 | } | 259 | } |
259 | 260 | ||
260 | void arch_send_call_function_ipi(cpumask_t mask) | 261 | void arch_send_call_function_ipi_mask(const struct cpumask *mask) |
261 | { | 262 | { |
262 | send_IPI_mask(mask, IPI_CALL_FUNC); | 263 | send_IPI_mask(mask, IPI_CALL_FUNC); |
263 | } | 264 | } |
@@ -296,13 +297,14 @@ smp_cpu_init(int cpunum) | |||
296 | mb(); | 297 | mb(); |
297 | 298 | ||
298 | /* Well, support 2.4 linux scheme as well. */ | 299 | /* Well, support 2.4 linux scheme as well. */ |
299 | if (cpu_test_and_set(cpunum, cpu_online_map)) | 300 | if (cpu_isset(cpunum, cpu_online_map)) |
300 | { | 301 | { |
301 | extern void machine_halt(void); /* arch/parisc.../process.c */ | 302 | extern void machine_halt(void); /* arch/parisc.../process.c */ |
302 | 303 | ||
303 | printk(KERN_CRIT "CPU#%d already initialized!\n", cpunum); | 304 | printk(KERN_CRIT "CPU#%d already initialized!\n", cpunum); |
304 | machine_halt(); | 305 | machine_halt(); |
305 | } | 306 | } |
307 | set_cpu_online(cpunum, true); | ||
306 | 308 | ||
307 | /* Initialise the idle task for this CPU */ | 309 | /* Initialise the idle task for this CPU */ |
308 | atomic_inc(&init_mm.mm_count); | 310 | atomic_inc(&init_mm.mm_count); |
@@ -424,8 +426,8 @@ void __init smp_prepare_boot_cpu(void) | |||
424 | /* Setup BSP mappings */ | 426 | /* Setup BSP mappings */ |
425 | printk(KERN_INFO "SMP: bootstrap CPU ID is %d\n", bootstrap_processor); | 427 | printk(KERN_INFO "SMP: bootstrap CPU ID is %d\n", bootstrap_processor); |
426 | 428 | ||
427 | cpu_set(bootstrap_processor, cpu_online_map); | 429 | set_cpu_online(bootstrap_processor, true); |
428 | cpu_set(bootstrap_processor, cpu_present_map); | 430 | set_cpu_present(bootstrap_processor, true); |
429 | } | 431 | } |
430 | 432 | ||
431 | 433 | ||
@@ -436,8 +438,7 @@ void __init smp_prepare_boot_cpu(void) | |||
436 | */ | 438 | */ |
437 | void __init smp_prepare_cpus(unsigned int max_cpus) | 439 | void __init smp_prepare_cpus(unsigned int max_cpus) |
438 | { | 440 | { |
439 | cpus_clear(cpu_present_map); | 441 | init_cpu_present(cpumask_of(0)); |
440 | cpu_set(0, cpu_present_map); | ||
441 | 442 | ||
442 | parisc_max_cpus = max_cpus; | 443 | parisc_max_cpus = max_cpus; |
443 | if (!max_cpus) | 444 | if (!max_cpus) |
diff --git a/arch/parisc/kernel/stacktrace.c b/arch/parisc/kernel/stacktrace.c new file mode 100644 index 000000000000..2fe914c5f533 --- /dev/null +++ b/arch/parisc/kernel/stacktrace.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Stack trace management functions | ||
3 | * | ||
4 | * Copyright (C) 2009 Helge Deller <deller@gmx.de> | ||
5 | * based on arch/x86/kernel/stacktrace.c by Ingo Molnar <mingo@redhat.com> | ||
6 | * and parisc unwind functions by Randolph Chung <tausq@debian.org> | ||
7 | * | ||
8 | * TODO: Userspace stacktrace (CONFIG_USER_STACKTRACE_SUPPORT) | ||
9 | */ | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/stacktrace.h> | ||
12 | |||
13 | #include <asm/unwind.h> | ||
14 | |||
15 | static void dump_trace(struct task_struct *task, struct stack_trace *trace) | ||
16 | { | ||
17 | struct unwind_frame_info info; | ||
18 | |||
19 | /* initialize unwind info */ | ||
20 | if (task == current) { | ||
21 | unsigned long sp; | ||
22 | struct pt_regs r; | ||
23 | HERE: | ||
24 | asm volatile ("copy %%r30, %0" : "=r"(sp)); | ||
25 | memset(&r, 0, sizeof(struct pt_regs)); | ||
26 | r.iaoq[0] = (unsigned long)&&HERE; | ||
27 | r.gr[2] = (unsigned long)__builtin_return_address(0); | ||
28 | r.gr[30] = sp; | ||
29 | unwind_frame_init(&info, task, &r); | ||
30 | } else { | ||
31 | unwind_frame_init_from_blocked_task(&info, task); | ||
32 | } | ||
33 | |||
34 | /* unwind stack and save entries in stack_trace struct */ | ||
35 | trace->nr_entries = 0; | ||
36 | while (trace->nr_entries < trace->max_entries) { | ||
37 | if (unwind_once(&info) < 0 || info.ip == 0) | ||
38 | break; | ||
39 | |||
40 | if (__kernel_text_address(info.ip)) | ||
41 | trace->entries[trace->nr_entries++] = info.ip; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | |||
46 | /* | ||
47 | * Save stack-backtrace addresses into a stack_trace buffer. | ||
48 | */ | ||
49 | void save_stack_trace(struct stack_trace *trace) | ||
50 | { | ||
51 | dump_trace(current, trace); | ||
52 | if (trace->nr_entries < trace->max_entries) | ||
53 | trace->entries[trace->nr_entries++] = ULONG_MAX; | ||
54 | } | ||
55 | EXPORT_SYMBOL_GPL(save_stack_trace); | ||
56 | |||
57 | void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) | ||
58 | { | ||
59 | dump_trace(tsk, trace); | ||
60 | if (trace->nr_entries < trace->max_entries) | ||
61 | trace->entries[trace->nr_entries++] = ULONG_MAX; | ||
62 | } | ||
63 | EXPORT_SYMBOL_GPL(save_stack_trace_tsk); | ||
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 69b6eebc466e..59fc1a43ec3e 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S | |||
@@ -365,17 +365,51 @@ tracesys_sigexit: | |||
365 | 365 | ||
366 | 366 | ||
367 | /********************************************************* | 367 | /********************************************************* |
368 | Light-weight-syscall code | 368 | 32/64-bit Light-Weight-Syscall ABI |
369 | 369 | ||
370 | r20 - lws number | 370 | * - Indicates a hint for userspace inline asm |
371 | r26,r25,r24,r23,r22 - Input registers | 371 | implementations. |
372 | r28 - Function return register | ||
373 | r21 - Error code. | ||
374 | 372 | ||
375 | Scracth: Any of the above that aren't being | 373 | Syscall number (caller-saves) |
376 | currently used, including r1. | 374 | - %r20 |
375 | * In asm clobber. | ||
377 | 376 | ||
378 | Return pointer: r31 (Not usable) | 377 | Argument registers (caller-saves) |
378 | - %r26, %r25, %r24, %r23, %r22 | ||
379 | * In asm input. | ||
380 | |||
381 | Return registers (caller-saves) | ||
382 | - %r28 (return), %r21 (errno) | ||
383 | * In asm output. | ||
384 | |||
385 | Caller-saves registers | ||
386 | - %r1, %r27, %r29 | ||
387 | - %r2 (return pointer) | ||
388 | - %r31 (ble link register) | ||
389 | * In asm clobber. | ||
390 | |||
391 | Callee-saves registers | ||
392 | - %r3-%r18 | ||
393 | - %r30 (stack pointer) | ||
394 | * Not in asm clobber. | ||
395 | |||
396 | If userspace is 32-bit: | ||
397 | Callee-saves registers | ||
398 | - %r19 (32-bit PIC register) | ||
399 | |||
400 | Differences from 32-bit calling convention: | ||
401 | - Syscall number in %r20 | ||
402 | - Additional argument register %r22 (arg4) | ||
403 | - Callee-saves %r19. | ||
404 | |||
405 | If userspace is 64-bit: | ||
406 | Callee-saves registers | ||
407 | - %r27 (64-bit PIC register) | ||
408 | |||
409 | Differences from 64-bit calling convention: | ||
410 | - Syscall number in %r20 | ||
411 | - Additional argument register %r22 (arg4) | ||
412 | - Callee-saves %r27. | ||
379 | 413 | ||
380 | Error codes returned by entry path: | 414 | Error codes returned by entry path: |
381 | 415 | ||
@@ -473,7 +507,8 @@ lws_compare_and_swap64: | |||
473 | b,n lws_compare_and_swap | 507 | b,n lws_compare_and_swap |
474 | #else | 508 | #else |
475 | /* If we are not a 64-bit kernel, then we don't | 509 | /* If we are not a 64-bit kernel, then we don't |
476 | * implement having 64-bit input registers | 510 | * have 64-bit input registers, and calling |
511 | * the 64-bit LWS CAS returns ENOSYS. | ||
477 | */ | 512 | */ |
478 | b,n lws_exit_nosys | 513 | b,n lws_exit_nosys |
479 | #endif | 514 | #endif |
@@ -635,12 +670,15 @@ END(sys_call_table64) | |||
635 | /* | 670 | /* |
636 | All light-weight-syscall atomic operations | 671 | All light-weight-syscall atomic operations |
637 | will use this set of locks | 672 | will use this set of locks |
673 | |||
674 | NOTE: The lws_lock_start symbol must be | ||
675 | at least 16-byte aligned for safe use | ||
676 | with ldcw. | ||
638 | */ | 677 | */ |
639 | .section .data | 678 | .section .data |
640 | .align PAGE_SIZE | 679 | .align PAGE_SIZE |
641 | ENTRY(lws_lock_start) | 680 | ENTRY(lws_lock_start) |
642 | /* lws locks */ | 681 | /* lws locks */ |
643 | .align 16 | ||
644 | .rept 16 | 682 | .rept 16 |
645 | /* Keep locks aligned at 16-bytes */ | 683 | /* Keep locks aligned at 16-bytes */ |
646 | .word 1 | 684 | .word 1 |
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index 86a99d02234f..d4dd05674c62 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/profile.h> | 24 | #include <linux/profile.h> |
25 | #include <linux/clocksource.h> | 25 | #include <linux/clocksource.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/ftrace.h> | ||
27 | 28 | ||
28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
29 | #include <asm/io.h> | 30 | #include <asm/io.h> |
@@ -53,7 +54,7 @@ static unsigned long clocktick __read_mostly; /* timer cycles per tick */ | |||
53 | * held off for an arbitrarily long period of time by interrupts being | 54 | * held off for an arbitrarily long period of time by interrupts being |
54 | * disabled, so we may miss one or more ticks. | 55 | * disabled, so we may miss one or more ticks. |
55 | */ | 56 | */ |
56 | irqreturn_t timer_interrupt(int irq, void *dev_id) | 57 | irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id) |
57 | { | 58 | { |
58 | unsigned long now; | 59 | unsigned long now; |
59 | unsigned long next_tick; | 60 | unsigned long next_tick; |
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index ba658d2086f7..c32f5d6d778e 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c | |||
@@ -247,6 +247,8 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) | |||
247 | 247 | ||
248 | oops_in_progress = 1; | 248 | oops_in_progress = 1; |
249 | 249 | ||
250 | oops_enter(); | ||
251 | |||
250 | /* Amuse the user in a SPARC fashion */ | 252 | /* Amuse the user in a SPARC fashion */ |
251 | if (err) printk( | 253 | if (err) printk( |
252 | KERN_CRIT " _______________________________ \n" | 254 | KERN_CRIT " _______________________________ \n" |
@@ -293,6 +295,7 @@ KERN_CRIT " || ||\n"); | |||
293 | panic("Fatal exception"); | 295 | panic("Fatal exception"); |
294 | } | 296 | } |
295 | 297 | ||
298 | oops_exit(); | ||
296 | do_exit(SIGSEGV); | 299 | do_exit(SIGSEGV); |
297 | } | 300 | } |
298 | 301 | ||
@@ -494,7 +497,7 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o | |||
494 | panic(msg); | 497 | panic(msg); |
495 | } | 498 | } |
496 | 499 | ||
497 | void handle_interruption(int code, struct pt_regs *regs) | 500 | void notrace handle_interruption(int code, struct pt_regs *regs) |
498 | { | 501 | { |
499 | unsigned long fault_address = 0; | 502 | unsigned long fault_address = 0; |
500 | unsigned long fault_space = 0; | 503 | unsigned long fault_space = 0; |
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index 1a3b6ccd3620..fd2cc4fd2b65 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S | |||
@@ -54,6 +54,8 @@ SECTIONS | |||
54 | TEXT_TEXT | 54 | TEXT_TEXT |
55 | SCHED_TEXT | 55 | SCHED_TEXT |
56 | LOCK_TEXT | 56 | LOCK_TEXT |
57 | KPROBES_TEXT | ||
58 | IRQENTRY_TEXT | ||
57 | *(.text.do_softirq) | 59 | *(.text.do_softirq) |
58 | *(.text.sys_exit) | 60 | *(.text.sys_exit) |
59 | *(.text.do_sigaltstack) | 61 | *(.text.do_sigaltstack) |
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 9d704d9831d1..4356ceb1e366 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c | |||
@@ -456,6 +456,13 @@ void __init mem_init(void) | |||
456 | { | 456 | { |
457 | int codesize, reservedpages, datasize, initsize; | 457 | int codesize, reservedpages, datasize, initsize; |
458 | 458 | ||
459 | /* Do sanity checks on page table constants */ | ||
460 | BUILD_BUG_ON(PTE_ENTRY_SIZE != sizeof(pte_t)); | ||
461 | BUILD_BUG_ON(PMD_ENTRY_SIZE != sizeof(pmd_t)); | ||
462 | BUILD_BUG_ON(PGD_ENTRY_SIZE != sizeof(pgd_t)); | ||
463 | BUILD_BUG_ON(PAGE_SHIFT + BITS_PER_PTE + BITS_PER_PMD + BITS_PER_PGD | ||
464 | > BITS_PER_LONG); | ||
465 | |||
459 | high_memory = __va((max_pfn << PAGE_SHIFT)); | 466 | high_memory = __va((max_pfn << PAGE_SHIFT)); |
460 | 467 | ||
461 | #ifndef CONFIG_DISCONTIGMEM | 468 | #ifndef CONFIG_DISCONTIGMEM |