/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* bos72X src/bos/kernel/sys/pmzone.h 1.5.7.1 */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* COPYRIGHT International Business Machines Corp. 1988,2021 */ /* All Rights Reserved */ /* */ /* US Government Users Restricted Rights - Use, duplication or */ /* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* */ /* IBM_PROLOG_END_TAG */ /* @(#)54 1.5.7.1 src/bos/kernel/sys/pmzone.h, sysproc, bos72X, x2021_38A6 9/16/21 17:05:01 */ /* * COMPONENT_NAME: SYSPROC * * ORIGIN: 27, 83 * */ /* * LEVEL 1, 5 Years Bull Confidential Information */ #ifndef _H_PMZONE #define _H_PMZONE #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * A zone is a collection of fixed size blocks for which there * is fast allocation/deallocation access. Kernel routines can * use zones to manage data structures dynamically, creating a zone * for each type of data structure to be managed. * * Note: The link word must be unused when the element is free. Any other * words may be used even when the element is free (like p_stat which * holds SNONE). */ #define PM_ZERO 0x00000001L /* when allocated, an entry is zeroed */ #define PM_FIFO 0x00000002L /* the allocation scheme is FIFO */ #define PM_GLOBAL 0x00000004L /* pm_heap is in global memory */ #define PM_PROC 0x00000008L /* pm_heap is pvproc type */ #define PM_THREAD 0x00000010L /* pm_heap is pvthread type */ #define PM_PRIMARY 0x00000020L /* 1st zone with affinity for srad */ #define PM_LAST 0x00000040L /* last zone in global region */ #define PM_BIGZONE 0x00000080L /* zone element is > 1 page; e.g. * utzone, so pin only uthread size */ /* * XXX - SCALABILITY ISSUE * As the number of logical processors is scaled above 128, multiple SRADs * will need to be created. On a machine running more than 128 logical * processors that provides affinity information (i.e., not an SPLPAR machine) * the SRAD code should create multiple SRADs automatically. However, if * affinity information is not provided, the code will not create multiple * SRADs. * * Therefore, at such a time arises when multiple SRADs are needed when running * on machines that do not provide affinity information (i.e., a SPLPAR machine) * the code that creates SRADs will need to modified to automatically create * multiple SRADs or the underlying firmware/hypervisor will need to be * modified to provide affinity information. */ #ifdef __64BIT_KERNEL #define MAXCPUS_SRAD 1536 #define MAXCPUS_LKU 512 /* More will require another reserved zone */ #else #define MAXCPUS_SRAD 64 #endif struct pm_heap { struct pm_heap *next; /* points to secondary, if any */ Simple_lock lock; /* zone lock */ Simple_lock pm_grow_lock; /* per-srad lock only used in primary*/ uint lastin; /* last freed entry */ uint highwater; /* just beyond last used (monotonic) */ uint start; /* beginning of the zone */ uint end; /* just beyond end of the zone */ uint size; /* size of an element */ uint link; /* offset of link word in an element */ uint flags; /* zone flags */ int affinity; /* primary zone affinity */ unsigned long base; /* base address (PM_GLOBAL only) */ char *highwater_addr; /* address of highwater mark for */ /* global zones */ char *free_common; /* common free list for offnode frees*/ struct pm_heap *primary; /* primary zone for this heap */ char *free_anchor[MAXCPUS_SRAD]; /* per cpu free list - one */ /* per cpu on a given SRAD */ eye_catch8b_t pmh_eyec; /* heap eyecatcher */ #define EYEC_PM_HEAP __EYEC8('p','m','_','h','e','a','p','S') }; #ifndef _32KERMODE #ifdef _KERNEL struct pm_heap_global { char * start; /* beginning of the zone */ char * end; /* just beyond end of the zone */ int size; /* size of an element */ int zone_size; /* Size of a zone in this structure */ int l2num_zones; /* log 2 of number of zones */ int link; /* offset of link word in an element */ long flags; /* zone flags */ int zone_hwm; /* initialized zones,high water mark */ int pad; /* pad for double word alignment */ Simple_lock pmhg_zone_lock; /* Lock to serialize alloc of zones */ long *zoneindex; /* primary zone by srad */ struct pm_heap **primary; /* pm zone per srad */ eye_catch8b_t pmhg_eyec; /* global eyecatcher */ #define EYEC_PM_HEAP_GLOBAL __EYEC8('p','m','g','l','o','b','a','l') }; typedef uint32long64_t pmbase_t; /* * pvthread/pvproc data structures must be a power of two in size. * PM_TZONE_SHIFT is the log 2 of the size of each subzone of the * global pvthread region. * * The size of a pvthread element is 2^8 bytes. * If we use a value of 2^23 for PM_TZONE_SHIFT, we get 2^15 elements per * sub-zone. 2^4 subzones will require 2^27 bytes of total memory. * * The size of a pvproc element is 2^10 bytes. * If we use a value of 2^24 for PM_PZONE_SHIFT, * we get 2^14 elements per zone. 2^4 subzones will require 2^28 bytes of * total memory, or a segment. * * Note that the maximum number of threads is 2^19, while the maximum * number of procs is 2^18, so we need to have twice as many threads * in each subzone as we have procs in a subzone as long as we have the * same number of thread subzones as proc subzones. */ /* log 2 of pvthread sub-zone size */ #define PM_TZONE_SHIFT (TIDXSHIFT + TV_LOGSIZE) /* log 2 of pvproc sub-zone size */ #define PM_PZONE_SHIFT (PIDXSHIFT + PV_LOGSIZE) #define PM_LZONE_SHIFT 28 /* Each zone is within a segment for Local zones */ #define MAX_PM_TZONE (1L << PM_TZONE_SHIFT) #define MAX_PM_PZONE (1L << PM_PZONE_SHIFT) #define MAX_PM_LZONE (1L << PM_LZONE_SHIFT) #define PM_TZONE_OFFSET(_x) ((uint)(_x) & (MAX_PM_TZONE-1)) #define PM_PZONE_OFFSET(_x) ((uint)(_x) & (MAX_PM_PZONE-1)) #define PM_LZONE_OFFSET(_x) ((uint)(_x) & (MAX_PM_LZONE-1)) #define PM_TZONE_BASE(_x) ((ulong)(_x) & ~(MAX_PM_TZONE-1)) #define PM_PZONE_BASE(_x) ((ulong)(_x) & ~(MAX_PM_PZONE-1)) #define PM_LZONE_BASE(_x) ((ulong)(_x) & ~(MAX_PM_LZONE-1)) #define PM_ZONE_OFFSET(_x,flags) ((flags & PM_GLOBAL)? \ ((flags & PM_PROC) ? PM_PZONE_OFFSET(_x) : \ PM_TZONE_OFFSET(_x)) : \ PM_LZONE_OFFSET(_x) ) /* Flags for pm_alloc */ #define PM_SKIPFREELIST 0x00000001 #define PM_RESERVED 0x00000002 #define PM_ZONE_LOCKED 0x00000004 /* * ZONE_BASE(pm_zone *zone) * returns the effective base address for a zone */ #define ZONE_BASE(_z) ( \ ((_z)->flags & PM_GLOBAL) ? (_z)->base : \ PM_LZONE_BASE(_z)) extern struct pm_heap_global pvproc_cb; extern struct pm_heap_global pvthread_cb; struct pvproc *get_next_pvproc(struct pvproc *); struct pvthread *get_next_pvthread(struct pvthread *); struct pvproc *get_next_pvproc_srad(struct pvproc *,sradid_t); struct pvthread *get_next_pvthread_srad(struct pvthread *,sradid_t); void pm_balance(void); int pm_validate_slot(long, long); int pm_init(struct pm_heap *zone, char *start, char *end, uint size, uint link, short _class, uint occurrence, long flags); void pm_release(struct pm_heap *zone); void pm_free(struct pm_heap *zone, char *element); void pm_zero(char *block, int size); char *pm_alloc(struct pm_heap *zone, ut_error_t *error, uint flags); char *pm_alloc_srad(struct pm_heap *zone, ut_error_t *error, int node); char *pm_allocext(struct pm_heap *zone1, struct pm_heap *zone2, char * elem, ut_error_t *error); int pm_init_global(struct pm_heap_global *global_zone, short _class, short occurrence); void pm_free_global(struct pm_heap_global *global_zone, char *element); char *pm_alloc_global(struct pm_heap_global *global_zone, ut_error_t *error, sradid_t target_srad); extern int klvup_is_base_pid(pid_t); #ifdef __64BIT_KERNEL #define pm_alloc_local(n, node) xmalloc_srad((n), 7, pinned_heap, (node)) #define pm_free_local(n) xmfree((n), pinned_heap) #else #define pm_alloc_local(n, node) xmalloc((n), 7, pinned_heap0) #define pm_free_local(n) xmfree((n), pinned_heap0) #endif #define round_down(addr,size) (char *)((pmbase_t)(addr) & ~(size-1)) #define round_up(addr,size) round_down((pmbase_t)(addr)+(size)-1,(size)) #endif #endif /* !_32KERMODE */ #ifdef __cplusplus } #endif /*__cplusplus*/ #endif /* _H_PMZONE */