diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-07 12:35:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-06-07 12:35:54 -0400 |
commit | 7244d545c123ff33a3a5bff7fcb96a07778c32d1 (patch) | |
tree | c4d2893faa844e4cd6e2b47bbd2663dc28d9af83 /arch | |
parent | 143a275984b37058d2d3ab1ec0e5be9026fda24d (diff) | |
parent | e7e8cc5ae63c39dbbbb5f14c5120bdf2d931fac9 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6:
[VIDEO] sunxvr500fb: Fix pseudo_palette array size
[VIDEO] sunxvr2500fb: Fix pseudo_palette array size
[VIDEO] ffb: The pseudo_palette is only 16 elements long
[VIDEO]: Fix section mismatch warning in promcon.
[ATA]: Back out bogus (SPARC64 && !PCI) Kconfig depends.
[SPARC64]: Fill in gaps in non-PCI dma_*() NOP implementation.
[SPARC64]: Fix {mc,smt}_capable().
[SPARC64]: Make core and sibling groups equal on UltraSPARC-IV.
[SPARC64]: Proper multi-core scheduling support.
[SPARC64]: Provide mmu statistics via sysfs.
[SPARC64]: Fix service channel hypervisor function names.
[SPARC64]: Export basic cpu properties via sysfs.
[SPARC64]: Move topology init code into new file, sysfs.c
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc64/Kconfig | 9 | ||||
-rw-r--r-- | arch/sparc64/kernel/Makefile | 4 | ||||
-rw-r--r-- | arch/sparc64/kernel/entry.S | 62 | ||||
-rw-r--r-- | arch/sparc64/kernel/mdesc.c | 53 | ||||
-rw-r--r-- | arch/sparc64/kernel/prom.c | 5 | ||||
-rw-r--r-- | arch/sparc64/kernel/setup.c | 19 | ||||
-rw-r--r-- | arch/sparc64/kernel/smp.c | 21 | ||||
-rw-r--r-- | arch/sparc64/kernel/sysfs.c | 297 |
8 files changed, 428 insertions, 42 deletions
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index bd00f89eed1..89a1b469b93 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig | |||
@@ -396,6 +396,15 @@ config SCHED_SMT | |||
396 | when dealing with UltraSPARC cpus at a cost of slightly increased | 396 | when dealing with UltraSPARC cpus at a cost of slightly increased |
397 | overhead in some places. If unsure say N here. | 397 | overhead in some places. If unsure say N here. |
398 | 398 | ||
399 | config SCHED_MC | ||
400 | bool "Multi-core scheduler support" | ||
401 | depends on SMP | ||
402 | default y | ||
403 | help | ||
404 | Multi-core scheduler support improves the CPU scheduler's decision | ||
405 | making when dealing with multi-core CPU chips at a cost of slightly | ||
406 | increased overhead in some places. If unsure say N here. | ||
407 | |||
399 | source "kernel/Kconfig.preempt" | 408 | source "kernel/Kconfig.preempt" |
400 | 409 | ||
401 | config CMDLINE_BOOL | 410 | config CMDLINE_BOOL |
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index d8d19093d12..f964bf28d21 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # $Id: Makefile,v 1.70 2002/02/09 19:49:30 davem Exp $ | 1 | # |
2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
3 | # | 3 | # |
4 | 4 | ||
@@ -8,7 +8,7 @@ EXTRA_CFLAGS := -Werror | |||
8 | extra-y := head.o init_task.o vmlinux.lds | 8 | extra-y := head.o init_task.o vmlinux.lds |
9 | 9 | ||
10 | obj-y := process.o setup.o cpu.o idprom.o \ | 10 | obj-y := process.o setup.o cpu.o idprom.o \ |
11 | traps.o auxio.o una_asm.o \ | 11 | traps.o auxio.o una_asm.o sysfs.o \ |
12 | irq.o ptrace.o time.o sys_sparc.o signal.o \ | 12 | irq.o ptrace.o time.o sys_sparc.o signal.o \ |
13 | unaligned.o central.o pci.o starfire.o semaphore.o \ | 13 | unaligned.o central.o pci.o starfire.o semaphore.o \ |
14 | power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \ | 14 | power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \ |
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index ed712e0b337..7d1a11822a1 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S | |||
@@ -2514,9 +2514,9 @@ sun4v_ncs_request: | |||
2514 | nop | 2514 | nop |
2515 | .size sun4v_ncs_request, .-sun4v_ncs_request | 2515 | .size sun4v_ncs_request, .-sun4v_ncs_request |
2516 | 2516 | ||
2517 | .globl sun4v_scv_send | 2517 | .globl sun4v_svc_send |
2518 | .type sun4v_scv_send,#function | 2518 | .type sun4v_svc_send,#function |
2519 | sun4v_scv_send: | 2519 | sun4v_svc_send: |
2520 | save %sp, -192, %sp | 2520 | save %sp, -192, %sp |
2521 | mov %i0, %o0 | 2521 | mov %i0, %o0 |
2522 | mov %i1, %o1 | 2522 | mov %i1, %o1 |
@@ -2526,11 +2526,11 @@ sun4v_scv_send: | |||
2526 | stx %o1, [%i3] | 2526 | stx %o1, [%i3] |
2527 | ret | 2527 | ret |
2528 | restore | 2528 | restore |
2529 | .size sun4v_scv_send, .-sun4v_scv_send | 2529 | .size sun4v_svc_send, .-sun4v_svc_send |
2530 | 2530 | ||
2531 | .globl sun4v_scv_recv | 2531 | .globl sun4v_svc_recv |
2532 | .type sun4v_scv_recv,#function | 2532 | .type sun4v_svc_recv,#function |
2533 | sun4v_scv_recv: | 2533 | sun4v_svc_recv: |
2534 | save %sp, -192, %sp | 2534 | save %sp, -192, %sp |
2535 | mov %i0, %o0 | 2535 | mov %i0, %o0 |
2536 | mov %i1, %o1 | 2536 | mov %i1, %o1 |
@@ -2540,33 +2540,55 @@ sun4v_scv_recv: | |||
2540 | stx %o1, [%i3] | 2540 | stx %o1, [%i3] |
2541 | ret | 2541 | ret |
2542 | restore | 2542 | restore |
2543 | .size sun4v_scv_recv, .-sun4v_scv_recv | 2543 | .size sun4v_svc_recv, .-sun4v_svc_recv |
2544 | 2544 | ||
2545 | .globl sun4v_scv_getstatus | 2545 | .globl sun4v_svc_getstatus |
2546 | .type sun4v_scv_getstatus,#function | 2546 | .type sun4v_svc_getstatus,#function |
2547 | sun4v_scv_getstatus: | 2547 | sun4v_svc_getstatus: |
2548 | mov HV_FAST_SVC_GETSTATUS, %o5 | 2548 | mov HV_FAST_SVC_GETSTATUS, %o5 |
2549 | mov %o1, %o4 | 2549 | mov %o1, %o4 |
2550 | ta HV_FAST_TRAP | 2550 | ta HV_FAST_TRAP |
2551 | stx %o1, [%o4] | 2551 | stx %o1, [%o4] |
2552 | retl | 2552 | retl |
2553 | nop | 2553 | nop |
2554 | .size sun4v_scv_getstatus, .-sun4v_scv_getstatus | 2554 | .size sun4v_svc_getstatus, .-sun4v_svc_getstatus |
2555 | 2555 | ||
2556 | .globl sun4v_scv_setstatus | 2556 | .globl sun4v_svc_setstatus |
2557 | .type sun4v_scv_setstatus,#function | 2557 | .type sun4v_svc_setstatus,#function |
2558 | sun4v_scv_setstatus: | 2558 | sun4v_svc_setstatus: |
2559 | mov HV_FAST_SVC_SETSTATUS, %o5 | 2559 | mov HV_FAST_SVC_SETSTATUS, %o5 |
2560 | ta HV_FAST_TRAP | 2560 | ta HV_FAST_TRAP |
2561 | retl | 2561 | retl |
2562 | nop | 2562 | nop |
2563 | .size sun4v_scv_setstatus, .-sun4v_scv_setstatus | 2563 | .size sun4v_svc_setstatus, .-sun4v_svc_setstatus |
2564 | 2564 | ||
2565 | .globl sun4v_scv_clrstatus | 2565 | .globl sun4v_svc_clrstatus |
2566 | .type sun4v_scv_clrstatus,#function | 2566 | .type sun4v_svc_clrstatus,#function |
2567 | sun4v_scv_clrstatus: | 2567 | sun4v_svc_clrstatus: |
2568 | mov HV_FAST_SVC_CLRSTATUS, %o5 | 2568 | mov HV_FAST_SVC_CLRSTATUS, %o5 |
2569 | ta HV_FAST_TRAP | 2569 | ta HV_FAST_TRAP |
2570 | retl | 2570 | retl |
2571 | nop | 2571 | nop |
2572 | .size sun4v_scv_clrstatus, .-sun4v_scv_clrstatus | 2572 | .size sun4v_svc_clrstatus, .-sun4v_svc_clrstatus |
2573 | |||
2574 | .globl sun4v_mmustat_conf | ||
2575 | .type sun4v_mmustat_conf,#function | ||
2576 | sun4v_mmustat_conf: | ||
2577 | mov %o1, %o4 | ||
2578 | mov HV_FAST_MMUSTAT_CONF, %o5 | ||
2579 | ta HV_FAST_TRAP | ||
2580 | stx %o1, [%o4] | ||
2581 | retl | ||
2582 | nop | ||
2583 | .size sun4v_mmustat_conf, .-sun4v_mmustat_conf | ||
2584 | |||
2585 | .globl sun4v_mmustat_info | ||
2586 | .type sun4v_mmustat_info,#function | ||
2587 | sun4v_mmustat_info: | ||
2588 | mov %o0, %o4 | ||
2589 | mov HV_FAST_MMUSTAT_INFO, %o5 | ||
2590 | ta HV_FAST_TRAP | ||
2591 | stx %o1, [%o4] | ||
2592 | retl | ||
2593 | nop | ||
2594 | .size sun4v_mmustat_info, .-sun4v_mmustat_info | ||
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c index 9246c2cf957..f0e16045fb1 100644 --- a/arch/sparc64/kernel/mdesc.c +++ b/arch/sparc64/kernel/mdesc.c | |||
@@ -473,6 +473,53 @@ static void __init set_core_ids(void) | |||
473 | } | 473 | } |
474 | } | 474 | } |
475 | 475 | ||
476 | static void __init mark_proc_ids(struct mdesc_node *mp, int proc_id) | ||
477 | { | ||
478 | int i; | ||
479 | |||
480 | for (i = 0; i < mp->num_arcs; i++) { | ||
481 | struct mdesc_node *t = mp->arcs[i].arc; | ||
482 | const u64 *id; | ||
483 | |||
484 | if (strcmp(mp->arcs[i].name, "back")) | ||
485 | continue; | ||
486 | |||
487 | if (strcmp(t->name, "cpu")) | ||
488 | continue; | ||
489 | |||
490 | id = md_get_property(t, "id", NULL); | ||
491 | if (*id < NR_CPUS) | ||
492 | cpu_data(*id).proc_id = proc_id; | ||
493 | } | ||
494 | } | ||
495 | |||
496 | static void __init __set_proc_ids(const char *exec_unit_name) | ||
497 | { | ||
498 | struct mdesc_node *mp; | ||
499 | int idx; | ||
500 | |||
501 | idx = 0; | ||
502 | md_for_each_node_by_name(mp, exec_unit_name) { | ||
503 | const char *type; | ||
504 | int len; | ||
505 | |||
506 | type = md_get_property(mp, "type", &len); | ||
507 | if (!find_in_proplist(type, "int", len) && | ||
508 | !find_in_proplist(type, "integer", len)) | ||
509 | continue; | ||
510 | |||
511 | mark_proc_ids(mp, idx); | ||
512 | |||
513 | idx++; | ||
514 | } | ||
515 | } | ||
516 | |||
517 | static void __init set_proc_ids(void) | ||
518 | { | ||
519 | __set_proc_ids("exec_unit"); | ||
520 | __set_proc_ids("exec-unit"); | ||
521 | } | ||
522 | |||
476 | static void __init get_one_mondo_bits(const u64 *p, unsigned int *mask, unsigned char def) | 523 | static void __init get_one_mondo_bits(const u64 *p, unsigned int *mask, unsigned char def) |
477 | { | 524 | { |
478 | u64 val; | 525 | u64 val; |
@@ -574,9 +621,15 @@ static void __init mdesc_fill_in_cpu_data(void) | |||
574 | #endif | 621 | #endif |
575 | 622 | ||
576 | c->core_id = 0; | 623 | c->core_id = 0; |
624 | c->proc_id = -1; | ||
577 | } | 625 | } |
578 | 626 | ||
627 | #ifdef CONFIG_SMP | ||
628 | sparc64_multi_core = 1; | ||
629 | #endif | ||
630 | |||
579 | set_core_ids(); | 631 | set_core_ids(); |
632 | set_proc_ids(); | ||
580 | 633 | ||
581 | smp_fill_in_sib_core_maps(); | 634 | smp_fill_in_sib_core_maps(); |
582 | } | 635 | } |
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index dad4b3ba705..6f4a5284b0e 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c | |||
@@ -1781,6 +1781,10 @@ static void __init of_fill_in_cpu_data(void) | |||
1781 | } | 1781 | } |
1782 | 1782 | ||
1783 | cpu_data(cpuid).core_id = portid + 1; | 1783 | cpu_data(cpuid).core_id = portid + 1; |
1784 | cpu_data(cpuid).proc_id = portid; | ||
1785 | #ifdef CONFIG_SMP | ||
1786 | sparc64_multi_core = 1; | ||
1787 | #endif | ||
1784 | } else { | 1788 | } else { |
1785 | cpu_data(cpuid).dcache_size = | 1789 | cpu_data(cpuid).dcache_size = |
1786 | of_getintprop_default(dp, "dcache-size", 16 * 1024); | 1790 | of_getintprop_default(dp, "dcache-size", 16 * 1024); |
@@ -1799,6 +1803,7 @@ static void __init of_fill_in_cpu_data(void) | |||
1799 | of_getintprop_default(dp, "ecache-line-size", 64); | 1803 | of_getintprop_default(dp, "ecache-line-size", 64); |
1800 | 1804 | ||
1801 | cpu_data(cpuid).core_id = 0; | 1805 | cpu_data(cpuid).core_id = 0; |
1806 | cpu_data(cpuid).proc_id = -1; | ||
1802 | } | 1807 | } |
1803 | 1808 | ||
1804 | #ifdef CONFIG_SMP | 1809 | #ifdef CONFIG_SMP |
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index de9b4c13f1c..7490cc670a5 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c | |||
@@ -513,22 +513,3 @@ void sun_do_break(void) | |||
513 | 513 | ||
514 | int serial_console = -1; | 514 | int serial_console = -1; |
515 | int stop_a_enabled = 1; | 515 | int stop_a_enabled = 1; |
516 | |||
517 | static int __init topology_init(void) | ||
518 | { | ||
519 | int i, err; | ||
520 | |||
521 | err = -ENOMEM; | ||
522 | |||
523 | for_each_possible_cpu(i) { | ||
524 | struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
525 | if (p) { | ||
526 | register_cpu(p, i); | ||
527 | err = 0; | ||
528 | } | ||
529 | } | ||
530 | |||
531 | return err; | ||
532 | } | ||
533 | |||
534 | subsys_initcall(topology_init); | ||
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index c550bba3490..4dcd7d0b60f 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c | |||
@@ -44,6 +44,8 @@ | |||
44 | 44 | ||
45 | extern void calibrate_delay(void); | 45 | extern void calibrate_delay(void); |
46 | 46 | ||
47 | int sparc64_multi_core __read_mostly; | ||
48 | |||
47 | /* Please don't make this stuff initdata!!! --DaveM */ | 49 | /* Please don't make this stuff initdata!!! --DaveM */ |
48 | unsigned char boot_cpu_id; | 50 | unsigned char boot_cpu_id; |
49 | 51 | ||
@@ -51,6 +53,8 @@ cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE; | |||
51 | cpumask_t phys_cpu_present_map __read_mostly = CPU_MASK_NONE; | 53 | cpumask_t phys_cpu_present_map __read_mostly = CPU_MASK_NONE; |
52 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly = | 54 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly = |
53 | { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; | 55 | { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; |
56 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly = | ||
57 | { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; | ||
54 | static cpumask_t smp_commenced_mask; | 58 | static cpumask_t smp_commenced_mask; |
55 | static cpumask_t cpu_callout_map; | 59 | static cpumask_t cpu_callout_map; |
56 | 60 | ||
@@ -1217,13 +1221,28 @@ void __devinit smp_fill_in_sib_core_maps(void) | |||
1217 | unsigned int j; | 1221 | unsigned int j; |
1218 | 1222 | ||
1219 | if (cpu_data(i).core_id == 0) { | 1223 | if (cpu_data(i).core_id == 0) { |
1220 | cpu_set(i, cpu_sibling_map[i]); | 1224 | cpu_set(i, cpu_core_map[i]); |
1221 | continue; | 1225 | continue; |
1222 | } | 1226 | } |
1223 | 1227 | ||
1224 | for_each_possible_cpu(j) { | 1228 | for_each_possible_cpu(j) { |
1225 | if (cpu_data(i).core_id == | 1229 | if (cpu_data(i).core_id == |
1226 | cpu_data(j).core_id) | 1230 | cpu_data(j).core_id) |
1231 | cpu_set(j, cpu_core_map[i]); | ||
1232 | } | ||
1233 | } | ||
1234 | |||
1235 | for_each_possible_cpu(i) { | ||
1236 | unsigned int j; | ||
1237 | |||
1238 | if (cpu_data(i).proc_id == -1) { | ||
1239 | cpu_set(i, cpu_sibling_map[i]); | ||
1240 | continue; | ||
1241 | } | ||
1242 | |||
1243 | for_each_possible_cpu(j) { | ||
1244 | if (cpu_data(i).proc_id == | ||
1245 | cpu_data(j).proc_id) | ||
1227 | cpu_set(j, cpu_sibling_map[i]); | 1246 | cpu_set(j, cpu_sibling_map[i]); |
1228 | } | 1247 | } |
1229 | } | 1248 | } |
diff --git a/arch/sparc64/kernel/sysfs.c b/arch/sparc64/kernel/sysfs.c new file mode 100644 index 00000000000..cdb1477af89 --- /dev/null +++ b/arch/sparc64/kernel/sysfs.c | |||
@@ -0,0 +1,297 @@ | |||
1 | /* sysfs.c: Toplogy sysfs support code for sparc64. | ||
2 | * | ||
3 | * Copyright (C) 2007 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | #include <linux/sysdev.h> | ||
6 | #include <linux/cpu.h> | ||
7 | #include <linux/smp.h> | ||
8 | #include <linux/percpu.h> | ||
9 | #include <linux/init.h> | ||
10 | |||
11 | #include <asm/hypervisor.h> | ||
12 | #include <asm/spitfire.h> | ||
13 | |||
14 | static DEFINE_PER_CPU(struct hv_mmu_statistics, mmu_stats) __attribute__((aligned(64))); | ||
15 | |||
16 | #define SHOW_MMUSTAT_ULONG(NAME) \ | ||
17 | static ssize_t show_##NAME(struct sys_device *dev, char *buf) \ | ||
18 | { \ | ||
19 | struct hv_mmu_statistics *p = &per_cpu(mmu_stats, dev->id); \ | ||
20 | return sprintf(buf, "%lu\n", p->NAME); \ | ||
21 | } \ | ||
22 | static SYSDEV_ATTR(NAME, 0444, show_##NAME, NULL) | ||
23 | |||
24 | SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_8k_tte); | ||
25 | SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_8k_tte); | ||
26 | SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_64k_tte); | ||
27 | SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_64k_tte); | ||
28 | SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_4mb_tte); | ||
29 | SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_4mb_tte); | ||
30 | SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_256mb_tte); | ||
31 | SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_256mb_tte); | ||
32 | SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_8k_tte); | ||
33 | SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_8k_tte); | ||
34 | SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_64k_tte); | ||
35 | SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_64k_tte); | ||
36 | SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_4mb_tte); | ||
37 | SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_4mb_tte); | ||
38 | SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_256mb_tte); | ||
39 | SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_256mb_tte); | ||
40 | SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_8k_tte); | ||
41 | SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_8k_tte); | ||
42 | SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_64k_tte); | ||
43 | SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_64k_tte); | ||
44 | SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_4mb_tte); | ||
45 | SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_4mb_tte); | ||
46 | SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_256mb_tte); | ||
47 | SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_256mb_tte); | ||
48 | SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_8k_tte); | ||
49 | SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_8k_tte); | ||
50 | SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_64k_tte); | ||
51 | SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_64k_tte); | ||
52 | SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_4mb_tte); | ||
53 | SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_4mb_tte); | ||
54 | SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_256mb_tte); | ||
55 | SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_256mb_tte); | ||
56 | |||
57 | static struct attribute *mmu_stat_attrs[] = { | ||
58 | &attr_immu_tsb_hits_ctx0_8k_tte.attr, | ||
59 | &attr_immu_tsb_ticks_ctx0_8k_tte.attr, | ||
60 | &attr_immu_tsb_hits_ctx0_64k_tte.attr, | ||
61 | &attr_immu_tsb_ticks_ctx0_64k_tte.attr, | ||
62 | &attr_immu_tsb_hits_ctx0_4mb_tte.attr, | ||
63 | &attr_immu_tsb_ticks_ctx0_4mb_tte.attr, | ||
64 | &attr_immu_tsb_hits_ctx0_256mb_tte.attr, | ||
65 | &attr_immu_tsb_ticks_ctx0_256mb_tte.attr, | ||
66 | &attr_immu_tsb_hits_ctxnon0_8k_tte.attr, | ||
67 | &attr_immu_tsb_ticks_ctxnon0_8k_tte.attr, | ||
68 | &attr_immu_tsb_hits_ctxnon0_64k_tte.attr, | ||
69 | &attr_immu_tsb_ticks_ctxnon0_64k_tte.attr, | ||
70 | &attr_immu_tsb_hits_ctxnon0_4mb_tte.attr, | ||
71 | &attr_immu_tsb_ticks_ctxnon0_4mb_tte.attr, | ||
72 | &attr_immu_tsb_hits_ctxnon0_256mb_tte.attr, | ||
73 | &attr_immu_tsb_ticks_ctxnon0_256mb_tte.attr, | ||
74 | &attr_dmmu_tsb_hits_ctx0_8k_tte.attr, | ||
75 | &attr_dmmu_tsb_ticks_ctx0_8k_tte.attr, | ||
76 | &attr_dmmu_tsb_hits_ctx0_64k_tte.attr, | ||
77 | &attr_dmmu_tsb_ticks_ctx0_64k_tte.attr, | ||
78 | &attr_dmmu_tsb_hits_ctx0_4mb_tte.attr, | ||
79 | &attr_dmmu_tsb_ticks_ctx0_4mb_tte.attr, | ||
80 | &attr_dmmu_tsb_hits_ctx0_256mb_tte.attr, | ||
81 | &attr_dmmu_tsb_ticks_ctx0_256mb_tte.attr, | ||
82 | &attr_dmmu_tsb_hits_ctxnon0_8k_tte.attr, | ||
83 | &attr_dmmu_tsb_ticks_ctxnon0_8k_tte.attr, | ||
84 | &attr_dmmu_tsb_hits_ctxnon0_64k_tte.attr, | ||
85 | &attr_dmmu_tsb_ticks_ctxnon0_64k_tte.attr, | ||
86 | &attr_dmmu_tsb_hits_ctxnon0_4mb_tte.attr, | ||
87 | &attr_dmmu_tsb_ticks_ctxnon0_4mb_tte.attr, | ||
88 | &attr_dmmu_tsb_hits_ctxnon0_256mb_tte.attr, | ||
89 | &attr_dmmu_tsb_ticks_ctxnon0_256mb_tte.attr, | ||
90 | NULL, | ||
91 | }; | ||
92 | |||
93 | static struct attribute_group mmu_stat_group = { | ||
94 | .attrs = mmu_stat_attrs, | ||
95 | .name = "mmu_stats", | ||
96 | }; | ||
97 | |||
98 | /* XXX convert to rusty's on_one_cpu */ | ||
99 | static unsigned long run_on_cpu(unsigned long cpu, | ||
100 | unsigned long (*func)(unsigned long), | ||
101 | unsigned long arg) | ||
102 | { | ||
103 | cpumask_t old_affinity = current->cpus_allowed; | ||
104 | unsigned long ret; | ||
105 | |||
106 | /* should return -EINVAL to userspace */ | ||
107 | if (set_cpus_allowed(current, cpumask_of_cpu(cpu))) | ||
108 | return 0; | ||
109 | |||
110 | ret = func(arg); | ||
111 | |||
112 | set_cpus_allowed(current, old_affinity); | ||
113 | |||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | static unsigned long read_mmustat_enable(unsigned long junk) | ||
118 | { | ||
119 | unsigned long ra = 0; | ||
120 | |||
121 | sun4v_mmustat_info(&ra); | ||
122 | |||
123 | return ra != 0; | ||
124 | } | ||
125 | |||
126 | static unsigned long write_mmustat_enable(unsigned long val) | ||
127 | { | ||
128 | unsigned long ra, orig_ra; | ||
129 | |||
130 | if (val) | ||
131 | ra = __pa(&per_cpu(mmu_stats, smp_processor_id())); | ||
132 | else | ||
133 | ra = 0UL; | ||
134 | |||
135 | return sun4v_mmustat_conf(ra, &orig_ra); | ||
136 | } | ||
137 | |||
138 | static ssize_t show_mmustat_enable(struct sys_device *s, char *buf) | ||
139 | { | ||
140 | unsigned long val = run_on_cpu(s->id, read_mmustat_enable, 0); | ||
141 | return sprintf(buf, "%lx\n", val); | ||
142 | } | ||
143 | |||
144 | static ssize_t store_mmustat_enable(struct sys_device *s, const char *buf, size_t count) | ||
145 | { | ||
146 | unsigned long val, err; | ||
147 | int ret = sscanf(buf, "%ld", &val); | ||
148 | |||
149 | if (ret != 1) | ||
150 | return -EINVAL; | ||
151 | |||
152 | err = run_on_cpu(s->id, write_mmustat_enable, val); | ||
153 | if (err) | ||
154 | return -EIO; | ||
155 | |||
156 | return count; | ||
157 | } | ||
158 | |||
159 | static SYSDEV_ATTR(mmustat_enable, 0644, show_mmustat_enable, store_mmustat_enable); | ||
160 | |||
161 | static int mmu_stats_supported; | ||
162 | |||
163 | static int register_mmu_stats(struct sys_device *s) | ||
164 | { | ||
165 | if (!mmu_stats_supported) | ||
166 | return 0; | ||
167 | sysdev_create_file(s, &attr_mmustat_enable); | ||
168 | return sysfs_create_group(&s->kobj, &mmu_stat_group); | ||
169 | } | ||
170 | |||
171 | #ifdef CONFIG_HOTPLUG_CPU | ||
172 | static void unregister_mmu_stats(struct sys_device *s) | ||
173 | { | ||
174 | if (!mmu_stats_supported) | ||
175 | return; | ||
176 | sysfs_remove_group(&s->kobj, &mmu_stat_group); | ||
177 | sysdev_remove_file(s, &attr_mmustat_enable); | ||
178 | } | ||
179 | #endif | ||
180 | |||
181 | #define SHOW_CPUDATA_ULONG_NAME(NAME, MEMBER) \ | ||
182 | static ssize_t show_##NAME(struct sys_device *dev, char *buf) \ | ||
183 | { \ | ||
184 | cpuinfo_sparc *c = &cpu_data(dev->id); \ | ||
185 | return sprintf(buf, "%lu\n", c->MEMBER); \ | ||
186 | } | ||
187 | |||
188 | #define SHOW_CPUDATA_UINT_NAME(NAME, MEMBER) \ | ||
189 | static ssize_t show_##NAME(struct sys_device *dev, char *buf) \ | ||
190 | { \ | ||
191 | cpuinfo_sparc *c = &cpu_data(dev->id); \ | ||
192 | return sprintf(buf, "%u\n", c->MEMBER); \ | ||
193 | } | ||
194 | |||
195 | SHOW_CPUDATA_ULONG_NAME(clock_tick, clock_tick); | ||
196 | SHOW_CPUDATA_ULONG_NAME(udelay_val, udelay_val); | ||
197 | SHOW_CPUDATA_UINT_NAME(l1_dcache_size, dcache_size); | ||
198 | SHOW_CPUDATA_UINT_NAME(l1_dcache_line_size, dcache_line_size); | ||
199 | SHOW_CPUDATA_UINT_NAME(l1_icache_size, icache_size); | ||
200 | SHOW_CPUDATA_UINT_NAME(l1_icache_line_size, icache_line_size); | ||
201 | SHOW_CPUDATA_UINT_NAME(l2_cache_size, ecache_size); | ||
202 | SHOW_CPUDATA_UINT_NAME(l2_cache_line_size, ecache_line_size); | ||
203 | |||
204 | static struct sysdev_attribute cpu_core_attrs[] = { | ||
205 | _SYSDEV_ATTR(clock_tick, 0444, show_clock_tick, NULL), | ||
206 | _SYSDEV_ATTR(udelay_val, 0444, show_udelay_val, NULL), | ||
207 | _SYSDEV_ATTR(l1_dcache_size, 0444, show_l1_dcache_size, NULL), | ||
208 | _SYSDEV_ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL), | ||
209 | _SYSDEV_ATTR(l1_icache_size, 0444, show_l1_icache_size, NULL), | ||
210 | _SYSDEV_ATTR(l1_icache_line_size, 0444, show_l1_icache_line_size, NULL), | ||
211 | _SYSDEV_ATTR(l2_cache_size, 0444, show_l2_cache_size, NULL), | ||
212 | _SYSDEV_ATTR(l2_cache_line_size, 0444, show_l2_cache_line_size, NULL), | ||
213 | }; | ||
214 | |||
215 | static DEFINE_PER_CPU(struct cpu, cpu_devices); | ||
216 | |||
217 | static void register_cpu_online(unsigned int cpu) | ||
218 | { | ||
219 | struct cpu *c = &per_cpu(cpu_devices, cpu); | ||
220 | struct sys_device *s = &c->sysdev; | ||
221 | int i; | ||
222 | |||
223 | for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++) | ||
224 | sysdev_create_file(s, &cpu_core_attrs[i]); | ||
225 | |||
226 | register_mmu_stats(s); | ||
227 | } | ||
228 | |||
229 | #ifdef CONFIG_HOTPLUG_CPU | ||
230 | static void unregister_cpu_online(unsigned int cpu) | ||
231 | { | ||
232 | struct cpu *c = &per_cpu(cpu_devices, cpu); | ||
233 | struct sys_device *s = &c->sysdev; | ||
234 | int i; | ||
235 | |||
236 | unregister_mmu_stats(s); | ||
237 | for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++) | ||
238 | sysdev_remove_file(s, &cpu_core_attrs[i]); | ||
239 | } | ||
240 | #endif | ||
241 | |||
242 | static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, | ||
243 | unsigned long action, void *hcpu) | ||
244 | { | ||
245 | unsigned int cpu = (unsigned int)(long)hcpu; | ||
246 | |||
247 | switch (action) { | ||
248 | case CPU_ONLINE: | ||
249 | case CPU_ONLINE_FROZEN: | ||
250 | register_cpu_online(cpu); | ||
251 | break; | ||
252 | #ifdef CONFIG_HOTPLUG_CPU | ||
253 | case CPU_DEAD: | ||
254 | case CPU_DEAD_FROZEN: | ||
255 | unregister_cpu_online(cpu); | ||
256 | break; | ||
257 | #endif | ||
258 | } | ||
259 | return NOTIFY_OK; | ||
260 | } | ||
261 | |||
262 | static struct notifier_block __cpuinitdata sysfs_cpu_nb = { | ||
263 | .notifier_call = sysfs_cpu_notify, | ||
264 | }; | ||
265 | |||
266 | static void __init check_mmu_stats(void) | ||
267 | { | ||
268 | unsigned long dummy1, err; | ||
269 | |||
270 | if (tlb_type != hypervisor) | ||
271 | return; | ||
272 | |||
273 | err = sun4v_mmustat_info(&dummy1); | ||
274 | if (!err) | ||
275 | mmu_stats_supported = 1; | ||
276 | } | ||
277 | |||
278 | static int __init topology_init(void) | ||
279 | { | ||
280 | int cpu; | ||
281 | |||
282 | check_mmu_stats(); | ||
283 | |||
284 | register_cpu_notifier(&sysfs_cpu_nb); | ||
285 | |||
286 | for_each_possible_cpu(cpu) { | ||
287 | struct cpu *c = &per_cpu(cpu_devices, cpu); | ||
288 | |||
289 | register_cpu(c, cpu); | ||
290 | if (cpu_online(cpu)) | ||
291 | register_cpu_online(cpu); | ||
292 | } | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | subsys_initcall(topology_init); | ||