From e73a04659c0b8cdee4dd40e58630e2cf63afb316 Mon Sep 17 00:00:00 2001 From: Kanoj Sarcar Date: Sat, 5 Feb 2000 02:12:32 +0000 Subject: Discover the amount of memory present in other nodes. Get ready to do numa style bootmem setup. --- arch/mips64/sgi-ip27/ip27-memory.c | 192 ++++++++++++++++++++++++++++++------- arch/mips64/sgi-ip27/ip27-setup.c | 2 - 2 files changed, 158 insertions(+), 36 deletions(-) (limited to 'arch') diff --git a/arch/mips64/sgi-ip27/ip27-memory.c b/arch/mips64/sgi-ip27/ip27-memory.c index 286c510b7..368a0d209 100644 --- a/arch/mips64/sgi-ip27/ip27-memory.c +++ b/arch/mips64/sgi-ip27/ip27-memory.c @@ -18,54 +18,178 @@ #include #include +#include +#include +#include #include +#include + +typedef unsigned long pfn_t; /* into */ +#define KDM_TO_PHYS(x) ((x) & TO_PHYS_MASK) /* into asm/addrspace.h */ + +#define SLOT_PFNSHIFT (SLOT_SHIFT - PAGE_SHIFT) /* into asm/sn/arch.h */ +#define PFN_NASIDSHFT (NASID_SHFT - PAGE_SHIFT) +#define mkpfn(nasid, off) (((pfn_t)(nasid) << PFN_NASIDSHFT) | (off)) +#define slot_getbasepfn(node,slot) \ + (mkpfn(COMPACT_TO_NASID_NODEID(node), slot<> PAGE_SHIFT) #define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) -void __init -prom_meminit(void) +short slot_lastfilled_cache[MAX_COMPACT_NODES]; +unsigned short slot_psize_cache[MAX_COMPACT_NODES][MAX_MEM_SLOTS]; + +/* + * Return pfn of first free page of memory on a node. PROM may allocate + * data structures on the first couple of pages of the first slot of each + * node. If this is the case, getfirstfree(node) > getslotstart(node, 0). + */ +pfn_t node_getfirstfree(cnodeid_t cnode) +{ +#ifdef LATER + nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); + + if (cnode == 0) + return KDM_TO_PHYS((unsigned long)(&_end)); + return KDM_TO_PHYS(SYMMON_STK_ADDR(nasid, 0)); +#endif + if (cnode == 0) + return (KDM_TO_PHYS(PFN_ALIGN(&_end) - (CKSEG0 - K0BASE)) + >> PAGE_SHIFT); + return slot_getbasepfn(cnode, 0); +} + +/* + * Return the number of pages of memory provided by the given slot + * on the specified node. + */ +pfn_t slot_getsize(cnodeid_t node, int slot) +{ + return (pfn_t) slot_psize_cache[node][slot]; +} + +/* + * Return the pfn of the last free page of memory on a node. + */ +pfn_t node_getmaxclick(cnodeid_t node) +{ + pfn_t slot_psize; + int slot; + + /* + * Start at the top slot. When we find a slot with memory in it, + * that's the winner. + */ + for (slot = (node_getnumslots(node) - 1); slot >= 0; slot--) { + if ((slot_psize = slot_getsize(node, slot))) { + /* Return the basepfn + the slot size, minus 1. */ + return slot_getbasepfn(node, slot) + slot_psize - 1; + } + } + + /* + * If there's no memory on the node, return 0. This is likely + * to cause problems. + */ + return (pfn_t)0; +} + +static pfn_t slot_psize_compute(cnodeid_t node, int slot) { - unsigned long free_start, free_end, start_pfn, mb, bootmap_size; - int bank, size; - lboard_t *board; - klmembnk_t *mem; - - board = find_lboard(KLTYPE_IP27); - if (!board) - panic("Can't find memory info for myself."); - - mem = (klmembnk_t *) KLCF_COMP(board, IP27_MEM_INDEX); - if (!mem) - panic("I'm running but don't exist?"); - - mb = 0; - for (bank = 0; bank < MD_MEM_BANKS; bank++) { - size = KLCONFIG_MEMBNK_SIZE(mem, bank); - mb += size; - if (size != 512) { - break; + nasid_t nasid; + lboard_t *brd; + klmembnk_t *banks; + unsigned long size; + + nasid = COMPACT_TO_NASID_NODEID(node); + /* Find the node board */ + brd = find_lboard_real((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); + if (!brd) + return 0; + + /* Get the memory bank structure */ + banks = (klmembnk_t *)find_first_component(brd, KLSTRUCT_MEMBNK); + if (!banks) + return 0; + + /* Size in _Megabytes_ */ + size = (unsigned long)banks->membnk_bnksz[slot/4]; + + /* hack for 128 dimm banks */ + if (size <= 128) { + if (slot%4 == 0) { + size <<= 20; /* size in bytes */ + return(size >> PAGE_SHIFT); + } else { + return 0; } + } else { + size /= 4; + size <<= 20; + return(size >> PAGE_SHIFT); } +} - free_start = PFN_ALIGN(&_end) - (CKSEG0 - K0BASE); - free_end = K0BASE + (mb << 20); - start_pfn = PFN_UP((unsigned long)&_end - CKSEG0); +pfn_t szmem(pfn_t fpage, pfn_t maxpmem) +{ + int node, slot; + int numslots; + pfn_t num_pages = 0; + pfn_t slot_psize; - if (bank != MD_MEM_BANKS && size != 0) - printk("Warning: noncontiguous memory configuration, " - "not using entire available memory."); + for (node = 0; node < numnodes; node++) { + numslots = node_getnumslots(node); + for (slot = 0; slot < numslots; slot++) { + slot_psize = slot_psize_compute(node, slot); + num_pages += slot_psize; + slot_psize_cache[node][slot] = + (unsigned short) slot_psize; + if (slot_psize) + slot_lastfilled_cache[node] = slot; + } + } + if (maxpmem) + return((maxpmem > num_pages) ? num_pages : maxpmem); + else + return num_pages; +} - /* Register all the contiguous memory with the bootmem allocator - and free it. Be careful about the bootmem freemap. */ - bootmap_size = init_bootmem(start_pfn, mb << (20 - PAGE_SHIFT)); - free_bootmem(__pa(free_start), (mb << 20) - __pa(free_start)); - reserve_bootmem(__pa(free_start), bootmap_size); - free_bootmem(0x19000, 0x1c000 - 0x19000); +/* + * Currently, the intranode memory hole support assumes that each slot + * contains at least 32 MBytes of memory. We assume all bootmem data + * fits on the first slot. + */ +void __init prom_meminit(void) +{ + extern void mlreset(void); + cnodeid_t node; + pfn_t slot_firstpfn, slot_lastpfn, slot_freepfn, numpages; + unsigned long bootmap_size; - printk("Found %ldmb of memory.\n", mb); + mlreset(); + numpages = szmem(0, 0); + for (node = 0; node < numnodes; node++) { + slot_firstpfn = slot_getbasepfn(node, 0); + slot_lastpfn = slot_firstpfn + slot_getsize(node, 0); + slot_freepfn = node_getfirstfree(node); + printk("Node %d slot 0: 0x%lx 0x%lx 0x%lx\n", node, + slot_firstpfn<