diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/kernel/armksyms.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/asm-offsets.c | 12 | ||||
-rw-r--r-- | arch/arm/kernel/bios32.c | 9 | ||||
-rw-r--r-- | arch/arm/kernel/debug.S | 4 | ||||
-rw-r--r-- | arch/arm/kernel/dma.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/ecard.c | 36 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 44 | ||||
-rw-r--r-- | arch/arm/kernel/head.S | 135 | ||||
-rw-r--r-- | arch/arm/kernel/irq.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/machine_kexec.c | 35 | ||||
-rw-r--r-- | arch/arm/kernel/module.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 37 | ||||
-rw-r--r-- | arch/arm/kernel/smp.c | 61 | ||||
-rw-r--r-- | arch/arm/kernel/smp_scu.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/time.c | 6 | ||||
-rw-r--r-- | arch/arm/kernel/topology.c | 148 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 52 | ||||
-rw-r--r-- | arch/arm/kernel/vmlinux.lds.S | 3 |
20 files changed, 411 insertions, 187 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index f7887dc53c1f..68036eece340 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -29,7 +29,7 @@ obj-$(CONFIG_MODULES) += armksyms.o module.o | |||
29 | obj-$(CONFIG_ARTHUR) += arthur.o | 29 | obj-$(CONFIG_ARTHUR) += arthur.o |
30 | obj-$(CONFIG_ISA_DMA) += dma-isa.o | 30 | obj-$(CONFIG_ISA_DMA) += dma-isa.o |
31 | obj-$(CONFIG_PCI) += bios32.o isa.o | 31 | obj-$(CONFIG_PCI) += bios32.o isa.o |
32 | obj-$(CONFIG_PM_SLEEP) += sleep.o | 32 | obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o |
33 | obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o | 33 | obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o |
34 | obj-$(CONFIG_SMP) += smp.o smp_tlb.o | 34 | obj-$(CONFIG_SMP) += smp.o smp_tlb.o |
35 | obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o | 35 | obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o |
@@ -66,6 +66,7 @@ obj-$(CONFIG_IWMMXT) += iwmmxt.o | |||
66 | obj-$(CONFIG_CPU_HAS_PMU) += pmu.o | 66 | obj-$(CONFIG_CPU_HAS_PMU) += pmu.o |
67 | obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o | 67 | obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o |
68 | AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt | 68 | AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt |
69 | obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o | ||
69 | 70 | ||
70 | ifneq ($(CONFIG_ARCH_EBSA110),y) | 71 | ifneq ($(CONFIG_ARCH_EBSA110),y) |
71 | obj-y += io.o | 72 | obj-y += io.o |
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index aeef960ff795..8e3c6f11b0a1 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c | |||
@@ -49,9 +49,6 @@ extern void __aeabi_ulcmp(void); | |||
49 | 49 | ||
50 | extern void fpundefinstr(void); | 50 | extern void fpundefinstr(void); |
51 | 51 | ||
52 | |||
53 | EXPORT_SYMBOL(__backtrace); | ||
54 | |||
55 | /* platform dependent support */ | 52 | /* platform dependent support */ |
56 | EXPORT_SYMBOL(__udelay); | 53 | EXPORT_SYMBOL(__udelay); |
57 | EXPORT_SYMBOL(__const_udelay); | 54 | EXPORT_SYMBOL(__const_udelay); |
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 16baba2e4369..1429d8989fb9 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <asm/thread_info.h> | 20 | #include <asm/thread_info.h> |
21 | #include <asm/memory.h> | 21 | #include <asm/memory.h> |
22 | #include <asm/procinfo.h> | 22 | #include <asm/procinfo.h> |
23 | #include <asm/hardware/cache-l2x0.h> | ||
23 | #include <linux/kbuild.h> | 24 | #include <linux/kbuild.h> |
24 | 25 | ||
25 | /* | 26 | /* |
@@ -92,6 +93,17 @@ int main(void) | |||
92 | DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0)); | 93 | DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0)); |
93 | DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs)); | 94 | DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs)); |
94 | BLANK(); | 95 | BLANK(); |
96 | #ifdef CONFIG_CACHE_L2X0 | ||
97 | DEFINE(L2X0_R_PHY_BASE, offsetof(struct l2x0_regs, phy_base)); | ||
98 | DEFINE(L2X0_R_AUX_CTRL, offsetof(struct l2x0_regs, aux_ctrl)); | ||
99 | DEFINE(L2X0_R_TAG_LATENCY, offsetof(struct l2x0_regs, tag_latency)); | ||
100 | DEFINE(L2X0_R_DATA_LATENCY, offsetof(struct l2x0_regs, data_latency)); | ||
101 | DEFINE(L2X0_R_FILTER_START, offsetof(struct l2x0_regs, filter_start)); | ||
102 | DEFINE(L2X0_R_FILTER_END, offsetof(struct l2x0_regs, filter_end)); | ||
103 | DEFINE(L2X0_R_PREFETCH_CTRL, offsetof(struct l2x0_regs, prefetch_ctrl)); | ||
104 | DEFINE(L2X0_R_PWR_CTRL, offsetof(struct l2x0_regs, pwr_ctrl)); | ||
105 | BLANK(); | ||
106 | #endif | ||
95 | #ifdef CONFIG_CPU_HAS_ASID | 107 | #ifdef CONFIG_CPU_HAS_ASID |
96 | DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id)); | 108 | DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id)); |
97 | BLANK(); | 109 | BLANK(); |
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index d6df359408f0..c0d9203fc75e 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c | |||
@@ -412,6 +412,9 @@ void pcibios_fixup_bus(struct pci_bus *bus) | |||
412 | printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n", | 412 | printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n", |
413 | bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis"); | 413 | bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis"); |
414 | } | 414 | } |
415 | #ifdef CONFIG_HOTPLUG | ||
416 | EXPORT_SYMBOL(pcibios_fixup_bus); | ||
417 | #endif | ||
415 | 418 | ||
416 | /* | 419 | /* |
417 | * Convert from Linux-centric to bus-centric addresses for bridge devices. | 420 | * Convert from Linux-centric to bus-centric addresses for bridge devices. |
@@ -431,6 +434,7 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, | |||
431 | region->start = res->start - offset; | 434 | region->start = res->start - offset; |
432 | region->end = res->end - offset; | 435 | region->end = res->end - offset; |
433 | } | 436 | } |
437 | EXPORT_SYMBOL(pcibios_resource_to_bus); | ||
434 | 438 | ||
435 | void __devinit | 439 | void __devinit |
436 | pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, | 440 | pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, |
@@ -447,12 +451,7 @@ pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, | |||
447 | res->start = region->start + offset; | 451 | res->start = region->start + offset; |
448 | res->end = region->end + offset; | 452 | res->end = region->end + offset; |
449 | } | 453 | } |
450 | |||
451 | #ifdef CONFIG_HOTPLUG | ||
452 | EXPORT_SYMBOL(pcibios_fixup_bus); | ||
453 | EXPORT_SYMBOL(pcibios_resource_to_bus); | ||
454 | EXPORT_SYMBOL(pcibios_bus_to_resource); | 454 | EXPORT_SYMBOL(pcibios_bus_to_resource); |
455 | #endif | ||
456 | 455 | ||
457 | /* | 456 | /* |
458 | * Swizzle the device pin each time we cross a bridge. | 457 | * Swizzle the device pin each time we cross a bridge. |
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S index bcd66e00bdbe..0f852d082fcf 100644 --- a/arch/arm/kernel/debug.S +++ b/arch/arm/kernel/debug.S | |||
@@ -151,6 +151,8 @@ printhex: adr r2, hexbuf | |||
151 | b printascii | 151 | b printascii |
152 | ENDPROC(printhex2) | 152 | ENDPROC(printhex2) |
153 | 153 | ||
154 | hexbuf: .space 16 | ||
155 | |||
154 | .ltorg | 156 | .ltorg |
155 | 157 | ||
156 | ENTRY(printascii) | 158 | ENTRY(printascii) |
@@ -175,5 +177,3 @@ ENTRY(printch) | |||
175 | mov r0, #0 | 177 | mov r0, #0 |
176 | b 1b | 178 | b 1b |
177 | ENDPROC(printch) | 179 | ENDPROC(printch) |
178 | |||
179 | hexbuf: .space 16 | ||
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index 2c4a185f92cd..7b829d9663b1 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | #include <asm/mach/dma.h> | 24 | #include <asm/mach/dma.h> |
25 | 25 | ||
26 | DEFINE_SPINLOCK(dma_spin_lock); | 26 | DEFINE_RAW_SPINLOCK(dma_spin_lock); |
27 | EXPORT_SYMBOL(dma_spin_lock); | 27 | EXPORT_SYMBOL(dma_spin_lock); |
28 | 28 | ||
29 | static dma_t *dma_chan[MAX_DMA_CHANNELS]; | 29 | static dma_t *dma_chan[MAX_DMA_CHANNELS]; |
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index d16500110ee9..4dd0edab6a65 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c | |||
@@ -237,7 +237,7 @@ static void ecard_init_pgtables(struct mm_struct *mm) | |||
237 | 237 | ||
238 | memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (IO_SIZE / PGDIR_SIZE)); | 238 | memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (IO_SIZE / PGDIR_SIZE)); |
239 | 239 | ||
240 | src_pgd = pgd_offset(mm, EASI_BASE); | 240 | src_pgd = pgd_offset(mm, (unsigned long)EASI_BASE); |
241 | dst_pgd = pgd_offset(mm, EASI_START); | 241 | dst_pgd = pgd_offset(mm, EASI_START); |
242 | 242 | ||
243 | memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (EASI_SIZE / PGDIR_SIZE)); | 243 | memcpy(dst_pgd, src_pgd, sizeof(pgd_t) * (EASI_SIZE / PGDIR_SIZE)); |
@@ -674,44 +674,37 @@ static int __init ecard_probeirqhw(void) | |||
674 | #define ecard_probeirqhw() (0) | 674 | #define ecard_probeirqhw() (0) |
675 | #endif | 675 | #endif |
676 | 676 | ||
677 | #ifndef IO_EC_MEMC8_BASE | 677 | static void __iomem *__ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) |
678 | #define IO_EC_MEMC8_BASE 0 | ||
679 | #endif | ||
680 | |||
681 | static unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) | ||
682 | { | 678 | { |
683 | unsigned long address = 0; | 679 | void __iomem *address = NULL; |
684 | int slot = ec->slot_no; | 680 | int slot = ec->slot_no; |
685 | 681 | ||
686 | if (ec->slot_no == 8) | 682 | if (ec->slot_no == 8) |
687 | return IO_EC_MEMC8_BASE; | 683 | return ECARD_MEMC8_BASE; |
688 | 684 | ||
689 | ectcr &= ~(1 << slot); | 685 | ectcr &= ~(1 << slot); |
690 | 686 | ||
691 | switch (type) { | 687 | switch (type) { |
692 | case ECARD_MEMC: | 688 | case ECARD_MEMC: |
693 | if (slot < 4) | 689 | if (slot < 4) |
694 | address = IO_EC_MEMC_BASE + (slot << 12); | 690 | address = ECARD_MEMC_BASE + (slot << 14); |
695 | break; | 691 | break; |
696 | 692 | ||
697 | case ECARD_IOC: | 693 | case ECARD_IOC: |
698 | if (slot < 4) | 694 | if (slot < 4) |
699 | address = IO_EC_IOC_BASE + (slot << 12); | 695 | address = ECARD_IOC_BASE + (slot << 14); |
700 | #ifdef IO_EC_IOC4_BASE | ||
701 | else | 696 | else |
702 | address = IO_EC_IOC4_BASE + ((slot - 4) << 12); | 697 | address = ECARD_IOC4_BASE + ((slot - 4) << 14); |
703 | #endif | ||
704 | if (address) | 698 | if (address) |
705 | address += speed << 17; | 699 | address += speed << 19; |
706 | break; | 700 | break; |
707 | 701 | ||
708 | #ifdef IO_EC_EASI_BASE | ||
709 | case ECARD_EASI: | 702 | case ECARD_EASI: |
710 | address = IO_EC_EASI_BASE + (slot << 22); | 703 | address = ECARD_EASI_BASE + (slot << 24); |
711 | if (speed == ECARD_FAST) | 704 | if (speed == ECARD_FAST) |
712 | ectcr |= 1 << slot; | 705 | ectcr |= 1 << slot; |
713 | break; | 706 | break; |
714 | #endif | 707 | |
715 | default: | 708 | default: |
716 | break; | 709 | break; |
717 | } | 710 | } |
@@ -990,6 +983,7 @@ ecard_probe(int slot, card_type_t type) | |||
990 | ecard_t **ecp; | 983 | ecard_t **ecp; |
991 | ecard_t *ec; | 984 | ecard_t *ec; |
992 | struct ex_ecid cid; | 985 | struct ex_ecid cid; |
986 | void __iomem *addr; | ||
993 | int i, rc; | 987 | int i, rc; |
994 | 988 | ||
995 | ec = ecard_alloc_card(type, slot); | 989 | ec = ecard_alloc_card(type, slot); |
@@ -999,7 +993,7 @@ ecard_probe(int slot, card_type_t type) | |||
999 | } | 993 | } |
1000 | 994 | ||
1001 | rc = -ENODEV; | 995 | rc = -ENODEV; |
1002 | if ((ec->podaddr = __ecard_address(ec, type, ECARD_SYNC)) == 0) | 996 | if ((addr = __ecard_address(ec, type, ECARD_SYNC)) == NULL) |
1003 | goto nodev; | 997 | goto nodev; |
1004 | 998 | ||
1005 | cid.r_zero = 1; | 999 | cid.r_zero = 1; |
@@ -1019,7 +1013,7 @@ ecard_probe(int slot, card_type_t type) | |||
1019 | ec->cid.fiqmask = cid.r_fiqmask; | 1013 | ec->cid.fiqmask = cid.r_fiqmask; |
1020 | ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff); | 1014 | ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff); |
1021 | ec->fiqaddr = | 1015 | ec->fiqaddr = |
1022 | ec->irqaddr = (void __iomem *)ioaddr(ec->podaddr); | 1016 | ec->irqaddr = addr; |
1023 | 1017 | ||
1024 | if (ec->cid.is) { | 1018 | if (ec->cid.is) { |
1025 | ec->irqmask = ec->cid.irqmask; | 1019 | ec->irqmask = ec->cid.irqmask; |
@@ -1048,10 +1042,8 @@ ecard_probe(int slot, card_type_t type) | |||
1048 | set_irq_flags(ec->irq, IRQF_VALID); | 1042 | set_irq_flags(ec->irq, IRQF_VALID); |
1049 | } | 1043 | } |
1050 | 1044 | ||
1051 | #ifdef IO_EC_MEMC8_BASE | ||
1052 | if (slot == 8) | 1045 | if (slot == 8) |
1053 | ec->irq = 11; | 1046 | ec->irq = 11; |
1054 | #endif | ||
1055 | #ifdef CONFIG_ARCH_RPC | 1047 | #ifdef CONFIG_ARCH_RPC |
1056 | /* On RiscPC, only first two slots have DMA capability */ | 1048 | /* On RiscPC, only first two slots have DMA capability */ |
1057 | if (slot < 2) | 1049 | if (slot < 2) |
@@ -1097,9 +1089,7 @@ static int __init ecard_init(void) | |||
1097 | ecard_probe(slot, ECARD_IOC); | 1089 | ecard_probe(slot, ECARD_IOC); |
1098 | } | 1090 | } |
1099 | 1091 | ||
1100 | #ifdef IO_EC_MEMC8_BASE | ||
1101 | ecard_probe(8, ECARD_IOC); | 1092 | ecard_probe(8, ECARD_IOC); |
1102 | #endif | ||
1103 | 1093 | ||
1104 | irqhw = ecard_probeirqhw(); | 1094 | irqhw = ecard_probeirqhw(); |
1105 | 1095 | ||
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index a87cbf889ff4..9ad50c4208ae 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/unwind.h> | 24 | #include <asm/unwind.h> |
25 | #include <asm/unistd.h> | 25 | #include <asm/unistd.h> |
26 | #include <asm/tls.h> | 26 | #include <asm/tls.h> |
27 | #include <asm/system.h> | ||
27 | 28 | ||
28 | #include "entry-header.S" | 29 | #include "entry-header.S" |
29 | #include <asm/entry-macro-multi.S> | 30 | #include <asm/entry-macro-multi.S> |
@@ -262,8 +263,7 @@ __und_svc: | |||
262 | ldr r0, [r4, #-4] | 263 | ldr r0, [r4, #-4] |
263 | #else | 264 | #else |
264 | ldrh r0, [r4, #-2] @ Thumb instruction at LR - 2 | 265 | ldrh r0, [r4, #-2] @ Thumb instruction at LR - 2 |
265 | and r9, r0, #0xf800 | 266 | cmp r0, #0xe800 @ 32-bit instruction if xx >= 0 |
266 | cmp r9, #0xe800 @ 32-bit instruction if xx >= 0 | ||
267 | ldrhhs r9, [r4] @ bottom 16 bits | 267 | ldrhhs r9, [r4] @ bottom 16 bits |
268 | orrhs r0, r9, r0, lsl #16 | 268 | orrhs r0, r9, r0, lsl #16 |
269 | #endif | 269 | #endif |
@@ -440,18 +440,46 @@ __und_usr: | |||
440 | #endif | 440 | #endif |
441 | beq call_fpe | 441 | beq call_fpe |
442 | @ Thumb instruction | 442 | @ Thumb instruction |
443 | #if __LINUX_ARM_ARCH__ >= 7 | 443 | #if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7 |
444 | /* | ||
445 | * Thumb-2 instruction handling. Note that because pre-v6 and >= v6 platforms | ||
446 | * can never be supported in a single kernel, this code is not applicable at | ||
447 | * all when __LINUX_ARM_ARCH__ < 6. This allows simplifying assumptions to be | ||
448 | * made about .arch directives. | ||
449 | */ | ||
450 | #if __LINUX_ARM_ARCH__ < 7 | ||
451 | /* If the target CPU may not be Thumb-2-capable, a run-time check is needed: */ | ||
452 | #define NEED_CPU_ARCHITECTURE | ||
453 | ldr r5, .LCcpu_architecture | ||
454 | ldr r5, [r5] | ||
455 | cmp r5, #CPU_ARCH_ARMv7 | ||
456 | blo __und_usr_unknown | ||
457 | /* | ||
458 | * The following code won't get run unless the running CPU really is v7, so | ||
459 | * coding round the lack of ldrht on older arches is pointless. Temporarily | ||
460 | * override the assembler target arch with the minimum required instead: | ||
461 | */ | ||
462 | .arch armv6t2 | ||
463 | #endif | ||
444 | 2: | 464 | 2: |
445 | ARM( ldrht r5, [r4], #2 ) | 465 | ARM( ldrht r5, [r4], #2 ) |
446 | THUMB( ldrht r5, [r4] ) | 466 | THUMB( ldrht r5, [r4] ) |
447 | THUMB( add r4, r4, #2 ) | 467 | THUMB( add r4, r4, #2 ) |
448 | and r0, r5, #0xf800 @ mask bits 111x x... .... .... | 468 | cmp r5, #0xe800 @ 32bit instruction if xx != 0 |
449 | cmp r0, #0xe800 @ 32bit instruction if xx != 0 | ||
450 | blo __und_usr_unknown | 469 | blo __und_usr_unknown |
451 | 3: ldrht r0, [r4] | 470 | 3: ldrht r0, [r4] |
452 | add r2, r2, #2 @ r2 is PC + 2, make it PC + 4 | 471 | add r2, r2, #2 @ r2 is PC + 2, make it PC + 4 |
453 | orr r0, r0, r5, lsl #16 | 472 | orr r0, r0, r5, lsl #16 |
473 | |||
474 | #if __LINUX_ARM_ARCH__ < 7 | ||
475 | /* If the target arch was overridden, change it back: */ | ||
476 | #ifdef CONFIG_CPU_32v6K | ||
477 | .arch armv6k | ||
454 | #else | 478 | #else |
479 | .arch armv6 | ||
480 | #endif | ||
481 | #endif /* __LINUX_ARM_ARCH__ < 7 */ | ||
482 | #else /* !(CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7) */ | ||
455 | b __und_usr_unknown | 483 | b __und_usr_unknown |
456 | #endif | 484 | #endif |
457 | UNWIND(.fnend ) | 485 | UNWIND(.fnend ) |
@@ -578,6 +606,12 @@ call_fpe: | |||
578 | movw_pc lr @ CP#14 (Debug) | 606 | movw_pc lr @ CP#14 (Debug) |
579 | movw_pc lr @ CP#15 (Control) | 607 | movw_pc lr @ CP#15 (Control) |
580 | 608 | ||
609 | #ifdef NEED_CPU_ARCHITECTURE | ||
610 | .align 2 | ||
611 | .LCcpu_architecture: | ||
612 | .word __cpu_architecture | ||
613 | #endif | ||
614 | |||
581 | #ifdef CONFIG_NEON | 615 | #ifdef CONFIG_NEON |
582 | .align 6 | 616 | .align 6 |
583 | 617 | ||
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 742b6108a001..239703dbdf4f 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/memory.h> | 21 | #include <asm/memory.h> |
22 | #include <asm/thread_info.h> | 22 | #include <asm/thread_info.h> |
23 | #include <asm/system.h> | 23 | #include <asm/system.h> |
24 | #include <asm/pgtable.h> | ||
24 | 25 | ||
25 | #ifdef CONFIG_DEBUG_LL | 26 | #ifdef CONFIG_DEBUG_LL |
26 | #include <mach/debug-macro.S> | 27 | #include <mach/debug-macro.S> |
@@ -38,11 +39,14 @@ | |||
38 | #error KERNEL_RAM_VADDR must start at 0xXXXX8000 | 39 | #error KERNEL_RAM_VADDR must start at 0xXXXX8000 |
39 | #endif | 40 | #endif |
40 | 41 | ||
42 | #define PG_DIR_SIZE 0x4000 | ||
43 | #define PMD_ORDER 2 | ||
44 | |||
41 | .globl swapper_pg_dir | 45 | .globl swapper_pg_dir |
42 | .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000 | 46 | .equ swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE |
43 | 47 | ||
44 | .macro pgtbl, rd, phys | 48 | .macro pgtbl, rd, phys |
45 | add \rd, \phys, #TEXT_OFFSET - 0x4000 | 49 | add \rd, \phys, #TEXT_OFFSET - PG_DIR_SIZE |
46 | .endm | 50 | .endm |
47 | 51 | ||
48 | #ifdef CONFIG_XIP_KERNEL | 52 | #ifdef CONFIG_XIP_KERNEL |
@@ -148,11 +152,11 @@ __create_page_tables: | |||
148 | pgtbl r4, r8 @ page table address | 152 | pgtbl r4, r8 @ page table address |
149 | 153 | ||
150 | /* | 154 | /* |
151 | * Clear the 16K level 1 swapper page table | 155 | * Clear the swapper page table |
152 | */ | 156 | */ |
153 | mov r0, r4 | 157 | mov r0, r4 |
154 | mov r3, #0 | 158 | mov r3, #0 |
155 | add r6, r0, #0x4000 | 159 | add r6, r0, #PG_DIR_SIZE |
156 | 1: str r3, [r0], #4 | 160 | 1: str r3, [r0], #4 |
157 | str r3, [r0], #4 | 161 | str r3, [r0], #4 |
158 | str r3, [r0], #4 | 162 | str r3, [r0], #4 |
@@ -171,30 +175,30 @@ __create_page_tables: | |||
171 | sub r0, r0, r3 @ virt->phys offset | 175 | sub r0, r0, r3 @ virt->phys offset |
172 | add r5, r5, r0 @ phys __enable_mmu | 176 | add r5, r5, r0 @ phys __enable_mmu |
173 | add r6, r6, r0 @ phys __enable_mmu_end | 177 | add r6, r6, r0 @ phys __enable_mmu_end |
174 | mov r5, r5, lsr #20 | 178 | mov r5, r5, lsr #SECTION_SHIFT |
175 | mov r6, r6, lsr #20 | 179 | mov r6, r6, lsr #SECTION_SHIFT |
176 | 180 | ||
177 | 1: orr r3, r7, r5, lsl #20 @ flags + kernel base | 181 | 1: orr r3, r7, r5, lsl #SECTION_SHIFT @ flags + kernel base |
178 | str r3, [r4, r5, lsl #2] @ identity mapping | 182 | str r3, [r4, r5, lsl #PMD_ORDER] @ identity mapping |
179 | teq r5, r6 | 183 | cmp r5, r6 |
180 | addne r5, r5, #1 @ next section | 184 | addlo r5, r5, #1 @ next section |
181 | bne 1b | 185 | blo 1b |
182 | 186 | ||
183 | /* | 187 | /* |
184 | * Now setup the pagetables for our kernel direct | 188 | * Now setup the pagetables for our kernel direct |
185 | * mapped region. | 189 | * mapped region. |
186 | */ | 190 | */ |
187 | mov r3, pc | 191 | mov r3, pc |
188 | mov r3, r3, lsr #20 | 192 | mov r3, r3, lsr #SECTION_SHIFT |
189 | orr r3, r7, r3, lsl #20 | 193 | orr r3, r7, r3, lsl #SECTION_SHIFT |
190 | add r0, r4, #(KERNEL_START & 0xff000000) >> 18 | 194 | add r0, r4, #(KERNEL_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) |
191 | str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]! | 195 | str r3, [r0, #((KERNEL_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]! |
192 | ldr r6, =(KERNEL_END - 1) | 196 | ldr r6, =(KERNEL_END - 1) |
193 | add r0, r0, #4 | 197 | add r0, r0, #1 << PMD_ORDER |
194 | add r6, r4, r6, lsr #18 | 198 | add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) |
195 | 1: cmp r0, r6 | 199 | 1: cmp r0, r6 |
196 | add r3, r3, #1 << 20 | 200 | add r3, r3, #1 << SECTION_SHIFT |
197 | strls r3, [r0], #4 | 201 | strls r3, [r0], #1 << PMD_ORDER |
198 | bls 1b | 202 | bls 1b |
199 | 203 | ||
200 | #ifdef CONFIG_XIP_KERNEL | 204 | #ifdef CONFIG_XIP_KERNEL |
@@ -203,11 +207,11 @@ __create_page_tables: | |||
203 | */ | 207 | */ |
204 | add r3, r8, #TEXT_OFFSET | 208 | add r3, r8, #TEXT_OFFSET |
205 | orr r3, r3, r7 | 209 | orr r3, r3, r7 |
206 | add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18 | 210 | add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) |
207 | str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]! | 211 | str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> (SECTION_SHIFT - PMD_ORDER)]! |
208 | ldr r6, =(_end - 1) | 212 | ldr r6, =(_end - 1) |
209 | add r0, r0, #4 | 213 | add r0, r0, #4 |
210 | add r6, r4, r6, lsr #18 | 214 | add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) |
211 | 1: cmp r0, r6 | 215 | 1: cmp r0, r6 |
212 | add r3, r3, #1 << 20 | 216 | add r3, r3, #1 << 20 |
213 | strls r3, [r0], #4 | 217 | strls r3, [r0], #4 |
@@ -218,12 +222,12 @@ __create_page_tables: | |||
218 | * Then map boot params address in r2 or | 222 | * Then map boot params address in r2 or |
219 | * the first 1MB of ram if boot params address is not specified. | 223 | * the first 1MB of ram if boot params address is not specified. |
220 | */ | 224 | */ |
221 | mov r0, r2, lsr #20 | 225 | mov r0, r2, lsr #SECTION_SHIFT |
222 | movs r0, r0, lsl #20 | 226 | movs r0, r0, lsl #SECTION_SHIFT |
223 | moveq r0, r8 | 227 | moveq r0, r8 |
224 | sub r3, r0, r8 | 228 | sub r3, r0, r8 |
225 | add r3, r3, #PAGE_OFFSET | 229 | add r3, r3, #PAGE_OFFSET |
226 | add r3, r4, r3, lsr #18 | 230 | add r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER) |
227 | orr r6, r7, r0 | 231 | orr r6, r7, r0 |
228 | str r6, [r3] | 232 | str r6, [r3] |
229 | 233 | ||
@@ -236,21 +240,21 @@ __create_page_tables: | |||
236 | */ | 240 | */ |
237 | addruart r7, r3 | 241 | addruart r7, r3 |
238 | 242 | ||
239 | mov r3, r3, lsr #20 | 243 | mov r3, r3, lsr #SECTION_SHIFT |
240 | mov r3, r3, lsl #2 | 244 | mov r3, r3, lsl #PMD_ORDER |
241 | 245 | ||
242 | add r0, r4, r3 | 246 | add r0, r4, r3 |
243 | rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long) | 247 | rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long) |
244 | cmp r3, #0x0800 @ limit to 512MB | 248 | cmp r3, #0x0800 @ limit to 512MB |
245 | movhi r3, #0x0800 | 249 | movhi r3, #0x0800 |
246 | add r6, r0, r3 | 250 | add r6, r0, r3 |
247 | mov r3, r7, lsr #20 | 251 | mov r3, r7, lsr #SECTION_SHIFT |
248 | ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags | 252 | ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags |
249 | orr r3, r7, r3, lsl #20 | 253 | orr r3, r7, r3, lsl #SECTION_SHIFT |
250 | 1: str r3, [r0], #4 | 254 | 1: str r3, [r0], #4 |
251 | add r3, r3, #1 << 20 | 255 | add r3, r3, #1 << SECTION_SHIFT |
252 | teq r0, r6 | 256 | cmp r0, r6 |
253 | bne 1b | 257 | blo 1b |
254 | 258 | ||
255 | #else /* CONFIG_DEBUG_ICEDCC */ | 259 | #else /* CONFIG_DEBUG_ICEDCC */ |
256 | /* we don't need any serial debugging mappings for ICEDCC */ | 260 | /* we don't need any serial debugging mappings for ICEDCC */ |
@@ -262,7 +266,7 @@ __create_page_tables: | |||
262 | * If we're using the NetWinder or CATS, we also need to map | 266 | * If we're using the NetWinder or CATS, we also need to map |
263 | * in the 16550-type serial port for the debug messages | 267 | * in the 16550-type serial port for the debug messages |
264 | */ | 268 | */ |
265 | add r0, r4, #0xff000000 >> 18 | 269 | add r0, r4, #0xff000000 >> (SECTION_SHIFT - PMD_ORDER) |
266 | orr r3, r7, #0x7c000000 | 270 | orr r3, r7, #0x7c000000 |
267 | str r3, [r0] | 271 | str r3, [r0] |
268 | #endif | 272 | #endif |
@@ -272,10 +276,10 @@ __create_page_tables: | |||
272 | * Similar reasons here - for debug. This is | 276 | * Similar reasons here - for debug. This is |
273 | * only for Acorn RiscPC architectures. | 277 | * only for Acorn RiscPC architectures. |
274 | */ | 278 | */ |
275 | add r0, r4, #0x02000000 >> 18 | 279 | add r0, r4, #0x02000000 >> (SECTION_SHIFT - PMD_ORDER) |
276 | orr r3, r7, #0x02000000 | 280 | orr r3, r7, #0x02000000 |
277 | str r3, [r0] | 281 | str r3, [r0] |
278 | add r0, r4, #0xd8000000 >> 18 | 282 | add r0, r4, #0xd8000000 >> (SECTION_SHIFT - PMD_ORDER) |
279 | str r3, [r0] | 283 | str r3, [r0] |
280 | #endif | 284 | #endif |
281 | #endif | 285 | #endif |
@@ -488,13 +492,8 @@ __fixup_pv_table: | |||
488 | add r5, r5, r3 @ adjust table end address | 492 | add r5, r5, r3 @ adjust table end address |
489 | add r7, r7, r3 @ adjust __pv_phys_offset address | 493 | add r7, r7, r3 @ adjust __pv_phys_offset address |
490 | str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset | 494 | str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset |
491 | #ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT | ||
492 | mov r6, r3, lsr #24 @ constant for add/sub instructions | 495 | mov r6, r3, lsr #24 @ constant for add/sub instructions |
493 | teq r3, r6, lsl #24 @ must be 16MiB aligned | 496 | teq r3, r6, lsl #24 @ must be 16MiB aligned |
494 | #else | ||
495 | mov r6, r3, lsr #16 @ constant for add/sub instructions | ||
496 | teq r3, r6, lsl #16 @ must be 64kiB aligned | ||
497 | #endif | ||
498 | THUMB( it ne @ cross section branch ) | 497 | THUMB( it ne @ cross section branch ) |
499 | bne __error | 498 | bne __error |
500 | str r6, [r7, #4] @ save to __pv_offset | 499 | str r6, [r7, #4] @ save to __pv_offset |
@@ -510,20 +509,8 @@ ENDPROC(__fixup_pv_table) | |||
510 | .text | 509 | .text |
511 | __fixup_a_pv_table: | 510 | __fixup_a_pv_table: |
512 | #ifdef CONFIG_THUMB2_KERNEL | 511 | #ifdef CONFIG_THUMB2_KERNEL |
513 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT | 512 | lsls r6, #24 |
514 | lsls r0, r6, #24 | 513 | beq 2f |
515 | lsr r6, #8 | ||
516 | beq 1f | ||
517 | clz r7, r0 | ||
518 | lsr r0, #24 | ||
519 | lsl r0, r7 | ||
520 | bic r0, 0x0080 | ||
521 | lsrs r7, #1 | ||
522 | orrcs r0, #0x0080 | ||
523 | orr r0, r0, r7, lsl #12 | ||
524 | #endif | ||
525 | 1: lsls r6, #24 | ||
526 | beq 4f | ||
527 | clz r7, r6 | 514 | clz r7, r6 |
528 | lsr r6, #24 | 515 | lsr r6, #24 |
529 | lsl r6, r7 | 516 | lsl r6, r7 |
@@ -532,43 +519,25 @@ __fixup_a_pv_table: | |||
532 | orrcs r6, #0x0080 | 519 | orrcs r6, #0x0080 |
533 | orr r6, r6, r7, lsl #12 | 520 | orr r6, r6, r7, lsl #12 |
534 | orr r6, #0x4000 | 521 | orr r6, #0x4000 |
535 | b 4f | 522 | b 2f |
536 | 2: @ at this point the C flag is always clear | 523 | 1: add r7, r3 |
537 | add r7, r3 | 524 | ldrh ip, [r7, #2] |
538 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT | ||
539 | ldrh ip, [r7] | ||
540 | tst ip, 0x0400 @ the i bit tells us LS or MS byte | ||
541 | beq 3f | ||
542 | cmp r0, #0 @ set C flag, and ... | ||
543 | biceq ip, 0x0400 @ immediate zero value has a special encoding | ||
544 | streqh ip, [r7] @ that requires the i bit cleared | ||
545 | #endif | ||
546 | 3: ldrh ip, [r7, #2] | ||
547 | and ip, 0x8f00 | 525 | and ip, 0x8f00 |
548 | orrcc ip, r6 @ mask in offset bits 31-24 | 526 | orr ip, r6 @ mask in offset bits 31-24 |
549 | orrcs ip, r0 @ mask in offset bits 23-16 | ||
550 | strh ip, [r7, #2] | 527 | strh ip, [r7, #2] |
551 | 4: cmp r4, r5 | 528 | 2: cmp r4, r5 |
552 | ldrcc r7, [r4], #4 @ use branch for delay slot | 529 | ldrcc r7, [r4], #4 @ use branch for delay slot |
553 | bcc 2b | 530 | bcc 1b |
554 | bx lr | 531 | bx lr |
555 | #else | 532 | #else |
556 | #ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT | 533 | b 2f |
557 | and r0, r6, #255 @ offset bits 23-16 | 534 | 1: ldr ip, [r7, r3] |
558 | mov r6, r6, lsr #8 @ offset bits 31-24 | ||
559 | #else | ||
560 | mov r0, #0 @ just in case... | ||
561 | #endif | ||
562 | b 3f | ||
563 | 2: ldr ip, [r7, r3] | ||
564 | bic ip, ip, #0x000000ff | 535 | bic ip, ip, #0x000000ff |
565 | tst ip, #0x400 @ rotate shift tells us LS or MS byte | 536 | orr ip, ip, r6 @ mask in offset bits 31-24 |
566 | orrne ip, ip, r6 @ mask in offset bits 31-24 | ||
567 | orreq ip, ip, r0 @ mask in offset bits 23-16 | ||
568 | str ip, [r7, r3] | 537 | str ip, [r7, r3] |
569 | 3: cmp r4, r5 | 538 | 2: cmp r4, r5 |
570 | ldrcc r7, [r4], #4 @ use branch for delay slot | 539 | ldrcc r7, [r4], #4 @ use branch for delay slot |
571 | bcc 2b | 540 | bcc 1b |
572 | mov pc, lr | 541 | mov pc, lr |
573 | #endif | 542 | #endif |
574 | ENDPROC(__fixup_a_pv_table) | 543 | ENDPROC(__fixup_a_pv_table) |
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index de3dcab8610b..53919b230e8b 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c | |||
@@ -35,8 +35,8 @@ | |||
35 | #include <linux/list.h> | 35 | #include <linux/list.h> |
36 | #include <linux/kallsyms.h> | 36 | #include <linux/kallsyms.h> |
37 | #include <linux/proc_fs.h> | 37 | #include <linux/proc_fs.h> |
38 | #include <linux/ftrace.h> | ||
39 | 38 | ||
39 | #include <asm/exception.h> | ||
40 | #include <asm/system.h> | 40 | #include <asm/system.h> |
41 | #include <asm/mach/arch.h> | 41 | #include <asm/mach/arch.h> |
42 | #include <asm/mach/irq.h> | 42 | #include <asm/mach/irq.h> |
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index e59bbd496c39..c1b4463dcc83 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c | |||
@@ -32,6 +32,24 @@ static atomic_t waiting_for_crash_ipi; | |||
32 | 32 | ||
33 | int machine_kexec_prepare(struct kimage *image) | 33 | int machine_kexec_prepare(struct kimage *image) |
34 | { | 34 | { |
35 | unsigned long page_list; | ||
36 | void *reboot_code_buffer; | ||
37 | page_list = image->head & PAGE_MASK; | ||
38 | |||
39 | reboot_code_buffer = page_address(image->control_code_page); | ||
40 | |||
41 | /* Prepare parameters for reboot_code_buffer*/ | ||
42 | kexec_start_address = image->start; | ||
43 | kexec_indirection_page = page_list; | ||
44 | kexec_mach_type = machine_arch_type; | ||
45 | kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; | ||
46 | |||
47 | /* copy our kernel relocation code to the control code page */ | ||
48 | memcpy(reboot_code_buffer, | ||
49 | relocate_new_kernel, relocate_new_kernel_size); | ||
50 | |||
51 | flush_icache_range((unsigned long) reboot_code_buffer, | ||
52 | (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); | ||
35 | return 0; | 53 | return 0; |
36 | } | 54 | } |
37 | 55 | ||
@@ -82,31 +100,14 @@ void (*kexec_reinit)(void); | |||
82 | 100 | ||
83 | void machine_kexec(struct kimage *image) | 101 | void machine_kexec(struct kimage *image) |
84 | { | 102 | { |
85 | unsigned long page_list; | ||
86 | unsigned long reboot_code_buffer_phys; | 103 | unsigned long reboot_code_buffer_phys; |
87 | void *reboot_code_buffer; | 104 | void *reboot_code_buffer; |
88 | 105 | ||
89 | |||
90 | page_list = image->head & PAGE_MASK; | ||
91 | |||
92 | /* we need both effective and real address here */ | 106 | /* we need both effective and real address here */ |
93 | reboot_code_buffer_phys = | 107 | reboot_code_buffer_phys = |
94 | page_to_pfn(image->control_code_page) << PAGE_SHIFT; | 108 | page_to_pfn(image->control_code_page) << PAGE_SHIFT; |
95 | reboot_code_buffer = page_address(image->control_code_page); | 109 | reboot_code_buffer = page_address(image->control_code_page); |
96 | 110 | ||
97 | /* Prepare parameters for reboot_code_buffer*/ | ||
98 | kexec_start_address = image->start; | ||
99 | kexec_indirection_page = page_list; | ||
100 | kexec_mach_type = machine_arch_type; | ||
101 | kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; | ||
102 | |||
103 | /* copy our kernel relocation code to the control code page */ | ||
104 | memcpy(reboot_code_buffer, | ||
105 | relocate_new_kernel, relocate_new_kernel_size); | ||
106 | |||
107 | |||
108 | flush_icache_range((unsigned long) reboot_code_buffer, | ||
109 | (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); | ||
110 | printk(KERN_INFO "Bye!\n"); | 111 | printk(KERN_INFO "Bye!\n"); |
111 | 112 | ||
112 | if (kexec_reinit) | 113 | if (kexec_reinit) |
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index cc2020c2c709..1e9be5d25e56 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c | |||
@@ -33,7 +33,7 @@ | |||
33 | * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off. | 33 | * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off. |
34 | */ | 34 | */ |
35 | #undef MODULES_VADDR | 35 | #undef MODULES_VADDR |
36 | #define MODULES_VADDR (((unsigned long)_etext + ~PGDIR_MASK) & PGDIR_MASK) | 36 | #define MODULES_VADDR (((unsigned long)_etext + ~PMD_MASK) & PMD_MASK) |
37 | #endif | 37 | #endif |
38 | 38 | ||
39 | #ifdef CONFIG_MMU | 39 | #ifdef CONFIG_MMU |
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 1a347f481e5e..fd0814076ff6 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -319,7 +319,7 @@ void show_regs(struct pt_regs * regs) | |||
319 | printk("\n"); | 319 | printk("\n"); |
320 | printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm); | 320 | printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm); |
321 | __show_regs(regs); | 321 | __show_regs(regs); |
322 | __backtrace(); | 322 | dump_stack(); |
323 | } | 323 | } |
324 | 324 | ||
325 | ATOMIC_NOTIFIER_HEAD(thread_notify_head); | 325 | ATOMIC_NOTIFIER_HEAD(thread_notify_head); |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index e514c76043b4..3fe93f75b55a 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
30 | #include <linux/proc_fs.h> | 30 | #include <linux/proc_fs.h> |
31 | #include <linux/memblock.h> | 31 | #include <linux/memblock.h> |
32 | #include <linux/bug.h> | ||
33 | #include <linux/compiler.h> | ||
32 | 34 | ||
33 | #include <asm/unified.h> | 35 | #include <asm/unified.h> |
34 | #include <asm/cpu.h> | 36 | #include <asm/cpu.h> |
@@ -42,6 +44,7 @@ | |||
42 | #include <asm/cacheflush.h> | 44 | #include <asm/cacheflush.h> |
43 | #include <asm/cachetype.h> | 45 | #include <asm/cachetype.h> |
44 | #include <asm/tlbflush.h> | 46 | #include <asm/tlbflush.h> |
47 | #include <asm/system.h> | ||
45 | 48 | ||
46 | #include <asm/prom.h> | 49 | #include <asm/prom.h> |
47 | #include <asm/mach/arch.h> | 50 | #include <asm/mach/arch.h> |
@@ -115,6 +118,13 @@ struct outer_cache_fns outer_cache __read_mostly; | |||
115 | EXPORT_SYMBOL(outer_cache); | 118 | EXPORT_SYMBOL(outer_cache); |
116 | #endif | 119 | #endif |
117 | 120 | ||
121 | /* | ||
122 | * Cached cpu_architecture() result for use by assembler code. | ||
123 | * C code should use the cpu_architecture() function instead of accessing this | ||
124 | * variable directly. | ||
125 | */ | ||
126 | int __cpu_architecture __read_mostly = CPU_ARCH_UNKNOWN; | ||
127 | |||
118 | struct stack { | 128 | struct stack { |
119 | u32 irq[3]; | 129 | u32 irq[3]; |
120 | u32 abt[3]; | 130 | u32 abt[3]; |
@@ -210,7 +220,7 @@ static const char *proc_arch[] = { | |||
210 | "?(17)", | 220 | "?(17)", |
211 | }; | 221 | }; |
212 | 222 | ||
213 | int cpu_architecture(void) | 223 | static int __get_cpu_architecture(void) |
214 | { | 224 | { |
215 | int cpu_arch; | 225 | int cpu_arch; |
216 | 226 | ||
@@ -243,11 +253,22 @@ int cpu_architecture(void) | |||
243 | return cpu_arch; | 253 | return cpu_arch; |
244 | } | 254 | } |
245 | 255 | ||
256 | int __pure cpu_architecture(void) | ||
257 | { | ||
258 | BUG_ON(__cpu_architecture == CPU_ARCH_UNKNOWN); | ||
259 | |||
260 | return __cpu_architecture; | ||
261 | } | ||
262 | |||
246 | static int cpu_has_aliasing_icache(unsigned int arch) | 263 | static int cpu_has_aliasing_icache(unsigned int arch) |
247 | { | 264 | { |
248 | int aliasing_icache; | 265 | int aliasing_icache; |
249 | unsigned int id_reg, num_sets, line_size; | 266 | unsigned int id_reg, num_sets, line_size; |
250 | 267 | ||
268 | /* PIPT caches never alias. */ | ||
269 | if (icache_is_pipt()) | ||
270 | return 0; | ||
271 | |||
251 | /* arch specifies the register format */ | 272 | /* arch specifies the register format */ |
252 | switch (arch) { | 273 | switch (arch) { |
253 | case CPU_ARCH_ARMv7: | 274 | case CPU_ARCH_ARMv7: |
@@ -282,8 +303,14 @@ static void __init cacheid_init(void) | |||
282 | /* ARMv7 register format */ | 303 | /* ARMv7 register format */ |
283 | arch = CPU_ARCH_ARMv7; | 304 | arch = CPU_ARCH_ARMv7; |
284 | cacheid = CACHEID_VIPT_NONALIASING; | 305 | cacheid = CACHEID_VIPT_NONALIASING; |
285 | if ((cachetype & (3 << 14)) == 1 << 14) | 306 | switch (cachetype & (3 << 14)) { |
307 | case (1 << 14): | ||
286 | cacheid |= CACHEID_ASID_TAGGED; | 308 | cacheid |= CACHEID_ASID_TAGGED; |
309 | break; | ||
310 | case (3 << 14): | ||
311 | cacheid |= CACHEID_PIPT; | ||
312 | break; | ||
313 | } | ||
287 | } else { | 314 | } else { |
288 | arch = CPU_ARCH_ARMv6; | 315 | arch = CPU_ARCH_ARMv6; |
289 | if (cachetype & (1 << 23)) | 316 | if (cachetype & (1 << 23)) |
@@ -300,10 +327,11 @@ static void __init cacheid_init(void) | |||
300 | printk("CPU: %s data cache, %s instruction cache\n", | 327 | printk("CPU: %s data cache, %s instruction cache\n", |
301 | cache_is_vivt() ? "VIVT" : | 328 | cache_is_vivt() ? "VIVT" : |
302 | cache_is_vipt_aliasing() ? "VIPT aliasing" : | 329 | cache_is_vipt_aliasing() ? "VIPT aliasing" : |
303 | cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown", | 330 | cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown", |
304 | cache_is_vivt() ? "VIVT" : | 331 | cache_is_vivt() ? "VIVT" : |
305 | icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" : | 332 | icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" : |
306 | icache_is_vipt_aliasing() ? "VIPT aliasing" : | 333 | icache_is_vipt_aliasing() ? "VIPT aliasing" : |
334 | icache_is_pipt() ? "PIPT" : | ||
307 | cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown"); | 335 | cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown"); |
308 | } | 336 | } |
309 | 337 | ||
@@ -414,6 +442,7 @@ static void __init setup_processor(void) | |||
414 | } | 442 | } |
415 | 443 | ||
416 | cpu_name = list->cpu_name; | 444 | cpu_name = list->cpu_name; |
445 | __cpu_architecture = __get_cpu_architecture(); | ||
417 | 446 | ||
418 | #ifdef MULTI_CPU | 447 | #ifdef MULTI_CPU |
419 | processor = *list->proc; | 448 | processor = *list->proc; |
@@ -861,7 +890,7 @@ static struct machine_desc * __init setup_machine_tags(unsigned int nr) | |||
861 | } | 890 | } |
862 | 891 | ||
863 | if (mdesc->fixup) | 892 | if (mdesc->fixup) |
864 | mdesc->fixup(mdesc, tags, &from, &meminfo); | 893 | mdesc->fixup(tags, &from, &meminfo); |
865 | 894 | ||
866 | if (tags->hdr.tag == ATAG_CORE) { | 895 | if (tags->hdr.tag == ATAG_CORE) { |
867 | if (meminfo.nr_banks != 0) | 896 | if (meminfo.nr_banks != 0) |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index d88ff0230e82..94f34a6c8610 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/cache.h> | 16 | #include <linux/cache.h> |
17 | #include <linux/profile.h> | 17 | #include <linux/profile.h> |
18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
19 | #include <linux/ftrace.h> | ||
20 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
21 | #include <linux/err.h> | 20 | #include <linux/err.h> |
22 | #include <linux/cpu.h> | 21 | #include <linux/cpu.h> |
@@ -31,6 +30,8 @@ | |||
31 | #include <asm/cacheflush.h> | 30 | #include <asm/cacheflush.h> |
32 | #include <asm/cpu.h> | 31 | #include <asm/cpu.h> |
33 | #include <asm/cputype.h> | 32 | #include <asm/cputype.h> |
33 | #include <asm/exception.h> | ||
34 | #include <asm/topology.h> | ||
34 | #include <asm/mmu_context.h> | 35 | #include <asm/mmu_context.h> |
35 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
36 | #include <asm/pgalloc.h> | 37 | #include <asm/pgalloc.h> |
@@ -39,6 +40,7 @@ | |||
39 | #include <asm/tlbflush.h> | 40 | #include <asm/tlbflush.h> |
40 | #include <asm/ptrace.h> | 41 | #include <asm/ptrace.h> |
41 | #include <asm/localtimer.h> | 42 | #include <asm/localtimer.h> |
43 | #include <asm/smp_plat.h> | ||
42 | 44 | ||
43 | /* | 45 | /* |
44 | * as from 2.5, kernels no longer have an init_tasks structure | 46 | * as from 2.5, kernels no longer have an init_tasks structure |
@@ -259,6 +261,20 @@ void __ref cpu_die(void) | |||
259 | } | 261 | } |
260 | #endif /* CONFIG_HOTPLUG_CPU */ | 262 | #endif /* CONFIG_HOTPLUG_CPU */ |
261 | 263 | ||
264 | int __cpu_logical_map[NR_CPUS]; | ||
265 | |||
266 | void __init smp_setup_processor_id(void) | ||
267 | { | ||
268 | int i; | ||
269 | u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0; | ||
270 | |||
271 | cpu_logical_map(0) = cpu; | ||
272 | for (i = 1; i < NR_CPUS; ++i) | ||
273 | cpu_logical_map(i) = i == cpu ? 0 : i; | ||
274 | |||
275 | printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu); | ||
276 | } | ||
277 | |||
262 | /* | 278 | /* |
263 | * Called by both boot and secondaries to move global data into | 279 | * Called by both boot and secondaries to move global data into |
264 | * per-processor storage. | 280 | * per-processor storage. |
@@ -268,6 +284,8 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid) | |||
268 | struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); | 284 | struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); |
269 | 285 | ||
270 | cpu_info->loops_per_jiffy = loops_per_jiffy; | 286 | cpu_info->loops_per_jiffy = loops_per_jiffy; |
287 | |||
288 | store_cpu_topology(cpuid); | ||
271 | } | 289 | } |
272 | 290 | ||
273 | /* | 291 | /* |
@@ -301,17 +319,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) | |||
301 | */ | 319 | */ |
302 | platform_secondary_init(cpu); | 320 | platform_secondary_init(cpu); |
303 | 321 | ||
304 | /* | ||
305 | * Enable local interrupts. | ||
306 | */ | ||
307 | notify_cpu_starting(cpu); | 322 | notify_cpu_starting(cpu); |
308 | local_irq_enable(); | ||
309 | local_fiq_enable(); | ||
310 | |||
311 | /* | ||
312 | * Setup the percpu timer for this CPU. | ||
313 | */ | ||
314 | percpu_timer_setup(); | ||
315 | 323 | ||
316 | calibrate_delay(); | 324 | calibrate_delay(); |
317 | 325 | ||
@@ -323,10 +331,23 @@ asmlinkage void __cpuinit secondary_start_kernel(void) | |||
323 | * before we continue. | 331 | * before we continue. |
324 | */ | 332 | */ |
325 | set_cpu_online(cpu, true); | 333 | set_cpu_online(cpu, true); |
334 | |||
335 | /* | ||
336 | * Setup the percpu timer for this CPU. | ||
337 | */ | ||
338 | percpu_timer_setup(); | ||
339 | |||
326 | while (!cpu_active(cpu)) | 340 | while (!cpu_active(cpu)) |
327 | cpu_relax(); | 341 | cpu_relax(); |
328 | 342 | ||
329 | /* | 343 | /* |
344 | * cpu_active bit is set, so it's safe to enalbe interrupts | ||
345 | * now. | ||
346 | */ | ||
347 | local_irq_enable(); | ||
348 | local_fiq_enable(); | ||
349 | |||
350 | /* | ||
330 | * OK, it's off to the idle thread for us | 351 | * OK, it's off to the idle thread for us |
331 | */ | 352 | */ |
332 | cpu_idle(); | 353 | cpu_idle(); |
@@ -358,6 +379,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
358 | { | 379 | { |
359 | unsigned int ncores = num_possible_cpus(); | 380 | unsigned int ncores = num_possible_cpus(); |
360 | 381 | ||
382 | init_cpu_topology(); | ||
383 | |||
361 | smp_store_cpu_info(smp_processor_id()); | 384 | smp_store_cpu_info(smp_processor_id()); |
362 | 385 | ||
363 | /* | 386 | /* |
@@ -460,6 +483,11 @@ static void ipi_timer(void) | |||
460 | #ifdef CONFIG_LOCAL_TIMERS | 483 | #ifdef CONFIG_LOCAL_TIMERS |
461 | asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs) | 484 | asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs) |
462 | { | 485 | { |
486 | handle_local_timer(regs); | ||
487 | } | ||
488 | |||
489 | void handle_local_timer(struct pt_regs *regs) | ||
490 | { | ||
463 | struct pt_regs *old_regs = set_irq_regs(regs); | 491 | struct pt_regs *old_regs = set_irq_regs(regs); |
464 | int cpu = smp_processor_id(); | 492 | int cpu = smp_processor_id(); |
465 | 493 | ||
@@ -538,7 +566,7 @@ static void percpu_timer_stop(void) | |||
538 | } | 566 | } |
539 | #endif | 567 | #endif |
540 | 568 | ||
541 | static DEFINE_SPINLOCK(stop_lock); | 569 | static DEFINE_RAW_SPINLOCK(stop_lock); |
542 | 570 | ||
543 | /* | 571 | /* |
544 | * ipi_cpu_stop - handle IPI from smp_send_stop() | 572 | * ipi_cpu_stop - handle IPI from smp_send_stop() |
@@ -547,10 +575,10 @@ static void ipi_cpu_stop(unsigned int cpu) | |||
547 | { | 575 | { |
548 | if (system_state == SYSTEM_BOOTING || | 576 | if (system_state == SYSTEM_BOOTING || |
549 | system_state == SYSTEM_RUNNING) { | 577 | system_state == SYSTEM_RUNNING) { |
550 | spin_lock(&stop_lock); | 578 | raw_spin_lock(&stop_lock); |
551 | printk(KERN_CRIT "CPU%u: stopping\n", cpu); | 579 | printk(KERN_CRIT "CPU%u: stopping\n", cpu); |
552 | dump_stack(); | 580 | dump_stack(); |
553 | spin_unlock(&stop_lock); | 581 | raw_spin_unlock(&stop_lock); |
554 | } | 582 | } |
555 | 583 | ||
556 | set_cpu_online(cpu, false); | 584 | set_cpu_online(cpu, false); |
@@ -567,6 +595,11 @@ static void ipi_cpu_stop(unsigned int cpu) | |||
567 | */ | 595 | */ |
568 | asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) | 596 | asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) |
569 | { | 597 | { |
598 | handle_IPI(ipinr, regs); | ||
599 | } | ||
600 | |||
601 | void handle_IPI(int ipinr, struct pt_regs *regs) | ||
602 | { | ||
570 | unsigned int cpu = smp_processor_id(); | 603 | unsigned int cpu = smp_processor_id(); |
571 | struct pt_regs *old_regs = set_irq_regs(regs); | 604 | struct pt_regs *old_regs = set_irq_regs(regs); |
572 | 605 | ||
diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c index 7fcddb75c877..8f5dd7963356 100644 --- a/arch/arm/kernel/smp_scu.c +++ b/arch/arm/kernel/smp_scu.c | |||
@@ -34,7 +34,7 @@ unsigned int __init scu_get_core_count(void __iomem *scu_base) | |||
34 | /* | 34 | /* |
35 | * Enable the SCU | 35 | * Enable the SCU |
36 | */ | 36 | */ |
37 | void __init scu_enable(void __iomem *scu_base) | 37 | void scu_enable(void __iomem *scu_base) |
38 | { | 38 | { |
39 | u32 scu_ctrl; | 39 | u32 scu_ctrl; |
40 | 40 | ||
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index cb634c3e28e9..5a54b95d6bd2 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c | |||
@@ -39,13 +39,11 @@ | |||
39 | */ | 39 | */ |
40 | static struct sys_timer *system_timer; | 40 | static struct sys_timer *system_timer; |
41 | 41 | ||
42 | #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) | 42 | #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \ |
43 | defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE) | ||
43 | /* this needs a better home */ | 44 | /* this needs a better home */ |
44 | DEFINE_SPINLOCK(rtc_lock); | 45 | DEFINE_SPINLOCK(rtc_lock); |
45 | |||
46 | #ifdef CONFIG_RTC_DRV_CMOS_MODULE | ||
47 | EXPORT_SYMBOL(rtc_lock); | 46 | EXPORT_SYMBOL(rtc_lock); |
48 | #endif | ||
49 | #endif /* pc-style 'CMOS' RTC support */ | 47 | #endif /* pc-style 'CMOS' RTC support */ |
50 | 48 | ||
51 | /* change this if you have some constant time drift */ | 49 | /* change this if you have some constant time drift */ |
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c new file mode 100644 index 000000000000..1040c00405d0 --- /dev/null +++ b/arch/arm/kernel/topology.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * arch/arm/kernel/topology.c | ||
3 | * | ||
4 | * Copyright (C) 2011 Linaro Limited. | ||
5 | * Written by: Vincent Guittot | ||
6 | * | ||
7 | * based on arch/sh/kernel/topology.c | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file "COPYING" in the main directory of this archive | ||
11 | * for more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/cpu.h> | ||
15 | #include <linux/cpumask.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/percpu.h> | ||
18 | #include <linux/node.h> | ||
19 | #include <linux/nodemask.h> | ||
20 | #include <linux/sched.h> | ||
21 | |||
22 | #include <asm/cputype.h> | ||
23 | #include <asm/topology.h> | ||
24 | |||
25 | #define MPIDR_SMP_BITMASK (0x3 << 30) | ||
26 | #define MPIDR_SMP_VALUE (0x2 << 30) | ||
27 | |||
28 | #define MPIDR_MT_BITMASK (0x1 << 24) | ||
29 | |||
30 | /* | ||
31 | * These masks reflect the current use of the affinity levels. | ||
32 | * The affinity level can be up to 16 bits according to ARM ARM | ||
33 | */ | ||
34 | |||
35 | #define MPIDR_LEVEL0_MASK 0x3 | ||
36 | #define MPIDR_LEVEL0_SHIFT 0 | ||
37 | |||
38 | #define MPIDR_LEVEL1_MASK 0xF | ||
39 | #define MPIDR_LEVEL1_SHIFT 8 | ||
40 | |||
41 | #define MPIDR_LEVEL2_MASK 0xFF | ||
42 | #define MPIDR_LEVEL2_SHIFT 16 | ||
43 | |||
44 | struct cputopo_arm cpu_topology[NR_CPUS]; | ||
45 | |||
46 | const struct cpumask *cpu_coregroup_mask(unsigned int cpu) | ||
47 | { | ||
48 | return &cpu_topology[cpu].core_sibling; | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * store_cpu_topology is called at boot when only one cpu is running | ||
53 | * and with the mutex cpu_hotplug.lock locked, when several cpus have booted, | ||
54 | * which prevents simultaneous write access to cpu_topology array | ||
55 | */ | ||
56 | void store_cpu_topology(unsigned int cpuid) | ||
57 | { | ||
58 | struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; | ||
59 | unsigned int mpidr; | ||
60 | unsigned int cpu; | ||
61 | |||
62 | /* If the cpu topology has been already set, just return */ | ||
63 | if (cpuid_topo->core_id != -1) | ||
64 | return; | ||
65 | |||
66 | mpidr = read_cpuid_mpidr(); | ||
67 | |||
68 | /* create cpu topology mapping */ | ||
69 | if ((mpidr & MPIDR_SMP_BITMASK) == MPIDR_SMP_VALUE) { | ||
70 | /* | ||
71 | * This is a multiprocessor system | ||
72 | * multiprocessor format & multiprocessor mode field are set | ||
73 | */ | ||
74 | |||
75 | if (mpidr & MPIDR_MT_BITMASK) { | ||
76 | /* core performance interdependency */ | ||
77 | cpuid_topo->thread_id = (mpidr >> MPIDR_LEVEL0_SHIFT) | ||
78 | & MPIDR_LEVEL0_MASK; | ||
79 | cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL1_SHIFT) | ||
80 | & MPIDR_LEVEL1_MASK; | ||
81 | cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL2_SHIFT) | ||
82 | & MPIDR_LEVEL2_MASK; | ||
83 | } else { | ||
84 | /* largely independent cores */ | ||
85 | cpuid_topo->thread_id = -1; | ||
86 | cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL0_SHIFT) | ||
87 | & MPIDR_LEVEL0_MASK; | ||
88 | cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT) | ||
89 | & MPIDR_LEVEL1_MASK; | ||
90 | } | ||
91 | } else { | ||
92 | /* | ||
93 | * This is an uniprocessor system | ||
94 | * we are in multiprocessor format but uniprocessor system | ||
95 | * or in the old uniprocessor format | ||
96 | */ | ||
97 | cpuid_topo->thread_id = -1; | ||
98 | cpuid_topo->core_id = 0; | ||
99 | cpuid_topo->socket_id = -1; | ||
100 | } | ||
101 | |||
102 | /* update core and thread sibling masks */ | ||
103 | for_each_possible_cpu(cpu) { | ||
104 | struct cputopo_arm *cpu_topo = &cpu_topology[cpu]; | ||
105 | |||
106 | if (cpuid_topo->socket_id == cpu_topo->socket_id) { | ||
107 | cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); | ||
108 | if (cpu != cpuid) | ||
109 | cpumask_set_cpu(cpu, | ||
110 | &cpuid_topo->core_sibling); | ||
111 | |||
112 | if (cpuid_topo->core_id == cpu_topo->core_id) { | ||
113 | cpumask_set_cpu(cpuid, | ||
114 | &cpu_topo->thread_sibling); | ||
115 | if (cpu != cpuid) | ||
116 | cpumask_set_cpu(cpu, | ||
117 | &cpuid_topo->thread_sibling); | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | smp_wmb(); | ||
122 | |||
123 | printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", | ||
124 | cpuid, cpu_topology[cpuid].thread_id, | ||
125 | cpu_topology[cpuid].core_id, | ||
126 | cpu_topology[cpuid].socket_id, mpidr); | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * init_cpu_topology is called at boot when only one cpu is running | ||
131 | * which prevent simultaneous write access to cpu_topology array | ||
132 | */ | ||
133 | void init_cpu_topology(void) | ||
134 | { | ||
135 | unsigned int cpu; | ||
136 | |||
137 | /* init core mask */ | ||
138 | for_each_possible_cpu(cpu) { | ||
139 | struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]); | ||
140 | |||
141 | cpu_topo->thread_id = -1; | ||
142 | cpu_topo->core_id = -1; | ||
143 | cpu_topo->socket_id = -1; | ||
144 | cpumask_clear(&cpu_topo->core_sibling); | ||
145 | cpumask_clear(&cpu_topo->thread_sibling); | ||
146 | } | ||
147 | smp_wmb(); | ||
148 | } | ||
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index bc9f9da782cb..99a572702509 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -21,12 +21,14 @@ | |||
21 | #include <linux/kdebug.h> | 21 | #include <linux/kdebug.h> |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/kexec.h> | 23 | #include <linux/kexec.h> |
24 | #include <linux/bug.h> | ||
24 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
25 | #include <linux/init.h> | 26 | #include <linux/init.h> |
26 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
27 | 28 | ||
28 | #include <linux/atomic.h> | 29 | #include <linux/atomic.h> |
29 | #include <asm/cacheflush.h> | 30 | #include <asm/cacheflush.h> |
31 | #include <asm/exception.h> | ||
30 | #include <asm/system.h> | 32 | #include <asm/system.h> |
31 | #include <asm/unistd.h> | 33 | #include <asm/unistd.h> |
32 | #include <asm/traps.h> | 34 | #include <asm/traps.h> |
@@ -255,7 +257,7 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt | |||
255 | return ret; | 257 | return ret; |
256 | } | 258 | } |
257 | 259 | ||
258 | static DEFINE_SPINLOCK(die_lock); | 260 | static DEFINE_RAW_SPINLOCK(die_lock); |
259 | 261 | ||
260 | /* | 262 | /* |
261 | * This function is protected against re-entrancy. | 263 | * This function is protected against re-entrancy. |
@@ -267,9 +269,11 @@ void die(const char *str, struct pt_regs *regs, int err) | |||
267 | 269 | ||
268 | oops_enter(); | 270 | oops_enter(); |
269 | 271 | ||
270 | spin_lock_irq(&die_lock); | 272 | raw_spin_lock_irq(&die_lock); |
271 | console_verbose(); | 273 | console_verbose(); |
272 | bust_spinlocks(1); | 274 | bust_spinlocks(1); |
275 | if (!user_mode(regs)) | ||
276 | report_bug(regs->ARM_pc, regs); | ||
273 | ret = __die(str, err, thread, regs); | 277 | ret = __die(str, err, thread, regs); |
274 | 278 | ||
275 | if (regs && kexec_should_crash(thread->task)) | 279 | if (regs && kexec_should_crash(thread->task)) |
@@ -277,7 +281,7 @@ void die(const char *str, struct pt_regs *regs, int err) | |||
277 | 281 | ||
278 | bust_spinlocks(0); | 282 | bust_spinlocks(0); |
279 | add_taint(TAINT_DIE); | 283 | add_taint(TAINT_DIE); |
280 | spin_unlock_irq(&die_lock); | 284 | raw_spin_unlock_irq(&die_lock); |
281 | oops_exit(); | 285 | oops_exit(); |
282 | 286 | ||
283 | if (in_interrupt()) | 287 | if (in_interrupt()) |
@@ -301,25 +305,43 @@ void arm_notify_die(const char *str, struct pt_regs *regs, | |||
301 | } | 305 | } |
302 | } | 306 | } |
303 | 307 | ||
308 | #ifdef CONFIG_GENERIC_BUG | ||
309 | |||
310 | int is_valid_bugaddr(unsigned long pc) | ||
311 | { | ||
312 | #ifdef CONFIG_THUMB2_KERNEL | ||
313 | unsigned short bkpt; | ||
314 | #else | ||
315 | unsigned long bkpt; | ||
316 | #endif | ||
317 | |||
318 | if (probe_kernel_address((unsigned *)pc, bkpt)) | ||
319 | return 0; | ||
320 | |||
321 | return bkpt == BUG_INSTR_VALUE; | ||
322 | } | ||
323 | |||
324 | #endif | ||
325 | |||
304 | static LIST_HEAD(undef_hook); | 326 | static LIST_HEAD(undef_hook); |
305 | static DEFINE_SPINLOCK(undef_lock); | 327 | static DEFINE_RAW_SPINLOCK(undef_lock); |
306 | 328 | ||
307 | void register_undef_hook(struct undef_hook *hook) | 329 | void register_undef_hook(struct undef_hook *hook) |
308 | { | 330 | { |
309 | unsigned long flags; | 331 | unsigned long flags; |
310 | 332 | ||
311 | spin_lock_irqsave(&undef_lock, flags); | 333 | raw_spin_lock_irqsave(&undef_lock, flags); |
312 | list_add(&hook->node, &undef_hook); | 334 | list_add(&hook->node, &undef_hook); |
313 | spin_unlock_irqrestore(&undef_lock, flags); | 335 | raw_spin_unlock_irqrestore(&undef_lock, flags); |
314 | } | 336 | } |
315 | 337 | ||
316 | void unregister_undef_hook(struct undef_hook *hook) | 338 | void unregister_undef_hook(struct undef_hook *hook) |
317 | { | 339 | { |
318 | unsigned long flags; | 340 | unsigned long flags; |
319 | 341 | ||
320 | spin_lock_irqsave(&undef_lock, flags); | 342 | raw_spin_lock_irqsave(&undef_lock, flags); |
321 | list_del(&hook->node); | 343 | list_del(&hook->node); |
322 | spin_unlock_irqrestore(&undef_lock, flags); | 344 | raw_spin_unlock_irqrestore(&undef_lock, flags); |
323 | } | 345 | } |
324 | 346 | ||
325 | static int call_undef_hook(struct pt_regs *regs, unsigned int instr) | 347 | static int call_undef_hook(struct pt_regs *regs, unsigned int instr) |
@@ -328,12 +350,12 @@ static int call_undef_hook(struct pt_regs *regs, unsigned int instr) | |||
328 | unsigned long flags; | 350 | unsigned long flags; |
329 | int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL; | 351 | int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL; |
330 | 352 | ||
331 | spin_lock_irqsave(&undef_lock, flags); | 353 | raw_spin_lock_irqsave(&undef_lock, flags); |
332 | list_for_each_entry(hook, &undef_hook, node) | 354 | list_for_each_entry(hook, &undef_hook, node) |
333 | if ((instr & hook->instr_mask) == hook->instr_val && | 355 | if ((instr & hook->instr_mask) == hook->instr_val && |
334 | (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) | 356 | (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) |
335 | fn = hook->fn; | 357 | fn = hook->fn; |
336 | spin_unlock_irqrestore(&undef_lock, flags); | 358 | raw_spin_unlock_irqrestore(&undef_lock, flags); |
337 | 359 | ||
338 | return fn ? fn(regs, instr) : 1; | 360 | return fn ? fn(regs, instr) : 1; |
339 | } | 361 | } |
@@ -706,16 +728,6 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs) | |||
706 | arm_notify_die("unknown data abort code", regs, &info, instr, 0); | 728 | arm_notify_die("unknown data abort code", regs, &info, instr, 0); |
707 | } | 729 | } |
708 | 730 | ||
709 | void __attribute__((noreturn)) __bug(const char *file, int line) | ||
710 | { | ||
711 | printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line); | ||
712 | *(int *)0 = 0; | ||
713 | |||
714 | /* Avoid "noreturn function does return" */ | ||
715 | for (;;); | ||
716 | } | ||
717 | EXPORT_SYMBOL(__bug); | ||
718 | |||
719 | void __readwrite_bug(const char *fn) | 731 | void __readwrite_bug(const char *fn) |
720 | { | 732 | { |
721 | printk("%s called, but not implemented\n", fn); | 733 | printk("%s called, but not implemented\n", fn); |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 4e66f62b8d41..20b3041e0860 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -21,7 +21,8 @@ | |||
21 | #define ARM_CPU_KEEP(x) | 21 | #define ARM_CPU_KEEP(x) |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | #if defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK) | 24 | #if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \ |
25 | defined(CONFIG_GENERIC_BUG) | ||
25 | #define ARM_EXIT_KEEP(x) x | 26 | #define ARM_EXIT_KEEP(x) x |
26 | #define ARM_EXIT_DISCARD(x) | 27 | #define ARM_EXIT_DISCARD(x) |
27 | #else | 28 | #else |