]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/commitdiff
sparc64: Probe cpu page size support more portably.
authorDavid S. Miller <davem@davemloft.net>
Fri, 7 Sep 2012 02:01:25 +0000 (19:01 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 7 Sep 2012 02:01:25 +0000 (19:01 -0700)
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>
arch/sparc/include/asm/mdesc.h
arch/sparc/kernel/mdesc.c
arch/sparc/mm/init_64.c

index 9faa046713fbaf3f6491a4dc3afca964849d9912..139097f3a67bb9dfaa77b01aed9bd177c27a846a 100644 (file)
@@ -73,6 +73,7 @@ extern void mdesc_register_notifier(struct mdesc_notifier_client *client);
 
 extern void mdesc_fill_in_cpu_data(cpumask_t *mask);
 extern void mdesc_populate_present_mask(cpumask_t *mask);
+extern void mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask);
 
 extern void sun4v_mdesc_init(void);
 
index 6dc796280589221f12526111647e20a9eb0911fc..831c001604e8e9bf431b2993ec577b40b6e3f776 100644 (file)
@@ -817,6 +817,30 @@ void __cpuinit mdesc_populate_present_mask(cpumask_t *mask)
        mdesc_iterate_over_cpus(record_one_cpu, NULL, mask);
 }
 
+static void * __init check_one_pgsz(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg)
+{
+       const u64 *pgsz_prop = mdesc_get_property(hp, mp, "mmu-page-size-list", NULL);
+       unsigned long *pgsz_mask = arg;
+       u64 val;
+
+       val = (HV_PGSZ_MASK_8K | HV_PGSZ_MASK_64K |
+              HV_PGSZ_MASK_512K | HV_PGSZ_MASK_4MB);
+       if (pgsz_prop)
+               val = *pgsz_prop;
+
+       if (!*pgsz_mask)
+               *pgsz_mask = val;
+       else
+               *pgsz_mask &= val;
+       return NULL;
+}
+
+void __init mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask)
+{
+       *pgsz_mask = 0;
+       mdesc_iterate_over_cpus(check_one_pgsz, pgsz_mask, mask);
+}
+
 static void * __cpuinit fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg)
 {
        const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
index c0fc25be0c51e9b2d02b0a8153c639818fe14403..445369132e03acc5164339893a7e72bc53696f36 100644 (file)
@@ -83,6 +83,8 @@ unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
 extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
 #endif
 
+static unsigned long cpu_pgsz_mask;
+
 #define MAX_BANKS      32
 
 static struct linux_prom64_registers pavail[MAX_BANKS] __devinitdata;
@@ -419,6 +421,12 @@ EXPORT_SYMBOL(flush_icache_range);
 
 void mmu_info(struct seq_file *m)
 {
+       static const char *pgsz_strings[] = {
+               "8K", "64K", "512K", "4MB", "32MB",
+               "256MB", "2GB", "16GB",
+       };
+       int i, printed;
+
        if (tlb_type == cheetah)
                seq_printf(m, "MMU Type\t: Cheetah\n");
        else if (tlb_type == cheetah_plus)
@@ -430,6 +438,17 @@ void mmu_info(struct seq_file *m)
        else
                seq_printf(m, "MMU Type\t: ???\n");
 
+       seq_printf(m, "MMU PGSZs\t: ");
+       printed = 0;
+       for (i = 0; i < ARRAY_SIZE(pgsz_strings); i++) {
+               if (cpu_pgsz_mask & (1UL << i)) {
+                       seq_printf(m, "%s%s",
+                                  printed ? "," : "", pgsz_strings[i]);
+                       printed++;
+               }
+       }
+       seq_putc(m, '\n');
+
 #ifdef CONFIG_DEBUG_DCFLUSH
        seq_printf(m, "DCPageFlushes\t: %d\n",
                   atomic_read(&dcpage_flushes));
@@ -1803,6 +1822,18 @@ void __init paging_init(void)
 #ifndef CONFIG_SMP
                mdesc_fill_in_cpu_data(cpu_all_mask);
 #endif
+               mdesc_get_page_sizes(cpu_all_mask, &cpu_pgsz_mask);
+       } else {
+               unsigned long impl, ver;
+
+               cpu_pgsz_mask = (HV_PGSZ_MASK_8K | HV_PGSZ_MASK_64K |
+                                HV_PGSZ_MASK_512K | HV_PGSZ_MASK_4MB);
+
+               __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver));
+               impl = ((ver >> 32) & 0xffff);
+               if (impl == PANTHER_IMPL)
+                       cpu_pgsz_mask |= (HV_PGSZ_MASK_32MB |
+                                         HV_PGSZ_MASK_256MB);
        }
 
        /* Setup bootmem... */