#include <sys/cpuvar.h>
#include <sys/lgrp.h>
#include <sys/memnode.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <vm/seg_spt.h>
#include <vm/seg_vn.h>
#include <vm/vm_dep.h>
#include <sys/errno.h>
#include <sys/kstat.h>
#include <sys/cmn_err.h>
#include <sys/memlist.h>
#include <sys/sysmacros.h>
#define NLGRP (MAX_MEM_NODES + 1)
struct lgrp_stats lgrp_stats[NLGRP];
static int nlgrps_alloc;
static lgrp_t lgrp_space[NLGRP];
int lgrphand_to_memnode[MAX_MEM_NODES];
int memnode_to_lgrphand[MAX_MEM_NODES];
static pgcnt_t lgrp_plat_mem_size_default(lgrp_handle_t, lgrp_mem_query_t);
int plat_lgrphand_to_mem_node(lgrp_handle_t);
lgrp_handle_t plat_mem_node_to_lgrphand(int);
void plat_assign_lgrphand_to_mem_node(lgrp_handle_t, int);
extern void plat_lgrp_init(void);
extern void plat_lgrp_config(lgrp_config_flag_t, uintptr_t);
extern lgrp_handle_t plat_lgrp_cpu_to_hand(processorid_t);
extern int plat_lgrp_latency(lgrp_handle_t, lgrp_handle_t);
extern lgrp_handle_t plat_lgrp_root_hand(void);
#pragma weak plat_lgrp_init
#pragma weak plat_lgrp_config
#pragma weak plat_lgrp_cpu_to_hand
#pragma weak plat_lgrp_latency
#pragma weak plat_lgrp_root_hand
int mpo_disabled = 0;
lgrp_handle_t lgrp_default_handle = LGRP_DEFAULT_HANDLE;
void
lgrp_plat_init(lgrp_init_stages_t stage)
{
int i;
switch (stage) {
case LGRP_INIT_STAGE1:
for (i = 0; i < MAX_MEM_NODES; i++) {
memnode_to_lgrphand[i] = -1;
lgrphand_to_memnode[i] = -1;
}
if (lgrp_topo_ht_limit() == 1) {
max_mem_nodes = 1;
return;
}
if (&plat_lgrp_cpu_to_hand)
max_mem_nodes = MAX_MEM_NODES;
if (&plat_lgrp_init)
plat_lgrp_init();
break;
default:
break;
}
}
void
lgrp_plat_config(lgrp_config_flag_t flag, uintptr_t arg)
{
if (max_mem_nodes == 1)
return;
if (&plat_lgrp_config) {
plat_lgrp_config(flag, arg);
}
}
lgrp_handle_t
lgrp_plat_cpu_to_hand(processorid_t id)
{
if (lgrp_topo_ht_limit() > 1 && &plat_lgrp_cpu_to_hand)
return (plat_lgrp_cpu_to_hand(id));
else
return (LGRP_DEFAULT_HANDLE);
}
lgrp_handle_t
lgrp_plat_pfn_to_hand(pfn_t pfn)
{
int mnode;
if (lgrp_topo_ht_limit() == 1 || max_mem_nodes == 1)
return (LGRP_DEFAULT_HANDLE);
if (pfn > physmax)
return (LGRP_NULL_HANDLE);
mnode = PFN_2_MEM_NODE(pfn);
if (mnode < 0)
return (LGRP_NULL_HANDLE);
return (MEM_NODE_2_LGRPHAND(mnode));
}
int
lgrp_plat_max_lgrps(void)
{
return (NLGRP);
}
pgcnt_t
lgrp_plat_mem_size(lgrp_handle_t plathand, lgrp_mem_query_t query)
{
int mnode;
pgcnt_t npgs = (pgcnt_t)0;
extern struct memlist *phys_avail;
extern struct memlist *phys_install;
if (lgrp_topo_ht_limit() == 1 || max_mem_nodes == 1 || mpo_disabled ||
plathand == LGRP_DEFAULT_HANDLE)
return (lgrp_plat_mem_size_default(plathand, query));
if (plathand != LGRP_NULL_HANDLE) {
mnode = plat_lgrphand_to_mem_node(plathand);
if (mnode >= 0 && mem_node_config[mnode].exists) {
switch (query) {
case LGRP_MEM_SIZE_FREE:
npgs = MNODE_PGCNT(mnode);
break;
case LGRP_MEM_SIZE_AVAIL:
npgs = mem_node_memlist_pages(mnode,
phys_avail);
break;
case LGRP_MEM_SIZE_INSTALL:
npgs = mem_node_memlist_pages(mnode,
phys_install);
break;
default:
break;
}
}
}
return (npgs);
}
int
lgrp_plat_latency(lgrp_handle_t from, lgrp_handle_t to)
{
if (lgrp_topo_ht_limit() > 1 && &plat_lgrp_latency)
return (plat_lgrp_latency(from, to));
else
return (0);
}
lgrp_handle_t
lgrp_plat_root_hand(void)
{
if (&plat_lgrp_root_hand)
return (plat_lgrp_root_hand());
else
return (LGRP_DEFAULT_HANDLE);
}
static pgcnt_t
lgrp_plat_mem_size_default(lgrp_handle_t lgrphand, lgrp_mem_query_t query)
{
extern struct memlist *phys_install;
extern struct memlist *phys_avail;
struct memlist *mlist;
pgcnt_t npgs = 0;
switch (query) {
case LGRP_MEM_SIZE_FREE:
return ((pgcnt_t)freemem);
case LGRP_MEM_SIZE_AVAIL:
memlist_read_lock();
for (mlist = phys_avail; mlist; mlist = mlist->ml_next)
npgs += btop(mlist->ml_size);
memlist_read_unlock();
return (npgs);
case LGRP_MEM_SIZE_INSTALL:
memlist_read_lock();
for (mlist = phys_install; mlist; mlist = mlist->ml_next)
npgs += btop(mlist->ml_size);
memlist_read_unlock();
return (npgs);
default:
return ((pgcnt_t)0);
}
}
int
plat_lgrphand_to_mem_node(lgrp_handle_t plathand)
{
int mnode;
if (lgrp_topo_ht_limit() == 1 || mpo_disabled || max_mem_nodes == 1)
return (-1);
ASSERT((int)plathand >= 0 && (int)plathand < max_mem_nodes);
mnode = lgrphand_to_memnode[(int)plathand];
return (mnode);
}
lgrp_handle_t
plat_mem_node_to_lgrphand(int mnode)
{
if (lgrp_topo_ht_limit() == 1 || mpo_disabled || max_mem_nodes == 1)
return (lgrp_default_handle);
ASSERT(mnode >= 0 && mnode < max_mem_nodes);
return (memnode_to_lgrphand[mnode]);
}
void
plat_assign_lgrphand_to_mem_node(lgrp_handle_t plathand, int mnode)
{
if (lgrp_topo_ht_limit() == 1 || mpo_disabled || max_mem_nodes == 1)
return;
ASSERT(plathand < max_mem_nodes);
ASSERT(mnode >= 0 && mnode < max_mem_nodes);
lgrphand_to_memnode[plathand] = mnode;
memnode_to_lgrphand[mnode] = plathand;
}
lgrp_t *
lgrp_plat_alloc(lgrp_id_t lgrpid)
{
lgrp_t *lgrp;
lgrp = &lgrp_space[nlgrps_alloc++];
if (lgrpid >= NLGRP || nlgrps_alloc > NLGRP)
return (NULL);
return (lgrp);
}