diff options
author | Olof Johansson <olof@lixom.net> | 2012-05-26 16:30:41 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2012-05-26 16:30:41 -0400 |
commit | 67e7ebc21ff5a5bbcb10c9a980896f0e253bcd40 (patch) | |
tree | f12706b80194f48aad3a1bd70ae9215d48875591 /arch | |
parent | 516fb7a22a5347dc6db731369c365ed1f9b64632 (diff) | |
parent | c533f32e1ac440b8840159f89ece8c9cca2422b5 (diff) |
Merge branch 'vexpress-v3.4' of git://git.linaro.org/people/pawelmoll/linux into late/soc
A few device tree updates and an include file fix for versatile.
* 'vexpress-v3.4' of git://git.linaro.org/people/pawelmoll/linux:
ARM: vexpress: Remove twice included header files
ARM: vexpress: Device Tree updates
+ update to 3.4
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch')
34 files changed, 424 insertions, 187 deletions
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts index 941b161ab78c..7e1091d91af8 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts | |||
@@ -73,7 +73,10 @@ | |||
73 | #address-cells = <0>; | 73 | #address-cells = <0>; |
74 | interrupt-controller; | 74 | interrupt-controller; |
75 | reg = <0x2c001000 0x1000>, | 75 | reg = <0x2c001000 0x1000>, |
76 | <0x2c002000 0x100>; | 76 | <0x2c002000 0x1000>, |
77 | <0x2c004000 0x2000>, | ||
78 | <0x2c006000 0x2000>; | ||
79 | interrupts = <1 9 0xf04>; | ||
77 | }; | 80 | }; |
78 | 81 | ||
79 | memory-controller@7ffd0000 { | 82 | memory-controller@7ffd0000 { |
@@ -93,6 +96,14 @@ | |||
93 | <0 91 4>; | 96 | <0 91 4>; |
94 | }; | 97 | }; |
95 | 98 | ||
99 | timer { | ||
100 | compatible = "arm,armv7-timer"; | ||
101 | interrupts = <1 13 0xf08>, | ||
102 | <1 14 0xf08>, | ||
103 | <1 11 0xf08>, | ||
104 | <1 10 0xf08>; | ||
105 | }; | ||
106 | |||
96 | pmu { | 107 | pmu { |
97 | compatible = "arm,cortex-a15-pmu", "arm,cortex-a9-pmu"; | 108 | compatible = "arm,cortex-a15-pmu", "arm,cortex-a9-pmu"; |
98 | interrupts = <0 68 4>, | 109 | interrupts = <0 68 4>, |
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts index 6905e66d4748..18917a0f8604 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts | |||
@@ -77,13 +77,18 @@ | |||
77 | 77 | ||
78 | timer@2c000600 { | 78 | timer@2c000600 { |
79 | compatible = "arm,cortex-a5-twd-timer"; | 79 | compatible = "arm,cortex-a5-twd-timer"; |
80 | reg = <0x2c000600 0x38>; | 80 | reg = <0x2c000600 0x20>; |
81 | interrupts = <1 2 0x304>, | 81 | interrupts = <1 13 0x304>; |
82 | <1 3 0x304>; | 82 | }; |
83 | |||
84 | watchdog@2c000620 { | ||
85 | compatible = "arm,cortex-a5-twd-wdt"; | ||
86 | reg = <0x2c000620 0x20>; | ||
87 | interrupts = <1 14 0x304>; | ||
83 | }; | 88 | }; |
84 | 89 | ||
85 | gic: interrupt-controller@2c001000 { | 90 | gic: interrupt-controller@2c001000 { |
86 | compatible = "arm,corex-a5-gic", "arm,cortex-a9-gic"; | 91 | compatible = "arm,cortex-a5-gic", "arm,cortex-a9-gic"; |
87 | #interrupt-cells = <3>; | 92 | #interrupt-cells = <3>; |
88 | #address-cells = <0>; | 93 | #address-cells = <0>; |
89 | interrupt-controller; | 94 | interrupt-controller; |
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca9.dts b/arch/arm/boot/dts/vexpress-v2p-ca9.dts index da778693be54..3f0c736d31d6 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca9.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca9.dts | |||
@@ -105,8 +105,13 @@ | |||
105 | timer@1e000600 { | 105 | timer@1e000600 { |
106 | compatible = "arm,cortex-a9-twd-timer"; | 106 | compatible = "arm,cortex-a9-twd-timer"; |
107 | reg = <0x1e000600 0x20>; | 107 | reg = <0x1e000600 0x20>; |
108 | interrupts = <1 2 0xf04>, | 108 | interrupts = <1 13 0xf04>; |
109 | <1 3 0xf04>; | 109 | }; |
110 | |||
111 | watchdog@1e000620 { | ||
112 | compatible = "arm,cortex-a9-twd-wdt"; | ||
113 | reg = <0x1e000620 0x20>; | ||
114 | interrupts = <1 14 0xf04>; | ||
110 | }; | 115 | }; |
111 | 116 | ||
112 | gic: interrupt-controller@1e001000 { | 117 | gic: interrupt-controller@1e001000 { |
diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c index 37c2de9b6f26..a7b9415d30f8 100644 --- a/arch/arm/mach-prima2/irq.c +++ b/arch/arm/mach-prima2/irq.c | |||
@@ -42,7 +42,8 @@ sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) | |||
42 | static __init void sirfsoc_irq_init(void) | 42 | static __init void sirfsoc_irq_init(void) |
43 | { | 43 | { |
44 | sirfsoc_alloc_gc(sirfsoc_intc_base, 0, 32); | 44 | sirfsoc_alloc_gc(sirfsoc_intc_base, 0, 32); |
45 | sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32, SIRFSOC_INTENAL_IRQ_END - 32); | 45 | sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32, |
46 | SIRFSOC_INTENAL_IRQ_END + 1 - 32); | ||
46 | 47 | ||
47 | writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0); | 48 | writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0); |
48 | writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1); | 49 | writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1); |
@@ -68,7 +69,8 @@ void __init sirfsoc_of_irq_init(void) | |||
68 | if (!sirfsoc_intc_base) | 69 | if (!sirfsoc_intc_base) |
69 | panic("unable to map intc cpu registers\n"); | 70 | panic("unable to map intc cpu registers\n"); |
70 | 71 | ||
71 | irq_domain_add_legacy(np, 32, 0, 0, &irq_domain_simple_ops, NULL); | 72 | irq_domain_add_legacy(np, SIRFSOC_INTENAL_IRQ_END + 1, 0, 0, |
73 | &irq_domain_simple_ops, NULL); | ||
72 | 74 | ||
73 | of_node_put(np); | 75 | of_node_put(np); |
74 | 76 | ||
diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c index fef66a7486ed..f07488e0bd32 100644 --- a/arch/arm/mach-tegra/flowctrl.c +++ b/arch/arm/mach-tegra/flowctrl.c | |||
@@ -53,10 +53,10 @@ static void flowctrl_update(u8 offset, u32 value) | |||
53 | 53 | ||
54 | void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value) | 54 | void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value) |
55 | { | 55 | { |
56 | return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value); | 56 | return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value); |
57 | } | 57 | } |
58 | 58 | ||
59 | void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value) | 59 | void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value) |
60 | { | 60 | { |
61 | return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value); | 61 | return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value); |
62 | } | 62 | } |
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 47cdcca5a7e7..e769ab612627 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/ata_platform.h> | 14 | #include <linux/ata_platform.h> |
15 | #include <linux/smsc911x.h> | 15 | #include <linux/smsc911x.h> |
16 | #include <linux/spinlock.h> | 16 | #include <linux/spinlock.h> |
17 | #include <linux/device.h> | ||
18 | #include <linux/usb/isp1760.h> | 17 | #include <linux/usb/isp1760.h> |
19 | #include <linux/clkdev.h> | 18 | #include <linux/clkdev.h> |
20 | #include <linux/mtd/physmap.h> | 19 | #include <linux/mtd/physmap.h> |
@@ -29,7 +28,6 @@ | |||
29 | #include <asm/hardware/gic.h> | 28 | #include <asm/hardware/gic.h> |
30 | #include <asm/hardware/timer-sp.h> | 29 | #include <asm/hardware/timer-sp.h> |
31 | #include <asm/hardware/sp810.h> | 30 | #include <asm/hardware/sp810.h> |
32 | #include <asm/hardware/gic.h> | ||
33 | 31 | ||
34 | #include <mach/ct-ca9x4.h> | 32 | #include <mach/ct-ca9x4.h> |
35 | #include <mach/motherboard.h> | 33 | #include <mach/motherboard.h> |
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index f07467533365..5bb48356d217 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -247,7 +247,9 @@ good_area: | |||
247 | return handle_mm_fault(mm, vma, addr & PAGE_MASK, flags); | 247 | return handle_mm_fault(mm, vma, addr & PAGE_MASK, flags); |
248 | 248 | ||
249 | check_stack: | 249 | check_stack: |
250 | if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr)) | 250 | /* Don't allow expansion below FIRST_USER_ADDRESS */ |
251 | if (vma->vm_flags & VM_GROWSDOWN && | ||
252 | addr >= FIRST_USER_ADDRESS && !expand_stack(vma, addr)) | ||
251 | goto good_area; | 253 | goto good_area; |
252 | out: | 254 | out: |
253 | return fault; | 255 | return fault; |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 2c7cf2f9c837..aa78de8bfdd3 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -489,7 +489,8 @@ static void __init build_mem_type_table(void) | |||
489 | */ | 489 | */ |
490 | for (i = 0; i < ARRAY_SIZE(mem_types); i++) { | 490 | for (i = 0; i < ARRAY_SIZE(mem_types); i++) { |
491 | mem_types[i].prot_pte |= PTE_EXT_AF; | 491 | mem_types[i].prot_pte |= PTE_EXT_AF; |
492 | mem_types[i].prot_sect |= PMD_SECT_AF; | 492 | if (mem_types[i].prot_sect) |
493 | mem_types[i].prot_sect |= PMD_SECT_AF; | ||
493 | } | 494 | } |
494 | kern_pgprot |= PTE_EXT_AF; | 495 | kern_pgprot |= PTE_EXT_AF; |
495 | vecs_pgprot |= PTE_EXT_AF; | 496 | vecs_pgprot |= PTE_EXT_AF; |
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index bc683b8219b5..b0197b2c857d 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
12 | #include <linux/cpu.h> | 12 | #include <linux/cpu.h> |
13 | #include <linux/cpu_pm.h> | 13 | #include <linux/cpu_pm.h> |
14 | #include <linux/hardirq.h> | ||
14 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
15 | #include <linux/notifier.h> | 16 | #include <linux/notifier.h> |
16 | #include <linux/signal.h> | 17 | #include <linux/signal.h> |
@@ -432,7 +433,10 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) | |||
432 | 433 | ||
433 | static void vfp_enable(void *unused) | 434 | static void vfp_enable(void *unused) |
434 | { | 435 | { |
435 | u32 access = get_copro_access(); | 436 | u32 access; |
437 | |||
438 | BUG_ON(preemptible()); | ||
439 | access = get_copro_access(); | ||
436 | 440 | ||
437 | /* | 441 | /* |
438 | * Enable full access to VFP (cp10 and cp11) | 442 | * Enable full access to VFP (cp10 and cp11) |
@@ -573,12 +577,6 @@ int vfp_preserve_user_clear_hwstate(struct user_vfp __user *ufp, | |||
573 | * entry. | 577 | * entry. |
574 | */ | 578 | */ |
575 | hwstate->fpscr &= ~(FPSCR_LENGTH_MASK | FPSCR_STRIDE_MASK); | 579 | hwstate->fpscr &= ~(FPSCR_LENGTH_MASK | FPSCR_STRIDE_MASK); |
576 | |||
577 | /* | ||
578 | * Disable VFP in the hwstate so that we can detect if it gets | ||
579 | * used. | ||
580 | */ | ||
581 | hwstate->fpexc &= ~FPEXC_EN; | ||
582 | return 0; | 580 | return 0; |
583 | } | 581 | } |
584 | 582 | ||
@@ -591,12 +589,8 @@ int vfp_restore_user_hwstate(struct user_vfp __user *ufp, | |||
591 | unsigned long fpexc; | 589 | unsigned long fpexc; |
592 | int err = 0; | 590 | int err = 0; |
593 | 591 | ||
594 | /* | 592 | /* Disable VFP to avoid corrupting the new thread state. */ |
595 | * If VFP has been used, then disable it to avoid corrupting | 593 | vfp_flush_hwstate(thread); |
596 | * the new thread state. | ||
597 | */ | ||
598 | if (hwstate->fpexc & FPEXC_EN) | ||
599 | vfp_flush_hwstate(thread); | ||
600 | 594 | ||
601 | /* | 595 | /* |
602 | * Copy the floating point registers. There can be unused | 596 | * Copy the floating point registers. There can be unused |
@@ -657,7 +651,7 @@ static int __init vfp_init(void) | |||
657 | unsigned int cpu_arch = cpu_architecture(); | 651 | unsigned int cpu_arch = cpu_architecture(); |
658 | 652 | ||
659 | if (cpu_arch >= CPU_ARCH_ARMv6) | 653 | if (cpu_arch >= CPU_ARCH_ARMv6) |
660 | vfp_enable(NULL); | 654 | on_each_cpu(vfp_enable, NULL, 1); |
661 | 655 | ||
662 | /* | 656 | /* |
663 | * First check that there is a VFP that we can use. | 657 | * First check that there is a VFP that we can use. |
@@ -678,8 +672,6 @@ static int __init vfp_init(void) | |||
678 | } else { | 672 | } else { |
679 | hotcpu_notifier(vfp_hotplug, 0); | 673 | hotcpu_notifier(vfp_hotplug, 0); |
680 | 674 | ||
681 | smp_call_function(vfp_enable, NULL, 1); | ||
682 | |||
683 | VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ | 675 | VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ |
684 | printk("implementor %02x architecture %d part %02x variant %x rev %x\n", | 676 | printk("implementor %02x architecture %d part %02x variant %x rev %x\n", |
685 | (vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT, | 677 | (vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT, |
diff --git a/arch/frv/include/asm/processor.h b/arch/frv/include/asm/processor.h index 81c2e271d620..9b1a92b73f60 100644 --- a/arch/frv/include/asm/processor.h +++ b/arch/frv/include/asm/processor.h | |||
@@ -135,10 +135,6 @@ unsigned long get_wchan(struct task_struct *p); | |||
135 | #define KSTK_EIP(tsk) ((tsk)->thread.frame0->pc) | 135 | #define KSTK_EIP(tsk) ((tsk)->thread.frame0->pc) |
136 | #define KSTK_ESP(tsk) ((tsk)->thread.frame0->sp) | 136 | #define KSTK_ESP(tsk) ((tsk)->thread.frame0->sp) |
137 | 137 | ||
138 | /* Allocation and freeing of basic task resources. */ | ||
139 | extern struct task_struct *alloc_task_struct_node(int node); | ||
140 | extern void free_task_struct(struct task_struct *p); | ||
141 | |||
142 | #define cpu_relax() barrier() | 138 | #define cpu_relax() barrier() |
143 | 139 | ||
144 | /* data cache prefetch */ | 140 | /* data cache prefetch */ |
diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c index 910dddf65e44..9cd69ad6aa02 100644 --- a/arch/mn10300/kernel/smp.c +++ b/arch/mn10300/kernel/smp.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/sched.h> | 24 | #include <linux/sched.h> |
25 | #include <linux/profile.h> | 25 | #include <linux/profile.h> |
26 | #include <linux/smp.h> | 26 | #include <linux/smp.h> |
27 | #include <linux/cpu.h> | ||
27 | #include <asm/tlbflush.h> | 28 | #include <asm/tlbflush.h> |
28 | #include <asm/bitops.h> | 29 | #include <asm/bitops.h> |
29 | #include <asm/processor.h> | 30 | #include <asm/processor.h> |
@@ -38,7 +39,6 @@ | |||
38 | #include "internal.h" | 39 | #include "internal.h" |
39 | 40 | ||
40 | #ifdef CONFIG_HOTPLUG_CPU | 41 | #ifdef CONFIG_HOTPLUG_CPU |
41 | #include <linux/cpu.h> | ||
42 | #include <asm/cacheflush.h> | 42 | #include <asm/cacheflush.h> |
43 | 43 | ||
44 | static unsigned long sleep_mode[NR_CPUS]; | 44 | static unsigned long sleep_mode[NR_CPUS]; |
@@ -874,10 +874,13 @@ static void __init smp_online(void) | |||
874 | 874 | ||
875 | cpu = smp_processor_id(); | 875 | cpu = smp_processor_id(); |
876 | 876 | ||
877 | local_irq_enable(); | 877 | notify_cpu_starting(cpu); |
878 | 878 | ||
879 | ipi_call_lock(); | ||
879 | set_cpu_online(cpu, true); | 880 | set_cpu_online(cpu, true); |
880 | smp_wmb(); | 881 | ipi_call_unlock(); |
882 | |||
883 | local_irq_enable(); | ||
881 | } | 884 | } |
882 | 885 | ||
883 | /** | 886 | /** |
diff --git a/arch/parisc/include/asm/prefetch.h b/arch/parisc/include/asm/prefetch.h index c5edc60c059f..1ee7c82672c1 100644 --- a/arch/parisc/include/asm/prefetch.h +++ b/arch/parisc/include/asm/prefetch.h | |||
@@ -21,7 +21,12 @@ | |||
21 | #define ARCH_HAS_PREFETCH | 21 | #define ARCH_HAS_PREFETCH |
22 | static inline void prefetch(const void *addr) | 22 | static inline void prefetch(const void *addr) |
23 | { | 23 | { |
24 | __asm__("ldw 0(%0), %%r0" : : "r" (addr)); | 24 | __asm__( |
25 | #ifndef CONFIG_PA20 | ||
26 | /* Need to avoid prefetch of NULL on PA7300LC */ | ||
27 | " extrw,u,= %0,31,32,%%r0\n" | ||
28 | #endif | ||
29 | " ldw 0(%0), %%r0" : : "r" (addr)); | ||
25 | } | 30 | } |
26 | 31 | ||
27 | /* LDD is a PA2.0 addition. */ | 32 | /* LDD is a PA2.0 addition. */ |
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 6f0594439143..535034217021 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
@@ -581,7 +581,11 @@ | |||
581 | */ | 581 | */ |
582 | cmpiclr,= 0x01,\tmp,%r0 | 582 | cmpiclr,= 0x01,\tmp,%r0 |
583 | ldi (_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot | 583 | ldi (_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot |
584 | #ifdef CONFIG_64BIT | ||
584 | depd,z \prot,8,7,\prot | 585 | depd,z \prot,8,7,\prot |
586 | #else | ||
587 | depw,z \prot,8,7,\prot | ||
588 | #endif | ||
585 | /* | 589 | /* |
586 | * OK, it is in the temp alias region, check whether "from" or "to". | 590 | * OK, it is in the temp alias region, check whether "from" or "to". |
587 | * Check "subtle" note in pacache.S re: r23/r26. | 591 | * Check "subtle" note in pacache.S re: r23/r26. |
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index 93ff3d90edd1..5d7218ad885c 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S | |||
@@ -692,7 +692,7 @@ ENTRY(flush_icache_page_asm) | |||
692 | 692 | ||
693 | /* Purge any old translation */ | 693 | /* Purge any old translation */ |
694 | 694 | ||
695 | pitlb (%sr0,%r28) | 695 | pitlb (%sr4,%r28) |
696 | 696 | ||
697 | ldil L%icache_stride, %r1 | 697 | ldil L%icache_stride, %r1 |
698 | ldw R%icache_stride(%r1), %r1 | 698 | ldw R%icache_stride(%r1), %r1 |
@@ -706,27 +706,29 @@ ENTRY(flush_icache_page_asm) | |||
706 | sub %r25, %r1, %r25 | 706 | sub %r25, %r1, %r25 |
707 | 707 | ||
708 | 708 | ||
709 | 1: fic,m %r1(%r28) | 709 | /* fic only has the type 26 form on PA1.1, requiring an |
710 | fic,m %r1(%r28) | 710 | * explicit space specification, so use %sr4 */ |
711 | fic,m %r1(%r28) | 711 | 1: fic,m %r1(%sr4,%r28) |
712 | fic,m %r1(%r28) | 712 | fic,m %r1(%sr4,%r28) |
713 | fic,m %r1(%r28) | 713 | fic,m %r1(%sr4,%r28) |
714 | fic,m %r1(%r28) | 714 | fic,m %r1(%sr4,%r28) |
715 | fic,m %r1(%r28) | 715 | fic,m %r1(%sr4,%r28) |
716 | fic,m %r1(%r28) | 716 | fic,m %r1(%sr4,%r28) |
717 | fic,m %r1(%r28) | 717 | fic,m %r1(%sr4,%r28) |
718 | fic,m %r1(%r28) | 718 | fic,m %r1(%sr4,%r28) |
719 | fic,m %r1(%r28) | 719 | fic,m %r1(%sr4,%r28) |
720 | fic,m %r1(%r28) | 720 | fic,m %r1(%sr4,%r28) |
721 | fic,m %r1(%r28) | 721 | fic,m %r1(%sr4,%r28) |
722 | fic,m %r1(%r28) | 722 | fic,m %r1(%sr4,%r28) |
723 | fic,m %r1(%r28) | 723 | fic,m %r1(%sr4,%r28) |
724 | fic,m %r1(%sr4,%r28) | ||
725 | fic,m %r1(%sr4,%r28) | ||
724 | cmpb,COND(<<) %r28, %r25,1b | 726 | cmpb,COND(<<) %r28, %r25,1b |
725 | fic,m %r1(%r28) | 727 | fic,m %r1(%sr4,%r28) |
726 | 728 | ||
727 | sync | 729 | sync |
728 | bv %r0(%r2) | 730 | bv %r0(%r2) |
729 | pitlb (%sr0,%r25) | 731 | pitlb (%sr4,%r25) |
730 | .exit | 732 | .exit |
731 | 733 | ||
732 | .procend | 734 | .procend |
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 0bb1d63907f8..4dc7b7942b4c 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | #include <linux/bitops.h> | 32 | #include <linux/bitops.h> |
33 | #include <linux/ftrace.h> | 33 | #include <linux/ftrace.h> |
34 | #include <linux/cpu.h> | ||
34 | 35 | ||
35 | #include <linux/atomic.h> | 36 | #include <linux/atomic.h> |
36 | #include <asm/current.h> | 37 | #include <asm/current.h> |
@@ -295,8 +296,13 @@ smp_cpu_init(int cpunum) | |||
295 | 296 | ||
296 | printk(KERN_CRIT "CPU#%d already initialized!\n", cpunum); | 297 | printk(KERN_CRIT "CPU#%d already initialized!\n", cpunum); |
297 | machine_halt(); | 298 | machine_halt(); |
298 | } | 299 | } |
300 | |||
301 | notify_cpu_starting(cpunum); | ||
302 | |||
303 | ipi_call_lock(); | ||
299 | set_cpu_online(cpunum, true); | 304 | set_cpu_online(cpunum, true); |
305 | ipi_call_unlock(); | ||
300 | 306 | ||
301 | /* Initialise the idle task for this CPU */ | 307 | /* Initialise the idle task for this CPU */ |
302 | atomic_inc(&init_mm.mm_count); | 308 | atomic_inc(&init_mm.mm_count); |
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index aa795ccef294..fd07f43d6622 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h | |||
@@ -81,12 +81,13 @@ struct kvmppc_vcpu_book3s { | |||
81 | u64 sdr1; | 81 | u64 sdr1; |
82 | u64 hior; | 82 | u64 hior; |
83 | u64 msr_mask; | 83 | u64 msr_mask; |
84 | u64 vsid_next; | ||
85 | #ifdef CONFIG_PPC_BOOK3S_32 | 84 | #ifdef CONFIG_PPC_BOOK3S_32 |
86 | u32 vsid_pool[VSID_POOL_SIZE]; | 85 | u32 vsid_pool[VSID_POOL_SIZE]; |
86 | u32 vsid_next; | ||
87 | #else | 87 | #else |
88 | u64 vsid_first; | 88 | u64 proto_vsid_first; |
89 | u64 vsid_max; | 89 | u64 proto_vsid_max; |
90 | u64 proto_vsid_next; | ||
90 | #endif | 91 | #endif |
91 | int context_id[SID_CONTEXTS]; | 92 | int context_id[SID_CONTEXTS]; |
92 | 93 | ||
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c index 6f87f39a1ac2..10fc8ec9d2a8 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_host.c +++ b/arch/powerpc/kvm/book3s_64_mmu_host.c | |||
@@ -194,14 +194,14 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid) | |||
194 | backwards_map = !backwards_map; | 194 | backwards_map = !backwards_map; |
195 | 195 | ||
196 | /* Uh-oh ... out of mappings. Let's flush! */ | 196 | /* Uh-oh ... out of mappings. Let's flush! */ |
197 | if (vcpu_book3s->vsid_next == vcpu_book3s->vsid_max) { | 197 | if (vcpu_book3s->proto_vsid_next == vcpu_book3s->proto_vsid_max) { |
198 | vcpu_book3s->vsid_next = vcpu_book3s->vsid_first; | 198 | vcpu_book3s->proto_vsid_next = vcpu_book3s->proto_vsid_first; |
199 | memset(vcpu_book3s->sid_map, 0, | 199 | memset(vcpu_book3s->sid_map, 0, |
200 | sizeof(struct kvmppc_sid_map) * SID_MAP_NUM); | 200 | sizeof(struct kvmppc_sid_map) * SID_MAP_NUM); |
201 | kvmppc_mmu_pte_flush(vcpu, 0, 0); | 201 | kvmppc_mmu_pte_flush(vcpu, 0, 0); |
202 | kvmppc_mmu_flush_segments(vcpu); | 202 | kvmppc_mmu_flush_segments(vcpu); |
203 | } | 203 | } |
204 | map->host_vsid = vcpu_book3s->vsid_next++; | 204 | map->host_vsid = vsid_scramble(vcpu_book3s->proto_vsid_next++, 256M); |
205 | 205 | ||
206 | map->guest_vsid = gvsid; | 206 | map->guest_vsid = gvsid; |
207 | map->valid = true; | 207 | map->valid = true; |
@@ -319,9 +319,10 @@ int kvmppc_mmu_init(struct kvm_vcpu *vcpu) | |||
319 | return -1; | 319 | return -1; |
320 | vcpu3s->context_id[0] = err; | 320 | vcpu3s->context_id[0] = err; |
321 | 321 | ||
322 | vcpu3s->vsid_max = ((vcpu3s->context_id[0] + 1) << USER_ESID_BITS) - 1; | 322 | vcpu3s->proto_vsid_max = ((vcpu3s->context_id[0] + 1) |
323 | vcpu3s->vsid_first = vcpu3s->context_id[0] << USER_ESID_BITS; | 323 | << USER_ESID_BITS) - 1; |
324 | vcpu3s->vsid_next = vcpu3s->vsid_first; | 324 | vcpu3s->proto_vsid_first = vcpu3s->context_id[0] << USER_ESID_BITS; |
325 | vcpu3s->proto_vsid_next = vcpu3s->proto_vsid_first; | ||
325 | 326 | ||
326 | kvmppc_mmu_hpte_init(vcpu); | 327 | kvmppc_mmu_hpte_init(vcpu); |
327 | 328 | ||
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index def880aea63a..cec4daddbf31 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c | |||
@@ -463,6 +463,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu) | |||
463 | /* insert R and C bits from PTE */ | 463 | /* insert R and C bits from PTE */ |
464 | rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C); | 464 | rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C); |
465 | args[j] |= rcbits << (56 - 5); | 465 | args[j] |= rcbits << (56 - 5); |
466 | hp[0] = 0; | ||
466 | continue; | 467 | continue; |
467 | } | 468 | } |
468 | 469 | ||
diff --git a/arch/powerpc/kvm/book3s_segment.S b/arch/powerpc/kvm/book3s_segment.S index 0676ae249b9f..6e6e9cef34a8 100644 --- a/arch/powerpc/kvm/book3s_segment.S +++ b/arch/powerpc/kvm/book3s_segment.S | |||
@@ -197,7 +197,8 @@ kvmppc_interrupt: | |||
197 | /* Save guest PC and MSR */ | 197 | /* Save guest PC and MSR */ |
198 | #ifdef CONFIG_PPC64 | 198 | #ifdef CONFIG_PPC64 |
199 | BEGIN_FTR_SECTION | 199 | BEGIN_FTR_SECTION |
200 | andi. r0,r12,0x2 | 200 | andi. r0, r12, 0x2 |
201 | cmpwi cr1, r0, 0 | ||
201 | beq 1f | 202 | beq 1f |
202 | mfspr r3,SPRN_HSRR0 | 203 | mfspr r3,SPRN_HSRR0 |
203 | mfspr r4,SPRN_HSRR1 | 204 | mfspr r4,SPRN_HSRR1 |
@@ -250,6 +251,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | |||
250 | beq ld_last_prev_inst | 251 | beq ld_last_prev_inst |
251 | cmpwi r12, BOOK3S_INTERRUPT_ALIGNMENT | 252 | cmpwi r12, BOOK3S_INTERRUPT_ALIGNMENT |
252 | beq- ld_last_inst | 253 | beq- ld_last_inst |
254 | #ifdef CONFIG_PPC64 | ||
255 | BEGIN_FTR_SECTION | ||
256 | cmpwi r12, BOOK3S_INTERRUPT_H_EMUL_ASSIST | ||
257 | beq- ld_last_inst | ||
258 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | ||
259 | #endif | ||
253 | 260 | ||
254 | b no_ld_last_inst | 261 | b no_ld_last_inst |
255 | 262 | ||
@@ -316,23 +323,17 @@ no_dcbz32_off: | |||
316 | * Having set up SRR0/1 with the address where we want | 323 | * Having set up SRR0/1 with the address where we want |
317 | * to continue with relocation on (potentially in module | 324 | * to continue with relocation on (potentially in module |
318 | * space), we either just go straight there with rfi[d], | 325 | * space), we either just go straight there with rfi[d], |
319 | * or we jump to an interrupt handler with bctr if there | 326 | * or we jump to an interrupt handler if there is an |
320 | * is an interrupt to be handled first. In the latter | 327 | * interrupt to be handled first. In the latter case, |
321 | * case, the rfi[d] at the end of the interrupt handler | 328 | * the rfi[d] at the end of the interrupt handler will |
322 | * will get us back to where we want to continue. | 329 | * get us back to where we want to continue. |
323 | */ | 330 | */ |
324 | 331 | ||
325 | cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL | ||
326 | beq 1f | ||
327 | cmpwi r12, BOOK3S_INTERRUPT_DECREMENTER | ||
328 | beq 1f | ||
329 | cmpwi r12, BOOK3S_INTERRUPT_PERFMON | ||
330 | 1: mtctr r12 | ||
331 | |||
332 | /* Register usage at this point: | 332 | /* Register usage at this point: |
333 | * | 333 | * |
334 | * R1 = host R1 | 334 | * R1 = host R1 |
335 | * R2 = host R2 | 335 | * R2 = host R2 |
336 | * R10 = raw exit handler id | ||
336 | * R12 = exit handler id | 337 | * R12 = exit handler id |
337 | * R13 = shadow vcpu (32-bit) or PACA (64-bit) | 338 | * R13 = shadow vcpu (32-bit) or PACA (64-bit) |
338 | * SVCPU.* = guest * | 339 | * SVCPU.* = guest * |
@@ -342,12 +343,25 @@ no_dcbz32_off: | |||
342 | PPC_LL r6, HSTATE_HOST_MSR(r13) | 343 | PPC_LL r6, HSTATE_HOST_MSR(r13) |
343 | PPC_LL r8, HSTATE_VMHANDLER(r13) | 344 | PPC_LL r8, HSTATE_VMHANDLER(r13) |
344 | 345 | ||
345 | /* Restore host msr -> SRR1 */ | 346 | #ifdef CONFIG_PPC64 |
347 | BEGIN_FTR_SECTION | ||
348 | beq cr1, 1f | ||
349 | mtspr SPRN_HSRR1, r6 | ||
350 | mtspr SPRN_HSRR0, r8 | ||
351 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | ||
352 | #endif | ||
353 | 1: /* Restore host msr -> SRR1 */ | ||
346 | mtsrr1 r6 | 354 | mtsrr1 r6 |
347 | /* Load highmem handler address */ | 355 | /* Load highmem handler address */ |
348 | mtsrr0 r8 | 356 | mtsrr0 r8 |
349 | 357 | ||
350 | /* RFI into the highmem handler, or jump to interrupt handler */ | 358 | /* RFI into the highmem handler, or jump to interrupt handler */ |
351 | beqctr | 359 | cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL |
360 | beqa BOOK3S_INTERRUPT_EXTERNAL | ||
361 | cmpwi r12, BOOK3S_INTERRUPT_DECREMENTER | ||
362 | beqa BOOK3S_INTERRUPT_DECREMENTER | ||
363 | cmpwi r12, BOOK3S_INTERRUPT_PERFMON | ||
364 | beqa BOOK3S_INTERRUPT_PERFMON | ||
365 | |||
352 | RFI | 366 | RFI |
353 | kvmppc_handler_trampoline_exit_end: | 367 | kvmppc_handler_trampoline_exit_end: |
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 96033e2d6845..74239dd77e06 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig | |||
@@ -11,6 +11,7 @@ config TILE | |||
11 | select GENERIC_IRQ_PROBE | 11 | select GENERIC_IRQ_PROBE |
12 | select GENERIC_PENDING_IRQ if SMP | 12 | select GENERIC_PENDING_IRQ if SMP |
13 | select GENERIC_IRQ_SHOW | 13 | select GENERIC_IRQ_SHOW |
14 | select HAVE_SYSCALL_WRAPPERS if TILEGX | ||
14 | select SYS_HYPERVISOR | 15 | select SYS_HYPERVISOR |
15 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 16 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
16 | 17 | ||
diff --git a/arch/tile/include/asm/thread_info.h b/arch/tile/include/asm/thread_info.h index bc4f562bd459..7594764d8a69 100644 --- a/arch/tile/include/asm/thread_info.h +++ b/arch/tile/include/asm/thread_info.h | |||
@@ -100,9 +100,14 @@ extern void cpu_idle_on_new_stack(struct thread_info *old_ti, | |||
100 | 100 | ||
101 | #else /* __ASSEMBLY__ */ | 101 | #else /* __ASSEMBLY__ */ |
102 | 102 | ||
103 | /* how to get the thread information struct from ASM */ | 103 | /* |
104 | * How to get the thread information struct from assembly. | ||
105 | * Note that we use different macros since different architectures | ||
106 | * have different semantics in their "mm" instruction and we would | ||
107 | * like to guarantee that the macro expands to exactly one instruction. | ||
108 | */ | ||
104 | #ifdef __tilegx__ | 109 | #ifdef __tilegx__ |
105 | #define GET_THREAD_INFO(reg) move reg, sp; mm reg, zero, LOG2_THREAD_SIZE, 63 | 110 | #define EXTRACT_THREAD_INFO(reg) mm reg, zero, LOG2_THREAD_SIZE, 63 |
106 | #else | 111 | #else |
107 | #define GET_THREAD_INFO(reg) mm reg, sp, zero, LOG2_THREAD_SIZE, 31 | 112 | #define GET_THREAD_INFO(reg) mm reg, sp, zero, LOG2_THREAD_SIZE, 31 |
108 | #endif | 113 | #endif |
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c index 77763ccd5a7d..cdef6e5ec022 100644 --- a/arch/tile/kernel/compat_signal.c +++ b/arch/tile/kernel/compat_signal.c | |||
@@ -403,19 +403,17 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
403 | * Set up registers for signal handler. | 403 | * Set up registers for signal handler. |
404 | * Registers that we don't modify keep the value they had from | 404 | * Registers that we don't modify keep the value they had from |
405 | * user-space at the time we took the signal. | 405 | * user-space at the time we took the signal. |
406 | * We always pass siginfo and mcontext, regardless of SA_SIGINFO, | ||
407 | * since some things rely on this (e.g. glibc's debug/segfault.c). | ||
406 | */ | 408 | */ |
407 | regs->pc = ptr_to_compat_reg(ka->sa.sa_handler); | 409 | regs->pc = ptr_to_compat_reg(ka->sa.sa_handler); |
408 | regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ | 410 | regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ |
409 | regs->sp = ptr_to_compat_reg(frame); | 411 | regs->sp = ptr_to_compat_reg(frame); |
410 | regs->lr = restorer; | 412 | regs->lr = restorer; |
411 | regs->regs[0] = (unsigned long) usig; | 413 | regs->regs[0] = (unsigned long) usig; |
412 | 414 | regs->regs[1] = ptr_to_compat_reg(&frame->info); | |
413 | if (ka->sa.sa_flags & SA_SIGINFO) { | 415 | regs->regs[2] = ptr_to_compat_reg(&frame->uc); |
414 | /* Need extra arguments, so mark to restore caller-saves. */ | 416 | regs->flags |= PT_FLAGS_CALLER_SAVES; |
415 | regs->regs[1] = ptr_to_compat_reg(&frame->info); | ||
416 | regs->regs[2] = ptr_to_compat_reg(&frame->uc); | ||
417 | regs->flags |= PT_FLAGS_CALLER_SAVES; | ||
418 | } | ||
419 | 417 | ||
420 | /* | 418 | /* |
421 | * Notify any tracer that was single-stepping it. | 419 | * Notify any tracer that was single-stepping it. |
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index 5d56a1ef5ba5..6943515100f8 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S | |||
@@ -839,6 +839,18 @@ STD_ENTRY(interrupt_return) | |||
839 | FEEDBACK_REENTER(interrupt_return) | 839 | FEEDBACK_REENTER(interrupt_return) |
840 | 840 | ||
841 | /* | 841 | /* |
842 | * Use r33 to hold whether we have already loaded the callee-saves | ||
843 | * into ptregs. We don't want to do it twice in this loop, since | ||
844 | * then we'd clobber whatever changes are made by ptrace, etc. | ||
845 | * Get base of stack in r32. | ||
846 | */ | ||
847 | { | ||
848 | GET_THREAD_INFO(r32) | ||
849 | movei r33, 0 | ||
850 | } | ||
851 | |||
852 | .Lretry_work_pending: | ||
853 | /* | ||
842 | * Disable interrupts so as to make sure we don't | 854 | * Disable interrupts so as to make sure we don't |
843 | * miss an interrupt that sets any of the thread flags (like | 855 | * miss an interrupt that sets any of the thread flags (like |
844 | * need_resched or sigpending) between sampling and the iret. | 856 | * need_resched or sigpending) between sampling and the iret. |
@@ -848,9 +860,6 @@ STD_ENTRY(interrupt_return) | |||
848 | IRQ_DISABLE(r20, r21) | 860 | IRQ_DISABLE(r20, r21) |
849 | TRACE_IRQS_OFF /* Note: clobbers registers r0-r29 */ | 861 | TRACE_IRQS_OFF /* Note: clobbers registers r0-r29 */ |
850 | 862 | ||
851 | /* Get base of stack in r32; note r30/31 are used as arguments here. */ | ||
852 | GET_THREAD_INFO(r32) | ||
853 | |||
854 | 863 | ||
855 | /* Check to see if there is any work to do before returning to user. */ | 864 | /* Check to see if there is any work to do before returning to user. */ |
856 | { | 865 | { |
@@ -866,16 +875,18 @@ STD_ENTRY(interrupt_return) | |||
866 | 875 | ||
867 | /* | 876 | /* |
868 | * Make sure we have all the registers saved for signal | 877 | * Make sure we have all the registers saved for signal |
869 | * handling or single-step. Call out to C code to figure out | 878 | * handling, notify-resume, or single-step. Call out to C |
870 | * exactly what we need to do for each flag bit, then if | 879 | * code to figure out exactly what we need to do for each flag bit, |
871 | * necessary, reload the flags and recheck. | 880 | * then if necessary, reload the flags and recheck. |
872 | */ | 881 | */ |
873 | push_extra_callee_saves r0 | ||
874 | { | 882 | { |
875 | PTREGS_PTR(r0, PTREGS_OFFSET_BASE) | 883 | PTREGS_PTR(r0, PTREGS_OFFSET_BASE) |
876 | jal do_work_pending | 884 | bnz r33, 1f |
877 | } | 885 | } |
878 | bnz r0, .Lresume_userspace | 886 | push_extra_callee_saves r0 |
887 | movei r33, 1 | ||
888 | 1: jal do_work_pending | ||
889 | bnz r0, .Lretry_work_pending | ||
879 | 890 | ||
880 | /* | 891 | /* |
881 | * In the NMI case we | 892 | * In the NMI case we |
@@ -1180,10 +1191,12 @@ handle_syscall: | |||
1180 | add r20, r20, tp | 1191 | add r20, r20, tp |
1181 | lw r21, r20 | 1192 | lw r21, r20 |
1182 | addi r21, r21, 1 | 1193 | addi r21, r21, 1 |
1183 | sw r20, r21 | 1194 | { |
1195 | sw r20, r21 | ||
1196 | GET_THREAD_INFO(r31) | ||
1197 | } | ||
1184 | 1198 | ||
1185 | /* Trace syscalls, if requested. */ | 1199 | /* Trace syscalls, if requested. */ |
1186 | GET_THREAD_INFO(r31) | ||
1187 | addi r31, r31, THREAD_INFO_FLAGS_OFFSET | 1200 | addi r31, r31, THREAD_INFO_FLAGS_OFFSET |
1188 | lw r30, r31 | 1201 | lw r30, r31 |
1189 | andi r30, r30, _TIF_SYSCALL_TRACE | 1202 | andi r30, r30, _TIF_SYSCALL_TRACE |
@@ -1362,7 +1375,10 @@ handle_ill: | |||
1362 | 3: | 1375 | 3: |
1363 | /* set PC and continue */ | 1376 | /* set PC and continue */ |
1364 | lw r26, r24 | 1377 | lw r26, r24 |
1365 | sw r28, r26 | 1378 | { |
1379 | sw r28, r26 | ||
1380 | GET_THREAD_INFO(r0) | ||
1381 | } | ||
1366 | 1382 | ||
1367 | /* | 1383 | /* |
1368 | * Clear TIF_SINGLESTEP to prevent recursion if we execute an ill. | 1384 | * Clear TIF_SINGLESTEP to prevent recursion if we execute an ill. |
@@ -1370,7 +1386,6 @@ handle_ill: | |||
1370 | * need to clear it here and can't really impose on all other arches. | 1386 | * need to clear it here and can't really impose on all other arches. |
1371 | * So what's another write between friends? | 1387 | * So what's another write between friends? |
1372 | */ | 1388 | */ |
1373 | GET_THREAD_INFO(r0) | ||
1374 | 1389 | ||
1375 | addi r1, r0, THREAD_INFO_FLAGS_OFFSET | 1390 | addi r1, r0, THREAD_INFO_FLAGS_OFFSET |
1376 | { | 1391 | { |
diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S index 49d9d6621682..30ae76e50c44 100644 --- a/arch/tile/kernel/intvec_64.S +++ b/arch/tile/kernel/intvec_64.S | |||
@@ -647,6 +647,20 @@ STD_ENTRY(interrupt_return) | |||
647 | FEEDBACK_REENTER(interrupt_return) | 647 | FEEDBACK_REENTER(interrupt_return) |
648 | 648 | ||
649 | /* | 649 | /* |
650 | * Use r33 to hold whether we have already loaded the callee-saves | ||
651 | * into ptregs. We don't want to do it twice in this loop, since | ||
652 | * then we'd clobber whatever changes are made by ptrace, etc. | ||
653 | */ | ||
654 | { | ||
655 | movei r33, 0 | ||
656 | move r32, sp | ||
657 | } | ||
658 | |||
659 | /* Get base of stack in r32. */ | ||
660 | EXTRACT_THREAD_INFO(r32) | ||
661 | |||
662 | .Lretry_work_pending: | ||
663 | /* | ||
650 | * Disable interrupts so as to make sure we don't | 664 | * Disable interrupts so as to make sure we don't |
651 | * miss an interrupt that sets any of the thread flags (like | 665 | * miss an interrupt that sets any of the thread flags (like |
652 | * need_resched or sigpending) between sampling and the iret. | 666 | * need_resched or sigpending) between sampling and the iret. |
@@ -656,9 +670,6 @@ STD_ENTRY(interrupt_return) | |||
656 | IRQ_DISABLE(r20, r21) | 670 | IRQ_DISABLE(r20, r21) |
657 | TRACE_IRQS_OFF /* Note: clobbers registers r0-r29 */ | 671 | TRACE_IRQS_OFF /* Note: clobbers registers r0-r29 */ |
658 | 672 | ||
659 | /* Get base of stack in r32; note r30/31 are used as arguments here. */ | ||
660 | GET_THREAD_INFO(r32) | ||
661 | |||
662 | 673 | ||
663 | /* Check to see if there is any work to do before returning to user. */ | 674 | /* Check to see if there is any work to do before returning to user. */ |
664 | { | 675 | { |
@@ -674,16 +685,18 @@ STD_ENTRY(interrupt_return) | |||
674 | 685 | ||
675 | /* | 686 | /* |
676 | * Make sure we have all the registers saved for signal | 687 | * Make sure we have all the registers saved for signal |
677 | * handling or single-step. Call out to C code to figure out | 688 | * handling or notify-resume. Call out to C code to figure out |
678 | * exactly what we need to do for each flag bit, then if | 689 | * exactly what we need to do for each flag bit, then if |
679 | * necessary, reload the flags and recheck. | 690 | * necessary, reload the flags and recheck. |
680 | */ | 691 | */ |
681 | push_extra_callee_saves r0 | ||
682 | { | 692 | { |
683 | PTREGS_PTR(r0, PTREGS_OFFSET_BASE) | 693 | PTREGS_PTR(r0, PTREGS_OFFSET_BASE) |
684 | jal do_work_pending | 694 | bnez r33, 1f |
685 | } | 695 | } |
686 | bnez r0, .Lresume_userspace | 696 | push_extra_callee_saves r0 |
697 | movei r33, 1 | ||
698 | 1: jal do_work_pending | ||
699 | bnez r0, .Lretry_work_pending | ||
687 | 700 | ||
688 | /* | 701 | /* |
689 | * In the NMI case we | 702 | * In the NMI case we |
@@ -968,11 +981,16 @@ handle_syscall: | |||
968 | shl16insli r20, r20, hw0(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET) | 981 | shl16insli r20, r20, hw0(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET) |
969 | add r20, r20, tp | 982 | add r20, r20, tp |
970 | ld4s r21, r20 | 983 | ld4s r21, r20 |
971 | addi r21, r21, 1 | 984 | { |
972 | st4 r20, r21 | 985 | addi r21, r21, 1 |
986 | move r31, sp | ||
987 | } | ||
988 | { | ||
989 | st4 r20, r21 | ||
990 | EXTRACT_THREAD_INFO(r31) | ||
991 | } | ||
973 | 992 | ||
974 | /* Trace syscalls, if requested. */ | 993 | /* Trace syscalls, if requested. */ |
975 | GET_THREAD_INFO(r31) | ||
976 | addi r31, r31, THREAD_INFO_FLAGS_OFFSET | 994 | addi r31, r31, THREAD_INFO_FLAGS_OFFSET |
977 | ld r30, r31 | 995 | ld r30, r31 |
978 | andi r30, r30, _TIF_SYSCALL_TRACE | 996 | andi r30, r30, _TIF_SYSCALL_TRACE |
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 2d5ef617bb39..54e6c64b85cc 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c | |||
@@ -567,6 +567,10 @@ struct task_struct *__sched _switch_to(struct task_struct *prev, | |||
567 | */ | 567 | */ |
568 | int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) | 568 | int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) |
569 | { | 569 | { |
570 | /* If we enter in kernel mode, do nothing and exit the caller loop. */ | ||
571 | if (!user_mode(regs)) | ||
572 | return 0; | ||
573 | |||
570 | if (thread_info_flags & _TIF_NEED_RESCHED) { | 574 | if (thread_info_flags & _TIF_NEED_RESCHED) { |
571 | schedule(); | 575 | schedule(); |
572 | return 1; | 576 | return 1; |
@@ -589,8 +593,7 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) | |||
589 | return 1; | 593 | return 1; |
590 | } | 594 | } |
591 | if (thread_info_flags & _TIF_SINGLESTEP) { | 595 | if (thread_info_flags & _TIF_SINGLESTEP) { |
592 | if ((regs->ex1 & SPR_EX_CONTEXT_1_1__PL_MASK) == 0) | 596 | single_step_once(regs); |
593 | single_step_once(regs); | ||
594 | return 0; | 597 | return 0; |
595 | } | 598 | } |
596 | panic("work_pending: bad flags %#x\n", thread_info_flags); | 599 | panic("work_pending: bad flags %#x\n", thread_info_flags); |
diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 41a7237606a3..94e91e401da9 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile | |||
@@ -134,6 +134,9 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,) | |||
134 | KBUILD_CFLAGS += $(mflags-y) | 134 | KBUILD_CFLAGS += $(mflags-y) |
135 | KBUILD_AFLAGS += $(mflags-y) | 135 | KBUILD_AFLAGS += $(mflags-y) |
136 | 136 | ||
137 | archscripts: | ||
138 | $(Q)$(MAKE) $(build)=arch/x86/tools relocs | ||
139 | |||
137 | ### | 140 | ### |
138 | # Syscall table generation | 141 | # Syscall table generation |
139 | 142 | ||
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index fd55a2ff3ad8..e398bb5d63bb 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile | |||
@@ -40,13 +40,12 @@ OBJCOPYFLAGS_vmlinux.bin := -R .comment -S | |||
40 | $(obj)/vmlinux.bin: vmlinux FORCE | 40 | $(obj)/vmlinux.bin: vmlinux FORCE |
41 | $(call if_changed,objcopy) | 41 | $(call if_changed,objcopy) |
42 | 42 | ||
43 | targets += vmlinux.bin.all vmlinux.relocs | ||
43 | 44 | ||
44 | targets += vmlinux.bin.all vmlinux.relocs relocs | 45 | CMD_RELOCS = arch/x86/tools/relocs |
45 | hostprogs-$(CONFIG_X86_NEED_RELOCS) += relocs | ||
46 | |||
47 | quiet_cmd_relocs = RELOCS $@ | 46 | quiet_cmd_relocs = RELOCS $@ |
48 | cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $< | 47 | cmd_relocs = $(CMD_RELOCS) $< > $@;$(CMD_RELOCS) --abs-relocs $< |
49 | $(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE | 48 | $(obj)/vmlinux.relocs: vmlinux FORCE |
50 | $(call if_changed,relocs) | 49 | $(call if_changed,relocs) |
51 | 50 | ||
52 | vmlinux.bin.all-y := $(obj)/vmlinux.bin | 51 | vmlinux.bin.all-y := $(obj)/vmlinux.bin |
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h index 734c3767cfac..183922e13de1 100644 --- a/arch/x86/include/asm/kvm_para.h +++ b/arch/x86/include/asm/kvm_para.h | |||
@@ -170,6 +170,9 @@ static inline int kvm_para_available(void) | |||
170 | unsigned int eax, ebx, ecx, edx; | 170 | unsigned int eax, ebx, ecx, edx; |
171 | char signature[13]; | 171 | char signature[13]; |
172 | 172 | ||
173 | if (boot_cpu_data.cpuid_level < 0) | ||
174 | return 0; /* So we don't blow up on old processors */ | ||
175 | |||
173 | cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx); | 176 | cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx); |
174 | memcpy(signature + 0, &ebx, 4); | 177 | memcpy(signature + 0, &ebx, 4); |
175 | memcpy(signature + 4, &ecx, 4); | 178 | memcpy(signature + 4, &ecx, 4); |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index a415b1f44365..7c439fe4941b 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -593,7 +593,7 @@ void __init acpi_set_irq_model_ioapic(void) | |||
593 | #ifdef CONFIG_ACPI_HOTPLUG_CPU | 593 | #ifdef CONFIG_ACPI_HOTPLUG_CPU |
594 | #include <acpi/processor.h> | 594 | #include <acpi/processor.h> |
595 | 595 | ||
596 | static void __cpuinitdata acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) | 596 | static void __cpuinit acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) |
597 | { | 597 | { |
598 | #ifdef CONFIG_ACPI_NUMA | 598 | #ifdef CONFIG_ACPI_NUMA |
599 | int nid; | 599 | int nid; |
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index d086a09c087d..11c9166c3337 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
@@ -945,9 +945,10 @@ struct mce_info { | |||
945 | atomic_t inuse; | 945 | atomic_t inuse; |
946 | struct task_struct *t; | 946 | struct task_struct *t; |
947 | __u64 paddr; | 947 | __u64 paddr; |
948 | int restartable; | ||
948 | } mce_info[MCE_INFO_MAX]; | 949 | } mce_info[MCE_INFO_MAX]; |
949 | 950 | ||
950 | static void mce_save_info(__u64 addr) | 951 | static void mce_save_info(__u64 addr, int c) |
951 | { | 952 | { |
952 | struct mce_info *mi; | 953 | struct mce_info *mi; |
953 | 954 | ||
@@ -955,6 +956,7 @@ static void mce_save_info(__u64 addr) | |||
955 | if (atomic_cmpxchg(&mi->inuse, 0, 1) == 0) { | 956 | if (atomic_cmpxchg(&mi->inuse, 0, 1) == 0) { |
956 | mi->t = current; | 957 | mi->t = current; |
957 | mi->paddr = addr; | 958 | mi->paddr = addr; |
959 | mi->restartable = c; | ||
958 | return; | 960 | return; |
959 | } | 961 | } |
960 | } | 962 | } |
@@ -1130,7 +1132,7 @@ void do_machine_check(struct pt_regs *regs, long error_code) | |||
1130 | mce_panic("Fatal machine check on current CPU", &m, msg); | 1132 | mce_panic("Fatal machine check on current CPU", &m, msg); |
1131 | if (worst == MCE_AR_SEVERITY) { | 1133 | if (worst == MCE_AR_SEVERITY) { |
1132 | /* schedule action before return to userland */ | 1134 | /* schedule action before return to userland */ |
1133 | mce_save_info(m.addr); | 1135 | mce_save_info(m.addr, m.mcgstatus & MCG_STATUS_RIPV); |
1134 | set_thread_flag(TIF_MCE_NOTIFY); | 1136 | set_thread_flag(TIF_MCE_NOTIFY); |
1135 | } else if (kill_it) { | 1137 | } else if (kill_it) { |
1136 | force_sig(SIGBUS, current); | 1138 | force_sig(SIGBUS, current); |
@@ -1179,7 +1181,13 @@ void mce_notify_process(void) | |||
1179 | 1181 | ||
1180 | pr_err("Uncorrected hardware memory error in user-access at %llx", | 1182 | pr_err("Uncorrected hardware memory error in user-access at %llx", |
1181 | mi->paddr); | 1183 | mi->paddr); |
1182 | if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0) { | 1184 | /* |
1185 | * We must call memory_failure() here even if the current process is | ||
1186 | * doomed. We still need to mark the page as poisoned and alert any | ||
1187 | * other users of the page. | ||
1188 | */ | ||
1189 | if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0 || | ||
1190 | mi->restartable == 0) { | ||
1183 | pr_err("Memory error not recovered"); | 1191 | pr_err("Memory error not recovered"); |
1184 | force_sig(SIGBUS, current); | 1192 | force_sig(SIGBUS, current); |
1185 | } | 1193 | } |
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 3ca42d0e43a2..0327e2b3c408 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c | |||
@@ -147,12 +147,6 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) | |||
147 | 147 | ||
148 | memset(csig, 0, sizeof(*csig)); | 148 | memset(csig, 0, sizeof(*csig)); |
149 | 149 | ||
150 | if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || | ||
151 | cpu_has(c, X86_FEATURE_IA64)) { | ||
152 | pr_err("CPU%d not a capable Intel processor\n", cpu_num); | ||
153 | return -1; | ||
154 | } | ||
155 | |||
156 | csig->sig = cpuid_eax(0x00000001); | 150 | csig->sig = cpuid_eax(0x00000001); |
157 | 151 | ||
158 | if ((c->x86_model >= 5) || (c->x86 > 6)) { | 152 | if ((c->x86_model >= 5) || (c->x86 > 6)) { |
@@ -463,6 +457,14 @@ static struct microcode_ops microcode_intel_ops = { | |||
463 | 457 | ||
464 | struct microcode_ops * __init init_intel_microcode(void) | 458 | struct microcode_ops * __init init_intel_microcode(void) |
465 | { | 459 | { |
460 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
461 | |||
462 | if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || | ||
463 | cpu_has(c, X86_FEATURE_IA64)) { | ||
464 | pr_err("Intel CPU family 0x%x not supported\n", c->x86); | ||
465 | return NULL; | ||
466 | } | ||
467 | |||
466 | return µcode_intel_ops; | 468 | return µcode_intel_ops; |
467 | } | 469 | } |
468 | 470 | ||
diff --git a/arch/x86/tools/.gitignore b/arch/x86/tools/.gitignore new file mode 100644 index 000000000000..be0ed065249b --- /dev/null +++ b/arch/x86/tools/.gitignore | |||
@@ -0,0 +1 @@ | |||
relocs | |||
diff --git a/arch/x86/tools/Makefile b/arch/x86/tools/Makefile index d511aa97533a..733057b435b0 100644 --- a/arch/x86/tools/Makefile +++ b/arch/x86/tools/Makefile | |||
@@ -36,3 +36,7 @@ HOSTCFLAGS_insn_sanity.o := -Wall -I$(objtree)/arch/x86/lib/ -I$(srctree)/arch/x | |||
36 | $(obj)/test_get_len.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c | 36 | $(obj)/test_get_len.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c |
37 | 37 | ||
38 | $(obj)/insn_sanity.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c | 38 | $(obj)/insn_sanity.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c |
39 | |||
40 | HOST_EXTRACFLAGS += -I$(srctree)/tools/include | ||
41 | hostprogs-y += relocs | ||
42 | relocs: $(obj)/relocs | ||
diff --git a/arch/x86/boot/compressed/relocs.c b/arch/x86/tools/relocs.c index fb7117a4ade1..b43cfcd9bf40 100644 --- a/arch/x86/boot/compressed/relocs.c +++ b/arch/x86/tools/relocs.c | |||
@@ -18,6 +18,8 @@ static void die(char *fmt, ...); | |||
18 | static Elf32_Ehdr ehdr; | 18 | static Elf32_Ehdr ehdr; |
19 | static unsigned long reloc_count, reloc_idx; | 19 | static unsigned long reloc_count, reloc_idx; |
20 | static unsigned long *relocs; | 20 | static unsigned long *relocs; |
21 | static unsigned long reloc16_count, reloc16_idx; | ||
22 | static unsigned long *relocs16; | ||
21 | 23 | ||
22 | struct section { | 24 | struct section { |
23 | Elf32_Shdr shdr; | 25 | Elf32_Shdr shdr; |
@@ -28,52 +30,86 @@ struct section { | |||
28 | }; | 30 | }; |
29 | static struct section *secs; | 31 | static struct section *secs; |
30 | 32 | ||
33 | enum symtype { | ||
34 | S_ABS, | ||
35 | S_REL, | ||
36 | S_SEG, | ||
37 | S_LIN, | ||
38 | S_NSYMTYPES | ||
39 | }; | ||
40 | |||
41 | static const char * const sym_regex_kernel[S_NSYMTYPES] = { | ||
31 | /* | 42 | /* |
32 | * Following symbols have been audited. There values are constant and do | 43 | * Following symbols have been audited. There values are constant and do |
33 | * not change if bzImage is loaded at a different physical address than | 44 | * not change if bzImage is loaded at a different physical address than |
34 | * the address for which it has been compiled. Don't warn user about | 45 | * the address for which it has been compiled. Don't warn user about |
35 | * absolute relocations present w.r.t these symbols. | 46 | * absolute relocations present w.r.t these symbols. |
36 | */ | 47 | */ |
37 | static const char abs_sym_regex[] = | 48 | [S_ABS] = |
38 | "^(xen_irq_disable_direct_reloc$|" | 49 | "^(xen_irq_disable_direct_reloc$|" |
39 | "xen_save_fl_direct_reloc$|" | 50 | "xen_save_fl_direct_reloc$|" |
40 | "VDSO|" | 51 | "VDSO|" |
41 | "__crc_)"; | 52 | "__crc_)", |
42 | static regex_t abs_sym_regex_c; | ||
43 | static int is_abs_reloc(const char *sym_name) | ||
44 | { | ||
45 | return !regexec(&abs_sym_regex_c, sym_name, 0, NULL, 0); | ||
46 | } | ||
47 | 53 | ||
48 | /* | 54 | /* |
49 | * These symbols are known to be relative, even if the linker marks them | 55 | * These symbols are known to be relative, even if the linker marks them |
50 | * as absolute (typically defined outside any section in the linker script.) | 56 | * as absolute (typically defined outside any section in the linker script.) |
51 | */ | 57 | */ |
52 | static const char rel_sym_regex[] = | 58 | [S_REL] = |
53 | "^_end$"; | 59 | "^(__init_(begin|end)|" |
54 | static regex_t rel_sym_regex_c; | 60 | "__x86_cpu_dev_(start|end)|" |
55 | static int is_rel_reloc(const char *sym_name) | 61 | "(__parainstructions|__alt_instructions)(|_end)|" |
62 | "(__iommu_table|__apicdrivers|__smp_locks)(|_end)|" | ||
63 | "_end)$" | ||
64 | }; | ||
65 | |||
66 | |||
67 | static const char * const sym_regex_realmode[S_NSYMTYPES] = { | ||
68 | /* | ||
69 | * These are 16-bit segment symbols when compiling 16-bit code. | ||
70 | */ | ||
71 | [S_SEG] = | ||
72 | "^real_mode_seg$", | ||
73 | |||
74 | /* | ||
75 | * These are offsets belonging to segments, as opposed to linear addresses, | ||
76 | * when compiling 16-bit code. | ||
77 | */ | ||
78 | [S_LIN] = | ||
79 | "^pa_", | ||
80 | }; | ||
81 | |||
82 | static const char * const *sym_regex; | ||
83 | |||
84 | static regex_t sym_regex_c[S_NSYMTYPES]; | ||
85 | static int is_reloc(enum symtype type, const char *sym_name) | ||
56 | { | 86 | { |
57 | return !regexec(&rel_sym_regex_c, sym_name, 0, NULL, 0); | 87 | return sym_regex[type] && |
88 | !regexec(&sym_regex_c[type], sym_name, 0, NULL, 0); | ||
58 | } | 89 | } |
59 | 90 | ||
60 | static void regex_init(void) | 91 | static void regex_init(int use_real_mode) |
61 | { | 92 | { |
62 | char errbuf[128]; | 93 | char errbuf[128]; |
63 | int err; | 94 | int err; |
64 | 95 | int i; | |
65 | err = regcomp(&abs_sym_regex_c, abs_sym_regex, | 96 | |
66 | REG_EXTENDED|REG_NOSUB); | 97 | if (use_real_mode) |
67 | if (err) { | 98 | sym_regex = sym_regex_realmode; |
68 | regerror(err, &abs_sym_regex_c, errbuf, sizeof errbuf); | 99 | else |
69 | die("%s", errbuf); | 100 | sym_regex = sym_regex_kernel; |
70 | } | ||
71 | 101 | ||
72 | err = regcomp(&rel_sym_regex_c, rel_sym_regex, | 102 | for (i = 0; i < S_NSYMTYPES; i++) { |
73 | REG_EXTENDED|REG_NOSUB); | 103 | if (!sym_regex[i]) |
74 | if (err) { | 104 | continue; |
75 | regerror(err, &rel_sym_regex_c, errbuf, sizeof errbuf); | 105 | |
76 | die("%s", errbuf); | 106 | err = regcomp(&sym_regex_c[i], sym_regex[i], |
107 | REG_EXTENDED|REG_NOSUB); | ||
108 | |||
109 | if (err) { | ||
110 | regerror(err, &sym_regex_c[i], errbuf, sizeof errbuf); | ||
111 | die("%s", errbuf); | ||
112 | } | ||
77 | } | 113 | } |
78 | } | 114 | } |
79 | 115 | ||
@@ -154,6 +190,10 @@ static const char *rel_type(unsigned type) | |||
154 | REL_TYPE(R_386_RELATIVE), | 190 | REL_TYPE(R_386_RELATIVE), |
155 | REL_TYPE(R_386_GOTOFF), | 191 | REL_TYPE(R_386_GOTOFF), |
156 | REL_TYPE(R_386_GOTPC), | 192 | REL_TYPE(R_386_GOTPC), |
193 | REL_TYPE(R_386_8), | ||
194 | REL_TYPE(R_386_PC8), | ||
195 | REL_TYPE(R_386_16), | ||
196 | REL_TYPE(R_386_PC16), | ||
157 | #undef REL_TYPE | 197 | #undef REL_TYPE |
158 | }; | 198 | }; |
159 | const char *name = "unknown type rel type name"; | 199 | const char *name = "unknown type rel type name"; |
@@ -189,7 +229,7 @@ static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym) | |||
189 | name = sym_strtab + sym->st_name; | 229 | name = sym_strtab + sym->st_name; |
190 | } | 230 | } |
191 | else { | 231 | else { |
192 | name = sec_name(secs[sym->st_shndx].shdr.sh_name); | 232 | name = sec_name(sym->st_shndx); |
193 | } | 233 | } |
194 | return name; | 234 | return name; |
195 | } | 235 | } |
@@ -472,7 +512,7 @@ static void print_absolute_relocs(void) | |||
472 | * Before warning check if this absolute symbol | 512 | * Before warning check if this absolute symbol |
473 | * relocation is harmless. | 513 | * relocation is harmless. |
474 | */ | 514 | */ |
475 | if (is_abs_reloc(name) || is_rel_reloc(name)) | 515 | if (is_reloc(S_ABS, name) || is_reloc(S_REL, name)) |
476 | continue; | 516 | continue; |
477 | 517 | ||
478 | if (!printed) { | 518 | if (!printed) { |
@@ -496,7 +536,8 @@ static void print_absolute_relocs(void) | |||
496 | printf("\n"); | 536 | printf("\n"); |
497 | } | 537 | } |
498 | 538 | ||
499 | static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) | 539 | static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym), |
540 | int use_real_mode) | ||
500 | { | 541 | { |
501 | int i; | 542 | int i; |
502 | /* Walk through the relocations */ | 543 | /* Walk through the relocations */ |
@@ -521,30 +562,67 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) | |||
521 | Elf32_Rel *rel; | 562 | Elf32_Rel *rel; |
522 | Elf32_Sym *sym; | 563 | Elf32_Sym *sym; |
523 | unsigned r_type; | 564 | unsigned r_type; |
565 | const char *symname; | ||
566 | int shn_abs; | ||
567 | |||
524 | rel = &sec->reltab[j]; | 568 | rel = &sec->reltab[j]; |
525 | sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; | 569 | sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; |
526 | r_type = ELF32_R_TYPE(rel->r_info); | 570 | r_type = ELF32_R_TYPE(rel->r_info); |
527 | /* Don't visit relocations to absolute symbols */ | 571 | |
528 | if (sym->st_shndx == SHN_ABS && | 572 | shn_abs = sym->st_shndx == SHN_ABS; |
529 | !is_rel_reloc(sym_name(sym_strtab, sym))) { | 573 | |
530 | continue; | ||
531 | } | ||
532 | switch (r_type) { | 574 | switch (r_type) { |
533 | case R_386_NONE: | 575 | case R_386_NONE: |
534 | case R_386_PC32: | 576 | case R_386_PC32: |
577 | case R_386_PC16: | ||
578 | case R_386_PC8: | ||
535 | /* | 579 | /* |
536 | * NONE can be ignored and and PC relative | 580 | * NONE can be ignored and and PC relative |
537 | * relocations don't need to be adjusted. | 581 | * relocations don't need to be adjusted. |
538 | */ | 582 | */ |
539 | break; | 583 | break; |
584 | |||
585 | case R_386_16: | ||
586 | symname = sym_name(sym_strtab, sym); | ||
587 | if (!use_real_mode) | ||
588 | goto bad; | ||
589 | if (shn_abs) { | ||
590 | if (is_reloc(S_ABS, symname)) | ||
591 | break; | ||
592 | else if (!is_reloc(S_SEG, symname)) | ||
593 | goto bad; | ||
594 | } else { | ||
595 | if (is_reloc(S_LIN, symname)) | ||
596 | goto bad; | ||
597 | else | ||
598 | break; | ||
599 | } | ||
600 | visit(rel, sym); | ||
601 | break; | ||
602 | |||
540 | case R_386_32: | 603 | case R_386_32: |
541 | /* Visit relocations that need to be adjusted */ | 604 | symname = sym_name(sym_strtab, sym); |
605 | if (shn_abs) { | ||
606 | if (is_reloc(S_ABS, symname)) | ||
607 | break; | ||
608 | else if (!is_reloc(S_REL, symname)) | ||
609 | goto bad; | ||
610 | } else { | ||
611 | if (use_real_mode && | ||
612 | !is_reloc(S_LIN, symname)) | ||
613 | break; | ||
614 | } | ||
542 | visit(rel, sym); | 615 | visit(rel, sym); |
543 | break; | 616 | break; |
544 | default: | 617 | default: |
545 | die("Unsupported relocation type: %s (%d)\n", | 618 | die("Unsupported relocation type: %s (%d)\n", |
546 | rel_type(r_type), r_type); | 619 | rel_type(r_type), r_type); |
547 | break; | 620 | break; |
621 | bad: | ||
622 | symname = sym_name(sym_strtab, sym); | ||
623 | die("Invalid %s %s relocation: %s\n", | ||
624 | shn_abs ? "absolute" : "relative", | ||
625 | rel_type(r_type), symname); | ||
548 | } | 626 | } |
549 | } | 627 | } |
550 | } | 628 | } |
@@ -552,13 +630,19 @@ static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) | |||
552 | 630 | ||
553 | static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym) | 631 | static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym) |
554 | { | 632 | { |
555 | reloc_count += 1; | 633 | if (ELF32_R_TYPE(rel->r_info) == R_386_16) |
634 | reloc16_count++; | ||
635 | else | ||
636 | reloc_count++; | ||
556 | } | 637 | } |
557 | 638 | ||
558 | static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) | 639 | static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) |
559 | { | 640 | { |
560 | /* Remember the address that needs to be adjusted. */ | 641 | /* Remember the address that needs to be adjusted. */ |
561 | relocs[reloc_idx++] = rel->r_offset; | 642 | if (ELF32_R_TYPE(rel->r_info) == R_386_16) |
643 | relocs16[reloc16_idx++] = rel->r_offset; | ||
644 | else | ||
645 | relocs[reloc_idx++] = rel->r_offset; | ||
562 | } | 646 | } |
563 | 647 | ||
564 | static int cmp_relocs(const void *va, const void *vb) | 648 | static int cmp_relocs(const void *va, const void *vb) |
@@ -568,23 +652,41 @@ static int cmp_relocs(const void *va, const void *vb) | |||
568 | return (*a == *b)? 0 : (*a > *b)? 1 : -1; | 652 | return (*a == *b)? 0 : (*a > *b)? 1 : -1; |
569 | } | 653 | } |
570 | 654 | ||
571 | static void emit_relocs(int as_text) | 655 | static int write32(unsigned int v, FILE *f) |
656 | { | ||
657 | unsigned char buf[4]; | ||
658 | |||
659 | put_unaligned_le32(v, buf); | ||
660 | return fwrite(buf, 1, 4, f) == 4 ? 0 : -1; | ||
661 | } | ||
662 | |||
663 | static void emit_relocs(int as_text, int use_real_mode) | ||
572 | { | 664 | { |
573 | int i; | 665 | int i; |
574 | /* Count how many relocations I have and allocate space for them. */ | 666 | /* Count how many relocations I have and allocate space for them. */ |
575 | reloc_count = 0; | 667 | reloc_count = 0; |
576 | walk_relocs(count_reloc); | 668 | walk_relocs(count_reloc, use_real_mode); |
577 | relocs = malloc(reloc_count * sizeof(relocs[0])); | 669 | relocs = malloc(reloc_count * sizeof(relocs[0])); |
578 | if (!relocs) { | 670 | if (!relocs) { |
579 | die("malloc of %d entries for relocs failed\n", | 671 | die("malloc of %d entries for relocs failed\n", |
580 | reloc_count); | 672 | reloc_count); |
581 | } | 673 | } |
674 | |||
675 | relocs16 = malloc(reloc16_count * sizeof(relocs[0])); | ||
676 | if (!relocs16) { | ||
677 | die("malloc of %d entries for relocs16 failed\n", | ||
678 | reloc16_count); | ||
679 | } | ||
582 | /* Collect up the relocations */ | 680 | /* Collect up the relocations */ |
583 | reloc_idx = 0; | 681 | reloc_idx = 0; |
584 | walk_relocs(collect_reloc); | 682 | walk_relocs(collect_reloc, use_real_mode); |
683 | |||
684 | if (reloc16_count && !use_real_mode) | ||
685 | die("Segment relocations found but --realmode not specified\n"); | ||
585 | 686 | ||
586 | /* Order the relocations for more efficient processing */ | 687 | /* Order the relocations for more efficient processing */ |
587 | qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs); | 688 | qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs); |
689 | qsort(relocs16, reloc16_count, sizeof(relocs16[0]), cmp_relocs); | ||
588 | 690 | ||
589 | /* Print the relocations */ | 691 | /* Print the relocations */ |
590 | if (as_text) { | 692 | if (as_text) { |
@@ -593,58 +695,83 @@ static void emit_relocs(int as_text) | |||
593 | */ | 695 | */ |
594 | printf(".section \".data.reloc\",\"a\"\n"); | 696 | printf(".section \".data.reloc\",\"a\"\n"); |
595 | printf(".balign 4\n"); | 697 | printf(".balign 4\n"); |
596 | for (i = 0; i < reloc_count; i++) { | 698 | if (use_real_mode) { |
597 | printf("\t .long 0x%08lx\n", relocs[i]); | 699 | printf("\t.long %lu\n", reloc16_count); |
700 | for (i = 0; i < reloc16_count; i++) | ||
701 | printf("\t.long 0x%08lx\n", relocs16[i]); | ||
702 | printf("\t.long %lu\n", reloc_count); | ||
703 | for (i = 0; i < reloc_count; i++) { | ||
704 | printf("\t.long 0x%08lx\n", relocs[i]); | ||
705 | } | ||
706 | } else { | ||
707 | /* Print a stop */ | ||
708 | printf("\t.long 0x%08lx\n", (unsigned long)0); | ||
709 | for (i = 0; i < reloc_count; i++) { | ||
710 | printf("\t.long 0x%08lx\n", relocs[i]); | ||
711 | } | ||
598 | } | 712 | } |
713 | |||
599 | printf("\n"); | 714 | printf("\n"); |
600 | } | 715 | } |
601 | else { | 716 | else { |
602 | unsigned char buf[4]; | 717 | if (use_real_mode) { |
603 | /* Print a stop */ | 718 | write32(reloc16_count, stdout); |
604 | fwrite("\0\0\0\0", 4, 1, stdout); | 719 | for (i = 0; i < reloc16_count; i++) |
605 | /* Now print each relocation */ | 720 | write32(relocs16[i], stdout); |
606 | for (i = 0; i < reloc_count; i++) { | 721 | write32(reloc_count, stdout); |
607 | put_unaligned_le32(relocs[i], buf); | 722 | |
608 | fwrite(buf, 4, 1, stdout); | 723 | /* Now print each relocation */ |
724 | for (i = 0; i < reloc_count; i++) | ||
725 | write32(relocs[i], stdout); | ||
726 | } else { | ||
727 | /* Print a stop */ | ||
728 | write32(0, stdout); | ||
729 | |||
730 | /* Now print each relocation */ | ||
731 | for (i = 0; i < reloc_count; i++) { | ||
732 | write32(relocs[i], stdout); | ||
733 | } | ||
609 | } | 734 | } |
610 | } | 735 | } |
611 | } | 736 | } |
612 | 737 | ||
613 | static void usage(void) | 738 | static void usage(void) |
614 | { | 739 | { |
615 | die("relocs [--abs-syms |--abs-relocs | --text] vmlinux\n"); | 740 | die("relocs [--abs-syms|--abs-relocs|--text|--realmode] vmlinux\n"); |
616 | } | 741 | } |
617 | 742 | ||
618 | int main(int argc, char **argv) | 743 | int main(int argc, char **argv) |
619 | { | 744 | { |
620 | int show_absolute_syms, show_absolute_relocs; | 745 | int show_absolute_syms, show_absolute_relocs; |
621 | int as_text; | 746 | int as_text, use_real_mode; |
622 | const char *fname; | 747 | const char *fname; |
623 | FILE *fp; | 748 | FILE *fp; |
624 | int i; | 749 | int i; |
625 | 750 | ||
626 | regex_init(); | ||
627 | |||
628 | show_absolute_syms = 0; | 751 | show_absolute_syms = 0; |
629 | show_absolute_relocs = 0; | 752 | show_absolute_relocs = 0; |
630 | as_text = 0; | 753 | as_text = 0; |
754 | use_real_mode = 0; | ||
631 | fname = NULL; | 755 | fname = NULL; |
632 | for (i = 1; i < argc; i++) { | 756 | for (i = 1; i < argc; i++) { |
633 | char *arg = argv[i]; | 757 | char *arg = argv[i]; |
634 | if (*arg == '-') { | 758 | if (*arg == '-') { |
635 | if (strcmp(argv[1], "--abs-syms") == 0) { | 759 | if (strcmp(arg, "--abs-syms") == 0) { |
636 | show_absolute_syms = 1; | 760 | show_absolute_syms = 1; |
637 | continue; | 761 | continue; |
638 | } | 762 | } |
639 | 763 | if (strcmp(arg, "--abs-relocs") == 0) { | |
640 | if (strcmp(argv[1], "--abs-relocs") == 0) { | ||
641 | show_absolute_relocs = 1; | 764 | show_absolute_relocs = 1; |
642 | continue; | 765 | continue; |
643 | } | 766 | } |
644 | else if (strcmp(argv[1], "--text") == 0) { | 767 | if (strcmp(arg, "--text") == 0) { |
645 | as_text = 1; | 768 | as_text = 1; |
646 | continue; | 769 | continue; |
647 | } | 770 | } |
771 | if (strcmp(arg, "--realmode") == 0) { | ||
772 | use_real_mode = 1; | ||
773 | continue; | ||
774 | } | ||
648 | } | 775 | } |
649 | else if (!fname) { | 776 | else if (!fname) { |
650 | fname = arg; | 777 | fname = arg; |
@@ -655,6 +782,7 @@ int main(int argc, char **argv) | |||
655 | if (!fname) { | 782 | if (!fname) { |
656 | usage(); | 783 | usage(); |
657 | } | 784 | } |
785 | regex_init(use_real_mode); | ||
658 | fp = fopen(fname, "r"); | 786 | fp = fopen(fname, "r"); |
659 | if (!fp) { | 787 | if (!fp) { |
660 | die("Cannot open %s: %s\n", | 788 | die("Cannot open %s: %s\n", |
@@ -673,6 +801,6 @@ int main(int argc, char **argv) | |||
673 | print_absolute_relocs(); | 801 | print_absolute_relocs(); |
674 | return 0; | 802 | return 0; |
675 | } | 803 | } |
676 | emit_relocs(as_text); | 804 | emit_relocs(as_text, use_real_mode); |
677 | return 0; | 805 | return 0; |
678 | } | 806 | } |