aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-09-06 22:01:25 -0400
committerDavid S. Miller <davem@davemloft.net>2012-09-06 22:01:25 -0400
commitce33fdc52ad50043eef07d11473bc51e225565bd (patch)
treeb2c9e53f3a8f269c7fc5a16e0ebdaf8cea48fdb1
parent4f93d21d2563353df813ee049f6489f340389aab (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.h1
-rw-r--r--arch/sparc/kernel/mdesc.c24
-rw-r--r--arch/sparc/mm/init_64.c31
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
74extern void mdesc_fill_in_cpu_data(cpumask_t *mask); 74extern void mdesc_fill_in_cpu_data(cpumask_t *mask);
75extern void mdesc_populate_present_mask(cpumask_t *mask); 75extern void mdesc_populate_present_mask(cpumask_t *mask);
76extern void mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask);
76 77
77extern void sun4v_mdesc_init(void); 78extern 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
820static 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
838void __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
820static void * __cpuinit fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg) 844static 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)];
83extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES]; 83extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
84#endif 84#endif
85 85
86static unsigned long cpu_pgsz_mask;
87
86#define MAX_BANKS 32 88#define MAX_BANKS 32
87 89
88static struct linux_prom64_registers pavail[MAX_BANKS] __devinitdata; 90static struct linux_prom64_registers pavail[MAX_BANKS] __devinitdata;
@@ -419,6 +421,12 @@ EXPORT_SYMBOL(flush_icache_range);
419 421
420void mmu_info(struct seq_file *m) 422void 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... */