Skip to content

Commit

Permalink
sparc64: Probe cpu page size support more portably.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David S. Miller committed Sep 7, 2012
1 parent 4f93d21 commit ce33fdc
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/sparc/include/asm/mdesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
24 changes: 24 additions & 0 deletions arch/sparc/kernel/mdesc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
31 changes: 31 additions & 0 deletions arch/sparc/mm/init_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand All @@ -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));
Expand Down Expand Up @@ -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... */
Expand Down

0 comments on commit ce33fdc

Please sign in to comment.