diff options
Diffstat (limited to 'arch/powerpc/kernel')
33 files changed, 1138 insertions, 1790 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 58d0572de6f9..1dda70129141 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -34,13 +34,14 @@ obj-y += vdso32/ | |||
34 | obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \ | 34 | obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \ |
35 | signal_64.o ptrace32.o \ | 35 | signal_64.o ptrace32.o \ |
36 | paca.o nvram_64.o firmware.o | 36 | paca.o nvram_64.o firmware.o |
37 | obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o | ||
37 | obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_ppc970.o cpu_setup_pa6t.o | 38 | obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_ppc970.o cpu_setup_pa6t.o |
38 | obj64-$(CONFIG_RELOCATABLE) += reloc_64.o | 39 | obj64-$(CONFIG_RELOCATABLE) += reloc_64.o |
39 | obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o | 40 | obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o idle_book3e.o |
40 | obj-$(CONFIG_PPC64) += vdso64/ | 41 | obj-$(CONFIG_PPC64) += vdso64/ |
41 | obj-$(CONFIG_ALTIVEC) += vecemu.o | 42 | obj-$(CONFIG_ALTIVEC) += vecemu.o |
42 | obj-$(CONFIG_PPC_970_NAP) += idle_power4.o | 43 | obj-$(CONFIG_PPC_970_NAP) += idle_power4.o |
43 | obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o | 44 | obj-$(CONFIG_PPC_OF) += of_platform.o prom_parse.o |
44 | obj-$(CONFIG_PPC_CLOCK) += clock.o | 45 | obj-$(CONFIG_PPC_CLOCK) += clock.o |
45 | procfs-y := proc_powerpc.o | 46 | procfs-y := proc_powerpc.o |
46 | obj-$(CONFIG_PROC_FS) += $(procfs-y) | 47 | obj-$(CONFIG_PROC_FS) += $(procfs-y) |
@@ -67,6 +68,7 @@ obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o | |||
67 | obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o | 68 | obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o |
68 | obj-$(CONFIG_44x) += cpu_setup_44x.o | 69 | obj-$(CONFIG_44x) += cpu_setup_44x.o |
69 | obj-$(CONFIG_FSL_BOOKE) += cpu_setup_fsl_booke.o dbell.o | 70 | obj-$(CONFIG_FSL_BOOKE) += cpu_setup_fsl_booke.o dbell.o |
71 | obj-$(CONFIG_PPC_BOOK3E_64) += dbell.o | ||
70 | 72 | ||
71 | extra-y := head_$(CONFIG_WORD_SIZE).o | 73 | extra-y := head_$(CONFIG_WORD_SIZE).o |
72 | extra-$(CONFIG_PPC_BOOK3E_32) := head_new_booke.o | 74 | extra-$(CONFIG_PPC_BOOK3E_32) := head_new_booke.o |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 496cc5b3984f..1c0607ddccc0 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -194,7 +194,6 @@ int main(void) | |||
194 | DEFINE(PACA_STARTSPURR, offsetof(struct paca_struct, startspurr)); | 194 | DEFINE(PACA_STARTSPURR, offsetof(struct paca_struct, startspurr)); |
195 | DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); | 195 | DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); |
196 | DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); | 196 | DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); |
197 | DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset)); | ||
198 | DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); | 197 | DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); |
199 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | 198 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER |
200 | DEFINE(PACA_KVM_SVCPU, offsetof(struct paca_struct, shadow_vcpu)); | 199 | DEFINE(PACA_KVM_SVCPU, offsetof(struct paca_struct, shadow_vcpu)); |
@@ -342,6 +341,7 @@ int main(void) | |||
342 | DEFINE(WTOM_CLOCK_SEC, offsetof(struct vdso_data, wtom_clock_sec)); | 341 | DEFINE(WTOM_CLOCK_SEC, offsetof(struct vdso_data, wtom_clock_sec)); |
343 | DEFINE(WTOM_CLOCK_NSEC, offsetof(struct vdso_data, wtom_clock_nsec)); | 342 | DEFINE(WTOM_CLOCK_NSEC, offsetof(struct vdso_data, wtom_clock_nsec)); |
344 | DEFINE(STAMP_XTIME, offsetof(struct vdso_data, stamp_xtime)); | 343 | DEFINE(STAMP_XTIME, offsetof(struct vdso_data, stamp_xtime)); |
344 | DEFINE(STAMP_SEC_FRAC, offsetof(struct vdso_data, stamp_sec_fraction)); | ||
345 | DEFINE(CFG_ICACHE_BLOCKSZ, offsetof(struct vdso_data, icache_block_size)); | 345 | DEFINE(CFG_ICACHE_BLOCKSZ, offsetof(struct vdso_data, icache_block_size)); |
346 | DEFINE(CFG_DCACHE_BLOCKSZ, offsetof(struct vdso_data, dcache_block_size)); | 346 | DEFINE(CFG_DCACHE_BLOCKSZ, offsetof(struct vdso_data, dcache_block_size)); |
347 | DEFINE(CFG_ICACHE_LOGBLOCKSZ, offsetof(struct vdso_data, icache_log_block_size)); | 347 | DEFINE(CFG_ICACHE_LOGBLOCKSZ, offsetof(struct vdso_data, icache_log_block_size)); |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 87aa0f3c6047..65e2b4e10f97 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -1364,10 +1364,10 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1364 | .machine_check = machine_check_4xx, | 1364 | .machine_check = machine_check_4xx, |
1365 | .platform = "ppc405", | 1365 | .platform = "ppc405", |
1366 | }, | 1366 | }, |
1367 | { /* 405EX */ | 1367 | { /* 405EX Rev. A/B with Security */ |
1368 | .pvr_mask = 0xffff0004, | 1368 | .pvr_mask = 0xffff000f, |
1369 | .pvr_value = 0x12910004, | 1369 | .pvr_value = 0x12910007, |
1370 | .cpu_name = "405EX", | 1370 | .cpu_name = "405EX Rev. A/B", |
1371 | .cpu_features = CPU_FTRS_40X, | 1371 | .cpu_features = CPU_FTRS_40X, |
1372 | .cpu_user_features = PPC_FEATURE_32 | | 1372 | .cpu_user_features = PPC_FEATURE_32 | |
1373 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | 1373 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, |
@@ -1377,10 +1377,114 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1377 | .machine_check = machine_check_4xx, | 1377 | .machine_check = machine_check_4xx, |
1378 | .platform = "ppc405", | 1378 | .platform = "ppc405", |
1379 | }, | 1379 | }, |
1380 | { /* 405EXr */ | 1380 | { /* 405EX Rev. C without Security */ |
1381 | .pvr_mask = 0xffff0004, | 1381 | .pvr_mask = 0xffff000f, |
1382 | .pvr_value = 0x1291000d, | ||
1383 | .cpu_name = "405EX Rev. C", | ||
1384 | .cpu_features = CPU_FTRS_40X, | ||
1385 | .cpu_user_features = PPC_FEATURE_32 | | ||
1386 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | ||
1387 | .mmu_features = MMU_FTR_TYPE_40x, | ||
1388 | .icache_bsize = 32, | ||
1389 | .dcache_bsize = 32, | ||
1390 | .machine_check = machine_check_4xx, | ||
1391 | .platform = "ppc405", | ||
1392 | }, | ||
1393 | { /* 405EX Rev. C with Security */ | ||
1394 | .pvr_mask = 0xffff000f, | ||
1395 | .pvr_value = 0x1291000f, | ||
1396 | .cpu_name = "405EX Rev. C", | ||
1397 | .cpu_features = CPU_FTRS_40X, | ||
1398 | .cpu_user_features = PPC_FEATURE_32 | | ||
1399 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | ||
1400 | .mmu_features = MMU_FTR_TYPE_40x, | ||
1401 | .icache_bsize = 32, | ||
1402 | .dcache_bsize = 32, | ||
1403 | .machine_check = machine_check_4xx, | ||
1404 | .platform = "ppc405", | ||
1405 | }, | ||
1406 | { /* 405EX Rev. D without Security */ | ||
1407 | .pvr_mask = 0xffff000f, | ||
1408 | .pvr_value = 0x12910003, | ||
1409 | .cpu_name = "405EX Rev. D", | ||
1410 | .cpu_features = CPU_FTRS_40X, | ||
1411 | .cpu_user_features = PPC_FEATURE_32 | | ||
1412 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | ||
1413 | .mmu_features = MMU_FTR_TYPE_40x, | ||
1414 | .icache_bsize = 32, | ||
1415 | .dcache_bsize = 32, | ||
1416 | .machine_check = machine_check_4xx, | ||
1417 | .platform = "ppc405", | ||
1418 | }, | ||
1419 | { /* 405EX Rev. D with Security */ | ||
1420 | .pvr_mask = 0xffff000f, | ||
1421 | .pvr_value = 0x12910005, | ||
1422 | .cpu_name = "405EX Rev. D", | ||
1423 | .cpu_features = CPU_FTRS_40X, | ||
1424 | .cpu_user_features = PPC_FEATURE_32 | | ||
1425 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | ||
1426 | .mmu_features = MMU_FTR_TYPE_40x, | ||
1427 | .icache_bsize = 32, | ||
1428 | .dcache_bsize = 32, | ||
1429 | .machine_check = machine_check_4xx, | ||
1430 | .platform = "ppc405", | ||
1431 | }, | ||
1432 | { /* 405EXr Rev. A/B without Security */ | ||
1433 | .pvr_mask = 0xffff000f, | ||
1434 | .pvr_value = 0x12910001, | ||
1435 | .cpu_name = "405EXr Rev. A/B", | ||
1436 | .cpu_features = CPU_FTRS_40X, | ||
1437 | .cpu_user_features = PPC_FEATURE_32 | | ||
1438 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | ||
1439 | .mmu_features = MMU_FTR_TYPE_40x, | ||
1440 | .icache_bsize = 32, | ||
1441 | .dcache_bsize = 32, | ||
1442 | .machine_check = machine_check_4xx, | ||
1443 | .platform = "ppc405", | ||
1444 | }, | ||
1445 | { /* 405EXr Rev. C without Security */ | ||
1446 | .pvr_mask = 0xffff000f, | ||
1447 | .pvr_value = 0x12910009, | ||
1448 | .cpu_name = "405EXr Rev. C", | ||
1449 | .cpu_features = CPU_FTRS_40X, | ||
1450 | .cpu_user_features = PPC_FEATURE_32 | | ||
1451 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | ||
1452 | .mmu_features = MMU_FTR_TYPE_40x, | ||
1453 | .icache_bsize = 32, | ||
1454 | .dcache_bsize = 32, | ||
1455 | .machine_check = machine_check_4xx, | ||
1456 | .platform = "ppc405", | ||
1457 | }, | ||
1458 | { /* 405EXr Rev. C with Security */ | ||
1459 | .pvr_mask = 0xffff000f, | ||
1460 | .pvr_value = 0x1291000b, | ||
1461 | .cpu_name = "405EXr Rev. C", | ||
1462 | .cpu_features = CPU_FTRS_40X, | ||
1463 | .cpu_user_features = PPC_FEATURE_32 | | ||
1464 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | ||
1465 | .mmu_features = MMU_FTR_TYPE_40x, | ||
1466 | .icache_bsize = 32, | ||
1467 | .dcache_bsize = 32, | ||
1468 | .machine_check = machine_check_4xx, | ||
1469 | .platform = "ppc405", | ||
1470 | }, | ||
1471 | { /* 405EXr Rev. D without Security */ | ||
1472 | .pvr_mask = 0xffff000f, | ||
1382 | .pvr_value = 0x12910000, | 1473 | .pvr_value = 0x12910000, |
1383 | .cpu_name = "405EXr", | 1474 | .cpu_name = "405EXr Rev. D", |
1475 | .cpu_features = CPU_FTRS_40X, | ||
1476 | .cpu_user_features = PPC_FEATURE_32 | | ||
1477 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | ||
1478 | .mmu_features = MMU_FTR_TYPE_40x, | ||
1479 | .icache_bsize = 32, | ||
1480 | .dcache_bsize = 32, | ||
1481 | .machine_check = machine_check_4xx, | ||
1482 | .platform = "ppc405", | ||
1483 | }, | ||
1484 | { /* 405EXr Rev. D with Security */ | ||
1485 | .pvr_mask = 0xffff000f, | ||
1486 | .pvr_value = 0x12910002, | ||
1487 | .cpu_name = "405EXr Rev. D", | ||
1384 | .cpu_features = CPU_FTRS_40X, | 1488 | .cpu_features = CPU_FTRS_40X, |
1385 | .cpu_user_features = PPC_FEATURE_32 | | 1489 | .cpu_user_features = PPC_FEATURE_32 | |
1386 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | 1490 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, |
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 40f524643ba6..8e05c16344e4 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c | |||
@@ -128,9 +128,9 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, | |||
128 | if (!csize) | 128 | if (!csize) |
129 | return 0; | 129 | return 0; |
130 | 130 | ||
131 | csize = min(csize, PAGE_SIZE); | 131 | csize = min_t(size_t, csize, PAGE_SIZE); |
132 | 132 | ||
133 | if (pfn < max_pfn) { | 133 | if ((min_low_pfn < pfn) && (pfn < max_pfn)) { |
134 | vaddr = __va(pfn << PAGE_SHIFT); | 134 | vaddr = __va(pfn << PAGE_SHIFT); |
135 | csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf); | 135 | csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf); |
136 | } else { | 136 | } else { |
diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c index 1493734cd871..3307a52d797f 100644 --- a/arch/powerpc/kernel/dbell.c +++ b/arch/powerpc/kernel/dbell.c | |||
@@ -13,32 +13,88 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/smp.h> | 14 | #include <linux/smp.h> |
15 | #include <linux/threads.h> | 15 | #include <linux/threads.h> |
16 | #include <linux/percpu.h> | ||
16 | 17 | ||
17 | #include <asm/dbell.h> | 18 | #include <asm/dbell.h> |
19 | #include <asm/irq_regs.h> | ||
18 | 20 | ||
19 | #ifdef CONFIG_SMP | 21 | #ifdef CONFIG_SMP |
20 | unsigned long dbell_smp_message[NR_CPUS]; | 22 | struct doorbell_cpu_info { |
23 | unsigned long messages; /* current messages bits */ | ||
24 | unsigned int tag; /* tag value */ | ||
25 | }; | ||
21 | 26 | ||
22 | void smp_dbell_message_pass(int target, int msg) | 27 | static DEFINE_PER_CPU(struct doorbell_cpu_info, doorbell_cpu_info); |
28 | |||
29 | void doorbell_setup_this_cpu(void) | ||
30 | { | ||
31 | struct doorbell_cpu_info *info = &__get_cpu_var(doorbell_cpu_info); | ||
32 | |||
33 | info->messages = 0; | ||
34 | info->tag = mfspr(SPRN_PIR) & 0x3fff; | ||
35 | } | ||
36 | |||
37 | void doorbell_message_pass(int target, int msg) | ||
23 | { | 38 | { |
39 | struct doorbell_cpu_info *info; | ||
24 | int i; | 40 | int i; |
25 | 41 | ||
26 | if(target < NR_CPUS) { | 42 | if (target < NR_CPUS) { |
27 | set_bit(msg, &dbell_smp_message[target]); | 43 | info = &per_cpu(doorbell_cpu_info, target); |
28 | ppc_msgsnd(PPC_DBELL, 0, target); | 44 | set_bit(msg, &info->messages); |
45 | ppc_msgsnd(PPC_DBELL, 0, info->tag); | ||
29 | } | 46 | } |
30 | else if(target == MSG_ALL_BUT_SELF) { | 47 | else if (target == MSG_ALL_BUT_SELF) { |
31 | for_each_online_cpu(i) { | 48 | for_each_online_cpu(i) { |
32 | if (i == smp_processor_id()) | 49 | if (i == smp_processor_id()) |
33 | continue; | 50 | continue; |
34 | set_bit(msg, &dbell_smp_message[i]); | 51 | info = &per_cpu(doorbell_cpu_info, i); |
35 | ppc_msgsnd(PPC_DBELL, 0, i); | 52 | set_bit(msg, &info->messages); |
53 | ppc_msgsnd(PPC_DBELL, 0, info->tag); | ||
36 | } | 54 | } |
37 | } | 55 | } |
38 | else { /* target == MSG_ALL */ | 56 | else { /* target == MSG_ALL */ |
39 | for_each_online_cpu(i) | 57 | for_each_online_cpu(i) { |
40 | set_bit(msg, &dbell_smp_message[i]); | 58 | info = &per_cpu(doorbell_cpu_info, i); |
59 | set_bit(msg, &info->messages); | ||
60 | } | ||
41 | ppc_msgsnd(PPC_DBELL, PPC_DBELL_MSG_BRDCAST, 0); | 61 | ppc_msgsnd(PPC_DBELL, PPC_DBELL_MSG_BRDCAST, 0); |
42 | } | 62 | } |
43 | } | 63 | } |
44 | #endif | 64 | |
65 | void doorbell_exception(struct pt_regs *regs) | ||
66 | { | ||
67 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
68 | struct doorbell_cpu_info *info = &__get_cpu_var(doorbell_cpu_info); | ||
69 | int msg; | ||
70 | |||
71 | /* Warning: regs can be NULL when called from irq enable */ | ||
72 | |||
73 | if (!info->messages || (num_online_cpus() < 2)) | ||
74 | goto out; | ||
75 | |||
76 | for (msg = 0; msg < 4; msg++) | ||
77 | if (test_and_clear_bit(msg, &info->messages)) | ||
78 | smp_message_recv(msg); | ||
79 | |||
80 | out: | ||
81 | set_irq_regs(old_regs); | ||
82 | } | ||
83 | |||
84 | void doorbell_check_self(void) | ||
85 | { | ||
86 | struct doorbell_cpu_info *info = &__get_cpu_var(doorbell_cpu_info); | ||
87 | |||
88 | if (!info->messages) | ||
89 | return; | ||
90 | |||
91 | ppc_msgsnd(PPC_DBELL, 0, info->tag); | ||
92 | } | ||
93 | |||
94 | #else /* CONFIG_SMP */ | ||
95 | void doorbell_exception(struct pt_regs *regs) | ||
96 | { | ||
97 | printk(KERN_WARNING "Received doorbell on non-smp system\n"); | ||
98 | } | ||
99 | #endif /* CONFIG_SMP */ | ||
100 | |||
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c index 02f724f36753..4295e0b94b2d 100644 --- a/arch/powerpc/kernel/dma-swiotlb.c +++ b/arch/powerpc/kernel/dma-swiotlb.c | |||
@@ -82,17 +82,9 @@ static struct notifier_block ppc_swiotlb_plat_bus_notifier = { | |||
82 | .priority = 0, | 82 | .priority = 0, |
83 | }; | 83 | }; |
84 | 84 | ||
85 | static struct notifier_block ppc_swiotlb_of_bus_notifier = { | ||
86 | .notifier_call = ppc_swiotlb_bus_notify, | ||
87 | .priority = 0, | ||
88 | }; | ||
89 | |||
90 | int __init swiotlb_setup_bus_notifier(void) | 85 | int __init swiotlb_setup_bus_notifier(void) |
91 | { | 86 | { |
92 | bus_register_notifier(&platform_bus_type, | 87 | bus_register_notifier(&platform_bus_type, |
93 | &ppc_swiotlb_plat_bus_notifier); | 88 | &ppc_swiotlb_plat_bus_notifier); |
94 | bus_register_notifier(&of_platform_bus_type, | ||
95 | &ppc_swiotlb_of_bus_notifier); | ||
96 | |||
97 | return 0; | 89 | return 0; |
98 | } | 90 | } |
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 24dcc0ecf246..5c43063d2506 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S | |||
@@ -191,6 +191,12 @@ exc_##n##_bad_stack: \ | |||
191 | sth r1,PACA_TRAP_SAVE(r13); /* store trap */ \ | 191 | sth r1,PACA_TRAP_SAVE(r13); /* store trap */ \ |
192 | b bad_stack_book3e; /* bad stack error */ | 192 | b bad_stack_book3e; /* bad stack error */ |
193 | 193 | ||
194 | /* WARNING: If you change the layout of this stub, make sure you chcek | ||
195 | * the debug exception handler which handles single stepping | ||
196 | * into exceptions from userspace, and the MM code in | ||
197 | * arch/powerpc/mm/tlb_nohash.c which patches the branch here | ||
198 | * and would need to be updated if that branch is moved | ||
199 | */ | ||
194 | #define EXCEPTION_STUB(loc, label) \ | 200 | #define EXCEPTION_STUB(loc, label) \ |
195 | . = interrupt_base_book3e + loc; \ | 201 | . = interrupt_base_book3e + loc; \ |
196 | nop; /* To make debug interrupts happy */ \ | 202 | nop; /* To make debug interrupts happy */ \ |
@@ -204,11 +210,30 @@ exc_##n##_bad_stack: \ | |||
204 | lis r,TSR_FIS@h; \ | 210 | lis r,TSR_FIS@h; \ |
205 | mtspr SPRN_TSR,r | 211 | mtspr SPRN_TSR,r |
206 | 212 | ||
213 | /* Used by asynchronous interrupt that may happen in the idle loop. | ||
214 | * | ||
215 | * This check if the thread was in the idle loop, and if yes, returns | ||
216 | * to the caller rather than the PC. This is to avoid a race if | ||
217 | * interrupts happen before the wait instruction. | ||
218 | */ | ||
219 | #define CHECK_NAPPING() \ | ||
220 | clrrdi r11,r1,THREAD_SHIFT; \ | ||
221 | ld r10,TI_LOCAL_FLAGS(r11); \ | ||
222 | andi. r9,r10,_TLF_NAPPING; \ | ||
223 | beq+ 1f; \ | ||
224 | ld r8,_LINK(r1); \ | ||
225 | rlwinm r7,r10,0,~_TLF_NAPPING; \ | ||
226 | std r8,_NIP(r1); \ | ||
227 | std r7,TI_LOCAL_FLAGS(r11); \ | ||
228 | 1: | ||
229 | |||
230 | |||
207 | #define MASKABLE_EXCEPTION(trapnum, label, hdlr, ack) \ | 231 | #define MASKABLE_EXCEPTION(trapnum, label, hdlr, ack) \ |
208 | START_EXCEPTION(label); \ | 232 | START_EXCEPTION(label); \ |
209 | NORMAL_EXCEPTION_PROLOG(trapnum, PROLOG_ADDITION_MASKABLE) \ | 233 | NORMAL_EXCEPTION_PROLOG(trapnum, PROLOG_ADDITION_MASKABLE) \ |
210 | EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE_ALL) \ | 234 | EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE_ALL) \ |
211 | ack(r8); \ | 235 | ack(r8); \ |
236 | CHECK_NAPPING(); \ | ||
212 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | 237 | addi r3,r1,STACK_FRAME_OVERHEAD; \ |
213 | bl hdlr; \ | 238 | bl hdlr; \ |
214 | b .ret_from_except_lite; | 239 | b .ret_from_except_lite; |
@@ -246,11 +271,9 @@ interrupt_base_book3e: /* fake trap */ | |||
246 | EXCEPTION_STUB(0x1a0, watchdog) /* 0x09f0 */ | 271 | EXCEPTION_STUB(0x1a0, watchdog) /* 0x09f0 */ |
247 | EXCEPTION_STUB(0x1c0, data_tlb_miss) | 272 | EXCEPTION_STUB(0x1c0, data_tlb_miss) |
248 | EXCEPTION_STUB(0x1e0, instruction_tlb_miss) | 273 | EXCEPTION_STUB(0x1e0, instruction_tlb_miss) |
274 | EXCEPTION_STUB(0x280, doorbell) | ||
275 | EXCEPTION_STUB(0x2a0, doorbell_crit) | ||
249 | 276 | ||
250 | #if 0 | ||
251 | EXCEPTION_STUB(0x280, processor_doorbell) | ||
252 | EXCEPTION_STUB(0x220, processor_doorbell_crit) | ||
253 | #endif | ||
254 | .globl interrupt_end_book3e | 277 | .globl interrupt_end_book3e |
255 | interrupt_end_book3e: | 278 | interrupt_end_book3e: |
256 | 279 | ||
@@ -259,6 +282,7 @@ interrupt_end_book3e: | |||
259 | CRIT_EXCEPTION_PROLOG(0x100, PROLOG_ADDITION_NONE) | 282 | CRIT_EXCEPTION_PROLOG(0x100, PROLOG_ADDITION_NONE) |
260 | // EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE_ALL) | 283 | // EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE_ALL) |
261 | // bl special_reg_save_crit | 284 | // bl special_reg_save_crit |
285 | // CHECK_NAPPING(); | ||
262 | // addi r3,r1,STACK_FRAME_OVERHEAD | 286 | // addi r3,r1,STACK_FRAME_OVERHEAD |
263 | // bl .critical_exception | 287 | // bl .critical_exception |
264 | // b ret_from_crit_except | 288 | // b ret_from_crit_except |
@@ -270,6 +294,7 @@ interrupt_end_book3e: | |||
270 | // EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE_ALL) | 294 | // EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE_ALL) |
271 | // bl special_reg_save_mc | 295 | // bl special_reg_save_mc |
272 | // addi r3,r1,STACK_FRAME_OVERHEAD | 296 | // addi r3,r1,STACK_FRAME_OVERHEAD |
297 | // CHECK_NAPPING(); | ||
273 | // bl .machine_check_exception | 298 | // bl .machine_check_exception |
274 | // b ret_from_mc_except | 299 | // b ret_from_mc_except |
275 | b . | 300 | b . |
@@ -340,6 +365,7 @@ interrupt_end_book3e: | |||
340 | CRIT_EXCEPTION_PROLOG(0x9f0, PROLOG_ADDITION_NONE) | 365 | CRIT_EXCEPTION_PROLOG(0x9f0, PROLOG_ADDITION_NONE) |
341 | // EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE_ALL) | 366 | // EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE_ALL) |
342 | // bl special_reg_save_crit | 367 | // bl special_reg_save_crit |
368 | // CHECK_NAPPING(); | ||
343 | // addi r3,r1,STACK_FRAME_OVERHEAD | 369 | // addi r3,r1,STACK_FRAME_OVERHEAD |
344 | // bl .unknown_exception | 370 | // bl .unknown_exception |
345 | // b ret_from_crit_except | 371 | // b ret_from_crit_except |
@@ -428,6 +454,20 @@ interrupt_end_book3e: | |||
428 | kernel_dbg_exc: | 454 | kernel_dbg_exc: |
429 | b . /* NYI */ | 455 | b . /* NYI */ |
430 | 456 | ||
457 | /* Doorbell interrupt */ | ||
458 | MASKABLE_EXCEPTION(0x2070, doorbell, .doorbell_exception, ACK_NONE) | ||
459 | |||
460 | /* Doorbell critical Interrupt */ | ||
461 | START_EXCEPTION(doorbell_crit); | ||
462 | CRIT_EXCEPTION_PROLOG(0x2080, PROLOG_ADDITION_NONE) | ||
463 | // EXCEPTION_COMMON(0x2080, PACA_EXCRIT, INTS_DISABLE_ALL) | ||
464 | // bl special_reg_save_crit | ||
465 | // CHECK_NAPPING(); | ||
466 | // addi r3,r1,STACK_FRAME_OVERHEAD | ||
467 | // bl .doorbell_critical_exception | ||
468 | // b ret_from_crit_except | ||
469 | b . | ||
470 | |||
431 | 471 | ||
432 | /* | 472 | /* |
433 | * An interrupt came in while soft-disabled; clear EE in SRR1, | 473 | * An interrupt came in while soft-disabled; clear EE in SRR1, |
@@ -563,6 +603,8 @@ BAD_STACK_TRAMPOLINE(0xd00) | |||
563 | BAD_STACK_TRAMPOLINE(0xe00) | 603 | BAD_STACK_TRAMPOLINE(0xe00) |
564 | BAD_STACK_TRAMPOLINE(0xf00) | 604 | BAD_STACK_TRAMPOLINE(0xf00) |
565 | BAD_STACK_TRAMPOLINE(0xf20) | 605 | BAD_STACK_TRAMPOLINE(0xf20) |
606 | BAD_STACK_TRAMPOLINE(0x2070) | ||
607 | BAD_STACK_TRAMPOLINE(0x2080) | ||
566 | 608 | ||
567 | .globl bad_stack_book3e | 609 | .globl bad_stack_book3e |
568 | bad_stack_book3e: | 610 | bad_stack_book3e: |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 3e423fbad6bc..f53029a01554 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -828,6 +828,7 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) | |||
828 | 828 | ||
829 | /* We have a data breakpoint exception - handle it */ | 829 | /* We have a data breakpoint exception - handle it */ |
830 | handle_dabr_fault: | 830 | handle_dabr_fault: |
831 | bl .save_nvgprs | ||
831 | ld r4,_DAR(r1) | 832 | ld r4,_DAR(r1) |
832 | ld r5,_DSISR(r1) | 833 | ld r5,_DSISR(r1) |
833 | addi r3,r1,STACK_FRAME_OVERHEAD | 834 | addi r3,r1,STACK_FRAME_OVERHEAD |
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c new file mode 100644 index 000000000000..5ecd0401cdb1 --- /dev/null +++ b/arch/powerpc/kernel/hw_breakpoint.c | |||
@@ -0,0 +1,364 @@ | |||
1 | /* | ||
2 | * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility, | ||
3 | * using the CPU's debug registers. Derived from | ||
4 | * "arch/x86/kernel/hw_breakpoint.c" | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | * | ||
20 | * Copyright 2010 IBM Corporation | ||
21 | * Author: K.Prasad <prasad@linux.vnet.ibm.com> | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/hw_breakpoint.h> | ||
26 | #include <linux/notifier.h> | ||
27 | #include <linux/kprobes.h> | ||
28 | #include <linux/percpu.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/smp.h> | ||
34 | |||
35 | #include <asm/hw_breakpoint.h> | ||
36 | #include <asm/processor.h> | ||
37 | #include <asm/sstep.h> | ||
38 | #include <asm/uaccess.h> | ||
39 | |||
40 | /* | ||
41 | * Stores the breakpoints currently in use on each breakpoint address | ||
42 | * register for every cpu | ||
43 | */ | ||
44 | static DEFINE_PER_CPU(struct perf_event *, bp_per_reg); | ||
45 | |||
46 | /* | ||
47 | * Returns total number of data or instruction breakpoints available. | ||
48 | */ | ||
49 | int hw_breakpoint_slots(int type) | ||
50 | { | ||
51 | if (type == TYPE_DATA) | ||
52 | return HBP_NUM; | ||
53 | return 0; /* no instruction breakpoints available */ | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * Install a perf counter breakpoint. | ||
58 | * | ||
59 | * We seek a free debug address register and use it for this | ||
60 | * breakpoint. | ||
61 | * | ||
62 | * Atomic: we hold the counter->ctx->lock and we only handle variables | ||
63 | * and registers local to this cpu. | ||
64 | */ | ||
65 | int arch_install_hw_breakpoint(struct perf_event *bp) | ||
66 | { | ||
67 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | ||
68 | struct perf_event **slot = &__get_cpu_var(bp_per_reg); | ||
69 | |||
70 | *slot = bp; | ||
71 | |||
72 | /* | ||
73 | * Do not install DABR values if the instruction must be single-stepped. | ||
74 | * If so, DABR will be populated in single_step_dabr_instruction(). | ||
75 | */ | ||
76 | if (current->thread.last_hit_ubp != bp) | ||
77 | set_dabr(info->address | info->type | DABR_TRANSLATION); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Uninstall the breakpoint contained in the given counter. | ||
84 | * | ||
85 | * First we search the debug address register it uses and then we disable | ||
86 | * it. | ||
87 | * | ||
88 | * Atomic: we hold the counter->ctx->lock and we only handle variables | ||
89 | * and registers local to this cpu. | ||
90 | */ | ||
91 | void arch_uninstall_hw_breakpoint(struct perf_event *bp) | ||
92 | { | ||
93 | struct perf_event **slot = &__get_cpu_var(bp_per_reg); | ||
94 | |||
95 | if (*slot != bp) { | ||
96 | WARN_ONCE(1, "Can't find the breakpoint"); | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | *slot = NULL; | ||
101 | set_dabr(0); | ||
102 | } | ||
103 | |||
104 | /* | ||
105 | * Perform cleanup of arch-specific counters during unregistration | ||
106 | * of the perf-event | ||
107 | */ | ||
108 | void arch_unregister_hw_breakpoint(struct perf_event *bp) | ||
109 | { | ||
110 | /* | ||
111 | * If the breakpoint is unregistered between a hw_breakpoint_handler() | ||
112 | * and the single_step_dabr_instruction(), then cleanup the breakpoint | ||
113 | * restoration variables to prevent dangling pointers. | ||
114 | */ | ||
115 | if (bp->ctx->task) | ||
116 | bp->ctx->task->thread.last_hit_ubp = NULL; | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * Check for virtual address in kernel space. | ||
121 | */ | ||
122 | int arch_check_bp_in_kernelspace(struct perf_event *bp) | ||
123 | { | ||
124 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | ||
125 | |||
126 | return is_kernel_addr(info->address); | ||
127 | } | ||
128 | |||
129 | int arch_bp_generic_fields(int type, int *gen_bp_type) | ||
130 | { | ||
131 | switch (type) { | ||
132 | case DABR_DATA_READ: | ||
133 | *gen_bp_type = HW_BREAKPOINT_R; | ||
134 | break; | ||
135 | case DABR_DATA_WRITE: | ||
136 | *gen_bp_type = HW_BREAKPOINT_W; | ||
137 | break; | ||
138 | case (DABR_DATA_WRITE | DABR_DATA_READ): | ||
139 | *gen_bp_type = (HW_BREAKPOINT_W | HW_BREAKPOINT_R); | ||
140 | break; | ||
141 | default: | ||
142 | return -EINVAL; | ||
143 | } | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * Validate the arch-specific HW Breakpoint register settings | ||
149 | */ | ||
150 | int arch_validate_hwbkpt_settings(struct perf_event *bp) | ||
151 | { | ||
152 | int ret = -EINVAL; | ||
153 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | ||
154 | |||
155 | if (!bp) | ||
156 | return ret; | ||
157 | |||
158 | switch (bp->attr.bp_type) { | ||
159 | case HW_BREAKPOINT_R: | ||
160 | info->type = DABR_DATA_READ; | ||
161 | break; | ||
162 | case HW_BREAKPOINT_W: | ||
163 | info->type = DABR_DATA_WRITE; | ||
164 | break; | ||
165 | case HW_BREAKPOINT_R | HW_BREAKPOINT_W: | ||
166 | info->type = (DABR_DATA_READ | DABR_DATA_WRITE); | ||
167 | break; | ||
168 | default: | ||
169 | return ret; | ||
170 | } | ||
171 | |||
172 | info->address = bp->attr.bp_addr; | ||
173 | info->len = bp->attr.bp_len; | ||
174 | |||
175 | /* | ||
176 | * Since breakpoint length can be a maximum of HW_BREAKPOINT_LEN(8) | ||
177 | * and breakpoint addresses are aligned to nearest double-word | ||
178 | * HW_BREAKPOINT_ALIGN by rounding off to the lower address, the | ||
179 | * 'symbolsize' should satisfy the check below. | ||
180 | */ | ||
181 | if (info->len > | ||
182 | (HW_BREAKPOINT_LEN - (info->address & HW_BREAKPOINT_ALIGN))) | ||
183 | return -EINVAL; | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * Restores the breakpoint on the debug registers. | ||
189 | * Invoke this function if it is known that the execution context is | ||
190 | * about to change to cause loss of MSR_SE settings. | ||
191 | */ | ||
192 | void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs) | ||
193 | { | ||
194 | struct arch_hw_breakpoint *info; | ||
195 | |||
196 | if (likely(!tsk->thread.last_hit_ubp)) | ||
197 | return; | ||
198 | |||
199 | info = counter_arch_bp(tsk->thread.last_hit_ubp); | ||
200 | regs->msr &= ~MSR_SE; | ||
201 | set_dabr(info->address | info->type | DABR_TRANSLATION); | ||
202 | tsk->thread.last_hit_ubp = NULL; | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * Handle debug exception notifications. | ||
207 | */ | ||
208 | int __kprobes hw_breakpoint_handler(struct die_args *args) | ||
209 | { | ||
210 | int rc = NOTIFY_STOP; | ||
211 | struct perf_event *bp; | ||
212 | struct pt_regs *regs = args->regs; | ||
213 | int stepped = 1; | ||
214 | struct arch_hw_breakpoint *info; | ||
215 | unsigned int instr; | ||
216 | unsigned long dar = regs->dar; | ||
217 | |||
218 | /* Disable breakpoints during exception handling */ | ||
219 | set_dabr(0); | ||
220 | |||
221 | /* | ||
222 | * The counter may be concurrently released but that can only | ||
223 | * occur from a call_rcu() path. We can then safely fetch | ||
224 | * the breakpoint, use its callback, touch its counter | ||
225 | * while we are in an rcu_read_lock() path. | ||
226 | */ | ||
227 | rcu_read_lock(); | ||
228 | |||
229 | bp = __get_cpu_var(bp_per_reg); | ||
230 | if (!bp) | ||
231 | goto out; | ||
232 | info = counter_arch_bp(bp); | ||
233 | |||
234 | /* | ||
235 | * Return early after invoking user-callback function without restoring | ||
236 | * DABR if the breakpoint is from ptrace which always operates in | ||
237 | * one-shot mode. The ptrace-ed process will receive the SIGTRAP signal | ||
238 | * generated in do_dabr(). | ||
239 | */ | ||
240 | if (bp->overflow_handler == ptrace_triggered) { | ||
241 | perf_bp_event(bp, regs); | ||
242 | rc = NOTIFY_DONE; | ||
243 | goto out; | ||
244 | } | ||
245 | |||
246 | /* | ||
247 | * Verify if dar lies within the address range occupied by the symbol | ||
248 | * being watched to filter extraneous exceptions. If it doesn't, | ||
249 | * we still need to single-step the instruction, but we don't | ||
250 | * generate an event. | ||
251 | */ | ||
252 | info->extraneous_interrupt = !((bp->attr.bp_addr <= dar) && | ||
253 | (dar - bp->attr.bp_addr < bp->attr.bp_len)); | ||
254 | |||
255 | /* Do not emulate user-space instructions, instead single-step them */ | ||
256 | if (user_mode(regs)) { | ||
257 | bp->ctx->task->thread.last_hit_ubp = bp; | ||
258 | regs->msr |= MSR_SE; | ||
259 | goto out; | ||
260 | } | ||
261 | |||
262 | stepped = 0; | ||
263 | instr = 0; | ||
264 | if (!__get_user_inatomic(instr, (unsigned int *) regs->nip)) | ||
265 | stepped = emulate_step(regs, instr); | ||
266 | |||
267 | /* | ||
268 | * emulate_step() could not execute it. We've failed in reliably | ||
269 | * handling the hw-breakpoint. Unregister it and throw a warning | ||
270 | * message to let the user know about it. | ||
271 | */ | ||
272 | if (!stepped) { | ||
273 | WARN(1, "Unable to handle hardware breakpoint. Breakpoint at " | ||
274 | "0x%lx will be disabled.", info->address); | ||
275 | perf_event_disable(bp); | ||
276 | goto out; | ||
277 | } | ||
278 | /* | ||
279 | * As a policy, the callback is invoked in a 'trigger-after-execute' | ||
280 | * fashion | ||
281 | */ | ||
282 | if (!info->extraneous_interrupt) | ||
283 | perf_bp_event(bp, regs); | ||
284 | |||
285 | set_dabr(info->address | info->type | DABR_TRANSLATION); | ||
286 | out: | ||
287 | rcu_read_unlock(); | ||
288 | return rc; | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * Handle single-step exceptions following a DABR hit. | ||
293 | */ | ||
294 | int __kprobes single_step_dabr_instruction(struct die_args *args) | ||
295 | { | ||
296 | struct pt_regs *regs = args->regs; | ||
297 | struct perf_event *bp = NULL; | ||
298 | struct arch_hw_breakpoint *bp_info; | ||
299 | |||
300 | bp = current->thread.last_hit_ubp; | ||
301 | /* | ||
302 | * Check if we are single-stepping as a result of a | ||
303 | * previous HW Breakpoint exception | ||
304 | */ | ||
305 | if (!bp) | ||
306 | return NOTIFY_DONE; | ||
307 | |||
308 | bp_info = counter_arch_bp(bp); | ||
309 | |||
310 | /* | ||
311 | * We shall invoke the user-defined callback function in the single | ||
312 | * stepping handler to confirm to 'trigger-after-execute' semantics | ||
313 | */ | ||
314 | if (!bp_info->extraneous_interrupt) | ||
315 | perf_bp_event(bp, regs); | ||
316 | |||
317 | set_dabr(bp_info->address | bp_info->type | DABR_TRANSLATION); | ||
318 | current->thread.last_hit_ubp = NULL; | ||
319 | |||
320 | /* | ||
321 | * If the process was being single-stepped by ptrace, let the | ||
322 | * other single-step actions occur (e.g. generate SIGTRAP). | ||
323 | */ | ||
324 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
325 | return NOTIFY_DONE; | ||
326 | |||
327 | return NOTIFY_STOP; | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * Handle debug exception notifications. | ||
332 | */ | ||
333 | int __kprobes hw_breakpoint_exceptions_notify( | ||
334 | struct notifier_block *unused, unsigned long val, void *data) | ||
335 | { | ||
336 | int ret = NOTIFY_DONE; | ||
337 | |||
338 | switch (val) { | ||
339 | case DIE_DABR_MATCH: | ||
340 | ret = hw_breakpoint_handler(data); | ||
341 | break; | ||
342 | case DIE_SSTEP: | ||
343 | ret = single_step_dabr_instruction(data); | ||
344 | break; | ||
345 | } | ||
346 | |||
347 | return ret; | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * Release the user breakpoints used by ptrace | ||
352 | */ | ||
353 | void flush_ptrace_hw_breakpoint(struct task_struct *tsk) | ||
354 | { | ||
355 | struct thread_struct *t = &tsk->thread; | ||
356 | |||
357 | unregister_hw_breakpoint(t->ptrace_bps[0]); | ||
358 | t->ptrace_bps[0] = NULL; | ||
359 | } | ||
360 | |||
361 | void hw_breakpoint_pmu_read(struct perf_event *bp) | ||
362 | { | ||
363 | /* TODO */ | ||
364 | } | ||
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index 21266abfbda6..9b626cfffce1 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c | |||
@@ -140,19 +140,19 @@ static struct dma_map_ops ibmebus_dma_ops = { | |||
140 | 140 | ||
141 | static int ibmebus_match_path(struct device *dev, void *data) | 141 | static int ibmebus_match_path(struct device *dev, void *data) |
142 | { | 142 | { |
143 | struct device_node *dn = to_of_device(dev)->dev.of_node; | 143 | struct device_node *dn = to_platform_device(dev)->dev.of_node; |
144 | return (dn->full_name && | 144 | return (dn->full_name && |
145 | (strcasecmp((char *)data, dn->full_name) == 0)); | 145 | (strcasecmp((char *)data, dn->full_name) == 0)); |
146 | } | 146 | } |
147 | 147 | ||
148 | static int ibmebus_match_node(struct device *dev, void *data) | 148 | static int ibmebus_match_node(struct device *dev, void *data) |
149 | { | 149 | { |
150 | return to_of_device(dev)->dev.of_node == data; | 150 | return to_platform_device(dev)->dev.of_node == data; |
151 | } | 151 | } |
152 | 152 | ||
153 | static int ibmebus_create_device(struct device_node *dn) | 153 | static int ibmebus_create_device(struct device_node *dn) |
154 | { | 154 | { |
155 | struct of_device *dev; | 155 | struct platform_device *dev; |
156 | int ret; | 156 | int ret; |
157 | 157 | ||
158 | dev = of_device_alloc(dn, NULL, &ibmebus_bus_device); | 158 | dev = of_device_alloc(dn, NULL, &ibmebus_bus_device); |
@@ -298,7 +298,7 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus, | |||
298 | 298 | ||
299 | if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path, | 299 | if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path, |
300 | ibmebus_match_path))) { | 300 | ibmebus_match_path))) { |
301 | of_device_unregister(to_of_device(dev)); | 301 | of_device_unregister(to_platform_device(dev)); |
302 | 302 | ||
303 | kfree(path); | 303 | kfree(path); |
304 | return count; | 304 | return count; |
diff --git a/arch/powerpc/kernel/idle_book3e.S b/arch/powerpc/kernel/idle_book3e.S new file mode 100644 index 000000000000..16c002d6bdf1 --- /dev/null +++ b/arch/powerpc/kernel/idle_book3e.S | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * Copyright 2010 IBM Corp, Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
3 | * | ||
4 | * Generic idle routine for Book3E processors | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/threads.h> | ||
13 | #include <asm/reg.h> | ||
14 | #include <asm/ppc_asm.h> | ||
15 | #include <asm/asm-offsets.h> | ||
16 | #include <asm/ppc-opcode.h> | ||
17 | #include <asm/processor.h> | ||
18 | #include <asm/thread_info.h> | ||
19 | |||
20 | /* 64-bit version only for now */ | ||
21 | #ifdef CONFIG_PPC64 | ||
22 | |||
23 | _GLOBAL(book3e_idle) | ||
24 | /* Save LR for later */ | ||
25 | mflr r0 | ||
26 | std r0,16(r1) | ||
27 | |||
28 | /* Hard disable interrupts */ | ||
29 | wrteei 0 | ||
30 | |||
31 | /* Now check if an interrupt came in while we were soft disabled | ||
32 | * since we may otherwise lose it (doorbells etc...). We know | ||
33 | * that since PACAHARDIRQEN will have been cleared in that case. | ||
34 | */ | ||
35 | lbz r3,PACAHARDIRQEN(r13) | ||
36 | cmpwi cr0,r3,0 | ||
37 | beqlr | ||
38 | |||
39 | /* Now we are going to mark ourselves as soft and hard enables in | ||
40 | * order to be able to take interrupts while asleep. We inform lockdep | ||
41 | * of that. We don't actually turn interrupts on just yet tho. | ||
42 | */ | ||
43 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
44 | stdu r1,-128(r1) | ||
45 | bl .trace_hardirqs_on | ||
46 | #endif | ||
47 | li r0,1 | ||
48 | stb r0,PACASOFTIRQEN(r13) | ||
49 | stb r0,PACAHARDIRQEN(r13) | ||
50 | |||
51 | /* Interrupts will make use return to LR, so get something we want | ||
52 | * in there | ||
53 | */ | ||
54 | bl 1f | ||
55 | |||
56 | /* Hard disable interrupts again */ | ||
57 | wrteei 0 | ||
58 | |||
59 | /* Mark them off again in the PACA as well */ | ||
60 | li r0,0 | ||
61 | stb r0,PACASOFTIRQEN(r13) | ||
62 | stb r0,PACAHARDIRQEN(r13) | ||
63 | |||
64 | /* Tell lockdep about it */ | ||
65 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
66 | bl .trace_hardirqs_off | ||
67 | addi r1,r1,128 | ||
68 | #endif | ||
69 | ld r0,16(r1) | ||
70 | mtlr r0 | ||
71 | blr | ||
72 | |||
73 | 1: /* Let's set the _TLF_NAPPING flag so interrupts make us return | ||
74 | * to the right spot | ||
75 | */ | ||
76 | clrrdi r11,r1,THREAD_SHIFT | ||
77 | ld r10,TI_LOCAL_FLAGS(r11) | ||
78 | ori r10,r10,_TLF_NAPPING | ||
79 | std r10,TI_LOCAL_FLAGS(r11) | ||
80 | |||
81 | /* We can now re-enable hard interrupts and go to sleep */ | ||
82 | wrteei 1 | ||
83 | 1: PPC_WAIT(0) | ||
84 | b 1b | ||
85 | |||
86 | #endif /* CONFIG_PPC64 */ | ||
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 77be3d058a65..d3ce67cf03be 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -53,6 +53,8 @@ | |||
53 | #include <linux/bootmem.h> | 53 | #include <linux/bootmem.h> |
54 | #include <linux/pci.h> | 54 | #include <linux/pci.h> |
55 | #include <linux/debugfs.h> | 55 | #include <linux/debugfs.h> |
56 | #include <linux/of.h> | ||
57 | #include <linux/of_irq.h> | ||
56 | 58 | ||
57 | #include <asm/uaccess.h> | 59 | #include <asm/uaccess.h> |
58 | #include <asm/system.h> | 60 | #include <asm/system.h> |
@@ -64,6 +66,8 @@ | |||
64 | #include <asm/ptrace.h> | 66 | #include <asm/ptrace.h> |
65 | #include <asm/machdep.h> | 67 | #include <asm/machdep.h> |
66 | #include <asm/udbg.h> | 68 | #include <asm/udbg.h> |
69 | #include <asm/dbell.h> | ||
70 | |||
67 | #ifdef CONFIG_PPC64 | 71 | #ifdef CONFIG_PPC64 |
68 | #include <asm/paca.h> | 72 | #include <asm/paca.h> |
69 | #include <asm/firmware.h> | 73 | #include <asm/firmware.h> |
@@ -153,14 +157,28 @@ notrace void raw_local_irq_restore(unsigned long en) | |||
153 | if (get_hard_enabled()) | 157 | if (get_hard_enabled()) |
154 | return; | 158 | return; |
155 | 159 | ||
160 | #if defined(CONFIG_BOOKE) && defined(CONFIG_SMP) | ||
161 | /* Check for pending doorbell interrupts and resend to ourself */ | ||
162 | doorbell_check_self(); | ||
163 | #endif | ||
164 | |||
156 | /* | 165 | /* |
157 | * Need to hard-enable interrupts here. Since currently disabled, | 166 | * Need to hard-enable interrupts here. Since currently disabled, |
158 | * no need to take further asm precautions against preemption; but | 167 | * no need to take further asm precautions against preemption; but |
159 | * use local_paca instead of get_paca() to avoid preemption checking. | 168 | * use local_paca instead of get_paca() to avoid preemption checking. |
160 | */ | 169 | */ |
161 | local_paca->hard_enabled = en; | 170 | local_paca->hard_enabled = en; |
171 | |||
172 | #ifndef CONFIG_BOOKE | ||
173 | /* On server, re-trigger the decrementer if it went negative since | ||
174 | * some processors only trigger on edge transitions of the sign bit. | ||
175 | * | ||
176 | * BookE has a level sensitive decrementer (latches in TSR) so we | ||
177 | * don't need that | ||
178 | */ | ||
162 | if ((int)mfspr(SPRN_DEC) < 0) | 179 | if ((int)mfspr(SPRN_DEC) < 0) |
163 | mtspr(SPRN_DEC, 1); | 180 | mtspr(SPRN_DEC, 1); |
181 | #endif /* CONFIG_BOOKE */ | ||
164 | 182 | ||
165 | /* | 183 | /* |
166 | * Force the delivery of pending soft-disabled interrupts on PS3. | 184 | * Force the delivery of pending soft-disabled interrupts on PS3. |
@@ -804,18 +822,6 @@ unsigned int irq_create_of_mapping(struct device_node *controller, | |||
804 | } | 822 | } |
805 | EXPORT_SYMBOL_GPL(irq_create_of_mapping); | 823 | EXPORT_SYMBOL_GPL(irq_create_of_mapping); |
806 | 824 | ||
807 | unsigned int irq_of_parse_and_map(struct device_node *dev, int index) | ||
808 | { | ||
809 | struct of_irq oirq; | ||
810 | |||
811 | if (of_irq_map_one(dev, index, &oirq)) | ||
812 | return NO_IRQ; | ||
813 | |||
814 | return irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
815 | oirq.size); | ||
816 | } | ||
817 | EXPORT_SYMBOL_GPL(irq_of_parse_and_map); | ||
818 | |||
819 | void irq_dispose_mapping(unsigned int virq) | 825 | void irq_dispose_mapping(unsigned int virq) |
820 | { | 826 | { |
821 | struct irq_host *host; | 827 | struct irq_host *host; |
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c index 82a7b228c81a..7f61a3ac787c 100644 --- a/arch/powerpc/kernel/kgdb.c +++ b/arch/powerpc/kernel/kgdb.c | |||
@@ -129,7 +129,7 @@ static int kgdb_handle_breakpoint(struct pt_regs *regs) | |||
129 | return 0; | 129 | return 0; |
130 | 130 | ||
131 | if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr)) | 131 | if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr)) |
132 | regs->nip += 4; | 132 | regs->nip += BREAK_INSTR_SIZE; |
133 | 133 | ||
134 | return 1; | 134 | return 1; |
135 | } | 135 | } |
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index 035ada5443ee..c1fd0f9658fd 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/serial_core.h> | 4 | #include <linux/serial_core.h> |
5 | #include <linux/console.h> | 5 | #include <linux/console.h> |
6 | #include <linux/pci.h> | 6 | #include <linux/pci.h> |
7 | #include <linux/of_address.h> | ||
7 | #include <linux/of_device.h> | 8 | #include <linux/of_device.h> |
8 | #include <asm/io.h> | 9 | #include <asm/io.h> |
9 | #include <asm/mmu.h> | 10 | #include <asm/mmu.h> |
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c index 89f005116aac..dd6c141f1662 100644 --- a/arch/powerpc/kernel/machine_kexec.c +++ b/arch/powerpc/kernel/machine_kexec.c | |||
@@ -45,6 +45,18 @@ void machine_kexec_cleanup(struct kimage *image) | |||
45 | ppc_md.machine_kexec_cleanup(image); | 45 | ppc_md.machine_kexec_cleanup(image); |
46 | } | 46 | } |
47 | 47 | ||
48 | void arch_crash_save_vmcoreinfo(void) | ||
49 | { | ||
50 | |||
51 | #ifdef CONFIG_NEED_MULTIPLE_NODES | ||
52 | VMCOREINFO_SYMBOL(node_data); | ||
53 | VMCOREINFO_LENGTH(node_data, MAX_NUMNODES); | ||
54 | #endif | ||
55 | #ifndef CONFIG_NEED_MULTIPLE_NODES | ||
56 | VMCOREINFO_SYMBOL(contig_page_data); | ||
57 | #endif | ||
58 | } | ||
59 | |||
48 | /* | 60 | /* |
49 | * Do not allocate memory (or fail in any way) in machine_kexec(). | 61 | * Do not allocate memory (or fail in any way) in machine_kexec(). |
50 | * We are past the point of no return, committed to rebooting now. | 62 | * We are past the point of no return, committed to rebooting now. |
@@ -144,24 +156,24 @@ int overlaps_crashkernel(unsigned long start, unsigned long size) | |||
144 | } | 156 | } |
145 | 157 | ||
146 | /* Values we need to export to the second kernel via the device tree. */ | 158 | /* Values we need to export to the second kernel via the device tree. */ |
147 | static unsigned long kernel_end; | 159 | static phys_addr_t kernel_end; |
148 | static unsigned long crashk_size; | 160 | static phys_addr_t crashk_size; |
149 | 161 | ||
150 | static struct property kernel_end_prop = { | 162 | static struct property kernel_end_prop = { |
151 | .name = "linux,kernel-end", | 163 | .name = "linux,kernel-end", |
152 | .length = sizeof(unsigned long), | 164 | .length = sizeof(phys_addr_t), |
153 | .value = &kernel_end, | 165 | .value = &kernel_end, |
154 | }; | 166 | }; |
155 | 167 | ||
156 | static struct property crashk_base_prop = { | 168 | static struct property crashk_base_prop = { |
157 | .name = "linux,crashkernel-base", | 169 | .name = "linux,crashkernel-base", |
158 | .length = sizeof(unsigned long), | 170 | .length = sizeof(phys_addr_t), |
159 | .value = &crashk_res.start, | 171 | .value = &crashk_res.start, |
160 | }; | 172 | }; |
161 | 173 | ||
162 | static struct property crashk_size_prop = { | 174 | static struct property crashk_size_prop = { |
163 | .name = "linux,crashkernel-size", | 175 | .name = "linux,crashkernel-size", |
164 | .length = sizeof(unsigned long), | 176 | .length = sizeof(phys_addr_t), |
165 | .value = &crashk_size, | 177 | .value = &crashk_size, |
166 | }; | 178 | }; |
167 | 179 | ||
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index ed31a29c4ff7..583af70c4b14 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <linux/thread_info.h> | 15 | #include <linux/thread_info.h> |
16 | #include <linux/init_task.h> | 16 | #include <linux/init_task.h> |
17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
18 | #include <linux/kernel.h> | ||
19 | #include <linux/cpu.h> | ||
18 | 20 | ||
19 | #include <asm/page.h> | 21 | #include <asm/page.h> |
20 | #include <asm/current.h> | 22 | #include <asm/current.h> |
@@ -25,6 +27,7 @@ | |||
25 | #include <asm/sections.h> /* _end */ | 27 | #include <asm/sections.h> /* _end */ |
26 | #include <asm/prom.h> | 28 | #include <asm/prom.h> |
27 | #include <asm/smp.h> | 29 | #include <asm/smp.h> |
30 | #include <asm/hw_breakpoint.h> | ||
28 | 31 | ||
29 | int default_machine_kexec_prepare(struct kimage *image) | 32 | int default_machine_kexec_prepare(struct kimage *image) |
30 | { | 33 | { |
@@ -165,6 +168,7 @@ static void kexec_smp_down(void *arg) | |||
165 | while(kexec_all_irq_disabled == 0) | 168 | while(kexec_all_irq_disabled == 0) |
166 | cpu_relax(); | 169 | cpu_relax(); |
167 | mb(); /* make sure all irqs are disabled before this */ | 170 | mb(); /* make sure all irqs are disabled before this */ |
171 | hw_breakpoint_disable(); | ||
168 | /* | 172 | /* |
169 | * Now every CPU has IRQs off, we can clear out any pending | 173 | * Now every CPU has IRQs off, we can clear out any pending |
170 | * IPIs and be sure that no more will come in after this. | 174 | * IPIs and be sure that no more will come in after this. |
@@ -180,8 +184,22 @@ static void kexec_prepare_cpus_wait(int wait_state) | |||
180 | { | 184 | { |
181 | int my_cpu, i, notified=-1; | 185 | int my_cpu, i, notified=-1; |
182 | 186 | ||
187 | hw_breakpoint_disable(); | ||
183 | my_cpu = get_cpu(); | 188 | my_cpu = get_cpu(); |
184 | /* Make sure each CPU has atleast made it to the state we need */ | 189 | /* Make sure each CPU has at least made it to the state we need. |
190 | * | ||
191 | * FIXME: There is a (slim) chance of a problem if not all of the CPUs | ||
192 | * are correctly onlined. If somehow we start a CPU on boot with RTAS | ||
193 | * start-cpu, but somehow that CPU doesn't write callin_cpu_map[] in | ||
194 | * time, the boot CPU will timeout. If it does eventually execute | ||
195 | * stuff, the secondary will start up (paca[].cpu_start was written) and | ||
196 | * get into a peculiar state. If the platform supports | ||
197 | * smp_ops->take_timebase(), the secondary CPU will probably be spinning | ||
198 | * in there. If not (i.e. pseries), the secondary will continue on and | ||
199 | * try to online itself/idle/etc. If it survives that, we need to find | ||
200 | * these possible-but-not-online-but-should-be CPUs and chaperone them | ||
201 | * into kexec_smp_wait(). | ||
202 | */ | ||
185 | for_each_online_cpu(i) { | 203 | for_each_online_cpu(i) { |
186 | if (i == my_cpu) | 204 | if (i == my_cpu) |
187 | continue; | 205 | continue; |
@@ -189,9 +207,9 @@ static void kexec_prepare_cpus_wait(int wait_state) | |||
189 | while (paca[i].kexec_state < wait_state) { | 207 | while (paca[i].kexec_state < wait_state) { |
190 | barrier(); | 208 | barrier(); |
191 | if (i != notified) { | 209 | if (i != notified) { |
192 | printk( "kexec: waiting for cpu %d (physical" | 210 | printk(KERN_INFO "kexec: waiting for cpu %d " |
193 | " %d) to enter %i state\n", | 211 | "(physical %d) to enter %i state\n", |
194 | i, paca[i].hw_cpu_id, wait_state); | 212 | i, paca[i].hw_cpu_id, wait_state); |
195 | notified = i; | 213 | notified = i; |
196 | } | 214 | } |
197 | } | 215 | } |
@@ -199,9 +217,32 @@ static void kexec_prepare_cpus_wait(int wait_state) | |||
199 | mb(); | 217 | mb(); |
200 | } | 218 | } |
201 | 219 | ||
202 | static void kexec_prepare_cpus(void) | 220 | /* |
221 | * We need to make sure each present CPU is online. The next kernel will scan | ||
222 | * the device tree and assume primary threads are online and query secondary | ||
223 | * threads via RTAS to online them if required. If we don't online primary | ||
224 | * threads, they will be stuck. However, we also online secondary threads as we | ||
225 | * may be using 'cede offline'. In this case RTAS doesn't see the secondary | ||
226 | * threads as offline -- and again, these CPUs will be stuck. | ||
227 | * | ||
228 | * So, we online all CPUs that should be running, including secondary threads. | ||
229 | */ | ||
230 | static void wake_offline_cpus(void) | ||
203 | { | 231 | { |
232 | int cpu = 0; | ||
204 | 233 | ||
234 | for_each_present_cpu(cpu) { | ||
235 | if (!cpu_online(cpu)) { | ||
236 | printk(KERN_INFO "kexec: Waking offline cpu %d.\n", | ||
237 | cpu); | ||
238 | cpu_up(cpu); | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | |||
243 | static void kexec_prepare_cpus(void) | ||
244 | { | ||
245 | wake_offline_cpus(); | ||
205 | smp_call_function(kexec_smp_down, NULL, /* wait */0); | 246 | smp_call_function(kexec_smp_down, NULL, /* wait */0); |
206 | local_irq_disable(); | 247 | local_irq_disable(); |
207 | mb(); /* make sure IRQs are disabled before we say they are */ | 248 | mb(); /* make sure IRQs are disabled before we say they are */ |
@@ -215,7 +256,10 @@ static void kexec_prepare_cpus(void) | |||
215 | if (ppc_md.kexec_cpu_down) | 256 | if (ppc_md.kexec_cpu_down) |
216 | ppc_md.kexec_cpu_down(0, 0); | 257 | ppc_md.kexec_cpu_down(0, 0); |
217 | 258 | ||
218 | /* Before removing MMU mapings make sure all CPUs have entered real mode */ | 259 | /* |
260 | * Before removing MMU mappings make sure all CPUs have entered real | ||
261 | * mode: | ||
262 | */ | ||
219 | kexec_prepare_cpus_wait(KEXEC_STATE_REAL_MODE); | 263 | kexec_prepare_cpus_wait(KEXEC_STATE_REAL_MODE); |
220 | 264 | ||
221 | put_cpu(); | 265 | put_cpu(); |
@@ -257,6 +301,12 @@ static void kexec_prepare_cpus(void) | |||
257 | static union thread_union kexec_stack __init_task_data = | 301 | static union thread_union kexec_stack __init_task_data = |
258 | { }; | 302 | { }; |
259 | 303 | ||
304 | /* | ||
305 | * For similar reasons to the stack above, the kexecing CPU needs to be on a | ||
306 | * static PACA; we switch to kexec_paca. | ||
307 | */ | ||
308 | struct paca_struct kexec_paca; | ||
309 | |||
260 | /* Our assembly helper, in kexec_stub.S */ | 310 | /* Our assembly helper, in kexec_stub.S */ |
261 | extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start, | 311 | extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start, |
262 | void *image, void *control, | 312 | void *image, void *control, |
@@ -278,12 +328,28 @@ void default_machine_kexec(struct kimage *image) | |||
278 | if (crashing_cpu == -1) | 328 | if (crashing_cpu == -1) |
279 | kexec_prepare_cpus(); | 329 | kexec_prepare_cpus(); |
280 | 330 | ||
331 | pr_debug("kexec: Starting switchover sequence.\n"); | ||
332 | |||
281 | /* switch to a staticly allocated stack. Based on irq stack code. | 333 | /* switch to a staticly allocated stack. Based on irq stack code. |
282 | * XXX: the task struct will likely be invalid once we do the copy! | 334 | * XXX: the task struct will likely be invalid once we do the copy! |
283 | */ | 335 | */ |
284 | kexec_stack.thread_info.task = current_thread_info()->task; | 336 | kexec_stack.thread_info.task = current_thread_info()->task; |
285 | kexec_stack.thread_info.flags = 0; | 337 | kexec_stack.thread_info.flags = 0; |
286 | 338 | ||
339 | /* We need a static PACA, too; copy this CPU's PACA over and switch to | ||
340 | * it. Also poison per_cpu_offset to catch anyone using non-static | ||
341 | * data. | ||
342 | */ | ||
343 | memcpy(&kexec_paca, get_paca(), sizeof(struct paca_struct)); | ||
344 | kexec_paca.data_offset = 0xedeaddeadeeeeeeeUL; | ||
345 | paca = (struct paca_struct *)RELOC_HIDE(&kexec_paca, 0) - | ||
346 | kexec_paca.paca_index; | ||
347 | setup_paca(&kexec_paca); | ||
348 | |||
349 | /* XXX: If anyone does 'dynamic lppacas' this will also need to be | ||
350 | * switched to a static version! | ||
351 | */ | ||
352 | |||
287 | /* Some things are best done in assembly. Finding globals with | 353 | /* Some things are best done in assembly. Finding globals with |
288 | * a toc is easier in C, so pass in what we can. | 354 | * a toc is easier in C, so pass in what we can. |
289 | */ | 355 | */ |
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c deleted file mode 100644 index df78e0236a02..000000000000 --- a/arch/powerpc/kernel/of_device.c +++ /dev/null | |||
@@ -1,133 +0,0 @@ | |||
1 | #include <linux/string.h> | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/of.h> | ||
4 | #include <linux/init.h> | ||
5 | #include <linux/module.h> | ||
6 | #include <linux/mod_devicetable.h> | ||
7 | #include <linux/slab.h> | ||
8 | #include <linux/of_device.h> | ||
9 | |||
10 | #include <asm/errno.h> | ||
11 | #include <asm/dcr.h> | ||
12 | |||
13 | static void of_device_make_bus_id(struct of_device *dev) | ||
14 | { | ||
15 | static atomic_t bus_no_reg_magic; | ||
16 | struct device_node *node = dev->dev.of_node; | ||
17 | const u32 *reg; | ||
18 | u64 addr; | ||
19 | int magic; | ||
20 | |||
21 | /* | ||
22 | * If it's a DCR based device, use 'd' for native DCRs | ||
23 | * and 'D' for MMIO DCRs. | ||
24 | */ | ||
25 | #ifdef CONFIG_PPC_DCR | ||
26 | reg = of_get_property(node, "dcr-reg", NULL); | ||
27 | if (reg) { | ||
28 | #ifdef CONFIG_PPC_DCR_NATIVE | ||
29 | dev_set_name(&dev->dev, "d%x.%s", *reg, node->name); | ||
30 | #else /* CONFIG_PPC_DCR_NATIVE */ | ||
31 | addr = of_translate_dcr_address(node, *reg, NULL); | ||
32 | if (addr != OF_BAD_ADDR) { | ||
33 | dev_set_name(&dev->dev, "D%llx.%s", | ||
34 | (unsigned long long)addr, node->name); | ||
35 | return; | ||
36 | } | ||
37 | #endif /* !CONFIG_PPC_DCR_NATIVE */ | ||
38 | } | ||
39 | #endif /* CONFIG_PPC_DCR */ | ||
40 | |||
41 | /* | ||
42 | * For MMIO, get the physical address | ||
43 | */ | ||
44 | reg = of_get_property(node, "reg", NULL); | ||
45 | if (reg) { | ||
46 | addr = of_translate_address(node, reg); | ||
47 | if (addr != OF_BAD_ADDR) { | ||
48 | dev_set_name(&dev->dev, "%llx.%s", | ||
49 | (unsigned long long)addr, node->name); | ||
50 | return; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * No BusID, use the node name and add a globally incremented | ||
56 | * counter (and pray...) | ||
57 | */ | ||
58 | magic = atomic_add_return(1, &bus_no_reg_magic); | ||
59 | dev_set_name(&dev->dev, "%s.%d", node->name, magic - 1); | ||
60 | } | ||
61 | |||
62 | struct of_device *of_device_alloc(struct device_node *np, | ||
63 | const char *bus_id, | ||
64 | struct device *parent) | ||
65 | { | ||
66 | struct of_device *dev; | ||
67 | |||
68 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
69 | if (!dev) | ||
70 | return NULL; | ||
71 | |||
72 | dev->dev.of_node = of_node_get(np); | ||
73 | dev->dev.dma_mask = &dev->archdata.dma_mask; | ||
74 | dev->dev.parent = parent; | ||
75 | dev->dev.release = of_release_dev; | ||
76 | |||
77 | if (bus_id) | ||
78 | dev_set_name(&dev->dev, "%s", bus_id); | ||
79 | else | ||
80 | of_device_make_bus_id(dev); | ||
81 | |||
82 | return dev; | ||
83 | } | ||
84 | EXPORT_SYMBOL(of_device_alloc); | ||
85 | |||
86 | int of_device_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
87 | { | ||
88 | struct of_device *ofdev; | ||
89 | const char *compat; | ||
90 | int seen = 0, cplen, sl; | ||
91 | |||
92 | if (!dev) | ||
93 | return -ENODEV; | ||
94 | |||
95 | ofdev = to_of_device(dev); | ||
96 | |||
97 | if (add_uevent_var(env, "OF_NAME=%s", ofdev->dev.of_node->name)) | ||
98 | return -ENOMEM; | ||
99 | |||
100 | if (add_uevent_var(env, "OF_TYPE=%s", ofdev->dev.of_node->type)) | ||
101 | return -ENOMEM; | ||
102 | |||
103 | /* Since the compatible field can contain pretty much anything | ||
104 | * it's not really legal to split it out with commas. We split it | ||
105 | * up using a number of environment variables instead. */ | ||
106 | |||
107 | compat = of_get_property(ofdev->dev.of_node, "compatible", &cplen); | ||
108 | while (compat && *compat && cplen > 0) { | ||
109 | if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat)) | ||
110 | return -ENOMEM; | ||
111 | |||
112 | sl = strlen (compat) + 1; | ||
113 | compat += sl; | ||
114 | cplen -= sl; | ||
115 | seen++; | ||
116 | } | ||
117 | |||
118 | if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen)) | ||
119 | return -ENOMEM; | ||
120 | |||
121 | /* modalias is trickier, we add it in 2 steps */ | ||
122 | if (add_uevent_var(env, "MODALIAS=")) | ||
123 | return -ENOMEM; | ||
124 | sl = of_device_get_modalias(ofdev, &env->buf[env->buflen-1], | ||
125 | sizeof(env->buf) - env->buflen); | ||
126 | if (sl >= (sizeof(env->buf) - env->buflen)) | ||
127 | return -ENOMEM; | ||
128 | env->buflen += sl; | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | EXPORT_SYMBOL(of_device_uevent); | ||
133 | EXPORT_SYMBOL(of_device_get_modalias); | ||
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 487a98851ba6..b2c363ef38ad 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c | |||
@@ -28,207 +28,6 @@ | |||
28 | #include <asm/ppc-pci.h> | 28 | #include <asm/ppc-pci.h> |
29 | #include <asm/atomic.h> | 29 | #include <asm/atomic.h> |
30 | 30 | ||
31 | /* | ||
32 | * The list of OF IDs below is used for matching bus types in the | ||
33 | * system whose devices are to be exposed as of_platform_devices. | ||
34 | * | ||
35 | * This is the default list valid for most platforms. This file provides | ||
36 | * functions who can take an explicit list if necessary though | ||
37 | * | ||
38 | * The search is always performed recursively looking for children of | ||
39 | * the provided device_node and recursively if such a children matches | ||
40 | * a bus type in the list | ||
41 | */ | ||
42 | |||
43 | static const struct of_device_id of_default_bus_ids[] = { | ||
44 | { .type = "soc", }, | ||
45 | { .compatible = "soc", }, | ||
46 | { .type = "spider", }, | ||
47 | { .type = "axon", }, | ||
48 | { .type = "plb5", }, | ||
49 | { .type = "plb4", }, | ||
50 | { .type = "opb", }, | ||
51 | { .type = "ebc", }, | ||
52 | {}, | ||
53 | }; | ||
54 | |||
55 | struct bus_type of_platform_bus_type = { | ||
56 | .uevent = of_device_uevent, | ||
57 | }; | ||
58 | EXPORT_SYMBOL(of_platform_bus_type); | ||
59 | |||
60 | static int __init of_bus_driver_init(void) | ||
61 | { | ||
62 | return of_bus_type_init(&of_platform_bus_type, "of_platform"); | ||
63 | } | ||
64 | |||
65 | postcore_initcall(of_bus_driver_init); | ||
66 | |||
67 | struct of_device* of_platform_device_create(struct device_node *np, | ||
68 | const char *bus_id, | ||
69 | struct device *parent) | ||
70 | { | ||
71 | struct of_device *dev; | ||
72 | |||
73 | dev = of_device_alloc(np, bus_id, parent); | ||
74 | if (!dev) | ||
75 | return NULL; | ||
76 | |||
77 | dev->archdata.dma_mask = 0xffffffffUL; | ||
78 | dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | ||
79 | |||
80 | dev->dev.bus = &of_platform_bus_type; | ||
81 | |||
82 | /* We do not fill the DMA ops for platform devices by default. | ||
83 | * This is currently the responsibility of the platform code | ||
84 | * to do such, possibly using a device notifier | ||
85 | */ | ||
86 | |||
87 | if (of_device_register(dev) != 0) { | ||
88 | of_device_free(dev); | ||
89 | return NULL; | ||
90 | } | ||
91 | |||
92 | return dev; | ||
93 | } | ||
94 | EXPORT_SYMBOL(of_platform_device_create); | ||
95 | |||
96 | |||
97 | |||
98 | /** | ||
99 | * of_platform_bus_create - Create an OF device for a bus node and all its | ||
100 | * children. Optionally recursively instanciate matching busses. | ||
101 | * @bus: device node of the bus to instanciate | ||
102 | * @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to | ||
103 | * disallow recursive creation of child busses | ||
104 | */ | ||
105 | static int of_platform_bus_create(const struct device_node *bus, | ||
106 | const struct of_device_id *matches, | ||
107 | struct device *parent) | ||
108 | { | ||
109 | struct device_node *child; | ||
110 | struct of_device *dev; | ||
111 | int rc = 0; | ||
112 | |||
113 | for_each_child_of_node(bus, child) { | ||
114 | pr_debug(" create child: %s\n", child->full_name); | ||
115 | dev = of_platform_device_create(child, NULL, parent); | ||
116 | if (dev == NULL) | ||
117 | rc = -ENOMEM; | ||
118 | else if (!of_match_node(matches, child)) | ||
119 | continue; | ||
120 | if (rc == 0) { | ||
121 | pr_debug(" and sub busses\n"); | ||
122 | rc = of_platform_bus_create(child, matches, &dev->dev); | ||
123 | } if (rc) { | ||
124 | of_node_put(child); | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | return rc; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * of_platform_bus_probe - Probe the device-tree for platform busses | ||
133 | * @root: parent of the first level to probe or NULL for the root of the tree | ||
134 | * @matches: match table, NULL to use the default | ||
135 | * @parent: parent to hook devices from, NULL for toplevel | ||
136 | * | ||
137 | * Note that children of the provided root are not instanciated as devices | ||
138 | * unless the specified root itself matches the bus list and is not NULL. | ||
139 | */ | ||
140 | |||
141 | int of_platform_bus_probe(struct device_node *root, | ||
142 | const struct of_device_id *matches, | ||
143 | struct device *parent) | ||
144 | { | ||
145 | struct device_node *child; | ||
146 | struct of_device *dev; | ||
147 | int rc = 0; | ||
148 | |||
149 | if (matches == NULL) | ||
150 | matches = of_default_bus_ids; | ||
151 | if (matches == OF_NO_DEEP_PROBE) | ||
152 | return -EINVAL; | ||
153 | if (root == NULL) | ||
154 | root = of_find_node_by_path("/"); | ||
155 | else | ||
156 | of_node_get(root); | ||
157 | |||
158 | pr_debug("of_platform_bus_probe()\n"); | ||
159 | pr_debug(" starting at: %s\n", root->full_name); | ||
160 | |||
161 | /* Do a self check of bus type, if there's a match, create | ||
162 | * children | ||
163 | */ | ||
164 | if (of_match_node(matches, root)) { | ||
165 | pr_debug(" root match, create all sub devices\n"); | ||
166 | dev = of_platform_device_create(root, NULL, parent); | ||
167 | if (dev == NULL) { | ||
168 | rc = -ENOMEM; | ||
169 | goto bail; | ||
170 | } | ||
171 | pr_debug(" create all sub busses\n"); | ||
172 | rc = of_platform_bus_create(root, matches, &dev->dev); | ||
173 | goto bail; | ||
174 | } | ||
175 | for_each_child_of_node(root, child) { | ||
176 | if (!of_match_node(matches, child)) | ||
177 | continue; | ||
178 | |||
179 | pr_debug(" match: %s\n", child->full_name); | ||
180 | dev = of_platform_device_create(child, NULL, parent); | ||
181 | if (dev == NULL) | ||
182 | rc = -ENOMEM; | ||
183 | else | ||
184 | rc = of_platform_bus_create(child, matches, &dev->dev); | ||
185 | if (rc) { | ||
186 | of_node_put(child); | ||
187 | break; | ||
188 | } | ||
189 | } | ||
190 | bail: | ||
191 | of_node_put(root); | ||
192 | return rc; | ||
193 | } | ||
194 | EXPORT_SYMBOL(of_platform_bus_probe); | ||
195 | |||
196 | static int of_dev_node_match(struct device *dev, void *data) | ||
197 | { | ||
198 | return to_of_device(dev)->dev.of_node == data; | ||
199 | } | ||
200 | |||
201 | struct of_device *of_find_device_by_node(struct device_node *np) | ||
202 | { | ||
203 | struct device *dev; | ||
204 | |||
205 | dev = bus_find_device(&of_platform_bus_type, | ||
206 | NULL, np, of_dev_node_match); | ||
207 | if (dev) | ||
208 | return to_of_device(dev); | ||
209 | return NULL; | ||
210 | } | ||
211 | EXPORT_SYMBOL(of_find_device_by_node); | ||
212 | |||
213 | static int of_dev_phandle_match(struct device *dev, void *data) | ||
214 | { | ||
215 | phandle *ph = data; | ||
216 | return to_of_device(dev)->dev.of_node->phandle == *ph; | ||
217 | } | ||
218 | |||
219 | struct of_device *of_find_device_by_phandle(phandle ph) | ||
220 | { | ||
221 | struct device *dev; | ||
222 | |||
223 | dev = bus_find_device(&of_platform_bus_type, | ||
224 | NULL, &ph, of_dev_phandle_match); | ||
225 | if (dev) | ||
226 | return to_of_device(dev); | ||
227 | return NULL; | ||
228 | } | ||
229 | EXPORT_SYMBOL(of_find_device_by_phandle); | ||
230 | |||
231 | |||
232 | #ifdef CONFIG_PPC_OF_PLATFORM_PCI | 31 | #ifdef CONFIG_PPC_OF_PLATFORM_PCI |
233 | 32 | ||
234 | /* The probing of PCI controllers from of_platform is currently | 33 | /* The probing of PCI controllers from of_platform is currently |
@@ -237,7 +36,7 @@ EXPORT_SYMBOL(of_find_device_by_phandle); | |||
237 | * lacking some bits needed here. | 36 | * lacking some bits needed here. |
238 | */ | 37 | */ |
239 | 38 | ||
240 | static int __devinit of_pci_phb_probe(struct of_device *dev, | 39 | static int __devinit of_pci_phb_probe(struct platform_device *dev, |
241 | const struct of_device_id *match) | 40 | const struct of_device_id *match) |
242 | { | 41 | { |
243 | struct pci_controller *phb; | 42 | struct pci_controller *phb; |
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index 139a773853f4..d0a26f1770fe 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c | |||
@@ -105,6 +105,16 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu) | |||
105 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 105 | #endif /* CONFIG_PPC_STD_MMU_64 */ |
106 | } | 106 | } |
107 | 107 | ||
108 | /* Put the paca pointer into r13 and SPRG_PACA */ | ||
109 | void setup_paca(struct paca_struct *new_paca) | ||
110 | { | ||
111 | local_paca = new_paca; | ||
112 | mtspr(SPRN_SPRG_PACA, local_paca); | ||
113 | #ifdef CONFIG_PPC_BOOK3E | ||
114 | mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb); | ||
115 | #endif | ||
116 | } | ||
117 | |||
108 | static int __initdata paca_size; | 118 | static int __initdata paca_size; |
109 | 119 | ||
110 | void __init allocate_pacas(void) | 120 | void __init allocate_pacas(void) |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 5b38f6ae2b29..9021c4ad4bbd 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
24 | #include <linux/of_address.h> | ||
24 | #include <linux/mm.h> | 25 | #include <linux/mm.h> |
25 | #include <linux/list.h> | 26 | #include <linux/list.h> |
26 | #include <linux/syscalls.h> | 27 | #include <linux/syscalls.h> |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 773424df828a..551f6713ff42 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/kernel_stat.h> | 37 | #include <linux/kernel_stat.h> |
38 | #include <linux/personality.h> | 38 | #include <linux/personality.h> |
39 | #include <linux/random.h> | 39 | #include <linux/random.h> |
40 | #include <linux/hw_breakpoint.h> | ||
40 | 41 | ||
41 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
42 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
@@ -462,14 +463,42 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
462 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 463 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
463 | switch_booke_debug_regs(&new->thread); | 464 | switch_booke_debug_regs(&new->thread); |
464 | #else | 465 | #else |
466 | /* | ||
467 | * For PPC_BOOK3S_64, we use the hw-breakpoint interfaces that would | ||
468 | * schedule DABR | ||
469 | */ | ||
470 | #ifndef CONFIG_HAVE_HW_BREAKPOINT | ||
465 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) | 471 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) |
466 | set_dabr(new->thread.dabr); | 472 | set_dabr(new->thread.dabr); |
473 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
467 | #endif | 474 | #endif |
468 | 475 | ||
469 | 476 | ||
470 | new_thread = &new->thread; | 477 | new_thread = &new->thread; |
471 | old_thread = ¤t->thread; | 478 | old_thread = ¤t->thread; |
472 | 479 | ||
480 | #if defined(CONFIG_PPC_BOOK3E_64) | ||
481 | /* XXX Current Book3E code doesn't deal with kernel side DBCR0, | ||
482 | * we always hold the user values, so we set it now. | ||
483 | * | ||
484 | * However, we ensure the kernel MSR:DE is appropriately cleared too | ||
485 | * to avoid spurrious single step exceptions in the kernel. | ||
486 | * | ||
487 | * This will have to change to merge with the ppc32 code at some point, | ||
488 | * but I don't like much what ppc32 is doing today so there's some | ||
489 | * thinking needed there | ||
490 | */ | ||
491 | if ((new_thread->dbcr0 | old_thread->dbcr0) & DBCR0_IDM) { | ||
492 | u32 dbcr0; | ||
493 | |||
494 | mtmsr(mfmsr() & ~MSR_DE); | ||
495 | isync(); | ||
496 | dbcr0 = mfspr(SPRN_DBCR0); | ||
497 | dbcr0 = (dbcr0 & DBCR0_EDM) | new_thread->dbcr0; | ||
498 | mtspr(SPRN_DBCR0, dbcr0); | ||
499 | } | ||
500 | #endif /* CONFIG_PPC64_BOOK3E */ | ||
501 | |||
473 | #ifdef CONFIG_PPC64 | 502 | #ifdef CONFIG_PPC64 |
474 | /* | 503 | /* |
475 | * Collect processor utilization data per process | 504 | * Collect processor utilization data per process |
@@ -642,7 +671,11 @@ void flush_thread(void) | |||
642 | { | 671 | { |
643 | discard_lazy_cpu_state(); | 672 | discard_lazy_cpu_state(); |
644 | 673 | ||
674 | #ifdef CONFIG_HAVE_HW_BREAKPOINTS | ||
675 | flush_ptrace_hw_breakpoint(current); | ||
676 | #else /* CONFIG_HAVE_HW_BREAKPOINTS */ | ||
645 | set_debug_reg_defaults(¤t->thread); | 677 | set_debug_reg_defaults(¤t->thread); |
678 | #endif /* CONFIG_HAVE_HW_BREAKPOINTS */ | ||
646 | } | 679 | } |
647 | 680 | ||
648 | void | 681 | void |
@@ -660,6 +693,9 @@ void prepare_to_copy(struct task_struct *tsk) | |||
660 | flush_altivec_to_thread(current); | 693 | flush_altivec_to_thread(current); |
661 | flush_vsx_to_thread(current); | 694 | flush_vsx_to_thread(current); |
662 | flush_spe_to_thread(current); | 695 | flush_spe_to_thread(current); |
696 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
697 | flush_ptrace_hw_breakpoint(tsk); | ||
698 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
663 | } | 699 | } |
664 | 700 | ||
665 | /* | 701 | /* |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 3b6f8ae9b8cc..941ff4dbc567 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -311,6 +311,24 @@ static void __init prom_print_hex(unsigned long val) | |||
311 | call_prom("write", 3, 1, _prom->stdout, buf, nibbles); | 311 | call_prom("write", 3, 1, _prom->stdout, buf, nibbles); |
312 | } | 312 | } |
313 | 313 | ||
314 | /* max number of decimal digits in an unsigned long */ | ||
315 | #define UL_DIGITS 21 | ||
316 | static void __init prom_print_dec(unsigned long val) | ||
317 | { | ||
318 | int i, size; | ||
319 | char buf[UL_DIGITS+1]; | ||
320 | struct prom_t *_prom = &RELOC(prom); | ||
321 | |||
322 | for (i = UL_DIGITS-1; i >= 0; i--) { | ||
323 | buf[i] = (val % 10) + '0'; | ||
324 | val = val/10; | ||
325 | if (val == 0) | ||
326 | break; | ||
327 | } | ||
328 | /* shift stuff down */ | ||
329 | size = UL_DIGITS - i; | ||
330 | call_prom("write", 3, 1, _prom->stdout, buf+i, size); | ||
331 | } | ||
314 | 332 | ||
315 | static void __init prom_printf(const char *format, ...) | 333 | static void __init prom_printf(const char *format, ...) |
316 | { | 334 | { |
@@ -350,6 +368,14 @@ static void __init prom_printf(const char *format, ...) | |||
350 | v = va_arg(args, unsigned long); | 368 | v = va_arg(args, unsigned long); |
351 | prom_print_hex(v); | 369 | prom_print_hex(v); |
352 | break; | 370 | break; |
371 | case 'l': | ||
372 | ++q; | ||
373 | if (*q == 'u') { /* '%lu' */ | ||
374 | ++q; | ||
375 | v = va_arg(args, unsigned long); | ||
376 | prom_print_dec(v); | ||
377 | } | ||
378 | break; | ||
353 | } | 379 | } |
354 | } | 380 | } |
355 | } | 381 | } |
@@ -835,11 +861,11 @@ static int __init prom_count_smt_threads(void) | |||
835 | if (plen == PROM_ERROR) | 861 | if (plen == PROM_ERROR) |
836 | break; | 862 | break; |
837 | plen >>= 2; | 863 | plen >>= 2; |
838 | prom_debug("Found 0x%x smt threads per core\n", (unsigned long)plen); | 864 | prom_debug("Found %lu smt threads per core\n", (unsigned long)plen); |
839 | 865 | ||
840 | /* Sanity check */ | 866 | /* Sanity check */ |
841 | if (plen < 1 || plen > 64) { | 867 | if (plen < 1 || plen > 64) { |
842 | prom_printf("Threads per core 0x%x out of bounds, assuming 1\n", | 868 | prom_printf("Threads per core %lu out of bounds, assuming 1\n", |
843 | (unsigned long)plen); | 869 | (unsigned long)plen); |
844 | return 1; | 870 | return 1; |
845 | } | 871 | } |
@@ -869,12 +895,12 @@ static void __init prom_send_capabilities(void) | |||
869 | cores = (u32 *)PTRRELOC(&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]); | 895 | cores = (u32 *)PTRRELOC(&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]); |
870 | if (*cores != NR_CPUS) { | 896 | if (*cores != NR_CPUS) { |
871 | prom_printf("WARNING ! " | 897 | prom_printf("WARNING ! " |
872 | "ibm_architecture_vec structure inconsistent: 0x%x !\n", | 898 | "ibm_architecture_vec structure inconsistent: %lu!\n", |
873 | *cores); | 899 | *cores); |
874 | } else { | 900 | } else { |
875 | *cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads()); | 901 | *cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads()); |
876 | prom_printf("Max number of cores passed to firmware: 0x%x\n", | 902 | prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n", |
877 | (unsigned long)*cores); | 903 | *cores, NR_CPUS); |
878 | } | 904 | } |
879 | 905 | ||
880 | /* try calling the ibm,client-architecture-support method */ | 906 | /* try calling the ibm,client-architecture-support method */ |
@@ -1482,7 +1508,7 @@ static void __init prom_hold_cpus(void) | |||
1482 | reg = -1; | 1508 | reg = -1; |
1483 | prom_getprop(node, "reg", ®, sizeof(reg)); | 1509 | prom_getprop(node, "reg", ®, sizeof(reg)); |
1484 | 1510 | ||
1485 | prom_debug("cpu hw idx = 0x%x\n", reg); | 1511 | prom_debug("cpu hw idx = %lu\n", reg); |
1486 | 1512 | ||
1487 | /* Init the acknowledge var which will be reset by | 1513 | /* Init the acknowledge var which will be reset by |
1488 | * the secondary cpu when it awakens from its OF | 1514 | * the secondary cpu when it awakens from its OF |
@@ -1492,7 +1518,7 @@ static void __init prom_hold_cpus(void) | |||
1492 | 1518 | ||
1493 | if (reg != _prom->cpu) { | 1519 | if (reg != _prom->cpu) { |
1494 | /* Primary Thread of non-boot cpu */ | 1520 | /* Primary Thread of non-boot cpu */ |
1495 | prom_printf("starting cpu hw idx %x... ", reg); | 1521 | prom_printf("starting cpu hw idx %lu... ", reg); |
1496 | call_prom("start-cpu", 3, 0, node, | 1522 | call_prom("start-cpu", 3, 0, node, |
1497 | secondary_hold, reg); | 1523 | secondary_hold, reg); |
1498 | 1524 | ||
@@ -1507,7 +1533,7 @@ static void __init prom_hold_cpus(void) | |||
1507 | } | 1533 | } |
1508 | #ifdef CONFIG_SMP | 1534 | #ifdef CONFIG_SMP |
1509 | else | 1535 | else |
1510 | prom_printf("boot cpu hw idx %x\n", reg); | 1536 | prom_printf("boot cpu hw idx %lu\n", reg); |
1511 | #endif /* CONFIG_SMP */ | 1537 | #endif /* CONFIG_SMP */ |
1512 | } | 1538 | } |
1513 | 1539 | ||
@@ -2420,7 +2446,7 @@ static void __init prom_find_boot_cpu(void) | |||
2420 | prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval)); | 2446 | prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval)); |
2421 | _prom->cpu = getprop_rval; | 2447 | _prom->cpu = getprop_rval; |
2422 | 2448 | ||
2423 | prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu); | 2449 | prom_debug("Booting CPU hw index = %lu\n", _prom->cpu); |
2424 | } | 2450 | } |
2425 | 2451 | ||
2426 | static void __init prom_check_initrd(unsigned long r3, unsigned long r4) | 2452 | static void __init prom_check_initrd(unsigned long r3, unsigned long r4) |
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 8362620c9e6f..88334af038e5 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c | |||
@@ -6,232 +6,11 @@ | |||
6 | #include <linux/module.h> | 6 | #include <linux/module.h> |
7 | #include <linux/ioport.h> | 7 | #include <linux/ioport.h> |
8 | #include <linux/etherdevice.h> | 8 | #include <linux/etherdevice.h> |
9 | #include <linux/of_address.h> | ||
9 | #include <asm/prom.h> | 10 | #include <asm/prom.h> |
10 | #include <asm/pci-bridge.h> | 11 | #include <asm/pci-bridge.h> |
11 | 12 | ||
12 | #ifdef DEBUG | ||
13 | #define DBG(fmt...) do { printk(fmt); } while(0) | ||
14 | #else | ||
15 | #define DBG(fmt...) do { } while(0) | ||
16 | #endif | ||
17 | |||
18 | #ifdef CONFIG_PPC64 | ||
19 | #define PRu64 "%lx" | ||
20 | #else | ||
21 | #define PRu64 "%llx" | ||
22 | #endif | ||
23 | |||
24 | /* Max address size we deal with */ | ||
25 | #define OF_MAX_ADDR_CELLS 4 | ||
26 | #define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ | ||
27 | (ns) > 0) | ||
28 | |||
29 | static struct of_bus *of_match_bus(struct device_node *np); | ||
30 | static int __of_address_to_resource(struct device_node *dev, | ||
31 | const u32 *addrp, u64 size, unsigned int flags, | ||
32 | struct resource *r); | ||
33 | |||
34 | |||
35 | /* Debug utility */ | ||
36 | #ifdef DEBUG | ||
37 | static void of_dump_addr(const char *s, const u32 *addr, int na) | ||
38 | { | ||
39 | printk("%s", s); | ||
40 | while(na--) | ||
41 | printk(" %08x", *(addr++)); | ||
42 | printk("\n"); | ||
43 | } | ||
44 | #else | ||
45 | static void of_dump_addr(const char *s, const u32 *addr, int na) { } | ||
46 | #endif | ||
47 | |||
48 | |||
49 | /* Callbacks for bus specific translators */ | ||
50 | struct of_bus { | ||
51 | const char *name; | ||
52 | const char *addresses; | ||
53 | int (*match)(struct device_node *parent); | ||
54 | void (*count_cells)(struct device_node *child, | ||
55 | int *addrc, int *sizec); | ||
56 | u64 (*map)(u32 *addr, const u32 *range, | ||
57 | int na, int ns, int pna); | ||
58 | int (*translate)(u32 *addr, u64 offset, int na); | ||
59 | unsigned int (*get_flags)(const u32 *addr); | ||
60 | }; | ||
61 | |||
62 | |||
63 | /* | ||
64 | * Default translator (generic bus) | ||
65 | */ | ||
66 | |||
67 | static void of_bus_default_count_cells(struct device_node *dev, | ||
68 | int *addrc, int *sizec) | ||
69 | { | ||
70 | if (addrc) | ||
71 | *addrc = of_n_addr_cells(dev); | ||
72 | if (sizec) | ||
73 | *sizec = of_n_size_cells(dev); | ||
74 | } | ||
75 | |||
76 | static u64 of_bus_default_map(u32 *addr, const u32 *range, | ||
77 | int na, int ns, int pna) | ||
78 | { | ||
79 | u64 cp, s, da; | ||
80 | |||
81 | cp = of_read_number(range, na); | ||
82 | s = of_read_number(range + na + pna, ns); | ||
83 | da = of_read_number(addr, na); | ||
84 | |||
85 | DBG("OF: default map, cp="PRu64", s="PRu64", da="PRu64"\n", | ||
86 | cp, s, da); | ||
87 | |||
88 | if (da < cp || da >= (cp + s)) | ||
89 | return OF_BAD_ADDR; | ||
90 | return da - cp; | ||
91 | } | ||
92 | |||
93 | static int of_bus_default_translate(u32 *addr, u64 offset, int na) | ||
94 | { | ||
95 | u64 a = of_read_number(addr, na); | ||
96 | memset(addr, 0, na * 4); | ||
97 | a += offset; | ||
98 | if (na > 1) | ||
99 | addr[na - 2] = a >> 32; | ||
100 | addr[na - 1] = a & 0xffffffffu; | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static unsigned int of_bus_default_get_flags(const u32 *addr) | ||
106 | { | ||
107 | return IORESOURCE_MEM; | ||
108 | } | ||
109 | |||
110 | |||
111 | #ifdef CONFIG_PCI | 13 | #ifdef CONFIG_PCI |
112 | /* | ||
113 | * PCI bus specific translator | ||
114 | */ | ||
115 | |||
116 | static int of_bus_pci_match(struct device_node *np) | ||
117 | { | ||
118 | /* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */ | ||
119 | return !strcmp(np->type, "pci") || !strcmp(np->type, "vci"); | ||
120 | } | ||
121 | |||
122 | static void of_bus_pci_count_cells(struct device_node *np, | ||
123 | int *addrc, int *sizec) | ||
124 | { | ||
125 | if (addrc) | ||
126 | *addrc = 3; | ||
127 | if (sizec) | ||
128 | *sizec = 2; | ||
129 | } | ||
130 | |||
131 | static unsigned int of_bus_pci_get_flags(const u32 *addr) | ||
132 | { | ||
133 | unsigned int flags = 0; | ||
134 | u32 w = addr[0]; | ||
135 | |||
136 | switch((w >> 24) & 0x03) { | ||
137 | case 0x01: | ||
138 | flags |= IORESOURCE_IO; | ||
139 | break; | ||
140 | case 0x02: /* 32 bits */ | ||
141 | case 0x03: /* 64 bits */ | ||
142 | flags |= IORESOURCE_MEM; | ||
143 | break; | ||
144 | } | ||
145 | if (w & 0x40000000) | ||
146 | flags |= IORESOURCE_PREFETCH; | ||
147 | return flags; | ||
148 | } | ||
149 | |||
150 | static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna) | ||
151 | { | ||
152 | u64 cp, s, da; | ||
153 | unsigned int af, rf; | ||
154 | |||
155 | af = of_bus_pci_get_flags(addr); | ||
156 | rf = of_bus_pci_get_flags(range); | ||
157 | |||
158 | /* Check address type match */ | ||
159 | if ((af ^ rf) & (IORESOURCE_MEM | IORESOURCE_IO)) | ||
160 | return OF_BAD_ADDR; | ||
161 | |||
162 | /* Read address values, skipping high cell */ | ||
163 | cp = of_read_number(range + 1, na - 1); | ||
164 | s = of_read_number(range + na + pna, ns); | ||
165 | da = of_read_number(addr + 1, na - 1); | ||
166 | |||
167 | DBG("OF: PCI map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da); | ||
168 | |||
169 | if (da < cp || da >= (cp + s)) | ||
170 | return OF_BAD_ADDR; | ||
171 | return da - cp; | ||
172 | } | ||
173 | |||
174 | static int of_bus_pci_translate(u32 *addr, u64 offset, int na) | ||
175 | { | ||
176 | return of_bus_default_translate(addr + 1, offset, na - 1); | ||
177 | } | ||
178 | |||
179 | const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, | ||
180 | unsigned int *flags) | ||
181 | { | ||
182 | const u32 *prop; | ||
183 | unsigned int psize; | ||
184 | struct device_node *parent; | ||
185 | struct of_bus *bus; | ||
186 | int onesize, i, na, ns; | ||
187 | |||
188 | /* Get parent & match bus type */ | ||
189 | parent = of_get_parent(dev); | ||
190 | if (parent == NULL) | ||
191 | return NULL; | ||
192 | bus = of_match_bus(parent); | ||
193 | if (strcmp(bus->name, "pci")) { | ||
194 | of_node_put(parent); | ||
195 | return NULL; | ||
196 | } | ||
197 | bus->count_cells(dev, &na, &ns); | ||
198 | of_node_put(parent); | ||
199 | if (!OF_CHECK_COUNTS(na, ns)) | ||
200 | return NULL; | ||
201 | |||
202 | /* Get "reg" or "assigned-addresses" property */ | ||
203 | prop = of_get_property(dev, bus->addresses, &psize); | ||
204 | if (prop == NULL) | ||
205 | return NULL; | ||
206 | psize /= 4; | ||
207 | |||
208 | onesize = na + ns; | ||
209 | for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) | ||
210 | if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) { | ||
211 | if (size) | ||
212 | *size = of_read_number(prop + na, ns); | ||
213 | if (flags) | ||
214 | *flags = bus->get_flags(prop); | ||
215 | return prop; | ||
216 | } | ||
217 | return NULL; | ||
218 | } | ||
219 | EXPORT_SYMBOL(of_get_pci_address); | ||
220 | |||
221 | int of_pci_address_to_resource(struct device_node *dev, int bar, | ||
222 | struct resource *r) | ||
223 | { | ||
224 | const u32 *addrp; | ||
225 | u64 size; | ||
226 | unsigned int flags; | ||
227 | |||
228 | addrp = of_get_pci_address(dev, bar, &size, &flags); | ||
229 | if (addrp == NULL) | ||
230 | return -EINVAL; | ||
231 | return __of_address_to_resource(dev, addrp, size, flags, r); | ||
232 | } | ||
233 | EXPORT_SYMBOL_GPL(of_pci_address_to_resource); | ||
234 | |||
235 | int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) | 14 | int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) |
236 | { | 15 | { |
237 | struct device_node *dn, *ppnode; | 16 | struct device_node *dn, *ppnode; |
@@ -313,345 +92,6 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) | |||
313 | EXPORT_SYMBOL_GPL(of_irq_map_pci); | 92 | EXPORT_SYMBOL_GPL(of_irq_map_pci); |
314 | #endif /* CONFIG_PCI */ | 93 | #endif /* CONFIG_PCI */ |
315 | 94 | ||
316 | /* | ||
317 | * ISA bus specific translator | ||
318 | */ | ||
319 | |||
320 | static int of_bus_isa_match(struct device_node *np) | ||
321 | { | ||
322 | return !strcmp(np->name, "isa"); | ||
323 | } | ||
324 | |||
325 | static void of_bus_isa_count_cells(struct device_node *child, | ||
326 | int *addrc, int *sizec) | ||
327 | { | ||
328 | if (addrc) | ||
329 | *addrc = 2; | ||
330 | if (sizec) | ||
331 | *sizec = 1; | ||
332 | } | ||
333 | |||
334 | static u64 of_bus_isa_map(u32 *addr, const u32 *range, int na, int ns, int pna) | ||
335 | { | ||
336 | u64 cp, s, da; | ||
337 | |||
338 | /* Check address type match */ | ||
339 | if ((addr[0] ^ range[0]) & 0x00000001) | ||
340 | return OF_BAD_ADDR; | ||
341 | |||
342 | /* Read address values, skipping high cell */ | ||
343 | cp = of_read_number(range + 1, na - 1); | ||
344 | s = of_read_number(range + na + pna, ns); | ||
345 | da = of_read_number(addr + 1, na - 1); | ||
346 | |||
347 | DBG("OF: ISA map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da); | ||
348 | |||
349 | if (da < cp || da >= (cp + s)) | ||
350 | return OF_BAD_ADDR; | ||
351 | return da - cp; | ||
352 | } | ||
353 | |||
354 | static int of_bus_isa_translate(u32 *addr, u64 offset, int na) | ||
355 | { | ||
356 | return of_bus_default_translate(addr + 1, offset, na - 1); | ||
357 | } | ||
358 | |||
359 | static unsigned int of_bus_isa_get_flags(const u32 *addr) | ||
360 | { | ||
361 | unsigned int flags = 0; | ||
362 | u32 w = addr[0]; | ||
363 | |||
364 | if (w & 1) | ||
365 | flags |= IORESOURCE_IO; | ||
366 | else | ||
367 | flags |= IORESOURCE_MEM; | ||
368 | return flags; | ||
369 | } | ||
370 | |||
371 | |||
372 | /* | ||
373 | * Array of bus specific translators | ||
374 | */ | ||
375 | |||
376 | static struct of_bus of_busses[] = { | ||
377 | #ifdef CONFIG_PCI | ||
378 | /* PCI */ | ||
379 | { | ||
380 | .name = "pci", | ||
381 | .addresses = "assigned-addresses", | ||
382 | .match = of_bus_pci_match, | ||
383 | .count_cells = of_bus_pci_count_cells, | ||
384 | .map = of_bus_pci_map, | ||
385 | .translate = of_bus_pci_translate, | ||
386 | .get_flags = of_bus_pci_get_flags, | ||
387 | }, | ||
388 | #endif /* CONFIG_PCI */ | ||
389 | /* ISA */ | ||
390 | { | ||
391 | .name = "isa", | ||
392 | .addresses = "reg", | ||
393 | .match = of_bus_isa_match, | ||
394 | .count_cells = of_bus_isa_count_cells, | ||
395 | .map = of_bus_isa_map, | ||
396 | .translate = of_bus_isa_translate, | ||
397 | .get_flags = of_bus_isa_get_flags, | ||
398 | }, | ||
399 | /* Default */ | ||
400 | { | ||
401 | .name = "default", | ||
402 | .addresses = "reg", | ||
403 | .match = NULL, | ||
404 | .count_cells = of_bus_default_count_cells, | ||
405 | .map = of_bus_default_map, | ||
406 | .translate = of_bus_default_translate, | ||
407 | .get_flags = of_bus_default_get_flags, | ||
408 | }, | ||
409 | }; | ||
410 | |||
411 | static struct of_bus *of_match_bus(struct device_node *np) | ||
412 | { | ||
413 | int i; | ||
414 | |||
415 | for (i = 0; i < ARRAY_SIZE(of_busses); i ++) | ||
416 | if (!of_busses[i].match || of_busses[i].match(np)) | ||
417 | return &of_busses[i]; | ||
418 | BUG(); | ||
419 | return NULL; | ||
420 | } | ||
421 | |||
422 | static int of_translate_one(struct device_node *parent, struct of_bus *bus, | ||
423 | struct of_bus *pbus, u32 *addr, | ||
424 | int na, int ns, int pna, const char *rprop) | ||
425 | { | ||
426 | const u32 *ranges; | ||
427 | unsigned int rlen; | ||
428 | int rone; | ||
429 | u64 offset = OF_BAD_ADDR; | ||
430 | |||
431 | /* Normally, an absence of a "ranges" property means we are | ||
432 | * crossing a non-translatable boundary, and thus the addresses | ||
433 | * below the current not cannot be converted to CPU physical ones. | ||
434 | * Unfortunately, while this is very clear in the spec, it's not | ||
435 | * what Apple understood, and they do have things like /uni-n or | ||
436 | * /ht nodes with no "ranges" property and a lot of perfectly | ||
437 | * useable mapped devices below them. Thus we treat the absence of | ||
438 | * "ranges" as equivalent to an empty "ranges" property which means | ||
439 | * a 1:1 translation at that level. It's up to the caller not to try | ||
440 | * to translate addresses that aren't supposed to be translated in | ||
441 | * the first place. --BenH. | ||
442 | */ | ||
443 | ranges = of_get_property(parent, rprop, &rlen); | ||
444 | if (ranges == NULL || rlen == 0) { | ||
445 | offset = of_read_number(addr, na); | ||
446 | memset(addr, 0, pna * 4); | ||
447 | DBG("OF: no ranges, 1:1 translation\n"); | ||
448 | goto finish; | ||
449 | } | ||
450 | |||
451 | DBG("OF: walking ranges...\n"); | ||
452 | |||
453 | /* Now walk through the ranges */ | ||
454 | rlen /= 4; | ||
455 | rone = na + pna + ns; | ||
456 | for (; rlen >= rone; rlen -= rone, ranges += rone) { | ||
457 | offset = bus->map(addr, ranges, na, ns, pna); | ||
458 | if (offset != OF_BAD_ADDR) | ||
459 | break; | ||
460 | } | ||
461 | if (offset == OF_BAD_ADDR) { | ||
462 | DBG("OF: not found !\n"); | ||
463 | return 1; | ||
464 | } | ||
465 | memcpy(addr, ranges + na, 4 * pna); | ||
466 | |||
467 | finish: | ||
468 | of_dump_addr("OF: parent translation for:", addr, pna); | ||
469 | DBG("OF: with offset: "PRu64"\n", offset); | ||
470 | |||
471 | /* Translate it into parent bus space */ | ||
472 | return pbus->translate(addr, offset, pna); | ||
473 | } | ||
474 | |||
475 | |||
476 | /* | ||
477 | * Translate an address from the device-tree into a CPU physical address, | ||
478 | * this walks up the tree and applies the various bus mappings on the | ||
479 | * way. | ||
480 | * | ||
481 | * Note: We consider that crossing any level with #size-cells == 0 to mean | ||
482 | * that translation is impossible (that is we are not dealing with a value | ||
483 | * that can be mapped to a cpu physical address). This is not really specified | ||
484 | * that way, but this is traditionally the way IBM at least do things | ||
485 | */ | ||
486 | u64 __of_translate_address(struct device_node *dev, const u32 *in_addr, | ||
487 | const char *rprop) | ||
488 | { | ||
489 | struct device_node *parent = NULL; | ||
490 | struct of_bus *bus, *pbus; | ||
491 | u32 addr[OF_MAX_ADDR_CELLS]; | ||
492 | int na, ns, pna, pns; | ||
493 | u64 result = OF_BAD_ADDR; | ||
494 | |||
495 | DBG("OF: ** translation for device %s **\n", dev->full_name); | ||
496 | |||
497 | /* Increase refcount at current level */ | ||
498 | of_node_get(dev); | ||
499 | |||
500 | /* Get parent & match bus type */ | ||
501 | parent = of_get_parent(dev); | ||
502 | if (parent == NULL) | ||
503 | goto bail; | ||
504 | bus = of_match_bus(parent); | ||
505 | |||
506 | /* Cound address cells & copy address locally */ | ||
507 | bus->count_cells(dev, &na, &ns); | ||
508 | if (!OF_CHECK_COUNTS(na, ns)) { | ||
509 | printk(KERN_ERR "prom_parse: Bad cell count for %s\n", | ||
510 | dev->full_name); | ||
511 | goto bail; | ||
512 | } | ||
513 | memcpy(addr, in_addr, na * 4); | ||
514 | |||
515 | DBG("OF: bus is %s (na=%d, ns=%d) on %s\n", | ||
516 | bus->name, na, ns, parent->full_name); | ||
517 | of_dump_addr("OF: translating address:", addr, na); | ||
518 | |||
519 | /* Translate */ | ||
520 | for (;;) { | ||
521 | /* Switch to parent bus */ | ||
522 | of_node_put(dev); | ||
523 | dev = parent; | ||
524 | parent = of_get_parent(dev); | ||
525 | |||
526 | /* If root, we have finished */ | ||
527 | if (parent == NULL) { | ||
528 | DBG("OF: reached root node\n"); | ||
529 | result = of_read_number(addr, na); | ||
530 | break; | ||
531 | } | ||
532 | |||
533 | /* Get new parent bus and counts */ | ||
534 | pbus = of_match_bus(parent); | ||
535 | pbus->count_cells(dev, &pna, &pns); | ||
536 | if (!OF_CHECK_COUNTS(pna, pns)) { | ||
537 | printk(KERN_ERR "prom_parse: Bad cell count for %s\n", | ||
538 | dev->full_name); | ||
539 | break; | ||
540 | } | ||
541 | |||
542 | DBG("OF: parent bus is %s (na=%d, ns=%d) on %s\n", | ||
543 | pbus->name, pna, pns, parent->full_name); | ||
544 | |||
545 | /* Apply bus translation */ | ||
546 | if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop)) | ||
547 | break; | ||
548 | |||
549 | /* Complete the move up one level */ | ||
550 | na = pna; | ||
551 | ns = pns; | ||
552 | bus = pbus; | ||
553 | |||
554 | of_dump_addr("OF: one level translation:", addr, na); | ||
555 | } | ||
556 | bail: | ||
557 | of_node_put(parent); | ||
558 | of_node_put(dev); | ||
559 | |||
560 | return result; | ||
561 | } | ||
562 | |||
563 | u64 of_translate_address(struct device_node *dev, const u32 *in_addr) | ||
564 | { | ||
565 | return __of_translate_address(dev, in_addr, "ranges"); | ||
566 | } | ||
567 | EXPORT_SYMBOL(of_translate_address); | ||
568 | |||
569 | u64 of_translate_dma_address(struct device_node *dev, const u32 *in_addr) | ||
570 | { | ||
571 | return __of_translate_address(dev, in_addr, "dma-ranges"); | ||
572 | } | ||
573 | EXPORT_SYMBOL(of_translate_dma_address); | ||
574 | |||
575 | const u32 *of_get_address(struct device_node *dev, int index, u64 *size, | ||
576 | unsigned int *flags) | ||
577 | { | ||
578 | const u32 *prop; | ||
579 | unsigned int psize; | ||
580 | struct device_node *parent; | ||
581 | struct of_bus *bus; | ||
582 | int onesize, i, na, ns; | ||
583 | |||
584 | /* Get parent & match bus type */ | ||
585 | parent = of_get_parent(dev); | ||
586 | if (parent == NULL) | ||
587 | return NULL; | ||
588 | bus = of_match_bus(parent); | ||
589 | bus->count_cells(dev, &na, &ns); | ||
590 | of_node_put(parent); | ||
591 | if (!OF_CHECK_COUNTS(na, ns)) | ||
592 | return NULL; | ||
593 | |||
594 | /* Get "reg" or "assigned-addresses" property */ | ||
595 | prop = of_get_property(dev, bus->addresses, &psize); | ||
596 | if (prop == NULL) | ||
597 | return NULL; | ||
598 | psize /= 4; | ||
599 | |||
600 | onesize = na + ns; | ||
601 | for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) | ||
602 | if (i == index) { | ||
603 | if (size) | ||
604 | *size = of_read_number(prop + na, ns); | ||
605 | if (flags) | ||
606 | *flags = bus->get_flags(prop); | ||
607 | return prop; | ||
608 | } | ||
609 | return NULL; | ||
610 | } | ||
611 | EXPORT_SYMBOL(of_get_address); | ||
612 | |||
613 | static int __of_address_to_resource(struct device_node *dev, const u32 *addrp, | ||
614 | u64 size, unsigned int flags, | ||
615 | struct resource *r) | ||
616 | { | ||
617 | u64 taddr; | ||
618 | |||
619 | if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0) | ||
620 | return -EINVAL; | ||
621 | taddr = of_translate_address(dev, addrp); | ||
622 | if (taddr == OF_BAD_ADDR) | ||
623 | return -EINVAL; | ||
624 | memset(r, 0, sizeof(struct resource)); | ||
625 | if (flags & IORESOURCE_IO) { | ||
626 | unsigned long port; | ||
627 | port = pci_address_to_pio(taddr); | ||
628 | if (port == (unsigned long)-1) | ||
629 | return -EINVAL; | ||
630 | r->start = port; | ||
631 | r->end = port + size - 1; | ||
632 | } else { | ||
633 | r->start = taddr; | ||
634 | r->end = taddr + size - 1; | ||
635 | } | ||
636 | r->flags = flags; | ||
637 | r->name = dev->name; | ||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | int of_address_to_resource(struct device_node *dev, int index, | ||
642 | struct resource *r) | ||
643 | { | ||
644 | const u32 *addrp; | ||
645 | u64 size; | ||
646 | unsigned int flags; | ||
647 | |||
648 | addrp = of_get_address(dev, index, &size, &flags); | ||
649 | if (addrp == NULL) | ||
650 | return -EINVAL; | ||
651 | return __of_address_to_resource(dev, addrp, size, flags, r); | ||
652 | } | ||
653 | EXPORT_SYMBOL_GPL(of_address_to_resource); | ||
654 | |||
655 | void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, | 95 | void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, |
656 | unsigned long *busno, unsigned long *phys, unsigned long *size) | 96 | unsigned long *busno, unsigned long *phys, unsigned long *size) |
657 | { | 97 | { |
@@ -678,342 +118,6 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, | |||
678 | *size = of_read_number(dma_window, cells); | 118 | *size = of_read_number(dma_window, cells); |
679 | } | 119 | } |
680 | 120 | ||
681 | /* | ||
682 | * Interrupt remapper | ||
683 | */ | ||
684 | |||
685 | static unsigned int of_irq_workarounds; | ||
686 | static struct device_node *of_irq_dflt_pic; | ||
687 | |||
688 | static struct device_node *of_irq_find_parent(struct device_node *child) | ||
689 | { | ||
690 | struct device_node *p; | ||
691 | const phandle *parp; | ||
692 | |||
693 | if (!of_node_get(child)) | ||
694 | return NULL; | ||
695 | |||
696 | do { | ||
697 | parp = of_get_property(child, "interrupt-parent", NULL); | ||
698 | if (parp == NULL) | ||
699 | p = of_get_parent(child); | ||
700 | else { | ||
701 | if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) | ||
702 | p = of_node_get(of_irq_dflt_pic); | ||
703 | else | ||
704 | p = of_find_node_by_phandle(*parp); | ||
705 | } | ||
706 | of_node_put(child); | ||
707 | child = p; | ||
708 | } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL); | ||
709 | |||
710 | return p; | ||
711 | } | ||
712 | |||
713 | /* This doesn't need to be called if you don't have any special workaround | ||
714 | * flags to pass | ||
715 | */ | ||
716 | void of_irq_map_init(unsigned int flags) | ||
717 | { | ||
718 | of_irq_workarounds = flags; | ||
719 | |||
720 | /* OldWorld, don't bother looking at other things */ | ||
721 | if (flags & OF_IMAP_OLDWORLD_MAC) | ||
722 | return; | ||
723 | |||
724 | /* If we don't have phandles, let's try to locate a default interrupt | ||
725 | * controller (happens when booting with BootX). We do a first match | ||
726 | * here, hopefully, that only ever happens on machines with one | ||
727 | * controller. | ||
728 | */ | ||
729 | if (flags & OF_IMAP_NO_PHANDLE) { | ||
730 | struct device_node *np; | ||
731 | |||
732 | for_each_node_with_property(np, "interrupt-controller") { | ||
733 | /* Skip /chosen/interrupt-controller */ | ||
734 | if (strcmp(np->name, "chosen") == 0) | ||
735 | continue; | ||
736 | /* It seems like at least one person on this planet wants | ||
737 | * to use BootX on a machine with an AppleKiwi controller | ||
738 | * which happens to pretend to be an interrupt | ||
739 | * controller too. | ||
740 | */ | ||
741 | if (strcmp(np->name, "AppleKiwi") == 0) | ||
742 | continue; | ||
743 | /* I think we found one ! */ | ||
744 | of_irq_dflt_pic = np; | ||
745 | break; | ||
746 | } | ||
747 | } | ||
748 | |||
749 | } | ||
750 | |||
751 | int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, | ||
752 | const u32 *addr, struct of_irq *out_irq) | ||
753 | { | ||
754 | struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; | ||
755 | const u32 *tmp, *imap, *imask; | ||
756 | u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; | ||
757 | int imaplen, match, i; | ||
758 | |||
759 | DBG("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n", | ||
760 | parent->full_name, intspec[0], intspec[1], ointsize); | ||
761 | |||
762 | ipar = of_node_get(parent); | ||
763 | |||
764 | /* First get the #interrupt-cells property of the current cursor | ||
765 | * that tells us how to interpret the passed-in intspec. If there | ||
766 | * is none, we are nice and just walk up the tree | ||
767 | */ | ||
768 | do { | ||
769 | tmp = of_get_property(ipar, "#interrupt-cells", NULL); | ||
770 | if (tmp != NULL) { | ||
771 | intsize = *tmp; | ||
772 | break; | ||
773 | } | ||
774 | tnode = ipar; | ||
775 | ipar = of_irq_find_parent(ipar); | ||
776 | of_node_put(tnode); | ||
777 | } while (ipar); | ||
778 | if (ipar == NULL) { | ||
779 | DBG(" -> no parent found !\n"); | ||
780 | goto fail; | ||
781 | } | ||
782 | |||
783 | DBG("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize); | ||
784 | |||
785 | if (ointsize != intsize) | ||
786 | return -EINVAL; | ||
787 | |||
788 | /* Look for this #address-cells. We have to implement the old linux | ||
789 | * trick of looking for the parent here as some device-trees rely on it | ||
790 | */ | ||
791 | old = of_node_get(ipar); | ||
792 | do { | ||
793 | tmp = of_get_property(old, "#address-cells", NULL); | ||
794 | tnode = of_get_parent(old); | ||
795 | of_node_put(old); | ||
796 | old = tnode; | ||
797 | } while(old && tmp == NULL); | ||
798 | of_node_put(old); | ||
799 | old = NULL; | ||
800 | addrsize = (tmp == NULL) ? 2 : *tmp; | ||
801 | |||
802 | DBG(" -> addrsize=%d\n", addrsize); | ||
803 | |||
804 | /* Now start the actual "proper" walk of the interrupt tree */ | ||
805 | while (ipar != NULL) { | ||
806 | /* Now check if cursor is an interrupt-controller and if it is | ||
807 | * then we are done | ||
808 | */ | ||
809 | if (of_get_property(ipar, "interrupt-controller", NULL) != | ||
810 | NULL) { | ||
811 | DBG(" -> got it !\n"); | ||
812 | memcpy(out_irq->specifier, intspec, | ||
813 | intsize * sizeof(u32)); | ||
814 | out_irq->size = intsize; | ||
815 | out_irq->controller = ipar; | ||
816 | of_node_put(old); | ||
817 | return 0; | ||
818 | } | ||
819 | |||
820 | /* Now look for an interrupt-map */ | ||
821 | imap = of_get_property(ipar, "interrupt-map", &imaplen); | ||
822 | /* No interrupt map, check for an interrupt parent */ | ||
823 | if (imap == NULL) { | ||
824 | DBG(" -> no map, getting parent\n"); | ||
825 | newpar = of_irq_find_parent(ipar); | ||
826 | goto skiplevel; | ||
827 | } | ||
828 | imaplen /= sizeof(u32); | ||
829 | |||
830 | /* Look for a mask */ | ||
831 | imask = of_get_property(ipar, "interrupt-map-mask", NULL); | ||
832 | |||
833 | /* If we were passed no "reg" property and we attempt to parse | ||
834 | * an interrupt-map, then #address-cells must be 0. | ||
835 | * Fail if it's not. | ||
836 | */ | ||
837 | if (addr == NULL && addrsize != 0) { | ||
838 | DBG(" -> no reg passed in when needed !\n"); | ||
839 | goto fail; | ||
840 | } | ||
841 | |||
842 | /* Parse interrupt-map */ | ||
843 | match = 0; | ||
844 | while (imaplen > (addrsize + intsize + 1) && !match) { | ||
845 | /* Compare specifiers */ | ||
846 | match = 1; | ||
847 | for (i = 0; i < addrsize && match; ++i) { | ||
848 | u32 mask = imask ? imask[i] : 0xffffffffu; | ||
849 | match = ((addr[i] ^ imap[i]) & mask) == 0; | ||
850 | } | ||
851 | for (; i < (addrsize + intsize) && match; ++i) { | ||
852 | u32 mask = imask ? imask[i] : 0xffffffffu; | ||
853 | match = | ||
854 | ((intspec[i-addrsize] ^ imap[i]) & mask) == 0; | ||
855 | } | ||
856 | imap += addrsize + intsize; | ||
857 | imaplen -= addrsize + intsize; | ||
858 | |||
859 | DBG(" -> match=%d (imaplen=%d)\n", match, imaplen); | ||
860 | |||
861 | /* Get the interrupt parent */ | ||
862 | if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) | ||
863 | newpar = of_node_get(of_irq_dflt_pic); | ||
864 | else | ||
865 | newpar = of_find_node_by_phandle((phandle)*imap); | ||
866 | imap++; | ||
867 | --imaplen; | ||
868 | |||
869 | /* Check if not found */ | ||
870 | if (newpar == NULL) { | ||
871 | DBG(" -> imap parent not found !\n"); | ||
872 | goto fail; | ||
873 | } | ||
874 | |||
875 | /* Get #interrupt-cells and #address-cells of new | ||
876 | * parent | ||
877 | */ | ||
878 | tmp = of_get_property(newpar, "#interrupt-cells", NULL); | ||
879 | if (tmp == NULL) { | ||
880 | DBG(" -> parent lacks #interrupt-cells !\n"); | ||
881 | goto fail; | ||
882 | } | ||
883 | newintsize = *tmp; | ||
884 | tmp = of_get_property(newpar, "#address-cells", NULL); | ||
885 | newaddrsize = (tmp == NULL) ? 0 : *tmp; | ||
886 | |||
887 | DBG(" -> newintsize=%d, newaddrsize=%d\n", | ||
888 | newintsize, newaddrsize); | ||
889 | |||
890 | /* Check for malformed properties */ | ||
891 | if (imaplen < (newaddrsize + newintsize)) | ||
892 | goto fail; | ||
893 | |||
894 | imap += newaddrsize + newintsize; | ||
895 | imaplen -= newaddrsize + newintsize; | ||
896 | |||
897 | DBG(" -> imaplen=%d\n", imaplen); | ||
898 | } | ||
899 | if (!match) | ||
900 | goto fail; | ||
901 | |||
902 | of_node_put(old); | ||
903 | old = of_node_get(newpar); | ||
904 | addrsize = newaddrsize; | ||
905 | intsize = newintsize; | ||
906 | intspec = imap - intsize; | ||
907 | addr = intspec - addrsize; | ||
908 | |||
909 | skiplevel: | ||
910 | /* Iterate again with new parent */ | ||
911 | DBG(" -> new parent: %s\n", newpar ? newpar->full_name : "<>"); | ||
912 | of_node_put(ipar); | ||
913 | ipar = newpar; | ||
914 | newpar = NULL; | ||
915 | } | ||
916 | fail: | ||
917 | of_node_put(ipar); | ||
918 | of_node_put(old); | ||
919 | of_node_put(newpar); | ||
920 | |||
921 | return -EINVAL; | ||
922 | } | ||
923 | EXPORT_SYMBOL_GPL(of_irq_map_raw); | ||
924 | |||
925 | #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) | ||
926 | static int of_irq_map_oldworld(struct device_node *device, int index, | ||
927 | struct of_irq *out_irq) | ||
928 | { | ||
929 | const u32 *ints = NULL; | ||
930 | int intlen; | ||
931 | |||
932 | /* | ||
933 | * Old machines just have a list of interrupt numbers | ||
934 | * and no interrupt-controller nodes. We also have dodgy | ||
935 | * cases where the APPL,interrupts property is completely | ||
936 | * missing behind pci-pci bridges and we have to get it | ||
937 | * from the parent (the bridge itself, as apple just wired | ||
938 | * everything together on these) | ||
939 | */ | ||
940 | while (device) { | ||
941 | ints = of_get_property(device, "AAPL,interrupts", &intlen); | ||
942 | if (ints != NULL) | ||
943 | break; | ||
944 | device = device->parent; | ||
945 | if (device && strcmp(device->type, "pci") != 0) | ||
946 | break; | ||
947 | } | ||
948 | if (ints == NULL) | ||
949 | return -EINVAL; | ||
950 | intlen /= sizeof(u32); | ||
951 | |||
952 | if (index >= intlen) | ||
953 | return -EINVAL; | ||
954 | |||
955 | out_irq->controller = NULL; | ||
956 | out_irq->specifier[0] = ints[index]; | ||
957 | out_irq->size = 1; | ||
958 | |||
959 | return 0; | ||
960 | } | ||
961 | #else /* defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) */ | ||
962 | static int of_irq_map_oldworld(struct device_node *device, int index, | ||
963 | struct of_irq *out_irq) | ||
964 | { | ||
965 | return -EINVAL; | ||
966 | } | ||
967 | #endif /* !(defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)) */ | ||
968 | |||
969 | int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq) | ||
970 | { | ||
971 | struct device_node *p; | ||
972 | const u32 *intspec, *tmp, *addr; | ||
973 | u32 intsize, intlen; | ||
974 | int res = -EINVAL; | ||
975 | |||
976 | DBG("of_irq_map_one: dev=%s, index=%d\n", device->full_name, index); | ||
977 | |||
978 | /* OldWorld mac stuff is "special", handle out of line */ | ||
979 | if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC) | ||
980 | return of_irq_map_oldworld(device, index, out_irq); | ||
981 | |||
982 | /* Get the interrupts property */ | ||
983 | intspec = of_get_property(device, "interrupts", &intlen); | ||
984 | if (intspec == NULL) | ||
985 | return -EINVAL; | ||
986 | intlen /= sizeof(u32); | ||
987 | |||
988 | /* Get the reg property (if any) */ | ||
989 | addr = of_get_property(device, "reg", NULL); | ||
990 | |||
991 | /* Look for the interrupt parent. */ | ||
992 | p = of_irq_find_parent(device); | ||
993 | if (p == NULL) | ||
994 | return -EINVAL; | ||
995 | |||
996 | /* Get size of interrupt specifier */ | ||
997 | tmp = of_get_property(p, "#interrupt-cells", NULL); | ||
998 | if (tmp == NULL) | ||
999 | goto out; | ||
1000 | intsize = *tmp; | ||
1001 | |||
1002 | DBG(" intsize=%d intlen=%d\n", intsize, intlen); | ||
1003 | |||
1004 | /* Check index */ | ||
1005 | if ((index + 1) * intsize > intlen) | ||
1006 | goto out; | ||
1007 | |||
1008 | /* Get new specifier and map it */ | ||
1009 | res = of_irq_map_raw(p, intspec + index * intsize, intsize, | ||
1010 | addr, out_irq); | ||
1011 | out: | ||
1012 | of_node_put(p); | ||
1013 | return res; | ||
1014 | } | ||
1015 | EXPORT_SYMBOL_GPL(of_irq_map_one); | ||
1016 | |||
1017 | /** | 121 | /** |
1018 | * Search the device tree for the best MAC address to use. 'mac-address' is | 122 | * Search the device tree for the best MAC address to use. 'mac-address' is |
1019 | * checked first, because that is supposed to contain to "most recent" MAC | 123 | * checked first, because that is supposed to contain to "most recent" MAC |
@@ -1051,29 +155,3 @@ const void *of_get_mac_address(struct device_node *np) | |||
1051 | return NULL; | 155 | return NULL; |
1052 | } | 156 | } |
1053 | EXPORT_SYMBOL(of_get_mac_address); | 157 | EXPORT_SYMBOL(of_get_mac_address); |
1054 | |||
1055 | int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) | ||
1056 | { | ||
1057 | int irq = irq_of_parse_and_map(dev, index); | ||
1058 | |||
1059 | /* Only dereference the resource if both the | ||
1060 | * resource and the irq are valid. */ | ||
1061 | if (r && irq != NO_IRQ) { | ||
1062 | r->start = r->end = irq; | ||
1063 | r->flags = IORESOURCE_IRQ; | ||
1064 | } | ||
1065 | |||
1066 | return irq; | ||
1067 | } | ||
1068 | EXPORT_SYMBOL_GPL(of_irq_to_resource); | ||
1069 | |||
1070 | void __iomem *of_iomap(struct device_node *np, int index) | ||
1071 | { | ||
1072 | struct resource res; | ||
1073 | |||
1074 | if (of_address_to_resource(np, index, &res)) | ||
1075 | return NULL; | ||
1076 | |||
1077 | return ioremap(res.start, 1 + res.end - res.start); | ||
1078 | } | ||
1079 | EXPORT_SYMBOL(of_iomap); | ||
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 7a0c0199ea28..11f3cd9c832f 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #ifdef CONFIG_PPC32 | 32 | #ifdef CONFIG_PPC32 |
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #endif | 34 | #endif |
35 | #include <linux/hw_breakpoint.h> | ||
36 | #include <linux/perf_event.h> | ||
35 | 37 | ||
36 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
37 | #include <asm/page.h> | 39 | #include <asm/page.h> |
@@ -866,9 +868,34 @@ void user_disable_single_step(struct task_struct *task) | |||
866 | clear_tsk_thread_flag(task, TIF_SINGLESTEP); | 868 | clear_tsk_thread_flag(task, TIF_SINGLESTEP); |
867 | } | 869 | } |
868 | 870 | ||
871 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
872 | void ptrace_triggered(struct perf_event *bp, int nmi, | ||
873 | struct perf_sample_data *data, struct pt_regs *regs) | ||
874 | { | ||
875 | struct perf_event_attr attr; | ||
876 | |||
877 | /* | ||
878 | * Disable the breakpoint request here since ptrace has defined a | ||
879 | * one-shot behaviour for breakpoint exceptions in PPC64. | ||
880 | * The SIGTRAP signal is generated automatically for us in do_dabr(). | ||
881 | * We don't have to do anything about that here | ||
882 | */ | ||
883 | attr = bp->attr; | ||
884 | attr.disabled = true; | ||
885 | modify_user_hw_breakpoint(bp, &attr); | ||
886 | } | ||
887 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
888 | |||
869 | int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | 889 | int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, |
870 | unsigned long data) | 890 | unsigned long data) |
871 | { | 891 | { |
892 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
893 | int ret; | ||
894 | struct thread_struct *thread = &(task->thread); | ||
895 | struct perf_event *bp; | ||
896 | struct perf_event_attr attr; | ||
897 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
898 | |||
872 | /* For ppc64 we support one DABR and no IABR's at the moment (ppc64). | 899 | /* For ppc64 we support one DABR and no IABR's at the moment (ppc64). |
873 | * For embedded processors we support one DAC and no IAC's at the | 900 | * For embedded processors we support one DAC and no IAC's at the |
874 | * moment. | 901 | * moment. |
@@ -896,6 +923,43 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | |||
896 | /* Ensure breakpoint translation bit is set */ | 923 | /* Ensure breakpoint translation bit is set */ |
897 | if (data && !(data & DABR_TRANSLATION)) | 924 | if (data && !(data & DABR_TRANSLATION)) |
898 | return -EIO; | 925 | return -EIO; |
926 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | ||
927 | bp = thread->ptrace_bps[0]; | ||
928 | if ((!data) || !(data & (DABR_DATA_WRITE | DABR_DATA_READ))) { | ||
929 | if (bp) { | ||
930 | unregister_hw_breakpoint(bp); | ||
931 | thread->ptrace_bps[0] = NULL; | ||
932 | } | ||
933 | return 0; | ||
934 | } | ||
935 | if (bp) { | ||
936 | attr = bp->attr; | ||
937 | attr.bp_addr = data & ~HW_BREAKPOINT_ALIGN; | ||
938 | arch_bp_generic_fields(data & | ||
939 | (DABR_DATA_WRITE | DABR_DATA_READ), | ||
940 | &attr.bp_type); | ||
941 | ret = modify_user_hw_breakpoint(bp, &attr); | ||
942 | if (ret) | ||
943 | return ret; | ||
944 | thread->ptrace_bps[0] = bp; | ||
945 | thread->dabr = data; | ||
946 | return 0; | ||
947 | } | ||
948 | |||
949 | /* Create a new breakpoint request if one doesn't exist already */ | ||
950 | hw_breakpoint_init(&attr); | ||
951 | attr.bp_addr = data & ~HW_BREAKPOINT_ALIGN; | ||
952 | arch_bp_generic_fields(data & (DABR_DATA_WRITE | DABR_DATA_READ), | ||
953 | &attr.bp_type); | ||
954 | |||
955 | thread->ptrace_bps[0] = bp = register_user_hw_breakpoint(&attr, | ||
956 | ptrace_triggered, task); | ||
957 | if (IS_ERR(bp)) { | ||
958 | thread->ptrace_bps[0] = NULL; | ||
959 | return PTR_ERR(bp); | ||
960 | } | ||
961 | |||
962 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | ||
899 | 963 | ||
900 | /* Move contents to the DABR register */ | 964 | /* Move contents to the DABR register */ |
901 | task->thread.dabr = data; | 965 | task->thread.dabr = data; |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index d0516dbee762..41048de3c6c3 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -47,14 +47,6 @@ struct rtas_t rtas = { | |||
47 | }; | 47 | }; |
48 | EXPORT_SYMBOL(rtas); | 48 | EXPORT_SYMBOL(rtas); |
49 | 49 | ||
50 | struct rtas_suspend_me_data { | ||
51 | atomic_t working; /* number of cpus accessing this struct */ | ||
52 | atomic_t done; | ||
53 | int token; /* ibm,suspend-me */ | ||
54 | int error; | ||
55 | struct completion *complete; /* wait on this until working == 0 */ | ||
56 | }; | ||
57 | |||
58 | DEFINE_SPINLOCK(rtas_data_buf_lock); | 50 | DEFINE_SPINLOCK(rtas_data_buf_lock); |
59 | EXPORT_SYMBOL(rtas_data_buf_lock); | 51 | EXPORT_SYMBOL(rtas_data_buf_lock); |
60 | 52 | ||
@@ -714,14 +706,53 @@ void rtas_os_term(char *str) | |||
714 | 706 | ||
715 | static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; | 707 | static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; |
716 | #ifdef CONFIG_PPC_PSERIES | 708 | #ifdef CONFIG_PPC_PSERIES |
717 | static void rtas_percpu_suspend_me(void *info) | 709 | static int __rtas_suspend_last_cpu(struct rtas_suspend_me_data *data, int wake_when_done) |
710 | { | ||
711 | u16 slb_size = mmu_slb_size; | ||
712 | int rc = H_MULTI_THREADS_ACTIVE; | ||
713 | int cpu; | ||
714 | |||
715 | slb_set_size(SLB_MIN_SIZE); | ||
716 | printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", smp_processor_id()); | ||
717 | |||
718 | while (rc == H_MULTI_THREADS_ACTIVE && !atomic_read(&data->done) && | ||
719 | !atomic_read(&data->error)) | ||
720 | rc = rtas_call(data->token, 0, 1, NULL); | ||
721 | |||
722 | if (rc || atomic_read(&data->error)) { | ||
723 | printk(KERN_DEBUG "ibm,suspend-me returned %d\n", rc); | ||
724 | slb_set_size(slb_size); | ||
725 | } | ||
726 | |||
727 | if (atomic_read(&data->error)) | ||
728 | rc = atomic_read(&data->error); | ||
729 | |||
730 | atomic_set(&data->error, rc); | ||
731 | |||
732 | if (wake_when_done) { | ||
733 | atomic_set(&data->done, 1); | ||
734 | |||
735 | for_each_online_cpu(cpu) | ||
736 | plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(cpu)); | ||
737 | } | ||
738 | |||
739 | if (atomic_dec_return(&data->working) == 0) | ||
740 | complete(data->complete); | ||
741 | |||
742 | return rc; | ||
743 | } | ||
744 | |||
745 | int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data) | ||
746 | { | ||
747 | atomic_inc(&data->working); | ||
748 | return __rtas_suspend_last_cpu(data, 0); | ||
749 | } | ||
750 | |||
751 | static int __rtas_suspend_cpu(struct rtas_suspend_me_data *data, int wake_when_done) | ||
718 | { | 752 | { |
719 | long rc = H_SUCCESS; | 753 | long rc = H_SUCCESS; |
720 | unsigned long msr_save; | 754 | unsigned long msr_save; |
721 | u16 slb_size = mmu_slb_size; | ||
722 | int cpu; | 755 | int cpu; |
723 | struct rtas_suspend_me_data *data = | ||
724 | (struct rtas_suspend_me_data *)info; | ||
725 | 756 | ||
726 | atomic_inc(&data->working); | 757 | atomic_inc(&data->working); |
727 | 758 | ||
@@ -729,7 +760,7 @@ static void rtas_percpu_suspend_me(void *info) | |||
729 | msr_save = mfmsr(); | 760 | msr_save = mfmsr(); |
730 | mtmsr(msr_save & ~(MSR_EE)); | 761 | mtmsr(msr_save & ~(MSR_EE)); |
731 | 762 | ||
732 | while (rc == H_SUCCESS && !atomic_read(&data->done)) | 763 | while (rc == H_SUCCESS && !atomic_read(&data->done) && !atomic_read(&data->error)) |
733 | rc = plpar_hcall_norets(H_JOIN); | 764 | rc = plpar_hcall_norets(H_JOIN); |
734 | 765 | ||
735 | mtmsr(msr_save); | 766 | mtmsr(msr_save); |
@@ -741,33 +772,37 @@ static void rtas_percpu_suspend_me(void *info) | |||
741 | /* All other cpus are in H_JOIN, this cpu does | 772 | /* All other cpus are in H_JOIN, this cpu does |
742 | * the suspend. | 773 | * the suspend. |
743 | */ | 774 | */ |
744 | slb_set_size(SLB_MIN_SIZE); | 775 | return __rtas_suspend_last_cpu(data, wake_when_done); |
745 | printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", | ||
746 | smp_processor_id()); | ||
747 | data->error = rtas_call(data->token, 0, 1, NULL); | ||
748 | |||
749 | if (data->error) { | ||
750 | printk(KERN_DEBUG "ibm,suspend-me returned %d\n", | ||
751 | data->error); | ||
752 | slb_set_size(slb_size); | ||
753 | } | ||
754 | } else { | 776 | } else { |
755 | printk(KERN_ERR "H_JOIN on cpu %i failed with rc = %ld\n", | 777 | printk(KERN_ERR "H_JOIN on cpu %i failed with rc = %ld\n", |
756 | smp_processor_id(), rc); | 778 | smp_processor_id(), rc); |
757 | data->error = rc; | 779 | atomic_set(&data->error, rc); |
758 | } | 780 | } |
759 | 781 | ||
760 | atomic_set(&data->done, 1); | 782 | if (wake_when_done) { |
783 | atomic_set(&data->done, 1); | ||
761 | 784 | ||
762 | /* This cpu did the suspend or got an error; in either case, | 785 | /* This cpu did the suspend or got an error; in either case, |
763 | * we need to prod all other other cpus out of join state. | 786 | * we need to prod all other other cpus out of join state. |
764 | * Extra prods are harmless. | 787 | * Extra prods are harmless. |
765 | */ | 788 | */ |
766 | for_each_online_cpu(cpu) | 789 | for_each_online_cpu(cpu) |
767 | plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(cpu)); | 790 | plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(cpu)); |
791 | } | ||
768 | out: | 792 | out: |
769 | if (atomic_dec_return(&data->working) == 0) | 793 | if (atomic_dec_return(&data->working) == 0) |
770 | complete(data->complete); | 794 | complete(data->complete); |
795 | return rc; | ||
796 | } | ||
797 | |||
798 | int rtas_suspend_cpu(struct rtas_suspend_me_data *data) | ||
799 | { | ||
800 | return __rtas_suspend_cpu(data, 0); | ||
801 | } | ||
802 | |||
803 | static void rtas_percpu_suspend_me(void *info) | ||
804 | { | ||
805 | __rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1); | ||
771 | } | 806 | } |
772 | 807 | ||
773 | static int rtas_ibm_suspend_me(struct rtas_args *args) | 808 | static int rtas_ibm_suspend_me(struct rtas_args *args) |
@@ -802,22 +837,22 @@ static int rtas_ibm_suspend_me(struct rtas_args *args) | |||
802 | 837 | ||
803 | atomic_set(&data.working, 0); | 838 | atomic_set(&data.working, 0); |
804 | atomic_set(&data.done, 0); | 839 | atomic_set(&data.done, 0); |
840 | atomic_set(&data.error, 0); | ||
805 | data.token = rtas_token("ibm,suspend-me"); | 841 | data.token = rtas_token("ibm,suspend-me"); |
806 | data.error = 0; | ||
807 | data.complete = &done; | 842 | data.complete = &done; |
808 | 843 | ||
809 | /* Call function on all CPUs. One of us will make the | 844 | /* Call function on all CPUs. One of us will make the |
810 | * rtas call | 845 | * rtas call |
811 | */ | 846 | */ |
812 | if (on_each_cpu(rtas_percpu_suspend_me, &data, 0)) | 847 | if (on_each_cpu(rtas_percpu_suspend_me, &data, 0)) |
813 | data.error = -EINVAL; | 848 | atomic_set(&data.error, -EINVAL); |
814 | 849 | ||
815 | wait_for_completion(&done); | 850 | wait_for_completion(&done); |
816 | 851 | ||
817 | if (data.error != 0) | 852 | if (atomic_read(&data.error) != 0) |
818 | printk(KERN_ERR "Error doing global join\n"); | 853 | printk(KERN_ERR "Error doing global join\n"); |
819 | 854 | ||
820 | return data.error; | 855 | return atomic_read(&data.error); |
821 | } | 856 | } |
822 | #else /* CONFIG_PPC_PSERIES */ | 857 | #else /* CONFIG_PPC_PSERIES */ |
823 | static int rtas_ibm_suspend_me(struct rtas_args *args) | 858 | static int rtas_ibm_suspend_me(struct rtas_args *args) |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index b7e6c7e193ae..15ade0d7bbb2 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -94,6 +94,10 @@ struct screen_info screen_info = { | |||
94 | .orig_video_points = 16 | 94 | .orig_video_points = 16 |
95 | }; | 95 | }; |
96 | 96 | ||
97 | /* Variables required to store legacy IO irq routing */ | ||
98 | int of_i8042_kbd_irq; | ||
99 | int of_i8042_aux_irq; | ||
100 | |||
97 | #ifdef __DO_IRQ_CANON | 101 | #ifdef __DO_IRQ_CANON |
98 | /* XXX should go elsewhere eventually */ | 102 | /* XXX should go elsewhere eventually */ |
99 | int ppc_do_canonicalize_irqs; | 103 | int ppc_do_canonicalize_irqs; |
@@ -575,6 +579,15 @@ int check_legacy_ioport(unsigned long base_port) | |||
575 | np = of_find_compatible_node(NULL, NULL, "pnpPNP,f03"); | 579 | np = of_find_compatible_node(NULL, NULL, "pnpPNP,f03"); |
576 | if (np) { | 580 | if (np) { |
577 | parent = of_get_parent(np); | 581 | parent = of_get_parent(np); |
582 | |||
583 | of_i8042_kbd_irq = irq_of_parse_and_map(parent, 0); | ||
584 | if (!of_i8042_kbd_irq) | ||
585 | of_i8042_kbd_irq = 1; | ||
586 | |||
587 | of_i8042_aux_irq = irq_of_parse_and_map(parent, 1); | ||
588 | if (!of_i8042_aux_irq) | ||
589 | of_i8042_aux_irq = 12; | ||
590 | |||
578 | of_node_put(np); | 591 | of_node_put(np); |
579 | np = parent; | 592 | np = parent; |
580 | break; | 593 | break; |
@@ -701,16 +714,9 @@ static struct notifier_block ppc_dflt_plat_bus_notifier = { | |||
701 | .priority = INT_MAX, | 714 | .priority = INT_MAX, |
702 | }; | 715 | }; |
703 | 716 | ||
704 | static struct notifier_block ppc_dflt_of_bus_notifier = { | ||
705 | .notifier_call = ppc_dflt_bus_notify, | ||
706 | .priority = INT_MAX, | ||
707 | }; | ||
708 | |||
709 | static int __init setup_bus_notifier(void) | 717 | static int __init setup_bus_notifier(void) |
710 | { | 718 | { |
711 | bus_register_notifier(&platform_bus_type, &ppc_dflt_plat_bus_notifier); | 719 | bus_register_notifier(&platform_bus_type, &ppc_dflt_plat_bus_notifier); |
712 | bus_register_notifier(&of_platform_bus_type, &ppc_dflt_of_bus_notifier); | ||
713 | |||
714 | return 0; | 720 | return 0; |
715 | } | 721 | } |
716 | 722 | ||
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index d135f93cb0f6..1bee4b68fa45 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -142,16 +142,6 @@ early_param("smt-enabled", early_smt_enabled); | |||
142 | #define check_smt_enabled() | 142 | #define check_smt_enabled() |
143 | #endif /* CONFIG_SMP */ | 143 | #endif /* CONFIG_SMP */ |
144 | 144 | ||
145 | /* Put the paca pointer into r13 and SPRG_PACA */ | ||
146 | static void __init setup_paca(struct paca_struct *new_paca) | ||
147 | { | ||
148 | local_paca = new_paca; | ||
149 | mtspr(SPRN_SPRG_PACA, local_paca); | ||
150 | #ifdef CONFIG_PPC_BOOK3E | ||
151 | mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb); | ||
152 | #endif | ||
153 | } | ||
154 | |||
155 | /* | 145 | /* |
156 | * Early initialization entry point. This is called by head.S | 146 | * Early initialization entry point. This is called by head.S |
157 | * with MMU translation disabled. We rely on the "feature" of | 147 | * with MMU translation disabled. We rely on the "feature" of |
@@ -600,6 +590,9 @@ static int pcpu_cpu_distance(unsigned int from, unsigned int to) | |||
600 | return REMOTE_DISTANCE; | 590 | return REMOTE_DISTANCE; |
601 | } | 591 | } |
602 | 592 | ||
593 | unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; | ||
594 | EXPORT_SYMBOL(__per_cpu_offset); | ||
595 | |||
603 | void __init setup_per_cpu_areas(void) | 596 | void __init setup_per_cpu_areas(void) |
604 | { | 597 | { |
605 | const size_t dyn_size = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE; | 598 | const size_t dyn_size = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE; |
@@ -624,8 +617,10 @@ void __init setup_per_cpu_areas(void) | |||
624 | panic("cannot initialize percpu area (err=%d)", rc); | 617 | panic("cannot initialize percpu area (err=%d)", rc); |
625 | 618 | ||
626 | delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start; | 619 | delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start; |
627 | for_each_possible_cpu(cpu) | 620 | for_each_possible_cpu(cpu) { |
628 | paca[cpu].data_offset = delta + pcpu_unit_offsets[cpu]; | 621 | __per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu]; |
622 | paca[cpu].data_offset = __per_cpu_offset[cpu]; | ||
623 | } | ||
629 | } | 624 | } |
630 | #endif | 625 | #endif |
631 | 626 | ||
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index a0afb555a7c9..7109f5b1baa8 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/tracehook.h> | 12 | #include <linux/tracehook.h> |
13 | #include <linux/signal.h> | 13 | #include <linux/signal.h> |
14 | #include <asm/hw_breakpoint.h> | ||
14 | #include <asm/uaccess.h> | 15 | #include <asm/uaccess.h> |
15 | #include <asm/unistd.h> | 16 | #include <asm/unistd.h> |
16 | 17 | ||
@@ -149,6 +150,8 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs) | |||
149 | if (current->thread.dabr) | 150 | if (current->thread.dabr) |
150 | set_dabr(current->thread.dabr); | 151 | set_dabr(current->thread.dabr); |
151 | #endif | 152 | #endif |
153 | /* Re-enable the breakpoints for the signal stack */ | ||
154 | thread_change_pc(current, regs); | ||
152 | 155 | ||
153 | if (is32) { | 156 | if (is32) { |
154 | if (ka.sa.sa_flags & SA_SIGINFO) | 157 | if (ka.sa.sa_flags & SA_SIGINFO) |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 5c196d1086d9..a61b3ddd7bb3 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -288,8 +288,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
288 | max_cpus = NR_CPUS; | 288 | max_cpus = NR_CPUS; |
289 | else | 289 | else |
290 | max_cpus = 1; | 290 | max_cpus = 1; |
291 | |||
292 | smp_space_timers(max_cpus); | ||
293 | 291 | ||
294 | for_each_possible_cpu(cpu) | 292 | for_each_possible_cpu(cpu) |
295 | if (cpu != boot_cpuid) | 293 | if (cpu != boot_cpuid) |
@@ -501,14 +499,6 @@ int __devinit start_secondary(void *unused) | |||
501 | current->active_mm = &init_mm; | 499 | current->active_mm = &init_mm; |
502 | 500 | ||
503 | smp_store_cpu_info(cpu); | 501 | smp_store_cpu_info(cpu); |
504 | |||
505 | #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) | ||
506 | /* Clear any pending timer interrupts */ | ||
507 | mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); | ||
508 | |||
509 | /* Enable decrementer interrupt */ | ||
510 | mtspr(SPRN_TCR, TCR_DIE); | ||
511 | #endif | ||
512 | set_dec(tb_ticks_per_jiffy); | 502 | set_dec(tb_ticks_per_jiffy); |
513 | preempt_disable(); | 503 | preempt_disable(); |
514 | cpu_callin_map[cpu] = 1; | 504 | cpu_callin_map[cpu] = 1; |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 0441bbdadbd1..ccb8759c8532 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -149,16 +149,6 @@ unsigned long tb_ticks_per_usec = 100; /* sane default */ | |||
149 | EXPORT_SYMBOL(tb_ticks_per_usec); | 149 | EXPORT_SYMBOL(tb_ticks_per_usec); |
150 | unsigned long tb_ticks_per_sec; | 150 | unsigned long tb_ticks_per_sec; |
151 | EXPORT_SYMBOL(tb_ticks_per_sec); /* for cputime_t conversions */ | 151 | EXPORT_SYMBOL(tb_ticks_per_sec); /* for cputime_t conversions */ |
152 | u64 tb_to_xs; | ||
153 | unsigned tb_to_us; | ||
154 | |||
155 | #define TICKLEN_SCALE NTP_SCALE_SHIFT | ||
156 | static u64 last_tick_len; /* units are ns / 2^TICKLEN_SCALE */ | ||
157 | static u64 ticklen_to_xs; /* 0.64 fraction */ | ||
158 | |||
159 | /* If last_tick_len corresponds to about 1/HZ seconds, then | ||
160 | last_tick_len << TICKLEN_SHIFT will be about 2^63. */ | ||
161 | #define TICKLEN_SHIFT (63 - 30 - TICKLEN_SCALE + SHIFT_HZ) | ||
162 | 152 | ||
163 | DEFINE_SPINLOCK(rtc_lock); | 153 | DEFINE_SPINLOCK(rtc_lock); |
164 | EXPORT_SYMBOL_GPL(rtc_lock); | 154 | EXPORT_SYMBOL_GPL(rtc_lock); |
@@ -174,7 +164,6 @@ unsigned long ppc_proc_freq; | |||
174 | EXPORT_SYMBOL(ppc_proc_freq); | 164 | EXPORT_SYMBOL(ppc_proc_freq); |
175 | unsigned long ppc_tb_freq; | 165 | unsigned long ppc_tb_freq; |
176 | 166 | ||
177 | static u64 tb_last_jiffy __cacheline_aligned_in_smp; | ||
178 | static DEFINE_PER_CPU(u64, last_jiffy); | 167 | static DEFINE_PER_CPU(u64, last_jiffy); |
179 | 168 | ||
180 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 169 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
@@ -423,30 +412,6 @@ void udelay(unsigned long usecs) | |||
423 | } | 412 | } |
424 | EXPORT_SYMBOL(udelay); | 413 | EXPORT_SYMBOL(udelay); |
425 | 414 | ||
426 | static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec, | ||
427 | u64 new_tb_to_xs) | ||
428 | { | ||
429 | /* | ||
430 | * tb_update_count is used to allow the userspace gettimeofday code | ||
431 | * to assure itself that it sees a consistent view of the tb_to_xs and | ||
432 | * stamp_xsec variables. It reads the tb_update_count, then reads | ||
433 | * tb_to_xs and stamp_xsec and then reads tb_update_count again. If | ||
434 | * the two values of tb_update_count match and are even then the | ||
435 | * tb_to_xs and stamp_xsec values are consistent. If not, then it | ||
436 | * loops back and reads them again until this criteria is met. | ||
437 | * We expect the caller to have done the first increment of | ||
438 | * vdso_data->tb_update_count already. | ||
439 | */ | ||
440 | vdso_data->tb_orig_stamp = new_tb_stamp; | ||
441 | vdso_data->stamp_xsec = new_stamp_xsec; | ||
442 | vdso_data->tb_to_xs = new_tb_to_xs; | ||
443 | vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec; | ||
444 | vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec; | ||
445 | vdso_data->stamp_xtime = xtime; | ||
446 | smp_wmb(); | ||
447 | ++(vdso_data->tb_update_count); | ||
448 | } | ||
449 | |||
450 | #ifdef CONFIG_SMP | 415 | #ifdef CONFIG_SMP |
451 | unsigned long profile_pc(struct pt_regs *regs) | 416 | unsigned long profile_pc(struct pt_regs *regs) |
452 | { | 417 | { |
@@ -470,7 +435,6 @@ EXPORT_SYMBOL(profile_pc); | |||
470 | 435 | ||
471 | static int __init iSeries_tb_recal(void) | 436 | static int __init iSeries_tb_recal(void) |
472 | { | 437 | { |
473 | struct div_result divres; | ||
474 | unsigned long titan, tb; | 438 | unsigned long titan, tb; |
475 | 439 | ||
476 | /* Make sure we only run on iSeries */ | 440 | /* Make sure we only run on iSeries */ |
@@ -501,10 +465,7 @@ static int __init iSeries_tb_recal(void) | |||
501 | tb_ticks_per_jiffy = new_tb_ticks_per_jiffy; | 465 | tb_ticks_per_jiffy = new_tb_ticks_per_jiffy; |
502 | tb_ticks_per_sec = new_tb_ticks_per_sec; | 466 | tb_ticks_per_sec = new_tb_ticks_per_sec; |
503 | calc_cputime_factors(); | 467 | calc_cputime_factors(); |
504 | div128_by_32( XSEC_PER_SEC, 0, tb_ticks_per_sec, &divres ); | ||
505 | tb_to_xs = divres.result_low; | ||
506 | vdso_data->tb_ticks_per_sec = tb_ticks_per_sec; | 468 | vdso_data->tb_ticks_per_sec = tb_ticks_per_sec; |
507 | vdso_data->tb_to_xs = tb_to_xs; | ||
508 | setup_cputime_one_jiffy(); | 469 | setup_cputime_one_jiffy(); |
509 | } | 470 | } |
510 | else { | 471 | else { |
@@ -667,27 +628,9 @@ void timer_interrupt(struct pt_regs * regs) | |||
667 | trace_timer_interrupt_exit(regs); | 628 | trace_timer_interrupt_exit(regs); |
668 | } | 629 | } |
669 | 630 | ||
670 | void wakeup_decrementer(void) | ||
671 | { | ||
672 | unsigned long ticks; | ||
673 | |||
674 | /* | ||
675 | * The timebase gets saved on sleep and restored on wakeup, | ||
676 | * so all we need to do is to reset the decrementer. | ||
677 | */ | ||
678 | ticks = tb_ticks_since(__get_cpu_var(last_jiffy)); | ||
679 | if (ticks < tb_ticks_per_jiffy) | ||
680 | ticks = tb_ticks_per_jiffy - ticks; | ||
681 | else | ||
682 | ticks = 1; | ||
683 | set_dec(ticks); | ||
684 | } | ||
685 | |||
686 | #ifdef CONFIG_SUSPEND | 631 | #ifdef CONFIG_SUSPEND |
687 | void generic_suspend_disable_irqs(void) | 632 | static void generic_suspend_disable_irqs(void) |
688 | { | 633 | { |
689 | preempt_disable(); | ||
690 | |||
691 | /* Disable the decrementer, so that it doesn't interfere | 634 | /* Disable the decrementer, so that it doesn't interfere |
692 | * with suspending. | 635 | * with suspending. |
693 | */ | 636 | */ |
@@ -697,12 +640,9 @@ void generic_suspend_disable_irqs(void) | |||
697 | set_dec(0x7fffffff); | 640 | set_dec(0x7fffffff); |
698 | } | 641 | } |
699 | 642 | ||
700 | void generic_suspend_enable_irqs(void) | 643 | static void generic_suspend_enable_irqs(void) |
701 | { | 644 | { |
702 | wakeup_decrementer(); | ||
703 | |||
704 | local_irq_enable(); | 645 | local_irq_enable(); |
705 | preempt_enable(); | ||
706 | } | 646 | } |
707 | 647 | ||
708 | /* Overrides the weak version in kernel/power/main.c */ | 648 | /* Overrides the weak version in kernel/power/main.c */ |
@@ -722,23 +662,6 @@ void arch_suspend_enable_irqs(void) | |||
722 | } | 662 | } |
723 | #endif | 663 | #endif |
724 | 664 | ||
725 | #ifdef CONFIG_SMP | ||
726 | void __init smp_space_timers(unsigned int max_cpus) | ||
727 | { | ||
728 | int i; | ||
729 | u64 previous_tb = per_cpu(last_jiffy, boot_cpuid); | ||
730 | |||
731 | /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */ | ||
732 | previous_tb -= tb_ticks_per_jiffy; | ||
733 | |||
734 | for_each_possible_cpu(i) { | ||
735 | if (i == boot_cpuid) | ||
736 | continue; | ||
737 | per_cpu(last_jiffy, i) = previous_tb; | ||
738 | } | ||
739 | } | ||
740 | #endif | ||
741 | |||
742 | /* | 665 | /* |
743 | * Scheduler clock - returns current time in nanosec units. | 666 | * Scheduler clock - returns current time in nanosec units. |
744 | * | 667 | * |
@@ -873,10 +796,37 @@ static cycle_t timebase_read(struct clocksource *cs) | |||
873 | return (cycle_t)get_tb(); | 796 | return (cycle_t)get_tb(); |
874 | } | 797 | } |
875 | 798 | ||
799 | static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec, | ||
800 | u64 new_tb_to_xs, struct timespec *now, | ||
801 | u32 frac_sec) | ||
802 | { | ||
803 | /* | ||
804 | * tb_update_count is used to allow the userspace gettimeofday code | ||
805 | * to assure itself that it sees a consistent view of the tb_to_xs and | ||
806 | * stamp_xsec variables. It reads the tb_update_count, then reads | ||
807 | * tb_to_xs and stamp_xsec and then reads tb_update_count again. If | ||
808 | * the two values of tb_update_count match and are even then the | ||
809 | * tb_to_xs and stamp_xsec values are consistent. If not, then it | ||
810 | * loops back and reads them again until this criteria is met. | ||
811 | * We expect the caller to have done the first increment of | ||
812 | * vdso_data->tb_update_count already. | ||
813 | */ | ||
814 | vdso_data->tb_orig_stamp = new_tb_stamp; | ||
815 | vdso_data->stamp_xsec = new_stamp_xsec; | ||
816 | vdso_data->tb_to_xs = new_tb_to_xs; | ||
817 | vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec; | ||
818 | vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec; | ||
819 | vdso_data->stamp_xtime = *now; | ||
820 | vdso_data->stamp_sec_fraction = frac_sec; | ||
821 | smp_wmb(); | ||
822 | ++(vdso_data->tb_update_count); | ||
823 | } | ||
824 | |||
876 | void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, | 825 | void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, |
877 | u32 mult) | 826 | u32 mult) |
878 | { | 827 | { |
879 | u64 t2x, stamp_xsec; | 828 | u64 t2x, stamp_xsec; |
829 | u32 frac_sec; | ||
880 | 830 | ||
881 | if (clock != &clocksource_timebase) | 831 | if (clock != &clocksource_timebase) |
882 | return; | 832 | return; |
@@ -888,10 +838,14 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, | |||
888 | /* XXX this assumes clock->shift == 22 */ | 838 | /* XXX this assumes clock->shift == 22 */ |
889 | /* 4611686018 ~= 2^(20+64-22) / 1e9 */ | 839 | /* 4611686018 ~= 2^(20+64-22) / 1e9 */ |
890 | t2x = (u64) mult * 4611686018ULL; | 840 | t2x = (u64) mult * 4611686018ULL; |
891 | stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC; | 841 | stamp_xsec = (u64) wall_time->tv_nsec * XSEC_PER_SEC; |
892 | do_div(stamp_xsec, 1000000000); | 842 | do_div(stamp_xsec, 1000000000); |
893 | stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC; | 843 | stamp_xsec += (u64) wall_time->tv_sec * XSEC_PER_SEC; |
894 | update_gtod(clock->cycle_last, stamp_xsec, t2x); | 844 | |
845 | BUG_ON(wall_time->tv_nsec >= NSEC_PER_SEC); | ||
846 | /* this is tv_nsec / 1e9 as a 0.32 fraction */ | ||
847 | frac_sec = ((u64) wall_time->tv_nsec * 18446744073ULL) >> 32; | ||
848 | update_gtod(clock->cycle_last, stamp_xsec, t2x, wall_time, frac_sec); | ||
895 | } | 849 | } |
896 | 850 | ||
897 | void update_vsyscall_tz(void) | 851 | void update_vsyscall_tz(void) |
@@ -1007,15 +961,13 @@ void secondary_cpu_time_init(void) | |||
1007 | /* This function is only called on the boot processor */ | 961 | /* This function is only called on the boot processor */ |
1008 | void __init time_init(void) | 962 | void __init time_init(void) |
1009 | { | 963 | { |
1010 | unsigned long flags; | ||
1011 | struct div_result res; | 964 | struct div_result res; |
1012 | u64 scale, x; | 965 | u64 scale; |
1013 | unsigned shift; | 966 | unsigned shift; |
1014 | 967 | ||
1015 | if (__USE_RTC()) { | 968 | if (__USE_RTC()) { |
1016 | /* 601 processor: dec counts down by 128 every 128ns */ | 969 | /* 601 processor: dec counts down by 128 every 128ns */ |
1017 | ppc_tb_freq = 1000000000; | 970 | ppc_tb_freq = 1000000000; |
1018 | tb_last_jiffy = get_rtcl(); | ||
1019 | } else { | 971 | } else { |
1020 | /* Normal PowerPC with timebase register */ | 972 | /* Normal PowerPC with timebase register */ |
1021 | ppc_md.calibrate_decr(); | 973 | ppc_md.calibrate_decr(); |
@@ -1023,50 +975,15 @@ void __init time_init(void) | |||
1023 | ppc_tb_freq / 1000000, ppc_tb_freq % 1000000); | 975 | ppc_tb_freq / 1000000, ppc_tb_freq % 1000000); |
1024 | printk(KERN_DEBUG "time_init: processor frequency = %lu.%.6lu MHz\n", | 976 | printk(KERN_DEBUG "time_init: processor frequency = %lu.%.6lu MHz\n", |
1025 | ppc_proc_freq / 1000000, ppc_proc_freq % 1000000); | 977 | ppc_proc_freq / 1000000, ppc_proc_freq % 1000000); |
1026 | tb_last_jiffy = get_tb(); | ||
1027 | } | 978 | } |
1028 | 979 | ||
1029 | tb_ticks_per_jiffy = ppc_tb_freq / HZ; | 980 | tb_ticks_per_jiffy = ppc_tb_freq / HZ; |
1030 | tb_ticks_per_sec = ppc_tb_freq; | 981 | tb_ticks_per_sec = ppc_tb_freq; |
1031 | tb_ticks_per_usec = ppc_tb_freq / 1000000; | 982 | tb_ticks_per_usec = ppc_tb_freq / 1000000; |
1032 | tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000); | ||
1033 | calc_cputime_factors(); | 983 | calc_cputime_factors(); |
1034 | setup_cputime_one_jiffy(); | 984 | setup_cputime_one_jiffy(); |
1035 | 985 | ||
1036 | /* | 986 | /* |
1037 | * Calculate the length of each tick in ns. It will not be | ||
1038 | * exactly 1e9/HZ unless ppc_tb_freq is divisible by HZ. | ||
1039 | * We compute 1e9 * tb_ticks_per_jiffy / ppc_tb_freq, | ||
1040 | * rounded up. | ||
1041 | */ | ||
1042 | x = (u64) NSEC_PER_SEC * tb_ticks_per_jiffy + ppc_tb_freq - 1; | ||
1043 | do_div(x, ppc_tb_freq); | ||
1044 | tick_nsec = x; | ||
1045 | last_tick_len = x << TICKLEN_SCALE; | ||
1046 | |||
1047 | /* | ||
1048 | * Compute ticklen_to_xs, which is a factor which gets multiplied | ||
1049 | * by (last_tick_len << TICKLEN_SHIFT) to get a tb_to_xs value. | ||
1050 | * It is computed as: | ||
1051 | * ticklen_to_xs = 2^N / (tb_ticks_per_jiffy * 1e9) | ||
1052 | * where N = 64 + 20 - TICKLEN_SCALE - TICKLEN_SHIFT | ||
1053 | * which turns out to be N = 51 - SHIFT_HZ. | ||
1054 | * This gives the result as a 0.64 fixed-point fraction. | ||
1055 | * That value is reduced by an offset amounting to 1 xsec per | ||
1056 | * 2^31 timebase ticks to avoid problems with time going backwards | ||
1057 | * by 1 xsec when we do timer_recalc_offset due to losing the | ||
1058 | * fractional xsec. That offset is equal to ppc_tb_freq/2^51 | ||
1059 | * since there are 2^20 xsec in a second. | ||
1060 | */ | ||
1061 | div128_by_32((1ULL << 51) - ppc_tb_freq, 0, | ||
1062 | tb_ticks_per_jiffy << SHIFT_HZ, &res); | ||
1063 | div128_by_32(res.result_high, res.result_low, NSEC_PER_SEC, &res); | ||
1064 | ticklen_to_xs = res.result_low; | ||
1065 | |||
1066 | /* Compute tb_to_xs from tick_nsec */ | ||
1067 | tb_to_xs = mulhdu(last_tick_len << TICKLEN_SHIFT, ticklen_to_xs); | ||
1068 | |||
1069 | /* | ||
1070 | * Compute scale factor for sched_clock. | 987 | * Compute scale factor for sched_clock. |
1071 | * The calibrate_decr() function has set tb_ticks_per_sec, | 988 | * The calibrate_decr() function has set tb_ticks_per_sec, |
1072 | * which is the timebase frequency. | 989 | * which is the timebase frequency. |
@@ -1087,21 +1004,14 @@ void __init time_init(void) | |||
1087 | /* Save the current timebase to pretty up CONFIG_PRINTK_TIME */ | 1004 | /* Save the current timebase to pretty up CONFIG_PRINTK_TIME */ |
1088 | boot_tb = get_tb_or_rtc(); | 1005 | boot_tb = get_tb_or_rtc(); |
1089 | 1006 | ||
1090 | write_seqlock_irqsave(&xtime_lock, flags); | ||
1091 | |||
1092 | /* If platform provided a timezone (pmac), we correct the time */ | 1007 | /* If platform provided a timezone (pmac), we correct the time */ |
1093 | if (timezone_offset) { | 1008 | if (timezone_offset) { |
1094 | sys_tz.tz_minuteswest = -timezone_offset / 60; | 1009 | sys_tz.tz_minuteswest = -timezone_offset / 60; |
1095 | sys_tz.tz_dsttime = 0; | 1010 | sys_tz.tz_dsttime = 0; |
1096 | } | 1011 | } |
1097 | 1012 | ||
1098 | vdso_data->tb_orig_stamp = tb_last_jiffy; | ||
1099 | vdso_data->tb_update_count = 0; | 1013 | vdso_data->tb_update_count = 0; |
1100 | vdso_data->tb_ticks_per_sec = tb_ticks_per_sec; | 1014 | vdso_data->tb_ticks_per_sec = tb_ticks_per_sec; |
1101 | vdso_data->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC; | ||
1102 | vdso_data->tb_to_xs = tb_to_xs; | ||
1103 | |||
1104 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
1105 | 1015 | ||
1106 | /* Start the decrementer on CPUs that have manual control | 1016 | /* Start the decrementer on CPUs that have manual control |
1107 | * such as BookE | 1017 | * such as BookE |
@@ -1195,39 +1105,6 @@ void to_tm(int tim, struct rtc_time * tm) | |||
1195 | GregorianDay(tm); | 1105 | GregorianDay(tm); |
1196 | } | 1106 | } |
1197 | 1107 | ||
1198 | /* Auxiliary function to compute scaling factors */ | ||
1199 | /* Actually the choice of a timebase running at 1/4 the of the bus | ||
1200 | * frequency giving resolution of a few tens of nanoseconds is quite nice. | ||
1201 | * It makes this computation very precise (27-28 bits typically) which | ||
1202 | * is optimistic considering the stability of most processor clock | ||
1203 | * oscillators and the precision with which the timebase frequency | ||
1204 | * is measured but does not harm. | ||
1205 | */ | ||
1206 | unsigned mulhwu_scale_factor(unsigned inscale, unsigned outscale) | ||
1207 | { | ||
1208 | unsigned mlt=0, tmp, err; | ||
1209 | /* No concern for performance, it's done once: use a stupid | ||
1210 | * but safe and compact method to find the multiplier. | ||
1211 | */ | ||
1212 | |||
1213 | for (tmp = 1U<<31; tmp != 0; tmp >>= 1) { | ||
1214 | if (mulhwu(inscale, mlt|tmp) < outscale) | ||
1215 | mlt |= tmp; | ||
1216 | } | ||
1217 | |||
1218 | /* We might still be off by 1 for the best approximation. | ||
1219 | * A side effect of this is that if outscale is too large | ||
1220 | * the returned value will be zero. | ||
1221 | * Many corner cases have been checked and seem to work, | ||
1222 | * some might have been forgotten in the test however. | ||
1223 | */ | ||
1224 | |||
1225 | err = inscale * (mlt+1); | ||
1226 | if (err <= inscale/2) | ||
1227 | mlt++; | ||
1228 | return mlt; | ||
1229 | } | ||
1230 | |||
1231 | /* | 1108 | /* |
1232 | * Divide a 128-bit dividend by a 32-bit divisor, leaving a 128 bit | 1109 | * Divide a 128-bit dividend by a 32-bit divisor, leaving a 128 bit |
1233 | * result. | 1110 | * result. |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 25fc33984c2b..a45a63c3a0c7 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -55,9 +55,6 @@ | |||
55 | #endif | 55 | #endif |
56 | #include <asm/kexec.h> | 56 | #include <asm/kexec.h> |
57 | #include <asm/ppc-opcode.h> | 57 | #include <asm/ppc-opcode.h> |
58 | #ifdef CONFIG_FSL_BOOKE | ||
59 | #include <asm/dbell.h> | ||
60 | #endif | ||
61 | 58 | ||
62 | #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) | 59 | #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) |
63 | int (*__debugger)(struct pt_regs *regs) __read_mostly; | 60 | int (*__debugger)(struct pt_regs *regs) __read_mostly; |
@@ -688,7 +685,7 @@ void RunModeException(struct pt_regs *regs) | |||
688 | 685 | ||
689 | void __kprobes single_step_exception(struct pt_regs *regs) | 686 | void __kprobes single_step_exception(struct pt_regs *regs) |
690 | { | 687 | { |
691 | regs->msr &= ~(MSR_SE | MSR_BE); /* Turn off 'trace' bits */ | 688 | clear_single_step(regs); |
692 | 689 | ||
693 | if (notify_die(DIE_SSTEP, "single_step", regs, 5, | 690 | if (notify_die(DIE_SSTEP, "single_step", regs, 5, |
694 | 5, SIGTRAP) == NOTIFY_STOP) | 691 | 5, SIGTRAP) == NOTIFY_STOP) |
@@ -707,10 +704,8 @@ void __kprobes single_step_exception(struct pt_regs *regs) | |||
707 | */ | 704 | */ |
708 | static void emulate_single_step(struct pt_regs *regs) | 705 | static void emulate_single_step(struct pt_regs *regs) |
709 | { | 706 | { |
710 | if (single_stepping(regs)) { | 707 | if (single_stepping(regs)) |
711 | clear_single_step(regs); | 708 | single_step_exception(regs); |
712 | _exception(SIGTRAP, regs, TRAP_TRACE, 0); | ||
713 | } | ||
714 | } | 709 | } |
715 | 710 | ||
716 | static inline int __parse_fpscr(unsigned long fpscr) | 711 | static inline int __parse_fpscr(unsigned long fpscr) |
@@ -1344,24 +1339,6 @@ void vsx_assist_exception(struct pt_regs *regs) | |||
1344 | #endif /* CONFIG_VSX */ | 1339 | #endif /* CONFIG_VSX */ |
1345 | 1340 | ||
1346 | #ifdef CONFIG_FSL_BOOKE | 1341 | #ifdef CONFIG_FSL_BOOKE |
1347 | |||
1348 | void doorbell_exception(struct pt_regs *regs) | ||
1349 | { | ||
1350 | #ifdef CONFIG_SMP | ||
1351 | int cpu = smp_processor_id(); | ||
1352 | int msg; | ||
1353 | |||
1354 | if (num_online_cpus() < 2) | ||
1355 | return; | ||
1356 | |||
1357 | for (msg = 0; msg < 4; msg++) | ||
1358 | if (test_and_clear_bit(msg, &dbell_smp_message[cpu])) | ||
1359 | smp_message_recv(msg); | ||
1360 | #else | ||
1361 | printk(KERN_WARNING "Received doorbell on non-smp system\n"); | ||
1362 | #endif | ||
1363 | } | ||
1364 | |||
1365 | void CacheLockingException(struct pt_regs *regs, unsigned long address, | 1342 | void CacheLockingException(struct pt_regs *regs, unsigned long address, |
1366 | unsigned long error_code) | 1343 | unsigned long error_code) |
1367 | { | 1344 | { |
diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S index ee038d4bf252..4ee09ee2e836 100644 --- a/arch/powerpc/kernel/vdso32/gettimeofday.S +++ b/arch/powerpc/kernel/vdso32/gettimeofday.S | |||
@@ -19,8 +19,10 @@ | |||
19 | /* Offset for the low 32-bit part of a field of long type */ | 19 | /* Offset for the low 32-bit part of a field of long type */ |
20 | #ifdef CONFIG_PPC64 | 20 | #ifdef CONFIG_PPC64 |
21 | #define LOPART 4 | 21 | #define LOPART 4 |
22 | #define TSPEC_TV_SEC TSPC64_TV_SEC+LOPART | ||
22 | #else | 23 | #else |
23 | #define LOPART 0 | 24 | #define LOPART 0 |
25 | #define TSPEC_TV_SEC TSPC32_TV_SEC | ||
24 | #endif | 26 | #endif |
25 | 27 | ||
26 | .text | 28 | .text |
@@ -41,23 +43,11 @@ V_FUNCTION_BEGIN(__kernel_gettimeofday) | |||
41 | mr r9, r3 /* datapage ptr in r9 */ | 43 | mr r9, r3 /* datapage ptr in r9 */ |
42 | cmplwi r10,0 /* check if tv is NULL */ | 44 | cmplwi r10,0 /* check if tv is NULL */ |
43 | beq 3f | 45 | beq 3f |
44 | bl __do_get_xsec@local /* get xsec from tb & kernel */ | 46 | lis r7,1000000@ha /* load up USEC_PER_SEC */ |
45 | bne- 2f /* out of line -> do syscall */ | 47 | addi r7,r7,1000000@l /* so we get microseconds in r4 */ |
46 | 48 | bl __do_get_tspec@local /* get sec/usec from tb & kernel */ | |
47 | /* seconds are xsec >> 20 */ | 49 | stw r3,TVAL32_TV_SEC(r10) |
48 | rlwinm r5,r4,12,20,31 | 50 | stw r4,TVAL32_TV_USEC(r10) |
49 | rlwimi r5,r3,12,0,19 | ||
50 | stw r5,TVAL32_TV_SEC(r10) | ||
51 | |||
52 | /* get remaining xsec and convert to usec. we scale | ||
53 | * up remaining xsec by 12 bits and get the top 32 bits | ||
54 | * of the multiplication | ||
55 | */ | ||
56 | rlwinm r5,r4,12,0,19 | ||
57 | lis r6,1000000@h | ||
58 | ori r6,r6,1000000@l | ||
59 | mulhwu r5,r5,r6 | ||
60 | stw r5,TVAL32_TV_USEC(r10) | ||
61 | 51 | ||
62 | 3: cmplwi r11,0 /* check if tz is NULL */ | 52 | 3: cmplwi r11,0 /* check if tz is NULL */ |
63 | beq 1f | 53 | beq 1f |
@@ -70,14 +60,6 @@ V_FUNCTION_BEGIN(__kernel_gettimeofday) | |||
70 | crclr cr0*4+so | 60 | crclr cr0*4+so |
71 | li r3,0 | 61 | li r3,0 |
72 | blr | 62 | blr |
73 | |||
74 | 2: | ||
75 | mtlr r12 | ||
76 | mr r3,r10 | ||
77 | mr r4,r11 | ||
78 | li r0,__NR_gettimeofday | ||
79 | sc | ||
80 | blr | ||
81 | .cfi_endproc | 63 | .cfi_endproc |
82 | V_FUNCTION_END(__kernel_gettimeofday) | 64 | V_FUNCTION_END(__kernel_gettimeofday) |
83 | 65 | ||
@@ -100,7 +82,8 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
100 | mr r11,r4 /* r11 saves tp */ | 82 | mr r11,r4 /* r11 saves tp */ |
101 | bl __get_datapage@local /* get data page */ | 83 | bl __get_datapage@local /* get data page */ |
102 | mr r9,r3 /* datapage ptr in r9 */ | 84 | mr r9,r3 /* datapage ptr in r9 */ |
103 | 85 | lis r7,NSEC_PER_SEC@h /* want nanoseconds */ | |
86 | ori r7,r7,NSEC_PER_SEC@l | ||
104 | 50: bl __do_get_tspec@local /* get sec/nsec from tb & kernel */ | 87 | 50: bl __do_get_tspec@local /* get sec/nsec from tb & kernel */ |
105 | bne cr1,80f /* not monotonic -> all done */ | 88 | bne cr1,80f /* not monotonic -> all done */ |
106 | 89 | ||
@@ -198,83 +181,12 @@ V_FUNCTION_END(__kernel_clock_getres) | |||
198 | 181 | ||
199 | 182 | ||
200 | /* | 183 | /* |
201 | * This is the core of gettimeofday() & friends, it returns the xsec | 184 | * This is the core of clock_gettime() and gettimeofday(), |
202 | * value in r3 & r4 and expects the datapage ptr (non clobbered) | 185 | * it returns the current time in r3 (seconds) and r4. |
203 | * in r9. clobbers r0,r4,r5,r6,r7,r8. | 186 | * On entry, r7 gives the resolution of r4, either USEC_PER_SEC |
204 | * When returning, r8 contains the counter value that can be reused | 187 | * or NSEC_PER_SEC, giving r4 in microseconds or nanoseconds. |
205 | * by the monotonic clock implementation | ||
206 | */ | ||
207 | __do_get_xsec: | ||
208 | .cfi_startproc | ||
209 | /* Check for update count & load values. We use the low | ||
210 | * order 32 bits of the update count | ||
211 | */ | ||
212 | 1: lwz r8,(CFG_TB_UPDATE_COUNT+LOPART)(r9) | ||
213 | andi. r0,r8,1 /* pending update ? loop */ | ||
214 | bne- 1b | ||
215 | xor r0,r8,r8 /* create dependency */ | ||
216 | add r9,r9,r0 | ||
217 | |||
218 | /* Load orig stamp (offset to TB) */ | ||
219 | lwz r5,CFG_TB_ORIG_STAMP(r9) | ||
220 | lwz r6,(CFG_TB_ORIG_STAMP+4)(r9) | ||
221 | |||
222 | /* Get a stable TB value */ | ||
223 | 2: mftbu r3 | ||
224 | mftbl r4 | ||
225 | mftbu r0 | ||
226 | cmpl cr0,r3,r0 | ||
227 | bne- 2b | ||
228 | |||
229 | /* Substract tb orig stamp. If the high part is non-zero, we jump to | ||
230 | * the slow path which call the syscall. | ||
231 | * If it's ok, then we have our 32 bits tb_ticks value in r7 | ||
232 | */ | ||
233 | subfc r7,r6,r4 | ||
234 | subfe. r0,r5,r3 | ||
235 | bne- 3f | ||
236 | |||
237 | /* Load scale factor & do multiplication */ | ||
238 | lwz r5,CFG_TB_TO_XS(r9) /* load values */ | ||
239 | lwz r6,(CFG_TB_TO_XS+4)(r9) | ||
240 | mulhwu r4,r7,r5 | ||
241 | mulhwu r6,r7,r6 | ||
242 | mullw r0,r7,r5 | ||
243 | addc r6,r6,r0 | ||
244 | |||
245 | /* At this point, we have the scaled xsec value in r4 + XER:CA | ||
246 | * we load & add the stamp since epoch | ||
247 | */ | ||
248 | lwz r5,CFG_STAMP_XSEC(r9) | ||
249 | lwz r6,(CFG_STAMP_XSEC+4)(r9) | ||
250 | adde r4,r4,r6 | ||
251 | addze r3,r5 | ||
252 | |||
253 | /* We now have our result in r3,r4. We create a fake dependency | ||
254 | * on that result and re-check the counter | ||
255 | */ | ||
256 | or r6,r4,r3 | ||
257 | xor r0,r6,r6 | ||
258 | add r9,r9,r0 | ||
259 | lwz r0,(CFG_TB_UPDATE_COUNT+LOPART)(r9) | ||
260 | cmpl cr0,r8,r0 /* check if updated */ | ||
261 | bne- 1b | ||
262 | |||
263 | /* Warning ! The caller expects CR:EQ to be set to indicate a | ||
264 | * successful calculation (so it won't fallback to the syscall | ||
265 | * method). We have overriden that CR bit in the counter check, | ||
266 | * but fortunately, the loop exit condition _is_ CR:EQ set, so | ||
267 | * we can exit safely here. If you change this code, be careful | ||
268 | * of that side effect. | ||
269 | */ | ||
270 | 3: blr | ||
271 | .cfi_endproc | ||
272 | |||
273 | /* | ||
274 | * This is the core of clock_gettime(), it returns the current | ||
275 | * time in seconds and nanoseconds in r3 and r4. | ||
276 | * It expects the datapage ptr in r9 and doesn't clobber it. | 188 | * It expects the datapage ptr in r9 and doesn't clobber it. |
277 | * It clobbers r0, r5, r6, r10 and returns NSEC_PER_SEC in r7. | 189 | * It clobbers r0, r5 and r6. |
278 | * On return, r8 contains the counter value that can be reused. | 190 | * On return, r8 contains the counter value that can be reused. |
279 | * This clobbers cr0 but not any other cr field. | 191 | * This clobbers cr0 but not any other cr field. |
280 | */ | 192 | */ |
@@ -297,70 +209,58 @@ __do_get_tspec: | |||
297 | 2: mftbu r3 | 209 | 2: mftbu r3 |
298 | mftbl r4 | 210 | mftbl r4 |
299 | mftbu r0 | 211 | mftbu r0 |
300 | cmpl cr0,r3,r0 | 212 | cmplw cr0,r3,r0 |
301 | bne- 2b | 213 | bne- 2b |
302 | 214 | ||
303 | /* Subtract tb orig stamp and shift left 12 bits. | 215 | /* Subtract tb orig stamp and shift left 12 bits. |
304 | */ | 216 | */ |
305 | subfc r7,r6,r4 | 217 | subfc r4,r6,r4 |
306 | subfe r0,r5,r3 | 218 | subfe r0,r5,r3 |
307 | slwi r0,r0,12 | 219 | slwi r0,r0,12 |
308 | rlwimi. r0,r7,12,20,31 | 220 | rlwimi. r0,r4,12,20,31 |
309 | slwi r7,r7,12 | 221 | slwi r4,r4,12 |
310 | 222 | ||
311 | /* Load scale factor & do multiplication */ | 223 | /* |
224 | * Load scale factor & do multiplication. | ||
225 | * We only use the high 32 bits of the tb_to_xs value. | ||
226 | * Even with a 1GHz timebase clock, the high 32 bits of | ||
227 | * tb_to_xs will be at least 4 million, so the error from | ||
228 | * ignoring the low 32 bits will be no more than 0.25ppm. | ||
229 | * The error will just make the clock run very very slightly | ||
230 | * slow until the next time the kernel updates the VDSO data, | ||
231 | * at which point the clock will catch up to the kernel's value, | ||
232 | * so there is no long-term error accumulation. | ||
233 | */ | ||
312 | lwz r5,CFG_TB_TO_XS(r9) /* load values */ | 234 | lwz r5,CFG_TB_TO_XS(r9) /* load values */ |
313 | lwz r6,(CFG_TB_TO_XS+4)(r9) | 235 | mulhwu r4,r4,r5 |
314 | mulhwu r3,r7,r6 | ||
315 | mullw r10,r7,r5 | ||
316 | mulhwu r4,r7,r5 | ||
317 | addc r10,r3,r10 | ||
318 | li r3,0 | 236 | li r3,0 |
319 | 237 | ||
320 | beq+ 4f /* skip high part computation if 0 */ | 238 | beq+ 4f /* skip high part computation if 0 */ |
321 | mulhwu r3,r0,r5 | 239 | mulhwu r3,r0,r5 |
322 | mullw r7,r0,r5 | 240 | mullw r5,r0,r5 |
323 | mulhwu r5,r0,r6 | ||
324 | mullw r6,r0,r6 | ||
325 | adde r4,r4,r7 | ||
326 | addze r3,r3 | ||
327 | addc r4,r4,r5 | 241 | addc r4,r4,r5 |
328 | addze r3,r3 | 242 | addze r3,r3 |
329 | addc r10,r10,r6 | 243 | 4: |
330 | 244 | /* At this point, we have seconds since the xtime stamp | |
331 | 4: addze r4,r4 /* add in carry */ | 245 | * as a 32.32 fixed-point number in r3 and r4. |
332 | lis r7,NSEC_PER_SEC@h | 246 | * Load & add the xtime stamp. |
333 | ori r7,r7,NSEC_PER_SEC@l | ||
334 | mulhwu r4,r4,r7 /* convert to nanoseconds */ | ||
335 | |||
336 | /* At this point, we have seconds & nanoseconds since the xtime | ||
337 | * stamp in r3+CA and r4. Load & add the xtime stamp. | ||
338 | */ | 247 | */ |
339 | #ifdef CONFIG_PPC64 | 248 | lwz r5,STAMP_XTIME+TSPEC_TV_SEC(r9) |
340 | lwz r5,STAMP_XTIME+TSPC64_TV_SEC+LOPART(r9) | 249 | lwz r6,STAMP_SEC_FRAC(r9) |
341 | lwz r6,STAMP_XTIME+TSPC64_TV_NSEC+LOPART(r9) | 250 | addc r4,r4,r6 |
342 | #else | ||
343 | lwz r5,STAMP_XTIME+TSPC32_TV_SEC(r9) | ||
344 | lwz r6,STAMP_XTIME+TSPC32_TV_NSEC(r9) | ||
345 | #endif | ||
346 | add r4,r4,r6 | ||
347 | adde r3,r3,r5 | 251 | adde r3,r3,r5 |
348 | 252 | ||
349 | /* We now have our result in r3,r4. We create a fake dependency | 253 | /* We create a fake dependency on the result in r3/r4 |
350 | * on that result and re-check the counter | 254 | * and re-check the counter |
351 | */ | 255 | */ |
352 | or r6,r4,r3 | 256 | or r6,r4,r3 |
353 | xor r0,r6,r6 | 257 | xor r0,r6,r6 |
354 | add r9,r9,r0 | 258 | add r9,r9,r0 |
355 | lwz r0,(CFG_TB_UPDATE_COUNT+LOPART)(r9) | 259 | lwz r0,(CFG_TB_UPDATE_COUNT+LOPART)(r9) |
356 | cmpl cr0,r8,r0 /* check if updated */ | 260 | cmplw cr0,r8,r0 /* check if updated */ |
357 | bne- 1b | 261 | bne- 1b |
358 | 262 | ||
359 | /* check for nanosecond overflow and adjust if necessary */ | 263 | mulhwu r4,r4,r7 /* convert to micro or nanoseconds */ |
360 | cmpw r4,r7 | ||
361 | bltlr /* all done if no overflow */ | ||
362 | subf r4,r7,r4 /* adjust if overflow */ | ||
363 | addi r3,r3,1 | ||
364 | 264 | ||
365 | blr | 265 | blr |
366 | .cfi_endproc | 266 | .cfi_endproc |
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S index 262cd5857a56..e97a9a0dc4ac 100644 --- a/arch/powerpc/kernel/vdso64/gettimeofday.S +++ b/arch/powerpc/kernel/vdso64/gettimeofday.S | |||
@@ -33,18 +33,11 @@ V_FUNCTION_BEGIN(__kernel_gettimeofday) | |||
33 | bl V_LOCAL_FUNC(__get_datapage) /* get data page */ | 33 | bl V_LOCAL_FUNC(__get_datapage) /* get data page */ |
34 | cmpldi r11,0 /* check if tv is NULL */ | 34 | cmpldi r11,0 /* check if tv is NULL */ |
35 | beq 2f | 35 | beq 2f |
36 | bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ | 36 | lis r7,1000000@ha /* load up USEC_PER_SEC */ |
37 | lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */ | 37 | addi r7,r7,1000000@l |
38 | ori r7,r7,16960 | 38 | bl V_LOCAL_FUNC(__do_get_tspec) /* get sec/us from tb & kernel */ |
39 | rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ | 39 | std r4,TVAL64_TV_SEC(r11) /* store sec in tv */ |
40 | rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ | 40 | std r5,TVAL64_TV_USEC(r11) /* store usec in tv */ |
41 | std r5,TVAL64_TV_SEC(r11) /* store sec in tv */ | ||
42 | subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ | ||
43 | mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) / | ||
44 | * XSEC_PER_SEC | ||
45 | */ | ||
46 | rldicl r0,r0,44,20 | ||
47 | std r0,TVAL64_TV_USEC(r11) /* store usec in tv */ | ||
48 | 2: cmpldi r10,0 /* check if tz is NULL */ | 41 | 2: cmpldi r10,0 /* check if tz is NULL */ |
49 | beq 1f | 42 | beq 1f |
50 | lwz r4,CFG_TZ_MINUTEWEST(r3)/* fill tz */ | 43 | lwz r4,CFG_TZ_MINUTEWEST(r3)/* fill tz */ |
@@ -77,6 +70,8 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
77 | .cfi_register lr,r12 | 70 | .cfi_register lr,r12 |
78 | mr r11,r4 /* r11 saves tp */ | 71 | mr r11,r4 /* r11 saves tp */ |
79 | bl V_LOCAL_FUNC(__get_datapage) /* get data page */ | 72 | bl V_LOCAL_FUNC(__get_datapage) /* get data page */ |
73 | lis r7,NSEC_PER_SEC@h /* want nanoseconds */ | ||
74 | ori r7,r7,NSEC_PER_SEC@l | ||
80 | 50: bl V_LOCAL_FUNC(__do_get_tspec) /* get time from tb & kernel */ | 75 | 50: bl V_LOCAL_FUNC(__do_get_tspec) /* get time from tb & kernel */ |
81 | bne cr1,80f /* if not monotonic, all done */ | 76 | bne cr1,80f /* if not monotonic, all done */ |
82 | 77 | ||
@@ -171,49 +166,12 @@ V_FUNCTION_END(__kernel_clock_getres) | |||
171 | 166 | ||
172 | 167 | ||
173 | /* | 168 | /* |
174 | * This is the core of gettimeofday(), it returns the xsec | 169 | * This is the core of clock_gettime() and gettimeofday(), |
175 | * value in r4 and expects the datapage ptr (non clobbered) | 170 | * it returns the current time in r4 (seconds) and r5. |
176 | * in r3. clobbers r0,r4,r5,r6,r7,r8 | 171 | * On entry, r7 gives the resolution of r5, either USEC_PER_SEC |
177 | * When returning, r8 contains the counter value that can be reused | 172 | * or NSEC_PER_SEC, giving r5 in microseconds or nanoseconds. |
178 | */ | ||
179 | V_FUNCTION_BEGIN(__do_get_xsec) | ||
180 | .cfi_startproc | ||
181 | /* check for update count & load values */ | ||
182 | 1: ld r8,CFG_TB_UPDATE_COUNT(r3) | ||
183 | andi. r0,r8,1 /* pending update ? loop */ | ||
184 | bne- 1b | ||
185 | xor r0,r8,r8 /* create dependency */ | ||
186 | add r3,r3,r0 | ||
187 | |||
188 | /* Get TB & offset it. We use the MFTB macro which will generate | ||
189 | * workaround code for Cell. | ||
190 | */ | ||
191 | MFTB(r7) | ||
192 | ld r9,CFG_TB_ORIG_STAMP(r3) | ||
193 | subf r7,r9,r7 | ||
194 | |||
195 | /* Scale result */ | ||
196 | ld r5,CFG_TB_TO_XS(r3) | ||
197 | mulhdu r7,r7,r5 | ||
198 | |||
199 | /* Add stamp since epoch */ | ||
200 | ld r6,CFG_STAMP_XSEC(r3) | ||
201 | add r4,r6,r7 | ||
202 | |||
203 | xor r0,r4,r4 | ||
204 | add r3,r3,r0 | ||
205 | ld r0,CFG_TB_UPDATE_COUNT(r3) | ||
206 | cmpld cr0,r0,r8 /* check if updated */ | ||
207 | bne- 1b | ||
208 | blr | ||
209 | .cfi_endproc | ||
210 | V_FUNCTION_END(__do_get_xsec) | ||
211 | |||
212 | /* | ||
213 | * This is the core of clock_gettime(), it returns the current | ||
214 | * time in seconds and nanoseconds in r4 and r5. | ||
215 | * It expects the datapage ptr in r3 and doesn't clobber it. | 173 | * It expects the datapage ptr in r3 and doesn't clobber it. |
216 | * It clobbers r0 and r6 and returns NSEC_PER_SEC in r7. | 174 | * It clobbers r0, r6 and r9. |
217 | * On return, r8 contains the counter value that can be reused. | 175 | * On return, r8 contains the counter value that can be reused. |
218 | * This clobbers cr0 but not any other cr field. | 176 | * This clobbers cr0 but not any other cr field. |
219 | */ | 177 | */ |
@@ -229,18 +187,18 @@ V_FUNCTION_BEGIN(__do_get_tspec) | |||
229 | /* Get TB & offset it. We use the MFTB macro which will generate | 187 | /* Get TB & offset it. We use the MFTB macro which will generate |
230 | * workaround code for Cell. | 188 | * workaround code for Cell. |
231 | */ | 189 | */ |
232 | MFTB(r7) | 190 | MFTB(r6) |
233 | ld r9,CFG_TB_ORIG_STAMP(r3) | 191 | ld r9,CFG_TB_ORIG_STAMP(r3) |
234 | subf r7,r9,r7 | 192 | subf r6,r9,r6 |
235 | 193 | ||
236 | /* Scale result */ | 194 | /* Scale result */ |
237 | ld r5,CFG_TB_TO_XS(r3) | 195 | ld r5,CFG_TB_TO_XS(r3) |
238 | sldi r7,r7,12 /* compute time since stamp_xtime */ | 196 | sldi r6,r6,12 /* compute time since stamp_xtime */ |
239 | mulhdu r6,r7,r5 /* in units of 2^-32 seconds */ | 197 | mulhdu r6,r6,r5 /* in units of 2^-32 seconds */ |
240 | 198 | ||
241 | /* Add stamp since epoch */ | 199 | /* Add stamp since epoch */ |
242 | ld r4,STAMP_XTIME+TSPC64_TV_SEC(r3) | 200 | ld r4,STAMP_XTIME+TSPC64_TV_SEC(r3) |
243 | ld r5,STAMP_XTIME+TSPC64_TV_NSEC(r3) | 201 | lwz r5,STAMP_SEC_FRAC(r3) |
244 | or r0,r4,r5 | 202 | or r0,r4,r5 |
245 | or r0,r0,r6 | 203 | or r0,r0,r6 |
246 | xor r0,r0,r0 | 204 | xor r0,r0,r0 |
@@ -250,17 +208,11 @@ V_FUNCTION_BEGIN(__do_get_tspec) | |||
250 | bne- 1b /* reload if so */ | 208 | bne- 1b /* reload if so */ |
251 | 209 | ||
252 | /* convert to seconds & nanoseconds and add to stamp */ | 210 | /* convert to seconds & nanoseconds and add to stamp */ |
253 | lis r7,NSEC_PER_SEC@h | 211 | add r6,r6,r5 /* add on fractional seconds of xtime */ |
254 | ori r7,r7,NSEC_PER_SEC@l | 212 | mulhwu r5,r6,r7 /* compute micro or nanoseconds and */ |
255 | mulhwu r0,r6,r7 /* compute nanoseconds and */ | ||
256 | srdi r6,r6,32 /* seconds since stamp_xtime */ | 213 | srdi r6,r6,32 /* seconds since stamp_xtime */ |
257 | clrldi r0,r0,32 | 214 | clrldi r5,r5,32 |
258 | add r5,r5,r0 /* add nanoseconds together */ | ||
259 | cmpd r5,r7 /* overflow? */ | ||
260 | add r4,r4,r6 | 215 | add r4,r4,r6 |
261 | bltlr /* all done if no overflow */ | ||
262 | subf r5,r7,r5 /* if overflow, adjust */ | ||
263 | addi r4,r4,1 | ||
264 | blr | 216 | blr |
265 | .cfi_endproc | 217 | .cfi_endproc |
266 | V_FUNCTION_END(__do_get_tspec) | 218 | V_FUNCTION_END(__do_get_tspec) |