/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* bos720 src/bos/kernel/sys/pseg.h 1.13.4.5 */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* COPYRIGHT International Business Machines Corp. 1988,2014 */ /* 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 */ /* @(#)42 1.13.4.5 src/bos/kernel/sys/pseg.h, sysproc, bos720, 1445A_720 9/24/14 17:40:18 */ /* * COMPONENT_NAME: SYSPROC * * FUNCTIONS: * * ORIGINS: 27, 83 * */ /* * LEVEL 1, 5 Years Bull Confidential Information */ #ifndef _H_PSEG #define _H_PSEG /* * For AIX, most of the regions of a 32-bit process are packaged into * a single virtual memory segment, called the process-private segment. * This arrangement is convenient, and avoids wasting lots of address * space giving each region a separate segment. Other machines might * not want to use this scheme. Nothing fundamental depends on it. */ #include #include #include /* The format of the process private segment (PRIVSEG) for a 32-bit process is as follows: _______________________ _ === PRIVSEG -> | user r/w data and text| | | | u_dsize <= u_dmax | | | ----------------------- | | | unused | | | ----------------------- | U_STKDATA_SIZE | | stack for user mode | | | | u_ssize <= u_smax | | | USTACK_TOP -> ----------------------- | | ERRNO -> | standard syscall errno| | | U_REGION_SIZE ----------------------- | | | pointer to std errno | | | ----------------------- _ <-USRSTACK | | unused space for >4K | | | | page size alignment | | U_PSIZE_PAD | ======================= - === | standard kernel stack | -- | U_BLOCK -> ----------------------- -- | one | | standard uthread block| | | pinned | ----------------------- | | page | K_REGION_SIZE | user structure | | -- | | swappable proc info | | ublock | ----------------------- | | | Future Stack | | | ----------------------- | | | AMR Stack | | | ----------------------- | | | 64-bit user (unused) | | | ----------------------- -- <-KLDRHEAPORG | | loader heap | | | | (loader entries) | | KLDRHEAPSIZE | SEGSIZE -> ----------------------- -- === The process private segment (PRIVSEG) for 64-bit processes contains nothing but kernel data. The segment is not mapped into the user address space. ERRNO64 is in the user stack segment. U_REGION_SIZE64=0 PRIVORG _______________________ -- <-SNODEORG64=KHEAPORG64 0 -> | snode heap | | SNODESIZE64 \ KHEAPSIZE64 ----------------------- -- <-UNODEORG64 | | | unode heap | | UNODESIZE64 | | ----------------------- -- <-KHEAPEND64-- | | standard kernel stack | _ | U_BLOCK -> ----------------------- -- | one | | standard uthread block| | | pinned | ----------------------- | | page | K_REGION_SIZE64 | user structure | | -- | (entire segment) | swappable proc info | | ublock | ----------------------- | | | Future stack | | | ----------------------- | | | AMR stack | | | ----------------------- |-- | | 64-bit user struct | | | pinned | ----------------------- ---|--<- KLDRHEAPORG | | loader heap or unused | | KLDRHEAPSIZE | SEGSIZE -> ----------------------- -- --- * The addresses of the u-block and of the standard and 64-bit errno * are exported by ipl.exp All code should use these values rather * than other constants. Everything defined here is derived from them. */ #ifdef _KERNSYS #define ERRNO (SEGOFFSET(&_errno)) #define ERRNO64 (SEGOFFSET(&_errno64)) #else extern int errno64; #define ERRNO (SEGOFFSET(&errno)) #define ERRNO64 (SEGOFFSET(&errno64)) #endif /* _KERNSYS */ #define U_BLOCK (SEGOFFSET(&__ublock)) /* To support multiple page sizes for a 32-bit process's private * segment, the boundary between the user and kernel accessible parts * of a process private segment must be aligned to the system's * largest supported pageable page size (MAXPGPSIZE). Thus, in order to * support larger than 4K alignments, the size of the user accessible * part of a 32-bit process private segment must be increased. * * However, to maintain backward compatibility with previous AIX * versions, the location of a process's errno and errnop variables * can't be moved. So, the stack and data limits stay the same for a * 32-bit process (U_STKDATA_SIZE). But, in reality, the size of the * user accessible part of the process private segment * (U_REGION_SIZE) is padded to a 64K page alignment with * U_PSIZE_PAD. Thus, there is a * small window of memory that a process could access with stray * references beyond errnop. * */ #define U_STKDATA_SIZE (ERRNO + 2*sizeof(int)) #define U_REGION_SIZE ((U_STKDATA_SIZE + MAXPGPSIZE - 1) & ~(MAXPGPSIZE-1)) #define U_PSIZE_PAD (U_REGION_SIZE - U_STKDATA_SIZE) #define K_REGION_SIZE (SEGSIZE - U_REGION_SIZE) #define U_REGION_SIZE64 (0) #define K_REGION_SIZE64 (SEGSIZE - U_REGION_SIZE64) /* U_ARGS_SIZE64: * * execargs max buffer size for 64-bit applications. * * - ARG_MAX () and NCARGS () dictate * the statically compiled in max size which must be less then this. * * - U_ARGS_ORG64 assumes that errno64 is placed near the end of the * 4Mb buffer, contained within it. * * errno64 is defined in ipl64.imp for 64-bit kernel. * */ #define U_ARGS_SIZE64 NCARGS_MAX #define U_ARGS_ORG64 ( (unsigned long long)&errno64 & \ ~((unsigned long long)(U_ARGS_SIZE64-1)) ) /* * The following defines are calculated from the preceeding values. * * USRSTACK is for 32-bit applications. * * KLDRHEAPORG32, KLDRHEAPORG64 and KLDRHEAPSIZE define the layout of the * memory where the loader heap will be. This memory is used for loader * entries for the shlap and all 32-bit processes. For 64-bit processes * other than the shlap, this memory is reserved for use by the loader. * * KHEAPORG64, KHEAPSIZE64 and KHEAPEND64 refer to the additional kernel * storage used to hold structures for a 64-bit process, consisting of address * space structures (segnodes and uadnodes). */ #define USRSTACK (PRIVORG_LO + U_STKDATA_SIZE) #ifdef _POWER /* Start of loader heap in process-private segment for 32-bit processes. */ #define KLDRHEAPORG32 ((uintptr_t)&U64+PAGESIZE) /* Start of loader heap in process-private segment for shlap. */ #define KLDRHEAPORG64 (((uintptr_t)(&__ublock+1) \ + (MAXPGPSIZE-1))&~(MAXPGPSIZE-1)) #define KLDRHEAPSIZE(s_addr) (SEGSIZE - SEGOFFSET((s_addr))) #define KHEAPSIZE64 ((ulong)((ulong)U_REGION_SIZE - \ (ulong)U_REGION_SIZE64) & 0x0FFFFFFFUL) #define KHEAPORG64 (PRIVORG + U_REGION_SIZE64) #define KHEAPEND64 (KHEAPORG64 + KHEAPSIZE64) /* * For 64-bit apps, PRIVSEG is not mapped into the user address space. * U_REGION_SIZE64 is 0, and loader entries are * allocated from segments managed by the loader. * */ #define LDRHDRSIZE64 0 #endif /* _POWER */ #define SNODEORG64 (KHEAPORG64 + LDRHDRSIZE64) /* Round SNODESIZE64 down to a multiple of the page size. */ #define SNODESIZE64 ((KHEAPSIZE64-LDRHDRSIZE64)/2 & ~((ulong)(MAXPGPSIZE-1))) #define UNODEORG64 (SNODEORG64 + SNODESIZE64) #define UNODESIZE64 (SNODESIZE64) /* * The following defines are offsets in a process private segment * to the appropriate data area. They can be used in pointer assignment * in addressing portions of the process private segment */ #define USTACK_TOP ERRNO #define USTACK_TOP64 ERRNO64 /* * Any change to the STACKTOUCH* #defines should also be reflected in * param.m4 as well. */ #define STACKTOUCH (2 * 1024) /* don't touch next segment */ #define STACKTOUCH_U STACKTOUCH /* touch above */ #define STACKTOUCH_M -STACKTOUCH /* touch middle */ #define STACKTOUCH_L -(6 * 1024) /* touch below */ #define STACKTOUCH_LL -(8 * 1024) /* touch far below */ #define KSTACKBLOCK (96 * 1024) /* size of uthr and kstack */ /* actual kstack bytes */ #define KSTACKSIZE (KSTACKBLOCK - sizeof(struct uthread)) /* * mininum initial stack frame is STKMIN. this is machine dependent. */ #ifdef __64BIT__ #define STKMIN 56*2 #define STKMINALIGN 112 #else #define STKMIN 56 #define STKMINALIGN 64 #endif /* __64BIT__ */ #ifdef _KERNEL #define STKMIN64 112 #define STKMINALIGN64 112 #endif /* _KERNEL */ #ifdef _KERNSYS /* * The user stack address of the 64bit process. * * STKTOP64 is the top of the stack + 1. * * STKFLOOR64 is the lowest address to which the stack * can grow architecturally. The implementation may limit * it to a higher address than this. * * MAXSTACK64 is the default size for how big we allow the stack * to grow. The rlimit may be unlimited, or bigger, but this is * how far we will actually let em go, unless the process defines * its own maxstack. * * HARDMAXSTK64 is the hard limit on the total stack that we will * allow a 64-bit process to consume. This is a kernel-specific * size. */ #ifdef _POWER #define STKTOP64 ((unsigned long long)(VM_MAXADDR + 1) << 32) #define STKFLOOR64 (0x0F00000000000000ull) #define MAXSTACK64 (SEGSIZE * 16ll) #endif /* _POWER */ #define HARDMAXSTK64 v.v_hardstack /* * The following describes layout of pm_heap segments, for multi-threaded * programs. pm_heap segments contain uthread structures and kernel/frr/AMR * stacks. Each segment is partitioned into zones for allocation of the * structures. The defines for these zones follow 0 ----------------------- --+ | FRR stack | | ----------------------- | | AMR stack | | ----------------------- | | kernel stack | | uthkstk[0] (one PM ZONE) | | | ----------------------- | | uthread | | ======================= --+ | FRR stack | ----------------------- | AMR stack | ----------------------- --+ | kernel stack | | | | | KSTACKBLOCK ----------------------- | | uthread | | ======================= --+ | . | | . | | . | | . | | . | ======================= --+ | FRR stack | | ----------------------- | | AMR stack | | ----------------------- | uthkstk[THREADS_PER_SEG-1] | kernel stack | | | | | ----------------------- | | uthread | | ======================= --+ | | | uthread pm_heap | | | ----------------------- | | | free space | | | SEGSIZE ----------------------- */ #define THREADS_PER_SEG 2048 /* must be a multiple of 128 */ #define TS_PAD1 \ (PAGESIZE-((THREADS_PER_SEG*(sizeof(struct mstext)))&(PAGESIZE-1))) /* * The kernel stack layout. * * Note: The kernel stacks for kprocs. * have a separate segment, so they do not get the gratuitous pinned * stack portion. Since their stacks are in different segment, the stack * space in kthreadseg (below &uth) is unused. */ struct uthkstk { char frrstk[FRRSTACKSIZE]; /* FRR stack for the thread */ char amrstack[AMRSTACKSIZE]; char kstk[KSTACKSIZE]; /* portion of kstack is pinned too. */ struct uthread uth; /* uth pinned */ }; struct threadseg { struct uthkstk utzone[THREADS_PER_SEG]; struct pm_heap uthread_heap; /* There is more space available in a thread segment. */ }; /* * Get the kstack and amrstack address for this thread... */ #define UT_KSTACK_ADDR(_ut) ((void *)(_ut)) /* * Get the recovery stack address for a specified uthread. * Note this macro only works for uthreads in threadseg segments. */ #define UT_FRRSTACK_ADDR(_ut) \ ((char *)(((char *)(_ut)) - offsetof(struct uthkstk, uth) + \ offsetof(struct uthkstk, frrstk) + FRRSTACKSIZE)) /* * Get the AMR stack address */ #define UT_AMRSTACK_ADDR(_ut) \ ((char *)(((char *)(_ut)) - offsetof(struct uthkstk, uth) + \ offsetof(struct uthkstk, amrstack) + AMRSTACKSIZE)) /* * Kproc's uthread blocks are maintained in KTHREADSEG as laid * out above in threadseg. Kprocs can have only one KTHREADSEG segment. * Kprocs in have their stack segment same as that of the 64bit * user processes. This layout is defined in structure kp64_stackseg below. * A region of KSTACKBLOCK size at the high-end of the stack segment size is * reserved for future use. * Initial stack segment layout for kproc threads. The initial * thread gets major piece of the stack segment to allow the ability to set * stack rlimit. The initial thread can even grow the stack beyond one segment. */ #define KP64_UTHR0_STKSZ_MAX (ulong)(SEGSIZE - ((THREADS_PER_SEG)*KSTACKBLOCK)) struct kp64_stackseg { char kp64_uthr0_kstack[KP64_UTHR0_STKSZ_MAX]; /* primary thread */ char kstack_zone[THREADS_PER_SEG-1][KSTACKBLOCK];/* other threads */ char reserved[KSTACKBLOCK]; }; /* * Get the kstack address for the initial thread of a kproc */ #define KP64_STACK_ORG ((STKTOP64-1) & ~(SEGSIZE-1)) #define KP64_UTHR0_KSTACK ((void *) \ &((struct kp64_stackseg *)KP64_STACK_ORG)-> \ kp64_uthr0_kstack[KP64_UTHR0_STKSZ_MAX]) /* * Get the index of this uthread into utzone[] in threadseg */ #define KPUT_INDEX(_ut) ((SEGOFFSET(_ut) - \ SEGOFFSET(&((((struct threadseg *)0)-> \ utzone[0]).uth))) \ /sizeof(struct uthkstk)) /* * Get the kstack address for this kproc thread... */ #define KP64_KSTACK_ADDR(_ut) ((void *) \ &((struct kp64_stackseg *)KP64_STACK_ORG)-> \ kstack_zone[KPUT_INDEX(_ut)][KSTACKBLOCK]) #endif /* _KERNSYS */ #endif /* _H_PSEG */