diff options
author | David S. Miller <davem@davemloft.net> | 2012-09-06 22:01:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-09-06 22:01:25 -0400 |
commit | ce33fdc52ad50043eef07d11473bc51e225565bd (patch) | |
tree | b2c9e53f3a8f269c7fc5a16e0ebdaf8cea48fdb1 | |
parent | 4f93d21d2563353df813ee049f6489f340389aab (diff) |
sparc64: Probe cpu page size support more portably.
On sun4v, interrogate the machine description. This code is extremely
defensive in nature, and a lot of the checks can probably be removed.
On sun4u things are a lot simpler. There are the page sizes all chips
support, and then Panther adds 32MB and 256MB pages.
Report the probed value in /proc/cpuinfo
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc/include/asm/mdesc.h | 1 | ||||
-rw-r--r-- | arch/sparc/kernel/mdesc.c | 24 | ||||
-rw-r--r-- | arch/sparc/mm/init_64.c | 31 |
3 files changed, 56 insertions, 0 deletions
diff --git a/arch/sparc/include/asm/mdesc.h b/arch/sparc/include/asm/mdesc.h index 9faa046713fb..139097f3a67b 100644 --- a/arch/sparc/include/asm/mdesc.h +++ b/arch/sparc/include/asm/mdesc.h | |||
@@ -73,6 +73,7 @@ extern void mdesc_register_notifier(struct mdesc_notifier_client *client); | |||
73 | 73 | ||
74 | extern void mdesc_fill_in_cpu_data(cpumask_t *mask); | 74 | extern void mdesc_fill_in_cpu_data(cpumask_t *mask); |
75 | extern void mdesc_populate_present_mask(cpumask_t *mask); | 75 | extern void mdesc_populate_present_mask(cpumask_t *mask); |
76 | extern void mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask); | ||
76 | 77 | ||
77 | extern void sun4v_mdesc_init(void); | 78 | extern void sun4v_mdesc_init(void); |
78 | 79 | ||
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index 6dc796280589..831c001604e8 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c | |||
@@ -817,6 +817,30 @@ void __cpuinit mdesc_populate_present_mask(cpumask_t *mask) | |||
817 | mdesc_iterate_over_cpus(record_one_cpu, NULL, mask); | 817 | mdesc_iterate_over_cpus(record_one_cpu, NULL, mask); |
818 | } | 818 | } |
819 | 819 | ||
820 | static void * __init check_one_pgsz(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg) | ||
821 | { | ||
822 | const u64 *pgsz_prop = mdesc_get_property(hp, mp, "mmu-page-size-list", NULL); | ||
823 | unsigned long *pgsz_mask = arg; | ||
824 | u64 val; | ||
825 | |||
826 | val = (HV_PGSZ_MASK_8K | HV_PGSZ_MASK_64K | | ||
827 | HV_PGSZ_MASK_512K | HV_PGSZ_MASK_4MB); | ||
828 | if (pgsz_prop) | ||
829 | val = *pgsz_prop; | ||
830 | |||
831 | if (!*pgsz_mask) | ||
832 | *pgsz_mask = val; | ||
833 | else | ||
834 | *pgsz_mask &= val; | ||
835 | return NULL; | ||
836 | } | ||
837 | |||
838 | void __init mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask) | ||
839 | { | ||
840 | *pgsz_mask = 0; | ||
841 | mdesc_iterate_over_cpus(check_one_pgsz, pgsz_mask, mask); | ||
842 | } | ||
843 | |||
820 | static void * __cpuinit fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg) | 844 | static void * __cpuinit fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg) |
821 | { | 845 | { |
822 | const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL); | 846 | const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL); |
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index c0fc25be0c51..445369132e03 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c | |||
@@ -83,6 +83,8 @@ unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; | |||
83 | extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES]; | 83 | extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES]; |
84 | #endif | 84 | #endif |
85 | 85 | ||
86 | static unsigned long cpu_pgsz_mask; | ||
87 | |||
86 | #define MAX_BANKS 32 | 88 | #define MAX_BANKS 32 |
87 | 89 | ||
88 | static struct linux_prom64_registers pavail[MAX_BANKS] __devinitdata; | 90 | static struct linux_prom64_registers pavail[MAX_BANKS] __devinitdata; |
@@ -419,6 +421,12 @@ EXPORT_SYMBOL(flush_icache_range); | |||
419 | 421 | ||
420 | void mmu_info(struct seq_file *m) | 422 | void mmu_info(struct seq_file *m) |
421 | { | 423 | { |
424 | static const char *pgsz_strings[] = { | ||
425 | "8K", "64K", "512K", "4MB", "32MB", | ||
426 | "256MB", "2GB", "16GB", | ||
427 | }; | ||
428 | int i, printed; | ||
429 | |||
422 | if (tlb_type == cheetah) | 430 | if (tlb_type == cheetah) |
423 | seq_printf(m, "MMU Type\t: Cheetah\n"); | 431 | seq_printf(m, "MMU Type\t: Cheetah\n"); |
424 | else if (tlb_type == cheetah_plus) | 432 | else if (tlb_type == cheetah_plus) |
@@ -430,6 +438,17 @@ void mmu_info(struct seq_file *m) | |||
430 | else | 438 | else |
431 | seq_printf(m, "MMU Type\t: ???\n"); | 439 | seq_printf(m, "MMU Type\t: ???\n"); |
432 | 440 | ||
441 | seq_printf(m, "MMU PGSZs\t: "); | ||
442 | printed = 0; | ||
443 | for (i = 0; i < ARRAY_SIZE(pgsz_strings); i++) { | ||
444 | if (cpu_pgsz_mask & (1UL << i)) { | ||
445 | seq_printf(m, "%s%s", | ||
446 | printed ? "," : "", pgsz_strings[i]); | ||
447 | printed++; | ||
448 | } | ||
449 | } | ||
450 | seq_putc(m, '\n'); | ||
451 | |||
433 | #ifdef CONFIG_DEBUG_DCFLUSH | 452 | #ifdef CONFIG_DEBUG_DCFLUSH |
434 | seq_printf(m, "DCPageFlushes\t: %d\n", | 453 | seq_printf(m, "DCPageFlushes\t: %d\n", |
435 | atomic_read(&dcpage_flushes)); | 454 | atomic_read(&dcpage_flushes)); |
@@ -1803,6 +1822,18 @@ void __init paging_init(void) | |||
1803 | #ifndef CONFIG_SMP | 1822 | #ifndef CONFIG_SMP |
1804 | mdesc_fill_in_cpu_data(cpu_all_mask); | 1823 | mdesc_fill_in_cpu_data(cpu_all_mask); |
1805 | #endif | 1824 | #endif |
1825 | mdesc_get_page_sizes(cpu_all_mask, &cpu_pgsz_mask); | ||
1826 | } else { | ||
1827 | unsigned long impl, ver; | ||
1828 | |||
1829 | cpu_pgsz_mask = (HV_PGSZ_MASK_8K | HV_PGSZ_MASK_64K | | ||
1830 | HV_PGSZ_MASK_512K | HV_PGSZ_MASK_4MB); | ||
1831 | |||
1832 | __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver)); | ||
1833 | impl = ((ver >> 32) & 0xffff); | ||
1834 | if (impl == PANTHER_IMPL) | ||
1835 | cpu_pgsz_mask |= (HV_PGSZ_MASK_32MB | | ||
1836 | HV_PGSZ_MASK_256MB); | ||
1806 | } | 1837 | } |
1807 | 1838 | ||
1808 | /* Setup bootmem... */ | 1839 | /* Setup bootmem... */ |